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 = $("
").attr("class", el.attr("class")).addClass(CL); var track = $("").addClass(rangePrefix + "track"); var thumb = $("").addClass(rangePrefix + "thumb").attr({ role: "slider", "aria-valuenow": el.val(), "aria-valuemax": max, "aria-valuemin": min }); var shadow = $(); if (params.shadow == true) { shadow = $("").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; }; };