UNPKG

weui

Version:

A UI library by WeChat official design team, includes the most useful widgets/modules in mobile web applications.

320 lines (293 loc) 9.15 kB
/** * Created by jf on 2015/9/11. * Modified by bear on 2016/9/7. */ const footerTmpl = $('#footerTmpl').html(); $(() => { const pageManager = { $container: $('#container'), _pageStack: [], _configs: [], _pageAppend() {}, _defaultPage: null, _pageIndex: 1, setDefault(defaultPage) { this._defaultPage = this._find('name', defaultPage); return this; }, setPageAppend(pageAppend) { this._pageAppend = pageAppend; return this; }, init() { const self = this; $(window).on('hashchange', () => { const state = history.state || {}; const url = location.hash.indexOf('#') === 0 ? location.hash : '#'; const page = self._find('url', url) || self._defaultPage; if (state._pageIndex <= self._pageIndex || self._findInStack(url)) { self._back(page); } else { self._go(page); } }); if (history.state && history.state._pageIndex) { this._pageIndex = history.state._pageIndex; } this._pageIndex -= 1; const url = location.hash.indexOf('#') === 0 ? location.hash : '#'; const page = self._find('url', url) || self._defaultPage; this._go(page); return this; }, push(config) { this._configs.push(config); return this; }, go(to) { const config = this._find('name', to); if (!config) { return; } location.hash = config.url; }, _go(config) { this._pageIndex += 1; history.replaceState && history.replaceState({ _pageIndex: this._pageIndex }, '', location.href); const html = $(config.template).html(); const $html = $(html).addClass('slideIn') .addClass(config.name); $html.on('animationend webkitAnimationEnd', () => { $html.removeClass('slideIn').addClass('js_show'); setPageA11y(); const event = new Event('switched'); window.dispatchEvent(event); }); this.$container.append($html); this._pageAppend.call(this, $html); this._pageStack.push({ config, dom: $html, }); if (!config.isBind) { this._bind(config); } return this; }, back() { history.back(); }, _back(config) { this._pageIndex -= 1; const stack = this._pageStack.pop(); if (!stack) { return; } const url = location.hash.indexOf('#') === 0 ? location.hash : '#'; const found = this._findInStack(url); if (!found) { const html = $(config.template).html(); const $html = $(html).addClass('js_show') .addClass(config.name); $html.insertBefore(stack.dom); if (!config.isBind) { this._bind(config); } this._pageStack.push({ config, dom: $html, }); } stack.dom.addClass('slideOut').on('animationend webkitAnimationEnd', () => { stack.dom.remove(); setPageA11y(); }); return this; }, _findInStack(url) { let found = null; for (let i = 0, len = this._pageStack.length; i < len; i++) { const stack = this._pageStack[i]; if (stack.config.url === url) { found = stack; break; } } return found; }, _find(key, value) { let page = null; for (let i = 0, len = this._configs.length; i < len; i++) { if (this._configs[i][key] === value) { page = this._configs[i]; break; } } return page; }, _bind(page) { const events = page.events || {}; for (const t in events) { for (const type in events[t]) { this.$container.on(type, t, events[t][type]); } } page.isBind = true; }, }; function fastClick() { const supportTouch = (function () { try { document.createEvent('TouchEvent'); return true; } catch (e) { return false; } }()); const _old$On = $.fn.on; $.fn.on = function () { if (/click/.test(arguments[0]) && typeof arguments[1] === 'function' && supportTouch) { // 只扩展支持touch的当前元素的click事件 let touchStartY; const callback = arguments[1]; _old$On.apply(this, ['touchstart', function (e) { touchStartY = e.changedTouches[0].clientY; }]); _old$On.apply(this, ['touchend', function (e) { if (Math.abs(e.changedTouches[0].clientY - touchStartY) > 10) return; e.preventDefault(); callback.apply(this, [e]); }]); } else { _old$On.apply(this, arguments); } return this; }; } function preload() { $(window).on('load', () => { const imgList = [ './images/layers/content.png', './images/layers/navigation.png', './images/layers/popout.png', './images/layers/transparent.gif', ]; for (let i = 0, len = imgList.length; i < len; ++i) { new Image().src = imgList[i]; } }); } function androidInputBugFix() { // .container 设置了 overflow 属性, 导致 Android 手机下输入框获取焦点时, 输入法挡住输入框的 bug // 相关 issue: https://github.com/weui/weui/issues/15 // 解决方法: // 0. .container 去掉 overflow 属性, 但此 demo 下会引发别的问题 // 1. 参考 http://stackoverflow.com/questions/23757345/android-does-not-correctly-scroll-on-input-focus-if-not-body-element // Android 手机下, input 或 textarea 元素聚焦时, 主动滚一把 if (/Android/gi.test(navigator.userAgent)) { window.addEventListener('resize', () => { if (document.activeElement.tagName == 'INPUT' || document.activeElement.tagName == 'TEXTAREA') { window.setTimeout(() => { document.activeElement.scrollIntoViewIfNeeded(); }, 0); } }); } } function setJSAPI() { const option = { title: 'WeUI, 为微信 Web 服务量身设计', desc: 'WeUI, 为微信 Web 服务量身设计', link: 'https://weui.io', imgUrl: 'https://mmbiz.qpic.cn/mmemoticon/ajNVdqHZLLA16apETUPXh9Q5GLpSic7lGuiaic0jqMt4UY8P4KHSBpEWgM7uMlbxxnVR7596b3NPjUfwg7cFbfCtA/0', }; $.getJSON(`https://weui.io/api/sign?url=${encodeURIComponent(location.href.split('#')[0])}`, (res) => { wx.config({ beta: true, debug: false, appId: res.appid, timestamp: res.timestamp, nonceStr: res.nonceStr, signature: res.signature, jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', // 'setNavigationBarColor', 'setBounceBackground', ], }); wx.ready(() => { /* wx.invoke('setNavigationBarColor', { color: '#F8F8F8' }); */ wx.invoke('setBounceBackground', { backgroundColor: '#F8F8F8', footerBounceColor: '#F8F8F8', }); wx.onMenuShareTimeline(option); wx.onMenuShareQQ(option); wx.onMenuShareAppMessage({ title: 'WeUI', desc: '为微信 Web 服务量身设计', link: location.href, imgUrl: 'https://mmbiz.qpic.cn/mmemoticon/ajNVdqHZLLA16apETUPXh9Q5GLpSic7lGuiaic0jqMt4UY8P4KHSBpEWgM7uMlbxxnVR7596b3NPjUfwg7cFbfCtA/0', }); }); }); } function setPageManager() { const pages = {}; const tpls = $('script[type="text/html"]'); for (let i = 0, len = tpls.length; i < len; ++i) { const tpl = tpls[i]; const name = tpl.id.replace(/tpl_/, ''); pages[name] = { name, url: `#${name}`, template: `#${tpl.id}`, }; } pages.home.url = '#'; for (const page in pages) { pageManager.push(pages[page]); } pageManager .setPageAppend(($html) => { $html.eq(0).append(footerTmpl); setTimeout(() => { const $foot = $html.find('.page__ft'); if ($foot.length < 1) return; const winH = $(window).height(); if ($foot.position().top + $foot.height() < winH) { $foot.addClass('j_bottom'); } else { $foot.removeClass('j_bottom'); } }); }) .setDefault('home') .init(); } function setPageA11y() { const $pages = $('.page'); const $lastPage = $pages.eq($pages.length - 1); $pages.attr('aria-hidden', 'true'); // 所有page都加 $lastPage.removeAttr('aria-hidden').attr('tabindex', '-1') .trigger('focus'); // 最后一个page不用加 } function init() { preload(); fastClick(); androidInputBugFix(); // setJSAPI(); setPageManager(); window.pageManager = pageManager; window.home = function () { location.hash = ''; }; var year = new Date().getFullYear(); document.getElementById('js_copyright_year').innerHTML = year; } init(); });