<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>ActionSheet</title> <script src="js/index.js"></script> <style> body { margin: 0; text-align: center; } button { margin: 100px auto; padding: 2em; border: 1px solid #CCC; border-radius: 5px; background: #FFF; } /*組件樣式*/ .pb-container { position: absolute; left: 0; top: 0; z-index: 999999 } .pb-cover { width: 100%; height: 100%; background: rgba(0, 0, 0, .2); } .pb-buttons { position: absolute; left: 0; bottom: 0; width: 100%; } .pb-button { background: #FFF; padding: 10px; text-align: center; } .pb-button:last-child { margin-top: 2px; } @-webkit-keyframes pb-easein { from { opacity: 0; } to { opacity: 1; } } @keyframes pb-easein { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes pb-easeout { from { opacity: 1; } to { opacity: 0; } } @keyframes pb-easeout { from { opacity: 1; } to { opacity: 0; } } .pb-in { -webkit-animation: pb-easein .30s forwards; animation: pb-easein .30s forwards; } .pb-out { -webkit-animation: pb-easeout .30s forwards; animation: pb-easeout .30s forwards; } @-webkit-keyframes pb-buttons-easein { from { -webkit-transform: translate(0, 100%) translateZ(0); transform: translate(0, 100%) translateZ(0); } to { -webkit-transform: translate(0, 0) translateZ(0); transform: translate(0, 0) translateZ(0); } } @keyframes pb-buttons-easein { from { -webkit-transform: translate(0, 100%) translateZ(0); transform: translate(0, 100%) translateZ(0); } to { -webkit-transform: translate(0, 0) translateZ(0); transform: translate(0, 0) translateZ(0); } } @-webkit-keyframes pb-buttons-easeout { from { -webkit-transform: translate(0, 0) translateZ(0); transform: translate(0, 0) translateZ(0); } to { -webkit-transform: translate(0, 100%) translateZ(0); transform: translate(0, 100%) translateZ(0); } } @keyframes pb-buttons-easeout { from { -webkit-transform: translate(0, 0) translateZ(0); transform: translate(0, 0) translateZ(0); } to { -webkit-transform: translate(0, 100%) translateZ(0); transform: translate(0, 100%) translateZ(0); } } .pb-in .pb-buttons { -webkit-animation: pb-buttons-easein .30s forwards; animation: pb-buttons-easein .30s forwards; } .pb-out .pb-buttons { -webkit-animation: pb-buttons-easeout .30s forwards; animation: pb-buttons-easeout .30s forwards; } </style> </head> <body> <p id="name">-</p> <p id="id">-</p> <p id="type">-</p> <button type="button" id="open">打開ActionSheet</button> <script> // data是你請求的數據 let data = [ { name: 'jack', id: '210121458', type: '信息安全需求' }, { name: 'tom', id: '210121238', type: '會議議程' }, { name: 'rose', id: '211121458', type: '其餘' } ] // btnsObj是用來裝數據的 傳到這個組件裏 let btnsObj = {} data.forEach(function(v){ let callBack = function(e) { getInfo(e.target.innerHTML) this.hide() } btnsObj[v.type] = callBack }) // 這個函數是點完actionSheet的回調 type是你選的那個的名字 let getInfo = function(type) { data.forEach(function(v){ if (v.type === type) { // 這個v就是當前選中的 document.querySelector("#name").innerHTML = v.name document.querySelector("#type").innerHTML = v.type document.querySelector("#id").innerHTML = v.id } }) } let as = new ActionSheet({ buttons: btnsObj }); document.getElementById('open').addEventListener('click', function() { console.log(btnsObj) as.show() }) </script> </body> </html>
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.ActionSheet = factory()); }(this, (function () { 'use strict'; function keyValue(args, getter, setter){ var attrs = {}, keys, key = args[0], value = args[1]; if(typeof key === 'object'){ attrs = key; }else if(args.length === 1){ return this[0] ? getter(this[0]) : null; }else{ attrs[key] = value; }; keys = Object.keys(attrs); return this.each(function(el){ keys.forEach(function(key){ setter(el, key, attrs); }); }); }; // 查找節點,返回一個可操做的節點數組 function tethys(selector, context){ var nodes = []; // 把參數轉換爲包含Node的數組 if(selector.each && selector.on){ // tethys 對象 return selector; }else if(typeof selector === 'string'){ // html代碼或選擇器 if(selector.match(/^[^\b\B]*\</)){ // html代碼 nodes = tethys.parseHtml(selector); }else{ // 選擇器 nodes = (context || document).querySelectorAll(selector); }; }else if(Array.isArray(selector) || selector.constructor === NodeList){ // 包含節點的數組或NodeList nodes = selector; }else if(selector.constructor === Node){ // 節點 nodes = [selector]; }else{ throw 'error param'; }; // 當Node被appendChild方法添加到其它元素中後,該Node會被從它所在的NodeList中移除 // 爲了不這種狀況,咱們要把NodeList轉換成包含Node的數組 nodes = Array.prototype.map.call(nodes, function(n){ return n; }); // 給數組添加dom操做方法 tethys.extend(nodes, tethys.fn); return nodes; }; // 擴展 tethys.extend = function(){ var args = arguments, deep = false, dest, prop = Array.prototype; if (typeof args[0] === 'boolean') { deep = prop.shift.call(args); }; dest = prop.shift.call(args); prop.forEach.call(args, function (src) { Object.keys(src).forEach(function (key) { if (deep && typeof src[key] === 'object' && typeof dest[key] === 'object') { extend(true, dest[key], src[key]); } else if (typeof src[key] !== 'undefined') { dest[key] = src[key]; }; }); }); return dest; }; // 合併數組 tethys.merge = function(ary1, ary2){ (ary2 || []).forEach(function(n){ ary1.push(n); }); }; // 把html代碼轉換成NodeList tethys.parseHtml = function(str){ var div = document.createElement('DIV'); div.innerHTML = str; return div.childNodes; }; // 微型模板 tethys.tpl = function(s, o) { var SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g; return s.replace ? s.replace(SUBREGEX, function (match, key) { return typeof o[key] === 'undefined' ? match : o[key]; }) : s; }; // tethys.fn = { // 遍歷 each: function(fn){ Array.prototype.forEach.call(this || [], fn); return this; }, // 綁定事件 on: function(events, fn){ events = events.split(/\s*\,\s*/); return this.each(function(el){ fn = fn.bind(el); events.forEach(function(event){ el.addEventListener(event, fn); }); }); }, // 設置css // css('color', 'red') // css({ color: 'red' }) css: function(key, value){ var format = function(key){ return key.replace(/(-([a-z]))/g, function(s, s1, s2){ return s2.toUpperCase(); }); }; return keyValue.call(this, arguments, function(el){ return el.style[format(key)]; }, function(el, key, attrs){ el.style[format(key)] = attrs[key] + ''; }); }, // 設置或者返回屬性 attr: function(key, value){ return keyValue.call(this, arguments, function(el){ return el.getAttribute(key); }, function(el, key, attrs){ el.setAttribute(key, attrs[key] + ''); }); }, // 檢查是否有class hasClass: function(cls){ var has = false, reg = new RegExp('\\b' + cls + '\\b'); this.each(function(el){ has = has || !!el.className.match(reg); }); return has; }, // 添加class addClass: function(cls, type){ var reg = new RegExp('\\b' + cls + '\\b'); // 爲全部節點添加或刪除class return this.each(function(el){ var name = el.className; if(typeof name !== 'string') return; if(type === 'remove'){ // remove if(name.match(reg)) { el.className = name.replace(reg, ''); } }else{ // add if(!name.match(reg)) { el.className += ' ' + cls; } } }); }, // 刪除class removeClass: function(cls){ return this.addClass(cls, 'remove'); }, // 設置html html: function(html){ return this.each(function(el){ el.innerHTML = html; }); }, // 顯示 show: function(){ return this.each(function(el){ if(el.style.display === 'none'){ el.style.display = el.getAttribute('o-d') || ''; }; }); }, // 隱藏 hide: function(){ return this.each(function(el){ if(el.style.display !== 'none') { el.setAttribute('o-d', el.style.display); el.style.display = 'none'; }; }); }, // 切換顯示隱藏 toggle: function(){ return this.each(function(el){ var e = $(el); e.css("display") == "none" ? e.show() : e.hide(); }); }, // 追加節點 append: function(child){ var children = tethys(child); return this.each(function(el){ children.each(function(child, i){ el.appendChild(child); }); }); }, // 查找 find: function(selector){ var nodes = []; this.each(function(el){ tethys(selector, el).each(function(node){ nodes.push(node); }); }); return tethys(nodes); } }; /*! * tap.js * Copyright (c) 2015 Alex Gibson * https://github.com/alexgibson/tap.js/ * Released under MIT license */ function Tap(el) { this.el = typeof el === 'object' ? el : document.getElementById(el); this.moved = false; //flags if the finger has moved this.startX = 0; //starting x coordinate this.startY = 0; //starting y coordinate this.hasTouchEventOccured = false; //flag touch event this.el.addEventListener('touchstart', this, false); this.el.addEventListener('mousedown', this, false); } // return true if left click is in the event, handle many browsers Tap.prototype.leftButton = function(event) { // modern & preferred: MSIE>=9, Firefox(all) if ('buttons' in event) { // https://developer.mozilla.org/docs/Web/API/MouseEvent/buttons return event.buttons === 1; } else { return 'which' in event ? // 'which' is well defined (and doesn't exist on MSIE<=8) // https://developer.mozilla.org/docs/Web/API/MouseEvent/which event.which === 1 : // for MSIE<=8 button is 1=left (0 on all other browsers) // https://developer.mozilla.org/docs/Web/API/MouseEvent/button event.button === 1; } }; Tap.prototype.start = function(e) { if (e.type === 'touchstart') { this.hasTouchEventOccured = true; this.el.addEventListener('touchmove', this, false); this.el.addEventListener('touchend', this, false); this.el.addEventListener('touchcancel', this, false); } else if (e.type === 'mousedown' && this.leftButton(e)) { this.el.addEventListener('mousemove', this, false); this.el.addEventListener('mouseup', this, false); } this.moved = false; this.startX = e.type === 'touchstart' ? e.touches[0].clientX : e.clientX; this.startY = e.type === 'touchstart' ? e.touches[0].clientY : e.clientY; }; Tap.prototype.move = function(e) { //if finger moves more than 10px flag to cancel var x = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX; var y = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY; if (Math.abs(x - this.startX) > 10 || Math.abs(y - this.startY) > 10) { this.moved = true; } }; Tap.prototype.end = function(e) { var evt; this.el.removeEventListener('touchmove', this, false); this.el.removeEventListener('touchend', this, false); this.el.removeEventListener('touchcancel', this, false); this.el.removeEventListener('mouseup', this, false); this.el.removeEventListener('mousemove', this, false); if (!this.moved) { //create custom event try { evt = new window.CustomEvent('tap', { bubbles: true, cancelable: true }); } catch (e) { evt = document.createEvent('Event'); evt.initEvent('tap', true, true); } //prevent touchend from propagating to any parent //nodes that may have a tap.js listener attached e.stopPropagation(); // dispatchEvent returns false if any handler calls preventDefault, if (!e.target.dispatchEvent(evt)) { // in which case we want to prevent clicks from firing. e.preventDefault(); } } }; Tap.prototype.cancel = function() { this.hasTouchEventOccured = false; this.moved = false; this.startX = 0; this.startY = 0; }; Tap.prototype.destroy = function() { this.el.removeEventListener('touchstart', this, false); this.el.removeEventListener('touchmove', this, false); this.el.removeEventListener('touchend', this, false); this.el.removeEventListener('touchcancel', this, false); this.el.removeEventListener('mousedown', this, false); this.el.removeEventListener('mouseup', this, false); this.el.removeEventListener('mousemove', this, false); }; Tap.prototype.handleEvent = function(e) { switch (e.type) { case 'touchstart': this.start(e); break; case 'touchmove': this.move(e); break; case 'touchend': this.end(e); break; case 'touchcancel': this.cancel(e); break; case 'mousedown': this.start(e); break; case 'mouseup': this.end(e); break; case 'mousemove': this.move(e); break; } }; const tpl = '<div class="pb-container">\ <div class="pb-cover"></div>\ <div class="pb-buttons"></div>\ </div>'; const buttonTpl = '<div class="pb-button">{text}</div>'; var ActionSheet = function(opt){ // 默認參數 opt = tethys.extend({ buttons: {}, inTime: 500, outTime: 500 }, opt); // 渲染 this.render().update(opt.buttons); }; // 綁定點擊事件 function bindTapEvent(el, fn){ new Tap(el); el.addEventListener('tap', fn, false); } ActionSheet.prototype = { // 初始化渲染 render: function(){ var doc = document.documentElement; this.el = tethys(tpl); this.el.hide().css({ width: doc.clientWidth + 'px', height: doc.clientHeight + 'px' }); bindTapEvent(this.el.find('.pb-cover')[0], this.hide.bind(this)); tethys('body').append(this.el); return this; }, // 顯示 show: function(){ this.el.show(); this.el.addClass('pb-in'); setTimeout(function(){ this.el.removeClass('pb-in'); }.bind(this), 350); return this; }, // 隱藏 hide: function(){ this.el.addClass('pb-out'); setTimeout(function(){ this.el.removeClass('pb-out').hide(); }.bind(this), 300); return this; }, // 更新按鈕 update: function(buttons){ var buttonContainer = this.el.find('.pb-buttons'); // 清空按鈕容器 buttonContainer.html(''); // 添加取消按鈕 buttons['取消'] = this.hide.bind(this); // 遍歷建立按鈕 Object.keys(buttons).forEach(function(key){ var n = buttons[key], btn = tethys(tethys.tpl(buttonTpl, { text: key })); // 綁定tap事件 bindTapEvent(btn[0], function(e){ e.stopPropagation(); e.preventDefault(); // 若是參數是函數則調用 // 若是是字符串則認爲是url直接跳轉 if(typeof this.action === 'function'){ this.action.call(this.context, e); }else if(typeof this.action === 'string'){ location.href = this.action; }; }.bind({action: n, context: this})); // 添加到按鈕容器 buttonContainer.append(btn); }.bind(this)); return this; } }; return ActionSheet; })));