/** * ydui main */ !function (window) { "use strict"; var doc = window.document, ydui = {}; /** * 鐩存帴缁戝畾FastClick */ $(window).on('load', function () { typeof FastClick == 'function' && FastClick.attach(doc.body); }); var util = ydui.util = { /** * 鏍煎紡鍖栧弬鏁 * @param string */ parseOptions: function (string) { if ($.isPlainObject(string)) { return string; } var start = (string ? string.indexOf('{') : -1), options = {}; if (start != -1) { try { options = (new Function('', 'var json = ' + string.substr(start) + '; return JSON.parse(JSON.stringify(json));'))(); } catch (e) { } } return options; }, /** * 椤甸潰婊氬姩鏂规硶銆愮Щ鍔ㄧ銆 * @type {{lock, unlock}} * lock锛氱姝㈤〉闈㈡粴鍔? unlock锛氶噴鏀鹃〉闈㈡粴鍔 */ pageScroll: function () { var fn = function (e) { e.preventDefault(); e.stopPropagation(); }; var islock = false; return { lock: function () { if (islock)return; islock = true; doc.addEventListener('touchmove', fn); }, unlock: function () { islock = false; doc.removeEventListener('touchmove', fn); } }; }(), /** * 鏈湴瀛樺偍 */ localStorage: function () { return storage(window.localStorage); }(), /** * Session瀛樺偍 */ sessionStorage: function () { return storage(window.sessionStorage); }(), /** * 搴忓垪鍖 * @param value * @returns {string} */ serialize: function (value) { if (typeof value === 'string') return value; return JSON.stringify(value); }, /** * 鍙嶅簭鍒楀寲 * @param value * @returns {*} */ deserialize: function (value) { if (typeof value !== 'string') return undefined; try { return JSON.parse(value); } catch (e) { return value || undefined; } } }; /** * HTML5瀛樺偍 */ function storage (ls) { return { set: function (key, value) { ls.setItem(key, util.serialize(value)); }, get: function (key) { return util.deserialize(ls.getItem(key)); }, remove: function (key) { ls.removeItem(key); }, clear: function () { ls.clear(); } }; } /** * 鍒ゆ柇css3鍔ㄧ敾鏄惁鎵ц瀹屾瘯 * @git http://blog.alexmaccaw.com/css-transitions * @param duration */ $.fn.emulateTransitionEnd = function (duration) { var called = false, $el = this; $(this).one('webkitTransitionEnd', function () { called = true; }); var callback = function () { if (!called) $($el).trigger('webkitTransitionEnd'); }; setTimeout(callback, duration); }; if (typeof define === 'function') { define(ydui); } else { window.YDUI = ydui; } }(window); /** * Device */ !function (window) { var doc = window.document, ydui = window.YDUI, ua = window.navigator && window.navigator.userAgent || ''; var ipad = !!ua.match(/(iPad).*OS\s([\d_]+)/), ipod = !!ua.match(/(iPod)(.*OS\s([\d_]+))?/), iphone = !ipad && !!ua.match(/(iPhone\sOS)\s([\d_]+)/); ydui.device = { /** * 鏄惁绉诲姩缁堢 * @return {Boolean} */ isMobile: !!ua.match(/AppleWebKit.*Mobile.*/) || 'ontouchstart' in doc.documentElement, /** * 鏄惁IOS缁堢 * @returns {boolean} */ isIOS: !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), /** * 鏄惁Android缁堢 * @returns {boolean} */ isAndroid: !!ua.match(/(Android);?[\s\/]+([\d.]+)?/), /** * 鏄惁ipad缁堢 * @returns {boolean} */ isIpad: ipad, /** * 鏄惁ipod缁堢 * @returns {boolean} */ isIpod: ipod, /** * 鏄惁iphone缁堢 * @returns {boolean} */ isIphone: iphone, /** * 鏄惁webview * @returns {boolean} */ isWebView: (iphone || ipad || ipod) && !!ua.match(/.*AppleWebKit(?!.*Safari)/i), /** * 鏄惁寰俊绔 * @returns {boolean} */ isWeixin: ua.indexOf('MicroMessenger') > -1, /** * 鏄惁鐏嫄娴忚鍣 */ isMozilla: /firefox/.test(navigator.userAgent.toLowerCase()), /** * 璁惧鍍忕礌姣 */ pixelRatio: window.devicePixelRatio || 1 }; }(window); /** * 瑙e喅:active杩欎釜楂樼娲嬫皵鐨凜SS浼被涓嶈兘浣跨敤闂 */ !function (window) { window.document.addEventListener('touchstart', function (event) { /* Do Nothing */ }, false); }(window); /** * InfiniteScroll Plugin */ !function (window) { "use strict"; var util = window.YDUI.util; function InfiniteScroll (element, options) { this.$element = $(element); this.options = $.extend({}, InfiniteScroll.DEFAULTS, options || {}); this.init(); } /** * 榛樿鍙傛暟 */ InfiniteScroll.DEFAULTS = { binder: window, // 缁戝畾娴忚鍣ㄦ粴鍔ㄤ簨浠禗OM initLoad: true, // 鏄惁鍒濆鍖栧姞杞界涓€灞忔暟鎹 pageSize: 0, // 姣忛〉璇锋眰鐨勬暟鎹噺 loadingHtml: '鍔犺浇涓?..', // 鍔犺浇涓彁绀猴紝鏀寔HTML doneTxt: '娌℃湁鏇村鏁版嵁浜?, // 鍔犺浇瀹屾瘯鎻愮ず backposition: false, // 鏄惁浠庤鎯呴〉杩斿洖鍒楄〃椤甸噸鏂板畾浣嶄箣鍓嶄綅缃 jumpLink: '', // 璺宠浆璇︽儏椤甸摼鎺ュ厓绱 loadListFn: null, // 鍔犺浇鏁版嵁鏂规硶 loadStorageListFn: null // 鍔犺浇SesstionStorage鏁版嵁鏂规硶 }; /** * 鍒濆鍖 */ InfiniteScroll.prototype.init = function () { var _this = this, options = _this.options, _location = window.location; if (~~options.pageSize <= 0) { console.error('[YDUI warn]: 闇€鎸囧畾pageSize鍙傛暟銆愬嵆姣忛〉璇锋眰鏁版嵁鐨勯暱搴︺€?); return; } // 鑾峰彇椤甸潰鍞竴閿紝闃叉澶氫釜椤甸潰璋冪敤鏁版嵁閿欎贡 var primaryKey = _location.pathname.toUpperCase().replace(/\/?\.?/g, ''); if (!primaryKey) { primaryKey = 'YDUI_' + _location.host.toUpperCase().replace(/\/?\.?:?/g, ''); } // 淇濆瓨杩斿洖椤甸潰瀹氫綅鎵€闇€鍙傛暟鐨勯敭鍚 _this.backParamsKey = primaryKey + '_BACKPARAMS'; // 淇濆瓨鍒楄〃鏁版嵁鐨勯敭鍚 _this.backParamsListKey = primaryKey + '_LIST_'; // 鍦ㄥ垪琛ㄥ簳閮ㄦ坊鍔犱竴涓爣璁帮紝鐢ㄥ叾鍒ゆ柇鏄惁婊氬姩鑷冲簳閮 _this.$element.append(_this.$tag = $('
')); // 鍒濆鍖栬祴鍊煎垪琛ㄨ窛绂婚《閮ㄧ殑璺濈(姣斿鍘婚櫎瀵艰埅鐨勯珮搴﹁窛绂?锛岀敤浠ヨ繑鍥炲垪琛ㄥ畾浣嶅噯纭綅缃 _this.listOffsetTop = _this.$element.offset().top; _this.initLoadingTip(); // 鏄惁鍒濆鍖栧氨闇€瑕佸姞杞界涓€灞忔暟鎹 if (options.initLoad) { if (!options.backposition) { _this.loadList(); } else { // !util.localStorage.get(_this.backParamsKey) && _this.loadList(); !util.sessionStorage.get(_this.backParamsKey) && _this.loadList(); } } _this.bindScrollEvent(); if (options.backposition) { _this.loadListFromStorage(); _this.bindLinkEvent(); } }; /** * 鍒濆鍖栧姞杞戒腑鎻愮ず */ InfiniteScroll.prototype.initLoadingTip = function () { var _this = this; _this.$element.append(_this.$loading = $('
' + _this.options.loadingHtml + '
')); }; /** * 婊氬姩椤甸潰鑷砈esstionStorage鍌ㄥ瓨鐨勫潗鏍 */ InfiniteScroll.prototype.scrollPosition = function () { var _this = this, options = _this.options, $binder = $(options.binder); var backParams = util.sessionStorage.get(_this.backParamsKey); // 婊氬姩椤甸潰 backParams && $binder.stop().animate({scrollTop: backParams.offsetTop}, 0, function () { _this.scrolling = false; }); options.backposition && _this.bindLinkEvent(); // 閲婃斁椤甸潰婊氬姩鏉冮檺 util.pageScroll.unlock(); // 鍒犻櫎淇濆瓨鍧愭爣椤电爜鐨勫瓨鍌 util.sessionStorage.remove(_this.backParamsKey); }; /** * 缁欐祻瑙堝櫒缁戝畾婊氬姩浜嬩欢 */ InfiniteScroll.prototype.bindScrollEvent = function () { var _this = this, $binder = $(_this.options.binder), isWindow = $binder.get(0) === window, contentHeight = isWindow ? $(window).height() : $binder.height(); $binder.on('scroll.ydui.infinitescroll', function () { if (_this.loading || _this.isDone)return; var contentTop = isWindow ? $(window).scrollTop() : $binder.offset().top; // 褰撴祻瑙堝櫒婊氬姩鍒板簳閮ㄦ椂锛屾鏃 _this.$tag.offset().top 绛変簬 contentTop + contentHeight if (_this.$tag.offset().top <= contentTop + contentHeight + contentHeight / 10) { _this.loadList(); } }); }; /** * 璺宠浆璇︽儏椤靛墠澶勭悊鎿嶄綔 * description: 鐐瑰嚮璺宠浆鍓嶅偍瀛樺綋鍓嶄綅缃互鍙婇〉闈紝涔嬪悗鍐嶈烦杞 */ InfiniteScroll.prototype.bindLinkEvent = function () { var _this = this, options = _this.options; if (!options.jumpLink) { console.error('[YDUI warn]: 闇€鎸囧畾璺宠浆璇︽儏椤甸摼鎺ュ厓绱?); return; } $(_this.options.binder).on('click.ydui.infinitescroll', _this.options.jumpLink, function (e) { e.preventDefault(); var $this = $(this), page = $this.data('page'); if (!page) { console.error('[YDUI warn]: 璺宠浆閾炬帴鍏冪礌闇€娣诲姞灞炴€data-page="鍏舵墍鍦ㄩ〉鐮?]'); return; } // 鍌ㄥ瓨top[璺濈椤堕儴鐨勮窛绂籡涓巔age[椤电爜] util.sessionStorage.set(_this.backParamsKey, { offsetTop: $(_this.options.binder).scrollTop() + $this.offset().top - _this.listOffsetTop, page: page }); location.href = $this.attr('href'); }); }; /** * 鍔犺浇鏁版嵁 */ InfiniteScroll.prototype.loadList = function () { var _this = this, options = _this.options; _this.loading = true; _this.$loading.show(); if (typeof options.loadListFn == 'function') { // 鐩戝惉澶栭儴鑾峰彇鏁版嵁鏂规硶锛屼互渚胯幏鍙栨暟鎹 options.loadListFn().done(function (listArr, page) { var len = listArr.length; console.log(page); // if (~~len <= 0) { // console.error('[YDUI warn]: 闇€鍦 resolve() 鏂规硶閲屽洖浼犳湰娆¤幏鍙栬褰曢泦鍚?); // return; // } _this.$loading.hide(); _this.loading = false; // 褰撹姹傜殑鏁版嵁灏忎簬pageSize[姣忛〉璇锋眰鏁版嵁鏁癩锛屽垯璁や负鏁版嵁鍔犺浇瀹屾瘯锛屾彁绀虹浉搴斾俊鎭 if (len < options.pageSize) { if(_this.$element.find(".list-donetip").length > 0){ _this.$element.find(".list-donetip").show(); }else{ _this.$element.append('
' + options.doneTxt + '
'); } _this.isDone = true; } // 灏嗚姹傚埌鐨勬暟鎹瓨鍏essionStorage if (options.backposition) { util.sessionStorage.set(_this.backParamsListKey + page, listArr); } }); } }; /** * 浠嶴essionStorage鍙栧嚭鏁版嵁 */ InfiniteScroll.prototype.loadListFromStorage = function () { var _this = this, storage = util.sessionStorage.get(_this.backParamsKey); if (!storage)return; // 閿佸畾椤甸潰绂佹婊氬姩 util.pageScroll.lock(); // 鎬婚渶婊氬姩鐨勯〉鐮佹暟 var pageTotal = storage.page; var listArr = []; // 鏍规嵁椤电爜浠嶴torage鑾峰彇鏁版嵁鎵€闇€鏁版嵁 for (var i = 1; i <= pageTotal; i++) { var _list = util.sessionStorage.get(_this.backParamsListKey + i); listArr.push({ page: i, list: _list }); // 鍒ゆ柇璺宠浆鍓嶆暟鎹槸鍚﹀姞杞藉畬姣 if (i == pageTotal && _list.length < _this.options.pageSize) { _this.$element.append('
' + _this.options.doneTxt + '
'); _this.$loading.hide(); _this.loading = false; _this.isDone = true; } } // 灏嗘暟鎹紶鍑哄閮ㄦ柟娉曪紝鐩磋嚦鍏堕€氱煡宸叉彃鍏ラ〉闈㈠悗婊氬姩鑷崇浉搴斾綅缃 _this.options.loadStorageListFn(listArr, pageTotal + 1).done(function () { _this.scrollPosition(); }); }; function Plugin (option) { return this.each(function () { new InfiniteScroll(this, option); }); } $.fn.infiniteScroll = Plugin; }(window); /** * PullRefresh Plugin */ !function (window) { "use strict"; function PullRefresh(element, options) { this.$element = $(element); this.options = $.extend({}, PullRefresh.DEFAULTS, options || {}); this.init(); } PullRefresh.DEFAULTS = { loadListFn: null, initLoad: true, distance: 100 }; PullRefresh.prototype.init = function () { var _this = this, touches = _this.touches; _this.$dragTip = $('
'); _this.$element.after(_this.$dragTip); _this.offsetTop = _this.$element.offset().top; _this.initTip(); _this.bindEvent(); if (_this.options.initLoad) { touches.loading = true; typeof _this.options.loadListFn == 'function' && _this.options.loadListFn().done(function () { touches.loading = false; }); } }; PullRefresh.prototype.bindEvent = function () { var _this = this; _this.$element.on('touchstart.ydui.pullrefresh', function (e) { _this.onTouchStart(e); }).on('touchmove.ydui.pullrefresh', function (e) { _this.onTouchMove(e); }).on('touchend.ydui.pullrefresh', function (e) { _this.onTouchEnd(e); }); _this.stopWeixinDrag(); }; PullRefresh.prototype.touches = { loading: false, startClientY: 0, moveOffset: 0, isDraging: false }; PullRefresh.prototype.stopWeixinDrag = function () { var _this = this; $(document.body).on('touchmove.ydui.pullrefresh', function (event) { _this.touches.isDraging && event.preventDefault(); }); }; PullRefresh.prototype.onTouchStart = function (event) { var _this = this; if (_this.touches.loading) { event.preventDefault(); return; } if (_this.$element.offset().top < _this.offsetTop) { return; } _this.touches.startClientY = event.originalEvent.touches[0].clientY; }; PullRefresh.prototype.onTouchMove = function (event) { var _this = this, _touches = event.originalEvent.touches[0]; if (_this.touches.loading) { event.preventDefault(); return; } if (_this.touches.startClientY > _touches.clientY || _this.$element.offset().top < _this.offsetTop || _this.touches.loading) { return; } _this.touches.isDraging = true; var deltaSlide = _touches.clientY - _this.touches.startClientY; _this.$dragTip.find('span').css('opacity', deltaSlide / 100); if (deltaSlide >= _this.options.distance) { deltaSlide = _this.options.distance; } _this.$dragTip.find('span').css('transform', 'rotate(' + deltaSlide / 0.25 + 'deg)'); _this.touches.moveOffset = deltaSlide; _this.moveDragTip(deltaSlide); }; PullRefresh.prototype.onTouchEnd = function (event) { var _this = this, touches = _this.touches; if (touches.loading) { event.preventDefault(); return; } if (_this.$element.offset().top < _this.offsetTop) { return; } _this.$dragTip.addClass('pullrefresh-animation-timing'); if (touches.moveOffset >= _this.options.distance) { _this.moveDragTip(_this.options.distance / 1.5); _this.$dragTip.find('span').addClass('pullrefresh-loading'); _this.triggerLoad(); return; } _this.touches.isDraging = false; _this.resetDragTip(); _this.resetLoading(); }; PullRefresh.prototype.triggerLoad = function () { var _this = this, touches = _this.touches; touches.loading = true; typeof _this.options.loadListFn == 'function' && _this.options.loadListFn().done(function () { setTimeout(function () { _this.$dragTip.css({'transform': 'translate3d(0px, ' + (_this.options.distance / 1.5) + 'px, 0px) scale(0)'}); _this.resetDragTip(); }, 200); }); }; PullRefresh.prototype.resetLoading = function () { var _this = this; _this.moveDragTip(0); _this.$dragTip.find('span').removeClass('pullrefresh-loading').css({'opacity': 0.5, 'transform': 'rotate(0deg)'}); }; PullRefresh.prototype.resetDragTip = function () { var _this = this, touches = _this.touches; setTimeout(function () { touches.isDraging = false; touches.loading = false; touches.moveOffset = 0; _this.moveDragTip(0); _this.resetLoading(); _this.$dragTip.removeClass('pullrefresh-animation-timing'); }, 150); }; PullRefresh.prototype.moveDragTip = function (y) { this.$dragTip.css({'transform': 'translate3d(0,' + y + 'px,0) scale(1)'}); }; PullRefresh.prototype.initTip = function () { var _this = this, ls = window.localStorage; if (ls.getItem('LIST-PULLREFRESH-TIP') == 'YDUI')return; _this.$tip = $('
涓嬫媺鏇存柊
'); _this.$tip.on('click.ydui.pullrefresh', function () { $(this).remove(); }); _this.$element.after(_this.$tip); ls.setItem('LIST-PULLREFRESH-TIP', 'YDUI'); setTimeout(function () { _this.$tip.remove(); }, 5000); }; function Plugin(option) { return this.each(function () { var self = this; new PullRefresh(self, option); }); } $.fn.pullRefresh = Plugin; }(window); /** * LazyLoad Plugin * @example $(selector).find("img").lazyLoad(); */ !function (window) { "use strict"; function LazyLoad (element, options) { this.$element = $(element); this.options = $.extend({}, LazyLoad.DEFAULTS, options || {}); this.init(); } LazyLoad.DEFAULTS = { attr: 'data-url', binder: window, placeholder: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQIHWN4BQAA7ADrKJeAMwAAAABJRU5ErkJggg==' }; LazyLoad.prototype.init = function () { var _this = this; _this.bindImgEvent(); _this.loadImg(); $(_this.options.binder).on('scroll.ydui.lazyload', function () { _this.loadImg(); }); $(window).on('resize.ydui.lazyload', function () { _this.loadImg(); }); }; /** * 鍔犺浇鍥剧墖 */ LazyLoad.prototype.loadImg = function () { var _this = this, options = _this.options, $binder = $(options.binder); var contentHeight = $binder.height(), contentTop = $binder.get(0) === window ? $(window).scrollTop() : $binder.offset().top; _this.$element.each(function () { var $img = $(this); var post = $img.offset().top - contentTop, posb = post + $img.height(); // 鍒ゆ柇鏄惁浣嶄簬鍙鍖哄煙鍐 if ((post >= 0 && post < contentHeight) || (posb > 0 && posb <= contentHeight)) { $img.trigger('appear.ydui.lazyload'); } }); }; /** * 缁欐墍鏈夊浘鐗囩粦瀹氬崟娆¤嚜瀹氫箟浜嬩欢 */ LazyLoad.prototype.bindImgEvent = function () { var _this = this, options = _this.options; _this.$element.each(function () { var $img = $(this); if ($img.is("img") && !$img.attr("src")) { $img.attr("src", options.placeholder); } $img.one("appear.ydui.lazyload", function () { if ($img.is("img")) { $img.attr("src", $img.attr(options.attr)); } }); }); }; $.fn.lazyLoad = function (option) { new LazyLoad(this, option); }; }(window); /** * KeyBoard Plugin */ !function (window) { "use strict"; var $body = $(window.document.body), isMobile = !!(window.navigator && window.navigator.userAgent || '').match(/AppleWebKit.*Mobile.*/) || 'ontouchstart' in window.document.documentElement, triggerEvent = isMobile ? 'touchstart' : 'click'; function KeyBoard (element, options) { this.$element = $(element); this.options = $.extend({}, KeyBoard.DEFAULTS, options || {}); this.init(); } KeyBoard.DEFAULTS = { disorder: false, title: '瀹夊叏閿洏' }; KeyBoard.prototype.init = function () { var _this = this; _this.inputNums = ''; _this.toggleClass = 'keyboard-show'; function getDot () { var s = ''; for (var i = 0; i < 6; i++) { s += '
  • '; } return s; } var hd = '' + '
    杈撳叆鏁板瓧瀵嗙爜
    ' + '
    ' + ''; var ft = '' + '
    ' + '
    ' + _this.options.title + '
    ' + ' ' + '
    '; _this.$element.prepend(hd).append(ft); _this.$numsBox = _this.$element.find('.keyboard-numbers'); _this.$mask = $('
    '); }; /** * 鎵撳紑閿洏绐楀彛 */ KeyBoard.prototype.open = function () { var _this = this, $element = _this.$element, $numsBox = _this.$numsBox; YDUI.device.isIOS && $('.g-scrollview').addClass('g-fix-ios-overflow-scrolling-bug'); $element.addClass(_this.toggleClass); if (_this.options.disorder || $numsBox.data('loaded-nums') != 1) { $numsBox.data('loaded-nums', 1).html(_this.createNumsHtml()); } $body.append(_this.$mask); _this.bindEvent(); }; /** * 鍏抽棴閿洏绐楀彛 */ KeyBoard.prototype.close = function () { var _this = this; YDUI.device.isIOS && $('.g-scrollview').removeClass('g-fix-ios-overflow-scrolling-bug'); _this.$mask.remove(); _this.$element.removeClass(_this.toggleClass); _this.unbindEvent(); _this.inputNums = ''; _this.fillPassword(); _this.clearError(); }; /** * 浜嬩欢缁戝畾 */ KeyBoard.prototype.bindEvent = function () { var _this = this, $element = _this.$element; _this.$mask.on(triggerEvent + '.ydui.keyboard.mask', function (e) { e.preventDefault(); _this.close(); }); $element.on(triggerEvent + '.ydui.keyboard.nums', '.J_Nums', function (e) { if (_this.inputNums.length >= 6)return; _this.inputNums = _this.inputNums + $(this).html(); _this.clearError(); _this.fillPassword(); }); // 閫€鏍 $element.on(triggerEvent + '.ydui.keyboard.backspace', '.J_Backspace', function (e) { e.preventDefault(); _this.backspace(); }); // 鍙栨秷 $element.on(triggerEvent + '.ydui.keyboard.cancel', '.J_Cancel', function (e) { e.preventDefault(); _this.close(); }); }; /** * 瑙g粦浜嬩欢 */ KeyBoard.prototype.unbindEvent = function () { this.$element.off(triggerEvent + '.ydui.keyboard'); $(window).off('hashchange.ydui.keyboard'); }; /** * 濉厖瀵嗙爜 */ KeyBoard.prototype.fillPassword = function () { var _this = this, inputNums = _this.inputNums, length = inputNums.length; var $li = _this.$element.find('.J_FillPwdBox').find('li'); $li.find('i').hide(); $li.filter(':lt(' + length + ')').find('i').css('display', 'block'); if (length >= 6) { _this.$element.trigger($.Event('done.ydui.keyboard', { password: inputNums })); } }; /** * 娓呯┖閿欒淇℃伅 */ KeyBoard.prototype.clearError = function () { this.$element.find('.keyboard-error').html(''); }; /** * 鎻愮ず閿欒淇℃伅 * @param mes */ KeyBoard.prototype.error = function (mes) { var _this = this; _this.$element.find('.keyboard-error').html(mes); _this.inputNums = ''; _this.fillPassword(); }; /** * 閫€鏍煎鐞 */ KeyBoard.prototype.backspace = function () { var _this = this; var _inputNums = _this.inputNums; if (_inputNums) { _this.inputNums = _inputNums.substr(0, _inputNums.length - 1); } _this.fillPassword(); }; /** * 鍒涘缓閿洏HTML * @returns {string} */ KeyBoard.prototype.createNumsHtml = function () { var _this = this, nums = _this.createNums(); _this.options.disorder && _this.upsetOrder(nums); var arr = []; $.each(nums, function (k) { if (k % 3 == 0) { if (k >= nums.length - 2) { arr.push('
  • 鍙栨秷' + nums.slice(k, k + 3).join('') + '
  • '); } else { arr.push('
  • ' + nums.slice(k, k + 3).join('') + '
  • '); } } }); return arr.join(''); }; /** * 鍒涘缓閿洏鏁板瓧 * @returns {Array} DOM鏁扮粍 */ KeyBoard.prototype.createNums = function () { var _this = this; var disorder = _this.options.disorder; if (disorder && _this.cacheNums) { return _this.cacheNums; } var strArr = []; for (var i = 1; i <= 10; i++) { strArr.push('' + (i % 10) + ''); } if (!disorder) { _this.cacheNums = strArr; } return strArr; }; /** * 鎵撲贡鏁扮粍椤哄簭 * @param arr 鏁扮粍 * @returns {*} */ KeyBoard.prototype.upsetOrder = function (arr) { var floor = Math.floor, random = Math.random, len = arr.length, i, j, temp, n = floor(len / 2) + 1; while (n--) { i = floor(random() * len); j = floor(random() * len); if (i !== j) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } return arr; }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), keyboard = $this.data('ydui.keyboard'); if (!keyboard) { $this.data('ydui.keyboard', (keyboard = new KeyBoard(this, option))); } if (typeof option == 'string') { keyboard[option] && keyboard[option].apply(keyboard, args); } }); } $.fn.keyBoard = Plugin; }(window); /** * CitySelect Plugin */ !function (window) { "use strict"; var $body = $(window.document.body); function CitySelect (element, options) { this.$element = $(element); this.options = $.extend({}, CitySelect.DEFAULTS, options || {}); this.init(); } CitySelect.DEFAULTS = { provance: '', city: '', area: '' }; CitySelect.prototype.init = function () { var _this = this, options = _this.options; if (typeof YDUI_CITYS == 'undefined') { console.error('璇峰湪ydui.js鍓嶅紩鍏dui.citys.js銆備笅杞藉湴鍧€锛歨ttp://cityselect.ydui.org'); return; } _this.citys = YDUI_CITYS; _this.createDOM(); _this.defaultSet = { provance: options.provance, city: options.city, area: options.area }; }; CitySelect.prototype.open = function () { var _this = this; $body.append(_this.$mask); // 闃叉鐏嫄娴忚鍣ㄦ枃鏈涓戜笐鐨勪竴鍧ㄥ皬姘存淮 YDUI.device.isMozilla && _this.$element.blur(); _this.$mask.on('click.ydui.cityselect.mask', function () { _this.close(); }); var $cityElement = _this.$cityElement, defaultSet = _this.defaultSet; $cityElement.find('.cityselect-content').removeClass('cityselect-move-animate cityselect-next cityselect-prev'); _this.loadProvance(); if (defaultSet.provance) { _this.setNavTxt(0, defaultSet.provance); } else { $cityElement.find('.cityselect-nav a').eq(0).addClass('crt').html('璇烽€夋嫨'); } if (defaultSet.city) { _this.loadCity(); _this.setNavTxt(1, defaultSet.city) } if (defaultSet.area) { _this.loadArea(); _this.ForwardView(false); _this.setNavTxt(2, defaultSet.area); } $cityElement.addClass('brouce-in'); }; CitySelect.prototype.close = function () { var _this = this; _this.$mask.remove(); _this.$cityElement.removeClass('brouce-in').find('.cityselect-nav a').removeClass('crt').html(''); _this.$itemBox.html(''); }; CitySelect.prototype.createDOM = function () { var _this = this; _this.$mask = $('
    '); _this.$cityElement = $('' + '
    ' + '
    ' + '

    鎵€鍦ㄥ湴鍖裹/p>' + '

    ' + ' ' + ' ' + ' ' + '
    ' + '
    ' + ' ' + '
    '); $body.append(_this.$cityElement); _this.$itemBox = _this.$cityElement.find('.cityselect-item-box'); _this.$cityElement.on('click.ydui.cityselect', '.cityselect-nav a', function () { var $this = $(this); $this.addClass('crt').siblings().removeClass('crt'); $this.index() < 2 ? _this.backOffView() : _this.ForwardView(true); }); }; CitySelect.prototype.setNavTxt = function (index, txt) { var $nav = this.$cityElement.find('.cityselect-nav a'); index < 2 && $nav.removeClass('crt'); $nav.eq(index).html(txt); $nav.eq(index + 1).addClass('crt').html('璇烽€夋嫨'); $nav.eq(index + 2).removeClass('crt').html(''); }; CitySelect.prototype.backOffView = function () { this.$cityElement.find('.cityselect-content').removeClass('cityselect-next') .addClass('cityselect-move-animate cityselect-prev'); }; CitySelect.prototype.ForwardView = function (animate) { this.$cityElement.find('.cityselect-content').removeClass('cityselect-move-animate cityselect-prev') .addClass((animate ? 'cityselect-move-animate' : '') + ' cityselect-next'); }; CitySelect.prototype.bindItemEvent = function () { var _this = this, $cityElement = _this.$cityElement; $cityElement.on('click.ydui.cityselect', '.cityselect-item-box a', function () { var $this = $(this); if ($this.hasClass('crt'))return; $this.addClass('crt').siblings().removeClass('crt'); var tag = $this.data('tag'); _this.setNavTxt(tag, $this.text()); var $nav = $cityElement.find('.cityselect-nav a'), defaultSet = _this.defaultSet; if (tag == 0) { _this.loadCity(); $cityElement.find('.cityselect-item-box').eq(1).find('a').removeClass('crt'); } else if (tag == 1) { _this.loadArea(); _this.ForwardView(true); $cityElement.find('.cityselect-item-box').eq(2).find('a').removeClass('crt'); } else { defaultSet.provance = $nav.eq(0).html(); defaultSet.city = $nav.eq(1).html(); defaultSet.area = $nav.eq(2).html(); _this.returnValue(); } }); }; CitySelect.prototype.returnValue = function () { var _this = this, defaultSet = _this.defaultSet; _this.$element.trigger($.Event('done.ydui.cityselect', { provance: defaultSet.provance, city: defaultSet.city, area: defaultSet.area })); _this.close(); }; CitySelect.prototype.scrollPosition = function (index) { var _this = this, $itemBox = _this.$itemBox.eq(index), itemHeight = $itemBox.find('a.crt').height(), itemBoxHeight = $itemBox.parent().height(); $itemBox.parent().animate({ scrollTop: $itemBox.find('a.crt').index() * itemHeight - itemBoxHeight / 3 }, 0, function () { _this.bindItemEvent(); }); }; CitySelect.prototype.fillItems = function (index, arr) { var _this = this; _this.$itemBox.eq(index).html(arr).parent().animate({scrollTop: 0}, 10); _this.scrollPosition(index); }; CitySelect.prototype.loadProvance = function () { var _this = this; var arr = []; $.each(_this.citys, function (k, v) { arr.push($('' + v.n + '').data({ citys: v.c, tag: 0 })); }); _this.fillItems(0, arr); }; CitySelect.prototype.loadCity = function () { var _this = this; var cityData = _this.$itemBox.eq(0).find('a.crt').data('citys'); var arr = []; $.each(cityData, function (k, v) { arr.push($('' + v.n + '').data({ citys: v.a, tag: 1 })); }); _this.fillItems(1, arr); }; CitySelect.prototype.loadArea = function () { var _this = this; var areaData = _this.$itemBox.eq(1).find('a.crt').data('citys'); var arr = []; $.each(areaData, function (k, v) { arr.push($('' + v + '').data({tag: 2})); }); if (arr.length <= 0) { arr.push($('鍏ㄥ尯').data({tag: 2})); } _this.fillItems(2, arr); }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), citySelect = $this.data('ydui.cityselect'); if (!citySelect) { $this.data('ydui.cityselect', (citySelect = new CitySelect(this, option))); } if (typeof option == 'string') { citySelect[option] && citySelect[option].apply(citySelect, args); } }); } $.fn.citySelect = Plugin; }(window); /** * Spinner Plugin */ !function (window) { "use strict"; function Spinner(element, options) { this.$element = $(element); this.options = $.extend({}, Spinner.DEFAULTS, options || {}); this.init(); } Spinner.DEFAULTS = { input: '.J_Input', add: '.J_Add', minus: '.J_Del', unit: 1, max: 0, min: -1, longpress: true, callback: null }; Spinner.prototype.init = function () { var _this = this, options = _this.options; _this.$input = $(options.input, _this.$element); _this.$add = $(options.add, _this.$element); _this.$minus = $(options.minus, _this.$element); _this.changeParameters(); _this.checkParameters(); _this.bindEvent(); }; Spinner.prototype.tapParams = {}; Spinner.prototype.isNumber = function (val) { //return /^([0]|[1-9]\d*)(\.\d{1,2})?$/.test(val); return /^\d*$/.test(val); }; Spinner.prototype.FixNumber = function (val) { //return parseFloat(val); return parseInt(val); }; Spinner.prototype.changeParameters = function () { var _this = this, options = _this.options; var params = [ {param: 'unit', default: 1}, {param: 'max', default: 0} ]; $.each(params, function (k, v) { var _val = options[v.param], _dataVal = _this.$input.data(v.param); if (!!_dataVal) { _val = _dataVal; if (!_this.isNumber(_dataVal)) { _val = options[v.param]; if (typeof _val == 'function') { _val = _val(); } } } else { if (typeof options[v.param] == 'function') { var _fnVal = options[v.param](); _val = _fnVal; if (!_this.isNumber(_fnVal)) { _val = options[v.param]; } } } if (!_this.isNumber(_val)) { _val = v.default; } options[v.param] = _this.FixNumber(_val); }); }; Spinner.prototype.checkParameters = function () { var _this = this, options = _this.options, value = _this.$input.val(); if (value) { _this.setValue(value); } else { if (options.max < options.min && options.max != 0) { options.max = options.min; } if (options.min < options.unit && options.min > 0) { options.min = options.unit; } if (options.min % options.unit != 0 && options.min > 0) { options.min = options.min - options.min % options.unit; } if (options.max < options.unit && options.max != 0) { options.max = options.unit; } if (options.max % options.unit != 0) { options.max = options.max - options.max % options.unit; } if (options.min < 0) { options.min = options.unit; } _this.setValue(options.min); } }; Spinner.prototype.calculation = function (type) { var _this = this, options = _this.options, max = options.max, unit = options.unit, min = options.min, $input = _this.$input, val = _this.FixNumber($input.val()); if (!!$input.attr('readonly') || !!$input.attr('disabled'))return; var newval; if (type == 'add') { newval = val + unit; if (max != 0 && newval > max)return; } else { newval = val - unit; if (newval < min)return; } _this.setValue(newval); options.longpress && _this.longpressHandler(type); }; Spinner.prototype.longpressHandler = function (type) { var _this = this; var currentDate = new Date().getTime() / 1000, intervalTime = currentDate - _this.tapStartTime; if (intervalTime < 1) intervalTime = 0.5; var secondCount = intervalTime * 10; if (intervalTime == 30) secondCount = 50; if (intervalTime >= 40) secondCount = 100; _this.tapParams.timer = setTimeout(function () { _this.calculation(type); }, 1000 / secondCount); }; Spinner.prototype.setValue = function (val) { var _this = this, options = _this.options, max = options.max, unit = options.unit, min = options.min < 0 ? unit : options.min; if (!/^(([1-9]\d*)|0)$/.test(val)) val = max; if (val > max && max != 0) val = max; if (val % unit > 0) { val = val - val % unit + unit; if (val > max && max != 0) val -= unit; } if (val < min) val = min - min % unit; _this.$input.val(val); typeof options.callback == 'function' && options.callback(val, _this.$input); }; Spinner.prototype.bindEvent = function () { var _this = this, options = _this.options, isMobile = YDUI.device.isMobile, mousedownEvent = 'mousedown.ydui.spinner', mouseupEvent = 'mouseup.ydui.spinner'; if (isMobile) { mousedownEvent = 'touchstart.ydui.spinner'; mouseupEvent = 'touchend.ydui.spinner'; } _this.$add.on(mousedownEvent, function (e) { if (options.longpress) { e.preventDefault(); e.stopPropagation(); _this.tapStartTime = new Date().getTime() / 1000; _this.$add.on(mouseupEvent, function () { _this.clearTapTimer(); }); } _this.calculation('add'); }); _this.$minus.on(mousedownEvent, function (e) { if (options.longpress) { e.preventDefault(); e.stopPropagation(); _this.tapStartTime = new Date().getTime() / 1000; _this.$minus.on(mouseupEvent, function () { _this.clearTapTimer(); }); } _this.calculation('minus'); }); _this.$input.on('change.ydui.spinner', function () { _this.setValue($(this).val()); }).on('keydown', function (event) { if (event.keyCode == 13) { _this.setValue($(this).val()); return false; } }); }; Spinner.prototype.clearTapTimer = function () { var _this = this; clearTimeout(_this.tapParams.timer); }; function Plugin(option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), spinner = $this.data('ydui.spinner'); if (!spinner) { $this.data('ydui.spinner', (spinner = new Spinner(this, option))); } if (typeof option == 'string') { spinner[option] && spinner[option].apply(spinner, args); } }); } $(window).on('load.ydui.spinner', function () { $('[data-ydui-spinner]').each(function () { var $this = $(this); $this.spinner(window.YDUI.util.parseOptions($this.data('ydui-spinner'))); }); }); $.fn.spinner = Plugin; }(window); /** * Slider Plugin */ !function (window) { "use strict"; function Slider (element, options) { this.$element = $(element); this.options = $.extend({}, Slider.DEFAULTS, options || {}); this.init(); } Slider.DEFAULTS = { speed: 300, // 绉诲姩閫熷害 autoplay: 3000, // 寰幆鏃堕棿 lazyLoad: false, // 鏄惁寤惰繜鍔犺浇鍥剧墖 data-src="" pagination: '.slider-pagination', wrapperClass: 'slider-wrapper', slideClass: 'slider-item', bulletClass: 'slider-pagination-item', bulletActiveClass: 'slider-pagination-item-active' }; /** * 鍒濆鍖 */ Slider.prototype.init = function () { var _this = this, options = _this.options, $element = _this.$element; _this.index = 1; _this.autoPlayTimer = null; _this.$pagination = $element.find(options.pagination); _this.$wrapper = $element.find('.' + options.wrapperClass); _this.itemNums = _this.$wrapper.find('.' + options.slideClass).length; options.lazyLoad && _this.loadImage(0); _this.createBullet(); _this.cloneItem().bindEvent(); }; /** * 缁戝畾浜嬩欢 */ Slider.prototype.bindEvent = function () { var _this = this, touchEvents = _this.touchEvents(); _this.$wrapper.find('.' + _this.options.slideClass) .on(touchEvents.start, function (e) { _this.onTouchStart(e); }).on(touchEvents.move, function (e) { _this.onTouchMove(e); }).on(touchEvents.end, function (e) { _this.onTouchEnd(e); }); $(window).on('resize.ydui.slider', function () { _this.setSlidesSize(); }); ~~_this.options.autoplay > 0 && _this.autoPlay(); _this.$wrapper.on('click.ydui.slider', function (e) { if (!_this.touches.allowClick) { e.preventDefault(); } }); }; /** * 澶嶅埗绗竴涓拰鏈€鍚庝竴涓猧tem * @returns {Slider} */ Slider.prototype.cloneItem = function () { var _this = this, $wrapper = _this.$wrapper, $sliderItem = _this.$wrapper.find('.' + _this.options.slideClass), $firstChild = $sliderItem.filter(':first-child').clone(), $lastChild = $sliderItem.filter(':last-child').clone(); $wrapper.prepend($lastChild); $wrapper.append($firstChild); _this.setSlidesSize(); return _this; }; /** * 鍒涘缓鐐圭偣鐐 */ Slider.prototype.createBullet = function () { var _this = this; if (!_this.$pagination[0])return; var initActive = ''; _this.$pagination.append(initActive + new Array(_this.itemNums).join('')); }; /** * 褰撳墠椤电爜鏍囪瘑鍔犻珮浜 */ Slider.prototype.activeBullet = function () { var _this = this; if (!_this.$pagination[0])return; var itemNums = _this.itemNums, index = _this.index % itemNums >= itemNums ? 0 : _this.index % itemNums - 1, bulletActiveClass = _this.options.bulletActiveClass; !!_this.$pagination[0] && _this.$pagination.find('.' + _this.options.bulletClass) .removeClass(bulletActiveClass) .eq(index).addClass(bulletActiveClass); }; /** * 璁剧疆item瀹藉害 */ Slider.prototype.setSlidesSize = function () { var _this = this, _width = _this.$wrapper.width(); _this.$wrapper.css('transform', 'translate3d(-' + _width + 'px,0,0)'); _this.$wrapper.find('.' + _this.options.slideClass).css({width: _width}); }; /** * 鑷姩鎾斁 */ Slider.prototype.autoPlay = function () { var _this = this; _this.autoPlayTimer = setInterval(function () { if (_this.index > _this.itemNums) { _this.index = 1; _this.setTranslate(0, -_this.$wrapper.width()); } _this.setTranslate(_this.options.speed, -(++_this.index * _this.$wrapper.width())); }, _this.options.autoplay); }; /** * 鍋滄鎾斁 * @returns {Slider} */ Slider.prototype.stopAutoplay = function () { var _this = this; clearInterval(_this.autoPlayTimer); return _this; }; /** * 寤惰繜鍔犺浇鍥剧墖 * @param index 绱㈠紩 */ Slider.prototype.loadImage = function (index) { var _this = this, $img = _this.$wrapper.find('.' + _this.options.slideClass).eq(index).find('img'), imgsrc = $img.data('src'); $img.data('load') != 1 && !!imgsrc && $img.attr('src', imgsrc).data('load', 1); }; /** * 宸﹀彸婊戝姩Slider * @param speed 绉诲姩閫熷害 0锛氬綋鍓嶆槸鍋峰伔鎽告懜鐨勭Щ鍔ㄥ暒锛岀敓鎬曠粰浣犵湅瑙 * @param x 妯悜绉诲姩瀹藉害 */ Slider.prototype.setTranslate = function (speed, x) { var _this = this; _this.options.lazyLoad && _this.loadImage(_this.index); _this.activeBullet(); _this.$wrapper.css({ 'transitionDuration': speed + 'ms', 'transform': 'translate3d(' + x + 'px,0,0)' }); }; /** * 澶勭悊婊戝姩涓€浜涙爣璇 */ Slider.prototype.touches = { moveTag: 0, // 绉诲姩鐘舵€?start,move,end)鏍囪 startClientX: 0, // 璧峰鎷栧姩鍧愭爣 moveOffset: 0, // 绉诲姩鍋忕Щ閲忥紙宸﹀彸鎷栧姩瀹藉害锛 touchStartTime: 0, // 寮€濮嬭Е鎽哥殑鏃堕棿鐐 isTouchEvent: false, // 鏄惁瑙︽懜浜嬩欢 allowClick: false // 鐢ㄤ簬鍒ゆ柇浜嬩欢涓虹偣鍑昏繕鏄嫋鍔 }; /** * 寮€濮嬫粦鍔 * @param event */ Slider.prototype.onTouchStart = function (event) { if (event.originalEvent.touches) event = event.originalEvent.touches[0]; var _this = this, touches = _this.touches; touches.allowClick = true; touches.isTouchEvent = event.type === 'touchstart'; // 榧犳爣鍙抽敭 if (!touches.isTouchEvent && 'which' in event && event.which === 3) return; if (touches.moveTag == 0) { touches.moveTag = 1; // 璁板綍榧犳爣璧峰鎷栧姩浣嶇疆 touches.startClientX = event.clientX; // 璁板綍寮€濮嬭Е鎽告椂闂 touches.touchStartTime = Date.now(); var itemNums = _this.itemNums; if (_this.index == 0) { _this.index = itemNums; _this.setTranslate(0, -itemNums * _this.$wrapper.width()); return; } if (_this.index > itemNums) { _this.index = 1; _this.setTranslate(0, -_this.$wrapper.width()); } } }; /** * 婊戝姩涓 * @param event */ Slider.prototype.onTouchMove = function (event) { event.preventDefault(); if (event.originalEvent.touches) event = event.originalEvent.touches[0]; var _this = this, touches = _this.touches; touches.allowClick = false; if (touches.isTouchEvent && event.type === 'mousemove') return; // 鎷栧姩鍋忕Щ閲 var deltaSlide = touches.moveOffset = event.clientX - touches.startClientX; if (deltaSlide != 0 && touches.moveTag != 0) { if (touches.moveTag == 1) { _this.stopAutoplay(); touches.moveTag = 2; } if (touches.moveTag == 2) { _this.setTranslate(0, -_this.index * _this.$wrapper.width() + deltaSlide); } } }; /** * 婊戝姩鍚 */ Slider.prototype.onTouchEnd = function () { var _this = this, speed = _this.options.speed, _width = _this.$wrapper.width(), touches = _this.touches, moveOffset = touches.moveOffset; // 閲婃斁a閾炬帴鐐瑰嚮璺宠浆 setTimeout(function () { touches.allowClick = true; }, 0); // 鐭殏鐐瑰嚮骞舵湭鎷栧姩 if (touches.moveTag == 1) { touches.moveTag = 0; } if (touches.moveTag == 2) { touches.moveTag = 0; // 璁$畻寮€濮嬭Е鎽稿埌缁撴潫瑙︽懜鏃堕棿锛岀敤浠ヨ绠楁槸鍚﹂渶瑕佹粦鑷充笅涓€椤 var timeDiff = Date.now() - touches.touchStartTime; // 鎷栧姩鏃堕棿瓒呰繃300姣鎴栬€呮湭鎷栧姩瓒呰繃鍐呭涓€鍗 if (timeDiff > 300 && Math.abs(moveOffset) <= _this.$wrapper.width() * .5) { // 寮瑰洖鍘 _this.setTranslate(speed, -_this.index * _this.$wrapper.width()); } else { // --涓哄乏绉伙紝++涓哄彸绉 _this.setTranslate(speed, -((moveOffset > 0 ? --_this.index : ++_this.index) * _width)); } _this.autoPlay(); } }; /** * 褰撳墠璁惧鏀寔鐨勪簨浠 * @type {{start, move, end}} */ Slider.prototype.touchEvents = function () { var supportTouch = (window.Modernizr && !!window.Modernizr.touch) || (function () { return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); })(); return { start: supportTouch ? 'touchstart.ydui.slider' : 'mousedown.ydui.slider', move: supportTouch ? 'touchmove.ydui.slider' : 'mousemove.ydui.slider', end: supportTouch ? 'touchend.ydui.slider' : 'mouseup.ydui.slider' }; }; function Plugin (option) { return this.each(function () { var $this = $(this), slider = $this.data('ydui.slider'); if (!slider) { $this.data('ydui.slider', new Slider(this, option)); } }); } $(window).on('load.ydui.slider', function () { $('[data-ydui-slider]').each(function () { var $this = $(this); $this.slider(window.YDUI.util.parseOptions($this.data('ydui-slider'))); }); }); $.fn.slider = Plugin; }(window); /** * Dialog */ !function (window, ydui) { "use strict"; var dialog = ydui.dialog = ydui.dialog || {}, $body = $(window.document.body); /** * 纭鎻愮ず妗 * @param title 鏍囬String 銆愬彲閫夈€ * @param mes 鍐呭String 銆愬繀濉€ * @param opts 鎸夐挳浠珹rray 鎴 鈥滅‘瀹氭寜閽€濆洖璋冨嚱鏁癋unction 銆愬繀濉€ * @constructor */ dialog.confirm = function (title, mes, opts) { var ID = 'YDUI_CONFRIM'; $('#' + ID).remove(); var args = arguments.length; if (args < 2) { console.error('From YDUI\'s confirm: Please set two or three parameters!!!'); return; } if (typeof arguments[1] != 'function' && args == 2 && !arguments[1] instanceof Array) { console.error('From YDUI\'s confirm: The second parameter must be a function or array!!!'); return; } if (args == 2) { opts = mes; mes = title; title = '鎻愮ず'; } var btnArr = opts; if (typeof opts === 'function') { btnArr = [{ txt: '鍙栨秷', color: false }, { txt: '纭畾', color: true, callback: function () { opts && opts(); } }]; } var $dom = $('' + '
    ' + '
    ' + '
    ' + title + '
    ' + '
    ' + mes + '
    ' + '
    ' + '
    '); // 閬嶅巻鎸夐挳鏁扮粍 var $btnBox = $('
    '); $.each(btnArr, function (i, val) { var $btn; // 鎸囧畾鎸夐挳棰滆壊 if (typeof val.color == 'boolean') { $btn = $('' + (val.txt || '') + ''); } else if (typeof val.color == 'string') { $btn = $('' + (val.txt || '') + ''); } // 缁欏搴旀寜閽坊鍔犵偣鍑讳簨浠 (function (p) { $btn.on('click', function (e) { e.stopPropagation(); // 鏄惁淇濈暀寮圭獥 if (!btnArr[p].stay) { // 閲婃斁椤甸潰婊氬姩 ydui.util.pageScroll.unlock(); $dom.remove(); } btnArr[p].callback && btnArr[p].callback(); }); })(i); $btnBox.append($btn); }); $dom.find('.m-confirm').append($btnBox); // 绂佹婊氬姩灞忓箷銆愮Щ鍔ㄧ銆 ydui.util.pageScroll.lock(); $body.append($dom); }; /** * 寮瑰嚭璀︾ず妗 * @param mes 鎻愮ず鏂囧瓧String 銆愬繀濉€ * @param callback 鍥炶皟鍑芥暟Function 銆愬彲閫夈€ */ dialog.alert = function (mes, callback) { var ID = 'YDUI_ALERT'; $('#' + ID).remove(); var $dom = $('' + '
    ' + '
    ' + '
    ' + '
    ' + (mes || 'YDUI Touch') + '
    ' + '
    ' + ' 纭畾' + '
    ' + '
    ' + '
    ' + '
    '); ydui.util.pageScroll.lock(); $body.append($dom); $dom.find('a').on('click', function () { $dom.remove(); ydui.util.pageScroll.unlock(); typeof callback === 'function' && callback(); }); }; /** * 寮瑰嚭鎻愮ず灞 */ dialog.toast = function () { var timer = null; /** * @param mes 鎻愮ず鏂囧瓧String 銆愬繀濉€ * @param type 绫诲瀷String success or error 銆愬繀濉€ * @param timeout 澶氫箙鍚庢秷澶盢umber 姣 銆愰粯璁わ細2000ms銆戙€愬彲閫夈€ * @param callback 鍥炶皟鍑芥暟Function 銆愬彲閫夈€ */ return function (mes, type, timeout, callback) { clearTimeout(timer); var ID = 'YDUI_TOAST'; $('#' + ID).remove(); var args = arguments.length; if (args < 2) { console.error('From YDUI\'s toast: Please set two or more parameters!!!'); return; } var iconHtml = ''; if (type == 'success' || type == 'error') { iconHtml = '
    '; } var $dom = $('' + '
    ' + '
    ' + iconHtml + '

    ' + (mes || '') + '

    ' + '
    ' + '
    '); ydui.util.pageScroll.lock(); $body.append($dom); if (typeof timeout === 'function' && arguments.length >= 3) { callback = timeout; timeout = 2000; } timer = setTimeout(function () { clearTimeout(timer); ydui.util.pageScroll.unlock(); $dom.remove(); typeof callback === 'function' && callback(); }, (~~timeout || 2000) + 100);//100涓哄姩鐢绘椂闂 }; }(); /** * 椤堕儴鎻愮ず灞 */ dialog.notify = function () { var timer = null; /** * @param mes 鎻愮ず鏂囧瓧String 銆愬繀濉€ * @param timeout 澶氫箙鍚庢秷澶盢umber 姣 銆愰粯璁わ細2000ms銆戙€愬彲閫夈€ */ return function (mes, timeout, callback) { clearTimeout(timer); var ID = 'YDUI_NOTIFY'; $('#' + ID).remove(); var $dom = $('
    ' + (mes || '') + '
    '); $body.append($dom); var next = function () { $dom.remove(); typeof callback == 'function' && callback(); }; var closeNotify = function () { clearTimeout(timer); $dom.find('.m-notify').addClass('notify-out'); $dom.one('webkitTransitionEnd', next).emulateTransitionEnd(150); }; $dom.on('click', closeNotify); if (~~timeout > 0) { timer = setTimeout(closeNotify, timeout + 200); } } }(); /** * 鍔犺浇涓彁绀烘 */ dialog.loading = function () { var ID = 'YDUI_LOADING'; return { /** * 鍔犺浇涓 - 鏄剧ず * @param text 鏄剧ず鏂囧瓧String 銆愬彲閫夈€ */ open: function (text) { $('#' + ID).remove(); var $dom = $('' + '
    ' + '
    ' + '
    ' + '
    ' + (text || '鏁版嵁鍔犺浇涓?) + '
    ' + '
    ' + '
    ').remove(); ydui.util.pageScroll.lock(); $body.append($dom); }, /** * 鍔犺浇涓 - 闅愯棌 */ close: function () { ydui.util.pageScroll.unlock(); $('#' + ID).remove(); } }; }(); }(window, YDUI); /** * ProgressBar Plugin * Refer to: https://github.com/kimmobrunfeldt/progressbar.js.git */ !function (window) { "use strict"; var doc = window.document, util = window.YDUI.util; function Circle (element, options) { this.pathTemplate = 'M 50,50 m 0,-{radius} a {radius},{radius} 0 1 1 0,{2radius} a {radius},{radius} 0 1 1 0,-{2radius}'; ProgressBar.apply(this, arguments); } Circle.prototype = new ProgressBar(); Circle.prototype.getPathString = function (widthOfWider) { var _this = this, r = 50 - widthOfWider / 2; return _this.render(_this.pathTemplate, { radius: r, '2radius': r * 2 }); }; Circle.prototype.initSvg = function (svg) { svg.setAttribute('viewBox', '0 0 100 100'); svg.style.display = 'block'; svg.style.width = '100%'; }; function Line (element, options) { this.pathTemplate = 'M 0,{center} L 100,{center}'; ProgressBar.apply(this, arguments); } Line.prototype = new ProgressBar(); Line.prototype.getPathString = function (widthOfWider) { var _this = this; return _this.render(_this.pathTemplate, { center: widthOfWider / 2 }); }; Line.prototype.initSvg = function (svg, options) { svg.setAttribute('viewBox', '0 0 100 ' + options.strokeWidth); svg.setAttribute('preserveAspectRatio', 'none'); svg.style.width = '100%'; svg.style.height = '100%'; }; function ProgressBar (element, options) { this.$element = $(element); this.options = $.extend({}, ProgressBar.DEFAULTS, options || {}); } ProgressBar.DEFAULTS = { type: 'circle', strokeWidth: 0, strokeColor: '#E5E5E5', trailWidth: 0, trailColor: '#646464', fill: '', progress: 0, delay: true, binder: window }; ProgressBar.prototype.set = function (progress) { var _this = this, length = _this.trailPath.getTotalLength(); if (!progress) progress = _this.options.progress; if (progress > 1)progress = 1; _this.trailPath.style.strokeDashoffset = length - progress * length; }; ProgressBar.prototype.appendView = function () { var _this = this, options = _this.options, progress = options.progress, svgView = _this.createSvgView(), $element = _this.$element; _this.$binder = options.binder === window || options.binder == 'window' ? $(window) : $(options.binder); var path = svgView.trailPath, length = path.getTotalLength(); path.style.strokeDasharray = length + ' ' + length; var $svg = $(svgView.svg); $svg.one('appear.ydui.progressbar', function () { _this.set(progress); }); $element.append($svg); if (options.delay) { _this.checkInView($svg); _this.$binder.on('scroll.ydui.progressbar', function () { _this.checkInView($svg); }); $(window).on('resize', function () { _this.checkInView($svg); }); } else { $svg.trigger('appear.ydui.progressbar'); } return this; }; ProgressBar.prototype.checkInView = function ($svg) { var _this = this, $binder = _this.$binder, contentHeight = $binder.height(), contentTop = $binder.get(0) === window ? $(window).scrollTop() : $binder.offset().top; var post = $svg.offset().top - contentTop, posb = post + $svg.height(); if ((post >= 0 && post < contentHeight) || (posb > 0 && posb <= contentHeight)) { $svg.trigger('appear.ydui.progressbar'); } }; ProgressBar.prototype.createSvgView = function () { var _this = this, options = _this.options; var svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg'); _this.initSvg(svg, options); var path = _this.createPath(options); svg.appendChild(path); var trailPath = null; if (options.trailColor || options.trailWidth) { trailPath = _this.createTrailPath(options); trailPath.style.strokeDashoffset = trailPath.getTotalLength(); svg.appendChild(trailPath); } _this.svg = svg; _this.trailPath = trailPath; return { svg: svg, trailPath: trailPath } }; ProgressBar.prototype.createTrailPath = function (options) { var _this = this; if (options.trailWidth == 0) { options.trailWidth = options.strokeWidth; } var pathString = _this.getPathString(options.trailWidth); return _this.createPathElement(pathString, options.trailColor, options.trailWidth); }; ProgressBar.prototype.createPath = function (options) { var _this = this, width = options.strokeWidth; if (options.trailWidth && options.trailWidth > options.strokeWidth) { width = options.trailWidth; } var pathString = _this.getPathString(width); return _this.createPathElement(pathString, options.strokeColor, options.strokeWidth, options.fill); }; ProgressBar.prototype.createPathElement = function (pathString, color, width, fill) { var path = doc.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('d', pathString); path.setAttribute('stroke', color); path.setAttribute('stroke-width', width); if (fill) { path.setAttribute('fill', fill); } else { path.setAttribute('fill-opacity', '0'); } return path; }; ProgressBar.prototype.render = function (template, vars) { var rendered = template; for (var key in vars) { if (vars.hasOwnProperty(key)) { var val = vars[key]; var regExpString = '\\{' + key + '\\}'; var regExp = new RegExp(regExpString, 'g'); rendered = rendered.replace(regExp, val); } } return rendered; }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), progressbar = $this.data('ydui.progressbar'); if (!progressbar) { if (option.type == 'line') { $this.data('ydui.progressbar', (progressbar = new Line(this, option))); } else { $this.data('ydui.progressbar', (progressbar = new Circle(this, option))); } if (!option || typeof option == 'object') { progressbar.appendView(); } } if (typeof option == 'string') { progressbar[option] && progressbar[option].apply(progressbar, args); } }); } $('[data-ydui-progressbar]').each(function () { var $this = $(this); Plugin.call($this, util.parseOptions($this.data('ydui-progressbar'))); }); $.fn.progressBar = Plugin; }(window); /** * ActionSheet Plugin */ !function (window) { "use strict"; var doc = window.document, $doc = $(doc), $body = $(doc.body), $mask = $('
    '); function ActionSheet (element, closeElement) { this.$element = $(element); this.closeElement = closeElement; this.toggleClass = 'actionsheet-toggle'; } ActionSheet.prototype.open = function () { YDUI.device.isIOS && $('.g-scrollview').addClass('g-fix-ios-overflow-scrolling-bug'); var _this = this; $body.append($mask); // 鐐瑰嚮閬僵灞傚叧闂獥鍙 $mask.on('click.ydui.actionsheet.mask', function () { _this.close(); }); // 绗笁鏂瑰叧闂獥鍙f搷浣 if (_this.closeElement) { $doc.on('click.ydui.actionsheet', _this.closeElement, function () { _this.close(); }); } _this.$element.addClass(_this.toggleClass).trigger('open.ydui.actionsheet'); }; ActionSheet.prototype.close = function () { var _this = this; YDUI.device.isIOS && $('.g-scrollview').removeClass('g-fix-ios-overflow-scrolling-bug'); $mask.off('click.ydui.actionsheet.mask').remove(); _this.$element.removeClass(_this.toggleClass).trigger('close.ydui.actionsheet'); //$doc.off('click.ydui.actionsheet', _this.closeElement); }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), actionsheet = $this.data('ydui.actionsheet'); if (!actionsheet) { $this.data('ydui.actionsheet', (actionsheet = new ActionSheet(this, option.closeElement))); if (!option || typeof option == 'object') { actionsheet.open(); } } if (typeof option == 'string') { actionsheet[option] && actionsheet[option].apply(actionsheet, args); } }); } $doc.on('click.ydui.actionsheet.data-api', '[data-ydui-actionsheet]', function (e) { e.preventDefault(); var options = window.YDUI.util.parseOptions($(this).data('ydui-actionsheet')), $target = $(options.target), option = $target.data('ydui.actionsheet') ? 'open' : options; Plugin.call($target, option); }); $.fn.actionSheet = Plugin; }(window); /** * ydui.util */ !function (window) { "use strict"; var util = window.YDUI.util = window.YDUI.util || {}, doc = window.document; /** * 鏃ユ湡鏍煎紡鍖 * @param format 鏃ユ湡鏍煎紡 {%d澶﹠{%h鏃秨{%m鍒唥{%s绉拀{%f姣} * @param time 鍗曚綅 姣 * @returns {string} */ util.timestampTotime = function (format, time) { var t = {}, floor = Math.floor; t.f = time % 1000; time = floor(time / 1000); t.s = time % 60; time = floor(time / 60); t.m = time % 60; time = floor(time / 60); t.h = time % 24; t.d = floor(time / 24); var ment = function (a) { if (a <= 0) { return ''; } return '$1' + (a < 10 ? '0' + a : a) + '$2'; }; format = format.replace(/\{([^{]*?)%d(.*?)\}/g, ment(t.d)); format = format.replace(/\{([^{]*?)%h(.*?)\}/g, ment(t.h)); format = format.replace(/\{([^{]*?)%m(.*?)\}/g, ment(t.m)); format = format.replace(/\{([^{]*?)%s(.*?)\}/g, ment(t.s)); format = format.replace(/\{([^{]*?)%f(.*?)\}/g, ment(t.f)); return format; }; /** * js鍊掕鏃 * @param format 鏃堕棿鏍煎紡 {%d}澶﹞%h}鏃秢%m}鍒唟%s}绉抺%f}姣 * @param time 缁撴潫鏃堕棿鏃堕棿鎴 姣 * @param speed 閫熷害 * @param callback ret 鍊掕鏃剁粨鏉熷洖璋冨嚱鏁 ret 鏃堕棿瀛楃 锛況et == '' 鍒欏€掕鏃剁粨鏉 * DEMO: YDUI.util.countdown('{%d澶﹠{%h鏃秨{%m鍒唥{%s绉拀{%f姣}', Date.parse(new Date()) + 60000, 1000, function(ret){ console.log(ret); }); */ util.countdown = function (format, time, speed, callback) { var that = this; var timer = setInterval(function () { var l_time = time - new Date().getTime(); if (l_time > 0) { callback(that.timestampTotime(format, l_time)); } else { clearInterval(timer); typeof callback == 'function' && callback(''); } }, speed); }; /** * js 鍔犲噺涔橀櫎 * @param arg1 鏁板€? * @param op 鎿嶄綔绗tring 銆? - * /銆 * @param arg2 鏁板€? * @returns {Object} arg1 涓 arg2杩愮畻鐨勭簿纭粨鏋 */ util.calc = function (arg1, op, arg2) { var ra = 1, rb = 1, m; try { ra = arg1.toString().split('.')[1].length; } catch (e) { } try { rb = arg2.toString().split('.')[1].length; } catch (e) { } m = Math.pow(10, Math.max(ra, rb)); switch (op) { case '+': case '-': arg1 = Math.round(arg1 * m); arg2 = Math.round(arg2 * m); break; case '*': ra = Math.pow(10, ra); rb = Math.pow(10, rb); m = ra * rb; arg1 = Math.round(arg1 * ra); arg2 = Math.round(arg2 * rb); break; case '/': arg1 = Math.round(arg1 * m); arg2 = Math.round(arg2 * m); m = 1; break; } try { var result = eval('(' + '(' + arg1 + ')' + op + '(' + arg2 + ')' + ')/' + m); } catch (e) { } return result; }; /** * 璇诲彇鍥剧墖鏂囦欢 骞惰繑鍥炲浘鐗囩殑DataUrl * @param obj * @param callback */ util.getImgBase64 = function (obj, callback) { var that = this, dataimg = '', file = obj.files[0]; if (!file)return; if (!/image\/\w+/.test(file.type)) { that.tipMes('璇蜂笂浼犲浘鐗囨枃浠?, 'error'); return; } var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { dataimg = this.result; typeof callback === 'function' && callback(dataimg); }; }; /** * 鑾峰彇鍦板潃鏍忓弬鏁 * @param name * @returns {*} */ util.getQueryString = function (name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"), r = window.location.search.substr(1).match(reg), qs = ''; if (r != null)qs = decodeURIComponent(r[2]); return qs; }; /** * Cookie * @type {{get, set}} */ util.cookie = function () { return { /** * 鑾峰彇 Cookie * @param {String} name * @return {String} */ get: function (name) { var m = doc.cookie.match('(?:^|;)\\s*' + name + '=([^;]*)'); return (m && m[1]) ? decodeURIComponent(m[1]) : ''; }, /** * 璁剧疆 Cookie * @param {String} name 鍚嶇О * @param {String} val 鍊 * @param {Number} expires 鍗曚綅锛堢锛 * @param {String} domain 鍩 * @param {String} path 鎵€鍦ㄧ殑鐩綍 * @param {Boolean} secure 璺ㄥ崗璁紶閫 */ set: function (name, val, expires, domain, path, secure) { var text = String(encodeURIComponent(val)), date = expires; // 浠庡綋鍓嶆椂闂村紑濮嬶紝澶氬皯灏忔椂鍚庤繃鏈 if (typeof date === 'number') { date = new Date(); date.setTime(date.getTime() + expires * 1000); } date instanceof Date && (text += '; expires=' + date.toUTCString()); !!domain && (text += '; domain=' + domain); text += '; path=' + (path || '/'); secure && (text += '; secure'); doc.cookie = name + '=' + text; } } }(); }(window); /** * Tab Plugin */ !function (window) { "use strict"; function Tab (element, options) { this.$element = $(element); this.options = $.extend({}, Tab.DEFAULTS, options || {}); this.init(); this.bindEvent(); this.transitioning = false; } // 150ms 涓哄垏鎹㈠姩鐢绘墽琛屾椂闂 Tab.TRANSITION_DURATION = 150; Tab.DEFAULTS = { nav: '.tab-nav-item', panel: '.tab-panel-item', activeClass: 'tab-active' }; Tab.prototype.init = function () { var _this = this, $element = _this.$element; _this.$nav = $element.find(_this.options.nav); _this.$panel = $element.find(_this.options.panel); }; /** * 绲﹂€夐」鍗″鑸粦瀹氱偣鍑讳簨浠 */ Tab.prototype.bindEvent = function () { var _this = this; _this.$nav.each(function (e) { $(this).on('click.ydui.tab', function () { _this.open(e); }); }); }; /** * 鎵撳紑閫夐」鍗 * @param index 褰撳墠瀵艰埅绱㈠紩 */ Tab.prototype.open = function (index) { var _this = this; index = typeof index == 'number' ? index : _this.$nav.filter(index).index(); var $curNav = _this.$nav.eq(index); // 濡傛灉鍒囨崲鍔ㄧ敾杩涜鏃舵垨鑰呭綋鍓嶄簩娆$偣鍑 绂佹閲嶅鎿嶄綔 if (_this.transitioning || $curNav.hasClass(_this.options.activeClass))return; _this.transitioning = true; // 鎵撳紑閫夐」鍗℃椂缁戝畾鑷畾涔変簨浠 $curNav.trigger($.Event('open.ydui.tab', { index: index })); // 缁檛ab瀵艰埅娣诲姞閫変腑鏍峰紡 _this.active($curNav, _this.$nav); // 缁檛ab鍐呭娣诲姞閫変腑鏍峰紡 _this.active(_this.$panel.eq(index), _this.$panel, function () { // 鎵撳紑閫夐」鍗″悗缁戝畾鑷畾涔変簨浠 $curNav.trigger({ type: 'opened.ydui.tab', index: index }); _this.transitioning = false; }); }; /** * 娣诲姞閫変腑鏍峰紡 * @param $element 褰撳墠闇€瑕佹坊鍔犻€変腑鏍峰紡鐨勫璞 * @param $container 褰撳墠瀵硅薄鐨勫悓绾ф墍鏈夊璞 * @param callback 鍥炶皟 */ Tab.prototype.active = function ($element, $container, callback) { var _this = this, activeClass = _this.options.activeClass; var $avtive = $container.filter('.' + activeClass); function next () { typeof callback == 'function' && callback(); } // 鍔ㄧ敾鎵ц瀹屾瘯鍚庡洖璋 $element.one('webkitTransitionEnd', next).emulateTransitionEnd(Tab.TRANSITION_DURATION); $avtive.removeClass(activeClass); $element.addClass(activeClass); }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var target = this, $this = $(target), tab = $this.data('ydui.tab'); if (!tab) { $this.data('ydui.tab', (tab = new Tab(target, option))); } if (typeof option == 'string') { tab[option] && tab[option].apply(tab, args); } }); } $(window).on('load.ydui.tab', function () { $('[data-ydui-tab]').each(function () { var $this = $(this); $this.tab(window.YDUI.util.parseOptions($this.data('ydui-tab'))); }); }); $.fn.tab = Plugin; }(window); ;(function () { 'use strict'; /** * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs. * * @codingstandard ftlabs-jsv2 * @copyright The Financial Times Limited [All Rights Reserved] * @license MIT License (see LICENSE.txt) */ /*jslint browser:true, node:true*/ /*global define, Event, Node*/ /** * Instantiate fast-clicking listeners on the specified layer. * * @constructor * @param {Element} layer The layer to listen on * @param {Object} [options={}] The options to override the defaults */ function FastClick(layer, options) { var oldOnClick; options = options || {}; /** * Whether a click is currently being tracked. * * @type boolean */ this.trackingClick = false; /** * Timestamp for when click tracking started. * * @type number */ this.trackingClickStart = 0; /** * The element being tracked for a click. * * @type EventTarget */ this.targetElement = null; /** * X-coordinate of touch start event. * * @type number */ this.touchStartX = 0; /** * Y-coordinate of touch start event. * * @type number */ this.touchStartY = 0; /** * ID of the last touch, retrieved from Touch.identifier. * * @type number */ this.lastTouchIdentifier = 0; /** * Touchmove boundary, beyond which a click will be cancelled. * * @type number */ this.touchBoundary = options.touchBoundary || 10; /** * The FastClick layer. * * @type Element */ this.layer = layer; /** * The minimum time between tap(touchstart and touchend) events * * @type number */ this.tapDelay = options.tapDelay || 200; /** * The maximum time for a tap * * @type number */ this.tapTimeout = options.tapTimeout || 700; if (FastClick.notNeeded(layer)) { return; } // Some old versions of Android don't have Function.prototype.bind function bind(method, context) { return function() { return method.apply(context, arguments); }; } var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel']; var context = this; for (var i = 0, l = methods.length; i < l; i++) { context[methods[i]] = bind(context[methods[i]], context); } // Set up event handlers as required if (deviceIsAndroid) { layer.addEventListener('mouseover', this.onMouse, true); layer.addEventListener('mousedown', this.onMouse, true); layer.addEventListener('mouseup', this.onMouse, true); } layer.addEventListener('click', this.onClick, true); layer.addEventListener('touchstart', this.onTouchStart, false); layer.addEventListener('touchmove', this.onTouchMove, false); layer.addEventListener('touchend', this.onTouchEnd, false); layer.addEventListener('touchcancel', this.onTouchCancel, false); // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick // layer when they are cancelled. if (!Event.prototype.stopImmediatePropagation) { layer.removeEventListener = function(type, callback, capture) { var rmv = Node.prototype.removeEventListener; if (type === 'click') { rmv.call(layer, type, callback.hijacked || callback, capture); } else { rmv.call(layer, type, callback, capture); } }; layer.addEventListener = function(type, callback, capture) { var adv = Node.prototype.addEventListener; if (type === 'click') { adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) { if (!event.propagationStopped) { callback(event); } }), capture); } else { adv.call(layer, type, callback, capture); } }; } // If a handler is already declared in the element's onclick attribute, it will be fired before // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and // adding it as listener. if (typeof layer.onclick === 'function') { // Android browser on at least 3.2 requires a new reference to the function in layer.onclick // - the old one won't work if passed to addEventListener directly. oldOnClick = layer.onclick; layer.addEventListener('click', function(event) { oldOnClick(event); }, false); layer.onclick = null; } } /** * Windows Phone 8.1 fakes user agent string to look like Android and iPhone. * * @type boolean */ var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0; /** * Android requires exceptions. * * @type boolean */ var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone; /** * iOS requires exceptions. * * @type boolean */ var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone; /** * iOS 4 requires an exception for select elements. * * @type boolean */ var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent); /** * iOS 6.0-7.* requires the target element to be manually derived * * @type boolean */ var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent); /** * BlackBerry requires exceptions. * * @type boolean */ var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0; /** * Determine whether a given element requires a native click. * * @param {EventTarget|Element} target Target DOM element * @returns {boolean} Returns true if the element needs a native click */ FastClick.prototype.needsClick = function(target) { switch (target.nodeName.toLowerCase()) { // Don't send a synthetic click to disabled inputs (issue #62) case 'button': case 'select': case 'textarea': if (target.disabled) { return true; } break; case 'input': // File inputs need real clicks on iOS 6 due to a browser bug (issue #68) if ((deviceIsIOS && target.type === 'file') || target.disabled) { return true; } break; case 'label': case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames case 'video': return true; } return (/\bneedsclick\b/).test(target.className); }; /** * Determine whether a given element requires a call to focus to simulate click into element. * * @param {EventTarget|Element} target Target DOM element * @returns {boolean} Returns true if the element requires a call to focus to simulate native click. */ FastClick.prototype.needsFocus = function(target) { switch (target.nodeName.toLowerCase()) { case 'textarea': return true; case 'select': return !deviceIsAndroid; case 'input': switch (target.type) { case 'button': case 'checkbox': case 'file': case 'image': case 'radio': case 'submit': return false; } // No point in attempting to focus disabled inputs return !target.disabled && !target.readOnly; default: return (/\bneedsfocus\b/).test(target.className); } }; /** * Send a click event to the specified element. * * @param {EventTarget|Element} targetElement * @param {Event} event */ FastClick.prototype.sendClick = function(targetElement, event) { var clickEvent, touch; // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) if (document.activeElement && document.activeElement !== targetElement) { document.activeElement.blur(); } touch = event.changedTouches[0]; // Synthesise a click event, with an extra attribute so it can be tracked clickEvent = document.createEvent('MouseEvents'); clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); clickEvent.forwardedTouchEvent = true; targetElement.dispatchEvent(clickEvent); }; FastClick.prototype.determineEventType = function(targetElement) { //Issue #159: Android Chrome Select Box does not open with a synthetic click event if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') { return 'mousedown'; } return 'click'; }; /** * @param {EventTarget|Element} targetElement */ FastClick.prototype.focus = function(targetElement) { var length; // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') { length = targetElement.value.length; targetElement.setSelectionRange(length, length); } else { targetElement.focus(); } }; /** * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it. * * @param {EventTarget|Element} targetElement */ FastClick.prototype.updateScrollParent = function(targetElement) { var scrollParent, parentElement; scrollParent = targetElement.fastClickScrollParent; // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the // target element was moved to another parent. if (!scrollParent || !scrollParent.contains(targetElement)) { parentElement = targetElement; do { if (parentElement.scrollHeight > parentElement.offsetHeight) { scrollParent = parentElement; targetElement.fastClickScrollParent = parentElement; break; } parentElement = parentElement.parentElement; } while (parentElement); } // Always update the scroll top tracker if possible. if (scrollParent) { scrollParent.fastClickLastScrollTop = scrollParent.scrollTop; } }; /** * @param {EventTarget} targetElement * @returns {Element|EventTarget} */ FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) { // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node. if (eventTarget.nodeType === Node.TEXT_NODE) { return eventTarget.parentNode; } return eventTarget; }; /** * On touch start, record the position and scroll offset. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchStart = function(event) { var targetElement, touch, selection; // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111). if (event.targetTouches.length > 1) { return true; } targetElement = this.getTargetElementFromEventTarget(event.target); touch = event.targetTouches[0]; if (deviceIsIOS) { // Only trusted events will deselect text on iOS (issue #49) selection = window.getSelection(); if (selection.rangeCount && !selection.isCollapsed) { return true; } if (!deviceIsIOS4) { // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23): // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched // with the same identifier as the touch event that previously triggered the click that triggered the alert. // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform. // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string, // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long, // random integers, it's safe to to continue if the identifier is 0 here. if (touch.identifier && touch.identifier === this.lastTouchIdentifier) { event.preventDefault(); return false; } this.lastTouchIdentifier = touch.identifier; // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and: // 1) the user does a fling scroll on the scrollable layer // 2) the user stops the fling scroll with another tap // then the event.target of the last 'touchend' event will be the element that was under the user's finger // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42). this.updateScrollParent(targetElement); } } this.trackingClick = true; this.trackingClickStart = event.timeStamp; this.targetElement = targetElement; this.touchStartX = touch.pageX; this.touchStartY = touch.pageY; // Prevent phantom clicks on fast double-tap (issue #36) if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { event.preventDefault(); } return true; }; /** * Based on a touchmove event object, check whether the touch has moved past a boundary since it started. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.touchHasMoved = function(event) { var touch = event.changedTouches[0], boundary = this.touchBoundary; if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) { return true; } return false; }; /** * Update the last position. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchMove = function(event) { if (!this.trackingClick) { return true; } // If the touch has moved, cancel the click tracking if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) { this.trackingClick = false; this.targetElement = null; } return true; }; /** * Attempt to find the labelled control for the given label element. * * @param {EventTarget|HTMLLabelElement} labelElement * @returns {Element|null} */ FastClick.prototype.findControl = function(labelElement) { // Fast path for newer browsers supporting the HTML5 control attribute if (labelElement.control !== undefined) { return labelElement.control; } // All browsers under test that support touch events also support the HTML5 htmlFor attribute if (labelElement.htmlFor) { return document.getElementById(labelElement.htmlFor); } // If no for attribute exists, attempt to retrieve the first labellable descendant element // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); }; /** * On touch end, determine whether to send a click event at once. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchEnd = function(event) { var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement; if (!this.trackingClick) { return true; } // Prevent phantom clicks on fast double-tap (issue #36) if ((event.timeStamp - this.lastClickTime) < this.tapDelay) { this.cancelNextClick = true; return true; } if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) { return true; } // Reset to prevent wrong click cancel on input (issue #156). this.cancelNextClick = false; this.lastClickTime = event.timeStamp; trackingClickStart = this.trackingClickStart; this.trackingClick = false; this.trackingClickStart = 0; // On some iOS devices, the targetElement supplied with the event is invalid if the layer // is performing a transition or scroll, and has to be re-detected manually. Note that // for this to function correctly, it must be called *after* the event target is checked! // See issue #57; also filed as rdar://13048589 . if (deviceIsIOSWithBadTarget) { touch = event.changedTouches[0]; // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement; targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent; } targetTagName = targetElement.tagName.toLowerCase(); if (targetTagName === 'label') { forElement = this.findControl(targetElement); if (forElement) { this.focus(targetElement); if (deviceIsAndroid) { return false; } targetElement = forElement; } } else if (this.needsFocus(targetElement)) { // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) { this.targetElement = null; return false; } this.focus(targetElement); this.sendClick(targetElement, event); // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) if (!deviceIsIOS || targetTagName !== 'select') { this.targetElement = null; event.preventDefault(); } return false; } if (deviceIsIOS && !deviceIsIOS4) { // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). scrollParent = targetElement.fastClickScrollParent; if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { return true; } } // Prevent the actual click from going though - unless the target node is marked as requiring // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. if (!this.needsClick(targetElement)) { event.preventDefault(); this.sendClick(targetElement, event); } return false; }; /** * On touch cancel, stop tracking the click. * * @returns {void} */ FastClick.prototype.onTouchCancel = function() { this.trackingClick = false; this.targetElement = null; }; /** * Determine mouse events which should be permitted. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onMouse = function(event) { // If a target element was never set (because a touch event was never fired) allow the event if (!this.targetElement) { return true; } if (event.forwardedTouchEvent) { return true; } // Programmatically generated events targeting a specific element should be permitted if (!event.cancelable) { return true; } // Derive and check the target element to see whether the mouse event needs to be permitted; // unless explicitly enabled, prevent non-touch click events from triggering actions, // to prevent ghost/doubleclicks. if (!this.needsClick(this.targetElement) || this.cancelNextClick) { // Prevent any user-added listeners declared on FastClick element from being fired. if (event.stopImmediatePropagation) { event.stopImmediatePropagation(); } else { // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) event.propagationStopped = true; } // Cancel the event event.stopPropagation(); event.preventDefault(); return false; } // If the mouse event is permitted, return true for the action to go through. return true; }; /** * On actual clicks, determine whether this is a touch-generated click, a click action occurring * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or * an actual click which should be permitted. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onClick = function(event) { var permitted; // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early. if (this.trackingClick) { this.targetElement = null; this.trackingClick = false; return true; } // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target. if (event.target.type === 'submit' && event.detail === 0) { return true; } permitted = this.onMouse(event); // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through. if (!permitted) { this.targetElement = null; } // If clicks are permitted, return true for the action to go through. return permitted; }; /** * Remove all FastClick's event listeners. * * @returns {void} */ FastClick.prototype.destroy = function() { var layer = this.layer; if (deviceIsAndroid) { layer.removeEventListener('mouseover', this.onMouse, true); layer.removeEventListener('mousedown', this.onMouse, true); layer.removeEventListener('mouseup', this.onMouse, true); } layer.removeEventListener('click', this.onClick, true); layer.removeEventListener('touchstart', this.onTouchStart, false); layer.removeEventListener('touchmove', this.onTouchMove, false); layer.removeEventListener('touchend', this.onTouchEnd, false); layer.removeEventListener('touchcancel', this.onTouchCancel, false); }; /** * Check whether FastClick is needed. * * @param {Element} layer The layer to listen on */ FastClick.notNeeded = function(layer) { var metaViewport; var chromeVersion; var blackberryVersion; var firefoxVersion; // Devices that don't support touch don't need FastClick if (typeof window.ontouchstart === 'undefined') { return true; } // Chrome version - zero for other browsers chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; if (chromeVersion) { if (deviceIsAndroid) { metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport) { // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89) if (metaViewport.content.indexOf('user-scalable=no') !== -1) { return true; } // Chrome 32 and above with width=device-width or less don't need FastClick if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) { return true; } } // Chrome desktop doesn't need FastClick (issue #15) } else { return true; } } if (deviceIsBlackBerry10) { blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/); // BlackBerry 10.3+ does not require Fastclick library. // https://github.com/ftlabs/fastclick/issues/251 if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) { metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport) { // user-scalable=no eliminates click delay. if (metaViewport.content.indexOf('user-scalable=no') !== -1) { return true; } // width=device-width (or less than device-width) eliminates click delay. if (document.documentElement.scrollWidth <= window.outerWidth) { return true; } } } } // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97) if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') { return true; } // Firefox version - zero for other browsers firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1]; if (firefoxVersion >= 27) { // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896 metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) { return true; } } // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') { return true; } return false; }; /** * Factory method for creating a FastClick object * * @param {Element} layer The layer to listen on * @param {Object} [options={}] The options to override the defaults */ FastClick.attach = function(layer, options) { return new FastClick(layer, options); }; if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) { // AMD. Register as an anonymous module. define(function() { return FastClick; }); } else if (typeof module !== 'undefined' && module.exports) { module.exports = FastClick.attach; module.exports.FastClick = FastClick; } else { window.FastClick = FastClick; } }()); /** * ScrollTab Plugin */ !function (window) { "use strict"; function ScrollTab (element, options) { this.$element = $(element); this.options = $.extend({}, ScrollTab.DEFAULTS, options || {}); this.init(); } ScrollTab.DEFAULTS = { navItem: '.scrolltab-item', content: '.scrolltab-content', contentItem: '.scrolltab-content-item', initIndex: 0 }; ScrollTab.prototype.init = function () { var _this = this, $element = _this.$element, options = _this.options; _this.$navItem = $element.find(options.navItem); _this.$content = $element.find(options.content); _this.$contentItem = $element.find(options.contentItem); _this.scrolling = false; _this.contentOffsetTop = _this.$content.offset().top; _this.bindEvent(); _this.movePosition(_this.options.initIndex, false); }; ScrollTab.prototype.bindEvent = function () { var _this = this; _this.$content.on('resize.ydui.scrolltab scroll.ydui.scrolltab', function () { _this.checkInView(); }); _this.$navItem.on('click.ydui.scrolltab', function () { _this.movePosition($(this).index(), true); }); }; ScrollTab.prototype.movePosition = function (index, animate) { var _this = this; if (_this.scrolling)return; _this.scrolling = true; _this.$navItem.removeClass('crt'); _this.$navItem.eq(index).addClass('crt'); var $item = _this.$contentItem.eq(index); if (!$item[0])return; var offset = $item.offset().top; var top = offset + _this.$content.scrollTop() - _this.contentOffsetTop + 1; _this.$content.stop().animate({scrollTop: top}, animate ? 200 : 0, function () { _this.scrolling = false; }); }; ScrollTab.prototype.checkInView = function () { var _this = this; if (_this.scrolling)return; if (_this.isScrollTop()) { _this.setClass(0); return; } if (_this.isScrollBottom()) { _this.setClass(_this.$navItem.length - 1); return; } _this.$contentItem.each(function () { var $this = $(this); if ($this.offset().top <= _this.contentOffsetTop) { _this.setClass($this.index()); } }); }; ScrollTab.prototype.setClass = function (index) { this.$navItem.removeClass('crt').eq(index).addClass('crt'); }; ScrollTab.prototype.isScrollTop = function () { return this.$content.scrollTop() == 0; }; ScrollTab.prototype.isScrollBottom = function () { var _this = this; return _this.$content.scrollTop() + 3 >= _this.$contentItem.height() * _this.$contentItem.length - _this.$content.height(); }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var target = this, $this = $(target), scrollTab = $this.data('ydui.scrolltab'); if (!scrollTab) { $this.data('ydui.scrolltab', (scrollTab = new ScrollTab(target, option))); } if (typeof option == 'string') { scrollTab[option] && scrollTab[option].apply(scrollTab, args); } }); } $(window).on('load.ydui.scrolltab', function () { $('[data-ydui-scrolltab]').each(function () { var $this = $(this); $this.scrollTab(window.YDUI.util.parseOptions($this.data('ydui-scrolltab'))); }); }); $.fn.scrollTab = Plugin; }(window); /** * SendCode Plugin */ !function () { "use strict"; function SendCode (element, options) { this.$btn = $(element); this.options = $.extend({}, SendCode.DEFAULTS, options || {}); } SendCode.DEFAULTS = { run: false, // 鏄惁鑷姩鍊掕鏃 secs: 60, // 鍊掕鏃舵椂闀匡紙绉掞級 disClass: '', // 绂佺敤鎸夐挳鏍峰紡 runStr: '{%s}绉掑悗閲嶆柊鑾峰彇', // 鍊掕鏃舵樉绀烘枃鏈 resetStr: '閲嶆柊鑾峰彇楠岃瘉鐮? // 鍊掕鏃剁粨鏉熷悗鎸夐挳鏄剧ず鏂囨湰 }; SendCode.timer = null; /** * 寮€濮嬪€掕鏃 */ SendCode.prototype.start = function () { var _this = this, options = _this.options, secs = options.secs; _this.$btn.html(_this.getStr(secs)).css('pointer-events', 'none').addClass(options.disClass); _this.timer = setInterval(function () { secs--; _this.$btn.html(_this.getStr(secs)); if (secs <= 0) { _this.resetBtn(); clearInterval(_this.timer); } }, 1000); }; /** * 鑾峰彇鍊掕鏃舵樉绀烘枃鏈 * @param secs * @returns {string} */ SendCode.prototype.getStr = function (secs) { return this.options.runStr.replace(/\{([^{]*?)%s(.*?)\}/g, secs); }; /** * 閲嶇疆鎸夐挳 */ SendCode.prototype.resetBtn = function () { var _this = this, options = _this.options; _this.$btn.html(options.resetStr).css('pointer-events', 'auto').removeClass(options.disClass); }; function Plugin (option) { var args = Array.prototype.slice.call(arguments, 1); return this.each(function () { var $this = $(this), sendcode = $this.data('ydui.sendcode'); if (!sendcode) { $this.data('ydui.sendcode', (sendcode = new SendCode(this, option))); if (typeof option == 'object' && option.run) { sendcode.start(); } } if (typeof option == 'string') { sendcode[option] && sendcode[option].apply(sendcode, args); } }); } $.fn.sendCode = Plugin; }(); undefined