Files
SEONexus/code/public/template/kuangyu/reader/wap/js/reader.js
2025-03-25 17:45:16 +08:00

1092 lines
36 KiB
JavaScript

var noop = function() {};
function SwipeReader(options) {
if (!options) {
options = {};
}
this.$wrapper = $(options.wrapperSelector);
this.$scroller = function() {
return this.$wrapper.find(options.scrollerSelector);
}.bind(this);
this.$pager = $(options.pagerSelector);
this.onCenterClick = options.onCenterClick || noop;
this.onSwipePrev = options.onSwipePrev || noop;
this.onSwipeNext = options.onSwipeNext || noop;
this.onWillSwipeNext = options.onWillSwipeNext || noop;
this.gap = options.gap || 16;
this.pager = {
cur: 1,
max: 1
};
this.enabled = false;
this.isPreloading = false;
this.initEvents();
this.initPager();
}
SwipeReader.prototype = {
initEvents: function() {
var self = this;
var $wrapper = self.$wrapper;
var $scroller = self.$scroller;
var isMoving = false;
var firstTouch;
var touch = {};
var startLeft = 0;
$wrapper.on({
touchstart: function(event) {
if (!self.enabled) {
return;
}
var target = event.target || {};
if (/^(?:a|input|label|i|use|svg)$/i.test(target.tagName) || $(target).parents("a").length) {
return;
}
isMoving = true;
firstTouch = event.touches[0] || event;
touch.x1 = firstTouch.pageX;
touch.y1 = firstTouch.pageY;
startLeft = $scroller().data("left") || 0;
},
touchmove: function(event) {
if (!isMoving) {
return;
}
event.preventDefault();
firstTouch = event.touches[0] || event;
touch.x2 = firstTouch.pageX;
touch.y2 = firstTouch.pageY;
var scrollLeft = startLeft - (touch.x2 - touch.x1);
$scroller().css({
"-webkit-transform": "translateX(" + -scrollLeft + "px)",
transform: "translateX(" + -scrollLeft + "px)"
});
},
touchend: function() {
if (!isMoving) {
return;
}
isMoving = false;
var distanceX = touch.x2 - touch.x1;
var distanceMin = self.gap;
if (!touch.x2 || Math.abs(distanceX) < distanceMin) {
var winWidth = window.innerWidth;
var range = [ winWidth / 3, winWidth * 2 / 3 ];
if (touch.x1 <= range[0]) {
self.turnLeft();
} else if (touch.x1 >= range[1]) {
self.turnRight();
} else {
self.scrollTo(startLeft);
self.onCenterClick();
}
} else if (distanceX > distanceMin) {
self.turnLeft();
} else if (distanceX < distanceMin) {
self.turnRight();
} else {
self.scrollTo(startLeft);
}
firstTouch = null;
touch = {};
startLeft = 0;
}
});
},
initPager: function() {
this.resetPager();
this.refreshPager();
},
resetPager: function() {
var elScroller = this.$scroller()[0];
var pager = this.pager;
var gap = this.gap;
pager.cur = 1;
pager.max = Math.round((elScroller.scrollWidth + gap) / (elScroller.clientWidth + gap));
},
refreshPager: function() {
var pager = this.pager;
this.$pager.html([ pager.cur, pager.max ].join("/"));
},
scrollTo: function(x) {
var $scroller = this.$scroller();
var left = $scroller.data("left") || 0;
var step = function() {
left += (x - left) * .5;
if (Math.abs(x - left) < 1) {
$scroller.data("left", x).css({
"-webkit-transform": "translateX(" + -x + "px)",
transform: "translateX(" + -x + "px)"
});
} else {
$scroller.css({
"-webkit-transform": "translateX(" + -left + "px)",
transform: "translateX(" + -left + "px)"
});
if (window.requestAnimationFrame) {
requestAnimationFrame(step);
} else {
setTimeout(step, 17);
}
}
};
step();
},
turnTo: function(current) {
var pager = this.pager;
var gap = this.gap;
var width = this.$scroller().width();
pager.cur = current;
this.scrollTo((current - 1) * (width + gap));
this.refreshPager();
},
turnLeft: function() {
var self = this;
var pager = self.pager;
var current = pager.cur - 1;
if (current < 1) {
pager.cur = 1;
self.enabled = false;
self.onSwipePrev(function() {
var $scroller = self.$scroller();
var maxLeft = $scroller[0].scrollWidth - $scroller.width();
self.enabled = true;
self.$scroller().data("left", maxLeft).css({
"-webkit-transform": "translateX(" + -maxLeft + "px)",
transform: "translateX(" + -maxLeft + "px)"
});
self.initPager();
pager.cur = pager.max;
self.refreshPager();
}, function() {
self.enabled = true;
});
} else {
this.turnTo(current);
}
},
turnRight: function() {
var self = this;
var pager = self.pager;
var current = pager.cur + 1;
if (current > pager.max) {
pager.cur = 1;
self.enabled = false;
self.onSwipeNext(function() {
self.enabled = true;
self.$scroller().css({
"-webkit-transform": "",
transform: ""
});
self.initPager();
}, function() {
self.enabled = true;
});
} else {
self.turnTo(current);
if (current > pager.max - 3 && !self.isPreloading) {
self.isPreloading = true;
self.onWillSwipeNext(function() {
self.isPreloading = false;
}, function() {
self.isPreloading = false;
});
}
}
},
enable: function() {
this.enabled = true;
this.refresh();
},
disable: function() {
this.enabled = false;
this.$scroller().css({
"-webkit-transform": "",
transform: ""
});
},
refresh: function() {
this.initPager();
},
restart: function() {
this.$scroller().css({
"-webkit-transform": "",
transform: ""
});
this.initPager();
}
};
function scaleStepable(value, arrValueStep, arrScaleStep) {
if (arrValueStep.length !== arrScaleStep.length) {
return value;
}
var scaleedValue = value;
var valueStepIndex = arrValueStep.length;
while (valueStepIndex--) {
if (value > arrValueStep[valueStepIndex]) {
scaleedValue = (value - arrValueStep[valueStepIndex]) * arrScaleStep[valueStepIndex];
for (var i = valueStepIndex; i > 0; i--) {
scaleedValue += (arrValueStep[i] - arrValueStep[i - 1]) * arrScaleStep[i - 1];
}
scaleedValue += arrValueStep[0] * 1;
break;
}
}
return scaleedValue;
}
function ScrollReader(options) {
if (!options) {
options = {};
}
this.$wrapper = $(options.wrapperSelector);
this.$scroller = $(options.scrollerSelector || window);
this.$prev = $(options.prevSelector);
this.$next = $(options.nextSelector);
this.$nextTrigger = $(options.nextTriggerSelector);
this.$mark = $(options.markSelector);
this.onPrevClick = options.onPrevClick || noop;
this.onCenterClick = options.onCenterClick || noop;
this.onNextClick = options.onNextClick || noop;
this.onScroll = options.onScroll || noop;
this.onScrollPrev = options.onScrollPrev || noop;
this.onScrollNext = options.onScrollNext || noop;
this.onWillScrollNext = options.onWillScrollNext || noop;
this.triggerMinHeight = options.triggerMinHeight || 58;
this.enabled = false;
this.isPreloading = false;
this.initEvents();
}
ScrollReader.prototype = {
initEvents: function() {
var self = this;
var $wrapper = self.$wrapper;
var $scroller = self.$scroller;
var $prev = self.$prev;
var $next = self.$next;
var $nextTrigger = self.$nextTrigger;
var isMoving = false;
var firstTouch;
var touch = {};
var pull = {};
var jump;
$wrapper.on({
touchstart: function(event) {
if (!self.enabled) {
return;
}
var target = event.target || {};
if (/^(?:a|input|label|i|use|svg)$/i.test(target.tagName) || $(target).parents("a").length) {
return;
}
isMoving = true;
firstTouch = event.touches[0] || event;
touch.x1 = firstTouch.pageX;
touch.y1 = firstTouch.pageY;
},
touchmove: function(event) {
if (!isMoving) {
return;
}
firstTouch = event.touches[0] || event;
touch.x2 = firstTouch.pageX;
touch.y2 = firstTouch.pageY;
var dy = touch.y2 - touch.y1;
var scrollTop = $scroller.scrollTop();
var maxScrollTop = $wrapper.offset().top + $wrapper.height() - $scroller.height();
if (scrollTop <= 0 && dy > 0) {
event.preventDefault();
if (pull.type !== "down") {
pull.type = "down";
pull.y1 = touch.y2;
}
pull.y2 = touch.y2;
pull.dy = pull.y2 - pull.y1;
var limitDownHeight = 52;
var downOffsetTop = Math.abs(parseInt($prev.css("margin-top"), 10));
if (pull.dy - limitDownHeight > 0) {
jump = -1;
$prev.css({
"border-bottom-width": scaleStepable(pull.dy - limitDownHeight, [ 20, 40, 60, 80, 100 ], [ .5, .4, .3, .2, .1 ]),
height: limitDownHeight,
transition: "none"
});
} else {
jump = 0;
$prev.css({
"border-bottom-width": Math.max(downOffsetTop - pull.dy, 0),
height: pull.dy,
transition: "none"
});
}
} else if (scrollTop >= maxScrollTop && dy < 0) {
event.preventDefault();
if (pull.type !== "up") {
pull.type = "up";
pull.y1 = touch.y2;
}
pull.y2 = touch.y2;
pull.dy = pull.y1 - pull.y2;
var limitUpHeight = 48;
if (pull.dy > 0) {
if (pull.dy > limitUpHeight) {
jump = 1;
} else {
jump = 0;
}
$next.prev().css({
position: "relative",
top: -scaleStepable(pull.dy, [ 20, 40, 60, 80, 100 ], [ .5, .4, .3, .2, .1 ])
});
} else {
jump = 0;
$next.prev().css({
position: "relative",
top: 0
});
}
} else {
self.checkWillScrollNext();
}
},
touchend: function(e) {
if (!isMoving) {
return;
}
isMoving = false;
var restore = function() {
$prev.css({
"border-bottom-width": "",
height: "",
transition: ""
});
$next.prev().css({
position: "",
top: "",
"-webkit-transition": "",
transition: ""
});
};
if (!touch.y2) {
self.handlerClick(touch.x1, touch.y1, e);
} else if (jump === -1) {
$prev.css({
"border-bottom-width": 0,
transition: ""
});
self.enabled = false;
self.onScrollPrev(function() {
restore();
var maxScrollTop = $wrapper.offset().top + $wrapper.height() - $scroller.height();
$scroller.scrollTop(maxScrollTop - 58 - 48);
self.enabled = true;
}, function() {
restore();
self.enabled = true;
});
} else if (jump === 1) {
$next.prev().css({
position: "relative",
top: 0,
"-webkit-transition": "top .25s",
transition: "top .25s"
});
self.enabled = false;
self.onScrollNext(function() {
restore();
self.enabled = true;
}, function() {
restore();
self.enabled = true;
});
} else if (pull.type) {
restore();
}
firstTouch = null;
touch = {};
pull = {};
jump = null;
}
});
$scroller.on("scroll", function() {
self.onScroll($scroller.scrollTop());
});
$nextTrigger.on("click", function() {
layer_login=layer.open({type: 2,content: '加载中'});
self.enabled = false;
self.onScrollNext(function() {
layer.close(layer_login);
self.enabled = true;
}, function() {
layer.close(layer_login);
self.enabled = true;
});
});
},
enable: function() {
this.enabled = true;
this.refresh();
},
disable: function() {
this.enabled = false;
this.$scroller.scrollTop(0);
},
refresh: function() {},
restart: function() {
this.$scroller.scrollTop(0);
},
handlerClick: function(x, y, e) {
var self = this;
var $wrapper = self.$wrapper;
var $scroller = self.$scroller;
var height = $scroller.height();
var scrollTop = $scroller.scrollTop();
var range = [ scrollTop + height / 3, scrollTop + height * 2 / 3 ];
var oneScreenContentHeight = height - 60;
if (y <= range[0]) {
self.adjusthMark(Math.max(scrollTop + 44, 0));
self.onPrevClick(e);
self.scrollTo(Math.max(scrollTop - oneScreenContentHeight, 0));
} else if (y >= range[1]) {
var maxScrollTop = $wrapper.offset().top + $wrapper.height() - $scroller.height();
self.adjusthMark(Math.min(scrollTop + height, maxScrollTop));
self.onNextClick(e);
self.scrollTo(Math.min(scrollTop + oneScreenContentHeight, maxScrollTop));
self.checkWillScrollNext();
} else {
self.onCenterClick();
}
},
checkWillScrollNext: function() {
var self = this;
var $wrapper = self.$wrapper;
var $scroller = self.$scroller;
var scrollTop = $scroller.scrollTop();
var maxScrollTop = $wrapper.offset().top + $wrapper.height() - $scroller.height();
if (scrollTop >= Math.min(maxScrollTop * .8, maxScrollTop - 200) && !self.isPreloading) {
self.isPreloading = true;
self.onWillScrollNext(function() {
self.isPreloading = false;
}, function() {
self.isPreloading = false;
});
}
},
scrollTo: function(y, callback) {
var $scroller = this.$scroller;
var scrollTop = $scroller.scrollTop();
if (y < 0) {
y = 0;
}
var step = function() {
scrollTop += (y - scrollTop) * .2;
if (Math.abs(y - scrollTop) < 1) {
$scroller.scrollTop(y);
if ($.isFunction(callback)) {
callback();
}
} else {
$scroller.scrollTop(scrollTop);
if (window.requestAnimationFrame) {
requestAnimationFrame(step);
} else {
setTimeout(step, 17);
}
}
};
step();
},
adjusthMark: function(y) {
var self = this;
var $wapper = self.$wrapper;
var $mark = self.$mark;
if (!$mark.data("init")) {
$mark.data("init", true);
$wapper.on("touchstart", function() {
if (!self.enabled) {
return;
}
clearTimeout($mark.timer);
$mark.css("opacity", 0);
});
}
$mark.css({
opacity: 1,
top: y
});
$mark.timer = setTimeout(function() {
$mark.css("opacity", 0);
}, 1500);
}
};
var ACTIVE = "active", ENABLED = "enabled";
var Toggle = function(selector, options) {
var self = this;
if (!selector) {
return self;
}
if ($.isFunction(options)) {
options = {
callback: options
};
}
var defaults = {
mode: "visible",
container: $("body"),
callback: function() {}
};
var params = $.extend({}, defaults, options || {});
self.callback = params.callback;
self.mode = params.mode;
if (!selector.size && $.isArray(selector)) {
selector = selector.join();
}
if (typeof selector == "string") {
params.container.on("click", selector, function(event) {
self.toggle($(this), event);
});
} else if (selector.length) {
selector.on("click", function(event) {
self.toggle($(this), event);
});
}
self.aria(selector);
};
Toggle.prototype.aria = function(selector) {
var self = this;
if (self.mode == "visible" && typeof selector == "string") {
$(selector).each(function() {
var trigger = $(this);
trigger.attr({
role: "menuitem",
"aria-expanded": trigger.hasClass(ACTIVE)
});
});
}
};
Toggle.prototype.toggle = function(trigger, event) {
var self = this;
var target = trigger;
var isActive;
if (self.mode == "visible") {
target = $("#" + trigger.attr("data-rel"));
isActive = trigger.hasClass(ACTIVE);
if (isActive) {
trigger.removeClass(ACTIVE).attr("aria-expanded", "false");
target.removeClass(ACTIVE);
} else {
trigger.addClass(ACTIVE).attr("aria-expanded", "true");
target.addClass(ACTIVE);
}
} else if (self.mode == "more") {
isActive = typeof trigger.attr("open") == "string";
if (isActive) {
trigger.removeAttr("open");
} else {
trigger.attr("open", "");
}
}
self.callback.call(trigger, trigger, target, isActive, event);
};
function isLocalStorageSupported() {
var testKey = "test";
try {
localStorage.setItem(testKey, testKey);
localStorage.removeItem(testKey);
return true;
} catch (ex) {
return false;
}
}
var isSupported = isLocalStorageSupported();
var Storage = {
get : function(key) {
if (!isSupported) {
return null;
}
try {
return JSON.parse(localStorage.getItem(key));
} catch (ex) {
return null;
}
},
set : function(key, value) {
if (!isSupported) {
return null;
}
try {
return localStorage.setItem(key, JSON.stringify(value));
} catch (ex) {
return null;
}
},
remove : function(key) {
if (!isSupported) {
return null;
}
return localStorage.removeItem(key);
},
clear : function() {
if (!isSupported) {
return null;
}
return localStorage.clear();
}
};
(function ($) {
"use strict";
var $ = window.Zepto;
var ACTIVE = "active";
var Aside;
$.fn.aside = function(options) {
if (!this.$aside) {
this.$aside = new Aside(this, options);
}
};
Aside = function(el, options) {
var defaults = {
scrollable: ".scrollable",
onInit: function() {},
onShow: function() {},
onHide: function() {},
onScroll: function() {}
};
var elTrigger = $(el);
var elBody = $(document.body);
if (elTrigger.length === 0) return;
var params = $.extend({}, defaults, options);
var idAside = el.data("rel");
var elAside = $("#" + idAside);
var isActive = function() {
return location.hash.replace("#&", "") === idAside;
};
var self = this;
self.el = {
trigger: elTrigger,
aside: elAside,
overlay: elAside.find(".aside-overlay"),
content: elAside.find(".aside-content")
};
self.callback = {
init: params.onInit,
show: params.onShow,
hide: params.onHide,
scroll: params.onScroll
};
self.title = elTrigger.attr("title");
elTrigger.attr({
role: "button",
"aria-haspopup": "true"
});
elTrigger.on("click", function(event) {
event.preventDefault();
self.show(this.href);
});
elAside.prependTo(elBody);
self.el.overlay.on("click", function() {
self.hide();
}).on("touchmove", function(event) {
event.preventDefault();
}).attr({
role: "button"
});
self.scrollable(params.scrollable);
self.swipeOut(params.scrollable);
if (isActive()) {
self.show();
}
window.addEventListener("popstate", function() {
if (isActive()) {
self.show();
} else {
self.hide(true);
}
});
};
Aside.prototype.show = function(hash) {
var self = this;
var el = self.el, callback = self.callback;
var elTrigger = el.trigger;
var elAside = el.aside;
if (elAside.hasClass(ACTIVE)) {
return;
}
elAside.addClass(ACTIVE);
el.overlay.attr("title", "点击关闭浮层");
elTrigger.attr("title", "浮层已显示");
if (!elTrigger.data("init")) {
elTrigger.data("init", true);
callback.init.call(self);
}
$("html").addClass("noscroll");
callback.show.call(self);
if (history.pushState && hash) {
history.pushState(null, null, hash);
}
};
Aside.prototype.hide = function(isFromPopState) {
var self = this;
var el = self.el, callback = self.callback;
var elTrigger = el.trigger;
var elAside = el.aside;
$("html").removeClass("noscroll");
if (!elAside.hasClass(ACTIVE)) {
return;
}
elAside.removeClass(ACTIVE);
el.overlay.attr("title", "浮层已关闭");
elTrigger.attr("title", self.title);
callback.hide.call(self);
if (history.pushState && !isFromPopState) {
var href = location.href.split("#")[0];
history.go(-1);
setTimeout(function() {
history.replaceState(null, null, href);
}, 0);
}
};
Aside.prototype.scrollable = function(selectorScrollable) {
var self = this;
var elAside = self.el.aside;
if (!selectorScrollable || elAside.data("isBindScroll")) {
return self;
}
var isSBBrowser = /mx\d.*mqqbrowser/i.test(navigator.userAgent);
var data = {
posY: 0,
maxscroll: 0
};
elAside.on("touchstart", selectorScrollable, function(event) {
var events = event.touches[0] || event;
data.elScroll = $(this);
data.posY = events.pageY;
data.scrollY = data.elScroll.scrollTop();
data.maxscroll = this.scrollHeight - this.clientHeight;
});
elAside.on("touchmove", function(event) {
if (data.maxscroll <= 0 || isSBBrowser) {
event.preventDefault();
}
var elScroll = data.elScroll;
var scrollTop = elScroll.scrollTop();
var events = event.touches[0] || event;
var distanceY = events.pageY - data.posY;
if (isSBBrowser) {
elScroll.scrollTop(data.scrollY - distanceY);
elScroll.trigger("scroll");
return;
}
if (distanceY > 0 && scrollTop == 0) {
event.preventDefault();
return;
}
if (distanceY < 0 && scrollTop + 1 >= data.maxscroll) {
event.preventDefault();
return;
}
self.callback.scroll.call(self, elScroll);
});
elAside.data("isBindScroll", true);
};
Aside.prototype.swipeOut = function(selectorScrollable) {
var self = this;
var elAside = self.el.aside;
var elContent = self.el.content;
var data = {};
elContent.on("touchstart", function(event) {
var events = event.touches[0] || event;
data.posX = events.pageX;
data.distanceX = 0;
if (data.transition) {
return;
}
elContent.css({
"-webkit-transition": "none",
transition: "none"
});
var target = event.target, elTarget = $(target);
var elScroll = elTarget.parents(selectorScrollable);
if (elTarget.is(selectorScrollable)) {
elScroll = elTarget;
}
if (elScroll.length && elScroll[0].scrollHeight > elScroll[0].clientHeight) {
data.moving = false;
return;
}
data.moving = true;
});
elAside.on("touchmove", function(event) {
var events = event.touches[0] || event;
var distanceX = events.pageX - data.posX;
data.distanceX = distanceX;
if (distanceX < 0) {
distanceX = 0;
}
if (!data.moving) {
return;
}
elContent.css({
"-webkit-transform": "translateX(" + distanceX + "px)",
transform: "translateX(" + distanceX + "px)"
});
event.preventDefault();
});
elAside.on("touchend", function() {
elContent.css({
"-webkit-transition": "",
transition: ""
});
if (!data.moving) {
return;
}
data.transition = true;
if (data.distanceX > 100) {
self.hide();
elContent.css({
"-webkit-transform": "translateX(100%)",
transform: "translateX(100%)"
});
} else {
elContent.css({
"-webkit-transform": "translateX(0)",
transform: "translateX(0)"
});
}
setTimeout(function() {
elContent.css({
"-webkit-transform": "",
transform: ""
});
delete data.transition;
}, 151);
data.moving = false;
});
return self;
};
return Aside;
})(Zepto);
var CL = "range", rangePrefix = CL + "-";
$.fn.range = function(options) {
return $(this).each(function() {
if (this.$range) {
this.$range = new Range($(this), options);
}
});
};
var Range = function(el, options) {
var self = this;
var defaults = {
container: $("body"),
shadow: false,
buttons: [ "", "" ],
onChangeEnd: function() {},
tips: function(value) {
return value;
}
};
var params = $.extend({}, defaults, options || {});
var min = el.attr("min") || 0, max = el.attr("max") || 100, step = el.attr("step") || 1;
var container = $("<div></div>").attr("class", el.attr("class")).addClass(CL);
var track = $("<div></div>").addClass(rangePrefix + "track");
var thumb = $("<a></a>").addClass(rangePrefix + "thumb").attr({
role: "slider",
"aria-valuenow": el.val(),
"aria-valuemax": max,
"aria-valuemin": min
});
var shadow = $();
if (params.shadow == true) {
shadow = $("<a></a>").addClass(rangePrefix + "shadow").attr("title", "之前位置");
}
el.before(container);
if (container.width() == 0) {
container.width(el.width());
}
track.append(thumb);
container.append(track).prepend(shadow);
container.on("click", function(event) {
var target = event && event.target;
if (!target) {
return;
}
if (shadow.length && target == shadow[0]) {
var value = $(target).attr("data-value"), valueEl = el.val();
if (value && valueEl != value) {
self.value(value);
params.onChangeEnd.call(el, self);
}
} else if (target != thumb[0]) {
var distance = event.clientX - (thumb.offset().left - $(window).scrollLeft()) - thumb.width() / 2;
self.value(el.val() * 1 + (max - min) * distance / $(this).width());
params.onChangeEnd.call(el, self);
}
});
var posThumb = {
distance: 0
};
thumb.on("touchstart", function(event) {
var events = event.touches[0] || event;
posThumb.x = events.pageX;
posThumb.value = el.val() * 1;
posThumb.distance = 0;
var tips = posThumb.value;
if ($.isFunction(params.tips)) {
tips = params.tips.call(el, posThumb.value);
}
thumb.attr("data-tips", tips).attr("aria-valuenow", tips).addClass("active");
});
params.container.on({
touchmove: function(event) {
var events = event.touches[0] || event;
if (typeof posThumb.x == "number") {
var distance = events.pageX - posThumb.x;
posThumb.distance = distance;
self.value(posThumb.value + (max - min) * distance / container.width());
var tips = el.val();
if ($.isFunction(params.tips)) {
tips = params.tips.call(el, tips);
}
thumb.attr("data-tips", tips).attr("aria-valuenow", tips);
event.preventDefault();
}
},
touchend: function() {
if (Math.abs(posThumb.distance) > 0) {
params.onChangeEnd.call(el, self);
}
posThumb.x = null;
posThumb.value = null;
thumb.removeClass("active");
posThumb.distance = 0;
}
});
if ($.isArray(params.buttons)) {
params.buttons.forEach(function(button, index) {
if (!button) {
return;
}
if (typeof button == "string") {
button = $(button);
}
if (button.length) {
button.on("click", function() {
var indexBtn = +$(this).data("index");
var max = el.attr("max");
var min = el.attr("min") || "1";
var step = el.attr("step") || "1";
var value = el.val(), newValue = value;
if (indexBtn == 0) {
newValue = value - step;
if (newValue < min) {
newValue = min;
}
} else if (indexBtn == 1) {
newValue = value * 1 + step * 1;
if (newValue > max) {
newValue = max;
}
}
if (newValue !== value) {
self.value(newValue);
params.onChangeEnd.call(el, self);
}
}).data("index", index);
button.attr("role", "button");
}
});
}
this.num = {
min: +min,
max: +max,
step: +step
};
this.el = {
input: el,
container: container,
track: track,
thumb: thumb,
shadow: shadow
};
this.callback = {
changeEnd: params.onChangeEnd.bind(el, self)
};
this.obj = {};
this.value();
this.shadow();
return this;
};
Range.prototype.value = function(value) {
var input = this.el.input, oldvalue = input.val();
var max = this.num.max, min = this.num.min, step = this.num.step;
if (!value) {
oldvalue = value;
value = $.trim(input.val());
}
if (value > max || max - value < step / 2) {
value = max;
} else if (value == "" || value < min || value - min < step / 2) {
value = min;
} else {
value = min + Math.round((value - min) / step) * step;
}
input.val(value);
this.position();
if (value != oldvalue) {
input.trigger("change");
}
return this;
};
Range.prototype.position = function() {
var input = this.el.input, value = input.val();
var max = this.num.max, min = this.num.min, step = this.num.step;
this.el.track.css("borderLeftWidth", this.el.container.width() * (value - min) / (max - min));
return this;
};
Range.prototype.shadow = function() {
var el = this.el;
var track = el.track, shadow = el.shadow;
if (shadow.length) {
shadow.css("left", track.css("borderLeftWidth")).attr("data-value", el.input.val());
}
return this;
};
function debounce(func, wait) {
var context;
var args;
var result;
var previous;
var timer;
var later = function() {
var diff = Date.now() - previous;
if (diff < wait && diff > 0) {
timer = setTimeout(later, wait - diff);
} else {
timer = null;
result = func.apply(context, args);
if (!timer) {
context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
previous = Date.now();
if (!timer) {
timer = setTimeout(later, wait);
}
return result;
};
};