1.jquery.custombox.js
以页面元素为模板填充进对话框内容体,或者获取远程数据填充进内容体,实现PPT似的3D动效。
插件写作引入jquery,按原生js写就,效果依赖于支持css3以及Dom3级的浏览器,因此不包括ie8、ie9。
css源码:
/* * jQuery Custombox v1.1.3 - 2014/02/18 * jQuery Modal Window Effects. * http://dixso.github.io/custombox/ * (c) 2014 Julio De La Calle - http://dixso.net - @dixso9 * * Under MIT License - http://www.opensource.org/licenses/mit-license.php */ /* ------------------------------------------------- Overlay ------------------------------------------------- */ .custombox-overlay { position: fixed; width: 100%; height: 100%; top: 0; left: 0; opacity: 0; } /* ------------------------------------------------- Modal ------------------------------------------------- */ .custombox-modal { position: fixed; top: 50%; left: 50%; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden;/* 隐藏旋转元素的背面 */ -webkit-transform: translateY(-50%);/* 根据自身的尺寸大小向上移动50% */ -ms-transform: translateY(-50%); transform: translateY(-50%); } .custombox-modal { height: auto; visibility: hidden; } /* ------------------------------------------------- Error ------------------------------------------------- */ .custombox-error { padding: 20px; text-align: center; color: #F00; font-weight: bold; font-size: 14px; background-color: #FFF; border-radius: 5px; } /* ------------------------------------------------- Actions ------------------------------------------------- */ .custombox-show { visibility: visible; } .custombox-show ~ .custombox-overlay { opacity: 1; visibility: visible; } .custombox-perspective, .custombox-perspective body { height: 100%; overflow: hidden; } .custombox-perspective body { -webkit-perspective: 600px;/* 创建容器的景深,3D效果,容器内部子元素有3D透视效果,绘图中的透视画法 */ perspective: 600px; } .custombox-container { min-height: 100%; } .custombox-hide-scrollbar { overflow-y: hidden; } .custombox-hide-scrollbar body { position: relative; overflow: hidden; } /* ------------------------------------------------- Fade in and scale up ------------------------------------------------- */ .custombox-fadein .custombox-modal-content { -webkit-transform: scale(0.7); -ms-transform: scale(0.7); transform: scale(0.7); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all;/* 所有属性改变的平滑过渡效果,即缩放scale */ opacity: 0; } .custombox-show.custombox-fadein .custombox-modal-content { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } /* ------------------------------------------------- Slide and stick to top ------------------------------------------------- */ .custombox-slide-top { top: 0; } .custombox-slide-top .custombox-modal-content, .custombox-close.custombox-slide-left-top .custombox-modal-content, .custombox-close.custombox-slide-right-top .custombox-modal-content { -webkit-transform: translateY(-200%); -ms-transform: translateY(-200%); transform: translateY(-200%); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; opacity: 0; } .custombox-show.custombox-slide-top .custombox-modal-content { -webkit-transform: translateY(0%); -ms-transform: translateY(0%); transform: translateY(0%); border-radius: 0 0 3px 3px; opacity: 1; } .custombox-close.custombox-slide-top-bottom .custombox-modal-content, .custombox-close.custombox-slide-right-bottom .custombox-modal-content, .custombox-close.custombox-slide-bottom-bottom .custombox-modal-content, .custombox-close.custombox-slide-left-bottom .custombox-modal-content { -webkit-transform: translateY(200%); -ms-transform: translateY(200%); transform: translateY(200%); } /* ------------------------------------------------- Slide from the right ------------------------------------------------- */ .custombox-slide-right .custombox-modal-content, .custombox-close.custombox-slide-bottom-right .custombox-modal-content, .custombox-close.custombox-slide-top-right .custombox-modal-content, .custombox-close.custombox-slide-center-right .custombox-modal-content { -webkit-transform: translateX(20%); -ms-transform: translateX(20%); transform: translateX(20%); opacity: 0; -webkit-transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); -ms-transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-slide-right .custombox-modal-content { -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); opacity: 1; } .custombox-close.custombox-slide-right-left .custombox-modal-content { -webkit-transform: translateX(-20%); -ms-transform: translateX(-20%); transform: translateX(-20%); } /* ------------------------------------------------- Slide from the bottom ------------------------------------------------- */ .custombox-slide-bottom .custombox-modal-content { -webkit-transform: translateY(20%); -ms-transform: translateY(20%); transform: translateY(20%); opacity: 0; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-slide-bottom .custombox-modal-content { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); opacity: 1; } .custombox-close.custombox-slide-bottom-top .custombox-modal-content { -webkit-transform: translateY(-20%); -ms-transform: translateY(-20%); transform: translateY(-20%); } /* ------------------------------------------------- Slide from the left ------------------------------------------------- */ .custombox-slide-left .custombox-modal-content, .custombox-close.custombox-slide-top-left .custombox-modal-content, .custombox-close.custombox-slide-center-left .custombox-modal-content { -webkit-transform: translateX(-20%); -ms-transform: translateX(-20%); transform: translateX(-20%); opacity: 0; -webkit-transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); -ms-transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); transition-timing-function: cubic-bezier(0.25, 0.5, 0.5, 0.9); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-slide-left .custombox-modal-content { -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); opacity: 1; } .custombox-close.custombox-slide-left-right .custombox-modal-content { -webkit-transform: translateX(20%); -ms-transform: translateX(20%); transform: translateX(20%); } /* ------------------------------------------------- Slide and stick to center ------------------------------------------------- */ .custombox-slide-center .custombox-modal-content { -webkit-transform: translateY(-200%); -ms-transform: translateY(-200%); transform: translateY(-200%); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; opacity: 0; } .custombox-show.custombox-slide-center .custombox-modal-content { -webkit-transform: translateY(0%); -ms-transform: translateY(0%); transform: translateY(0%); border-radius: 0 0 3px 3px; opacity: 1; } /* ------------------------------------------------- Newspaper ------------------------------------------------- */ .custombox-newspaper .custombox-modal-content { -webkit-transform: scale(0) rotate(720deg); -ms-transform: scale(0) rotate(720deg); transform: scale(0) rotate(720deg); opacity: 0; } .custombox-show.custombox-newspaper ~ .custombox-overlay, .custombox-newspaper .custombox-modal-content { -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-newspaper .custombox-modal-content { -webkit-transform: scale(1) rotate(0deg); -ms-transform: scale(1) rotate(0deg); transform: scale(1) rotate(0deg); opacity: 1; } /* ------------------------------------------------- Fall ------------------------------------------------- */ .custombox-fall.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-fall .custombox-modal-content { -webkit-transform-style: preserve-3d;/* 元素及子元素保持3D变换效果 */ -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: translateZ(600px) rotateX(20deg); /* translateZ正值,3D效果离用户更近,也就是更大 */ /* rotateX元素绕X轴旋转 */ -ms-transform: translateZ(600px) rotateX(20deg); transform: translateZ(600px) rotateX(20deg); opacity: 0; } .custombox-show.custombox-fall .custombox-modal-content { -webkit-transition-timing-function: ease-in; -ms-transition-timing-function: ease-in; transition-timing-function: ease-in; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; -webkit-transform: translateZ(0) rotateX(0deg); -ms-transform: translateZ(0) rotateX(0deg); transform: translateZ(0) rotateX(0deg); opacity: 1; } /* ------------------------------------------------- Side fall ------------------------------------------------- */ .custombox-sidefall.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-sidefall .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: translate(30%) translateZ(600px) rotate(10deg); -ms-transform: translate(30%) translateZ(600px) rotate(10deg); transform: translate(30%) translateZ(600px) rotate(10deg); opacity: 0; } .custombox-show.custombox-sidefall .custombox-modal-content { -webkit-transition-timing-function: ease-in; -ms-transition-timing-function: ease-in; transition-timing-function: ease-in; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; -webkit-transform: translate(0%) translateZ(0) rotate(0deg); -ms-transform: translate(0%) translateZ(0) rotate(0deg); transform: translate(0%) translateZ(0) rotate(0deg); opacity: 1; } /* ------------------------------------------------- Blur ------------------------------------------------- */ .custombox-show.custombox-blur ~ .custombox-container * { text-shadow: 0 0 5px rgba(0,0,0,0.5); color: transparent; } .custombox-show.custombox-blur ~ .custombox-container img { -webkit-filter: blur(10px); -moz-filter: blur(10px); -ms-filter: blur(10px); filter: blur(10px);/* 模糊滤镜 */ } .custombox-blur .custombox-modal-content { -webkit-transform: translateY(-5%); -ms-transform: translateY(-5%); transform: translateY(-5%); opacity: 0; } .custombox-blur .custombox-modal-content, .custombox-show.custombox-blur ~ .custombox-container { -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-blur .custombox-modal-content { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); opacity: 1; } /* ------------------------------------------------- 3D Flip horizontal ------------------------------------------------- */ .custombox-flip-horizontal.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-flip-horizontal .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: rotateY(-70deg); transform: rotateY(-70deg); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; opacity: 0; } .custombox-show.custombox-flip-horizontal .custombox-modal-content { -webkit-transform: rotateY(0deg); -ms-transform: rotateY(0deg); transform: rotateY(0deg); opacity: 1; } /* ------------------------------------------------- 3D Flip vertical ------------------------------------------------- */ .custombox-flip-vertical.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-flip-vertical .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: rotateX(-70deg); -ms-transform: rotateX(-70deg); transform: rotateX(-70deg); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; opacity: 0; } .custombox-show.custombox-flip-vertical .custombox-modal-content { -webkit-transform: rotateX(0deg); -ms-transform: rotateX(0deg); transform: rotateX(0deg); opacity: 1; } /* ------------------------------------------------- 3D Sign ------------------------------------------------- */ .custombox-sign.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-sign .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: rotateX(-60deg); -ms-transform: rotateX(-60deg); transform: rotateX(-60deg); -webkit-transform-origin: 50% 0; -ms-transform-origin: 50% 0; transform-origin: 50% 0;/* transform-origin默认是50% 50% */ opacity: 0; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-sign .custombox-modal-content { -webkit-transform: rotateX(0deg); -ms-transform: rotateX(0deg); transform: rotateX(0deg); opacity: 1; } /* ------------------------------------------------- Super scaled ------------------------------------------------- */ .custombox-superscaled .custombox-modal-content { -webkit-transform: scale(2); -ms-transform: scale(2); transform: scale(2); opacity: 0; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-superscaled .custombox-modal-content { -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1); opacity: 1; } /* ------------------------------------------------- 3D Slit ------------------------------------------------- */ .custombox-slit.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-slit .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: translateZ(-3000px) rotateY(90deg); -ms-transform: translateZ(-3000px) rotateY(90deg); transform: translateZ(-3000px) rotateY(90deg); opacity: 0; } .custombox-show.custombox-slit .custombox-modal-content { -webkit-animation: slit .7s forwards ease-out; -ms-animation: slit .7s forwards ease-out; animation: slit .7s forwards ease-out; } @-webkit-keyframes slit { 50% { -webkit-transform: translateZ(-250px) rotateY(89deg); opacity: .5; -webkit-animation-timing-function: ease-out;} 100% { -webkit-transform: translateZ(0) rotateY(0deg); opacity: 1; } } @-ms-keyframes slit { 50% { -ms-transform: translateZ(-250px) rotateY(89deg); opacity: .5; -ms-animation-timing-function: ease-out;} 100% { -ms-transform: translateZ(0) rotateY(0deg); opacity: 1; } } @keyframes slit { 50% { transform: translateZ(-250px) rotateY(89deg); opacity: 1; animation-timing-function: ease-out;} 100% { transform: translateZ(0) rotateY(0deg); opacity: 1; } } /* ------------------------------------------------- 3D Rotate from bottom ------------------------------------------------- */ .custombox-rotate-bottom.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-rotate-bottom .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: translateY(100%) rotateX(90deg); -ms-transform: translateY(100%) rotateX(90deg); transform: translateY(100%) rotateX(90deg); -webkit-transform-origin: 0 100%; -ms-transform-origin: 0 100%; transform-origin: 0 100%; opacity: 0; -webkit-transition-timing-function: ease-out; -ms-transition-timing-function: ease-out; transition-timing-function: ease-out; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-rotate-bottom .custombox-modal-content { -webkit-transform: translateY(0%) rotateX(0deg); -ms-transform: translateY(0%) rotateX(0deg); transform: translateY(0%) rotateX(0deg); opacity: 1; } /* ------------------------------------------------- 3D Rotate in from left ------------------------------------------------- */ .custombox-rotate-left.custombox-modal { -webkit-perspective: 1300px; -ms-perspective: 1300px; perspective: 1300px; } .custombox-rotate-left .custombox-modal-content { -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform: translateZ(100px) translateX(-30%) rotateY(90deg); -ms-transform: translateZ(100px) translateX(-30%) rotateY(90deg); transform: translateZ(100px) translateX(-30%) rotateY(90deg); -webkit-transform-origin: 0 100%; -ms-transform-origin: 0 100%; transform-origin: 0 100%; opacity: 0; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-rotate-left .custombox-modal-content { -webkit-transform: translateZ(0px) translateX(0%) rotateY(0deg); -ms-transform: translateZ(0px) translateX(0%) rotateY(0deg); transform: translateZ(0px) translateX(0%) rotateY(0deg); opacity: 1; } /* ------------------------------------------------- Slide in from bottom with perspective on container ------------------------------------------------- */ .custombox-show.custombox-letmein ~ .custombox-container { height: 100%; overflow: hidden; -webkit-transition-property: -webkit-transform; -ms-transition-property: -ms-transform; transition-property: transform; } .custombox-show.custombox-letmein ~ .custombox-container, .custombox-show.custombox-letmein ~ .custombox-overlay { -webkit-transform: rotateX(-2deg); -ms-transform: rotateX(-2deg); transform: rotateX(-2deg); -webkit-transform-origin: 50% 0%; -ms-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; } .custombox-letmein .custombox-modal-content { opacity: 0; -webkit-transform: translateY(200%); -ms-transform: translateY(200%); transform: translateY(200%); } .custombox-show.custombox-letmein .custombox-modal-content { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); opacity: 1; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } /* ------------------------------------------------- Slide from right with perspective on container ------------------------------------------------- */ .custombox-show.custombox-makeway ~ .custombox-container { height: 100%; overflow: hidden; } .custombox-show.custombox-makeway ~ .custombox-overlay { background: rgba(143,27,15,0.8); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-makeway ~ .custombox-container, .custombox-show.custombox-makeway ~ .custombox-overlay { -webkit-transform-style: preserve-3d; -webkit-transform-origin: 0% 50%; -webkit-animation: rotateRightSideFirst 0.5s forwards ease-in; -ms-transform-style: preserve-3d; -ms-transform-origin: 0% 50%; -ms-animation: rotateRightSideFirst 0.5s forwards ease-in; transform-style: preserve-3d; transform-origin: 0% 50%; animation: rotateRightSideFirst 0.5s forwards ease-in; } @-webkit-keyframes rotateRightSideFirst { 50% { -webkit-transform: translateZ(-50px) rotateY(5deg); -webkit-animation-timing-function: ease-out; } 100% { -webkit-transform: translateZ(-200px); } } @-ms-keyframes rotateRightSideFirst { 50% { -ms-transform: translateZ(-50px) rotateY(5deg); -ms-animation-timing-function: ease-out; } 100% { -ms-transform: translateZ(-200px); } } @keyframes rotateRightSideFirst { 50% { transform: translateZ(-50px) rotateY(5deg); animation-timing-function: ease-out; } 100% { transform: translateZ(-200px); } } .custombox-makeway .custombox-modal-content { -webkit-transform: translateX(200%); -ms-transform: translateX(200%); transform: translateX(200%); opacity: 0; } .custombox-show.custombox-makeway .custombox-modal-content { -webkit-transform: translateX(0); -ms-transform: translateX(0); transform: translateX(0); opacity: 1; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } /* ------------------------------------------------- Slip in from the top with perspective on container ------------------------------------------------- */ .custombox-show.custombox-slip ~ .custombox-container { height: 100%; overflow: hidden; } .custombox-show.custombox-slip ~ .custombox-overlay { -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; } .custombox-show.custombox-slip ~ .custombox-container, .custombox-show.custombox-slip ~ .custombox-overlay { -webkit-transform-style: preserve-3d; -webkit-transform-origin: 50% 100%; -webkit-animation: OpenTop 0.5s forwards ease-in; -ms-transform-style: preserve-3d; -ms-transform-origin: 50% 100%; -ms-animation: OpenTop 0.5s forwards ease-in; transform-style: preserve-3d; transform-origin: 50% 100%; animation: OpenTop 0.5s forwards ease-in; } @-webkit-keyframes OpenTop { 50% { -webkit-transform: rotateX(10deg); -webkit-animation-timing-function: ease-out; } } @-ms-keyframes OpenTop { 50% { -ms-transform: rotateX(10deg); -ms-animation-timing-function: ease-out; } } @keyframes OpenTop { 50% { transform: rotateX(10deg); animation-timing-function: ease-out; } } .custombox-slip .custombox-modal-content { -webkit-transform: translateY(-200%); -ms-transform: translateY(-200%); transform: translateY(-200%); opacity: 0; } .custombox-show.custombox-slip .custombox-modal-content { -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); opacity: 1; -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; }
js源码:
/** * 引入jquery同时使用原生js,其余代码的手法更像探索而不够成熟; */ /** * 用途: * 以页面元素为模板或者通过远程数据创建Dom元素,调整显示样式,实现动效显示; * 页面模板通过href以#、.开头配置,或者options.url配置; * * 实现思路: * document.createElement创建的对象包含css、style、id属性(初始时缩放样式等),赋值后插入页面; * 插件通过_create方法创建对话框包裹元素,设置css属性,进而用_box.create方法插入页面; * _box.build方法将对话框内容体插入包裹元素中,调整显示样式,添加transition-duration样式,添加custombox-show最后呈现样式; <style> .custombox-fadein .custombox-modal-content { -webkit-transform: scale(0.7); -ms-transform: scale(0.7); transform: scale(0.7); -webkit-transition-property: all; -ms-transition-property: all; transition-property: all; opacity: 0; } .custombox-show.custombox-fadein .custombox-modal-content { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } </style> <script type="text/javascript"> var dom=document.getElementsByClassName("custombox-fadein")[0]; document.getElementsByClassName("custombox-modal-content")[0].style["transition-duration"]="300ms"; setTimeout(function(){ dom.className=dom.className+" custombox-show"; },300) </script> * * 怎样使用时间戳避免多次产生实例??? */ /** * 样式:IE:div.style.fontSize="14px"; * Else:div.style.setProperty("font-size","14px"); 按情况添加-webkit-、-ms-前缀; * * document.defaultView.getComputedStyle(elems[i],null).getPropertyValue('z-index'); * * window.scrollTo(); * * document.body.insertBefore(modal, document.body.firstChild); * * 'onorientationchange'垂直或水平翻转设备时触发; * * var onCloseLaunch=new Function('onClose','return '+onClose )(onClose);同eval相似,将onClose传入函数以声名该函数; * onCloseLanch()执行,其中参数onClose是有待执行的函数声明; * 第一对括号中,首参为参数名,次参为执行的函数体;第二对括号传入具体的参数; * 事件监听和触发在此基础上写就???\ */ /* * jQuery Custombox v1.1.3 - 2014/02/18 * jQuery Modal Window Effects. * http://dixso.github.io/custombox/ * (c) 2014 Julio De La Calle - http://dixso.net - @dixso9 * * Under MIT License - http://www.opensource.org/licenses/mit-license.php */ // the semi-colon before function invocation is a safety net against concatenated // scripts and/or other plugins which may not be closed properly. ;(function ( $, window, document, undefined ) { "use strict"; // undefined is used here as the undefined global variable in ECMAScript 3 is // mutable (ie. it can be changed by someone else). undefined isn't really being // passed in so we can ensure the value of it is truly undefined. In ES5, undefined // can no longer be modified. // window and document are passed through as local variable rather than global // as this (slightly) quickens the resolution process and can be more efficiently // minified (especially when both are regularly referenced in your plugin). // Create the defaults once. var cb = 'custombox', defaults = { url: null, // Set the URL, ID or Class. // 当url以#或.开头时,以页面上的某个元素作为模板渲染对话框 cache: false, // If set to false, it will force requested pages not to be cached by the browser only when send by AJAX. escKey: true, // Allows the user to close the modal by pressing 'ESC'. eClose: null, // Element ID or Class for to be close the modal. zIndex: 9999, // Overlay z-index: Number or auto. overlay: true, // Show the overlay. overlayColor: '#000', // Overlay color. overlayOpacity: 0.8, // The overlay opacity level. Range: 0 to 1. overlayClose: true, // Allows the user to close the modal by clicking the overlay. overlaySpeed: 200, // Sets the speed of the overlay, in milliseconds. customClass: null, // Custom class to modal. width: null, // Set a fixed total width. height: null, // Set a fixed total height. effect: 'fadein', // fadein | slide | newspaper | fall | sidefall | blur | flip | sign | superscaled | slit | rotate | letmein | makeway | slip | blur. position: null, // Only with effects: slide, flip and rotate. (top, right, bottom, left and center) | (vertical or horizontal) and output position sseparated by commas. Ex: 'top, bottom'. speed: 600, // Sets the speed of the transitions, in milliseconds. open: null, // Callback that fires right before begins to open. complete: null, // Callback that fires right after loaded content is displayed. close: null, // Callback that fires once is closed. responsive: true, // Sets if you like box responsive or not. scrollbar: false, // Show scrollbar or hide automatically. error: 'Error 404!' // Text to be displayed when there is an error. }; // The plugin constructor. function Plugin ( element, options ) { this.element = element; // Get the max zIndex. if ( typeof this.element === 'object' && typeof options === 'object' && isNaN( options.zIndex ) && options.zIndex === 'auto' ) { options.zIndex = ( this._isIE() ? defaults.zIndex : this._zIndex() ); } // Merge objects. this.settings = this._extend( {}, defaults, options ); if ( typeof this.element === 'object' ) { // Private method. this._box.init( this ); } else { // Public method. this[this.element](); } } Plugin.prototype = { /* ---------------------------- Private methods ---------------------------- */ /* * _overlay创建灰色浮层; * _box.init根据setting.url或者调用ajax方式,或者以某元素为模板,或者直接创建错误提示对话框; * _box.create创建对话框包裹元素modal、内容体content,插入到页面尾部; 包裹元素modal添加自定义样式类setting.customClass,调用_box.effect方法添加动效样式; 内容体content添加动效持续时间transition-duration:obj.settings.speed+'ms'; 根据settings.overlay配置调用_overlay添加灰色浮层面板; 返回包裹元素modal、内容体content,数组形式; * _box.effect根据setting.effect、effect.position获取动效样式; newspaper、fall、sidefall、blur、sign、superscaled、slit、letmein、makeway、slip、blur动效返回custombox-[effect]; slide、flip、rotate返回custombox-slide-top或custombox-slide-top custombox-slide-top; letmein、makeway、slip、blur需要将body内元素添加到custombox-container容器中,letmein、makeway、slip需要给html添加perspective样式; 效果是实现整个页面的缩放、或者页面显出翻页效果; * _box.build将对话框内容体插入包裹元素中,并调整对话框内容体的宽度、是否显示滚动条等样式信息,并绑定事件; * _box.responsive(obj,tmp,modal,wsize)响应式调整对话框尺寸,wsize是屏幕的尺寸; * _box.ajax获取远程数据,以responseText为文本创建div,调用_box.build渲染后显示; * _close重置对话框样式,触发setting.close函数执行; * _listeners绑定对话框关闭事件,点击灰色浮层关闭、esc关闭、某元素关闭; * setting.close函数该函数赋值给data属性以供_close方法调用该函数; */ _overlay: function() { var rgba = this._hexToRgb(this.settings.overlayColor), styles = {}; // Only IE 8 if ( navigator.appVersion.indexOf('MSIE 8.') != -1 ) { styles.backgroundColor = this.settings.overlayColor; styles.zIndex = parseFloat(this.settings.zIndex) + 1; styles.filter = 'alpha(opacity=' + this.settings.overlayOpacity * 100 + ')'; } else { styles['background-color'] = 'rgba(' + rgba.r + ',' + rgba.g + ', ' + rgba.b + ',' + this.settings.overlayOpacity + ')'; styles['z-index'] = parseFloat(this.settings.zIndex) + 1; styles['transition'] = 'all ' + this.settings.overlaySpeed / 1000 + 's'; } document.getElementsByTagName('body')[0].appendChild(this._create({ id: 'overlay', eClass: 'overlay' }, styles)); }, _box: { init: function ( obj ) { // Check if callback 'open'. if ( obj.settings.open && typeof obj.settings.open === 'function' ) { obj.settings.open( undefined !== arguments[0] ? arguments[0] : '' ); } // Check 'href'. if ( obj.settings.url === null ) { if ( obj.element !== null ) { obj.settings.url = obj.element.getAttribute('href'); } } if ( typeof obj.settings.url === 'string' ) { if ( obj.settings.url.charAt(0) === '#' || obj.settings.url.charAt(0) === '.' ) { // Inline. if ( document.querySelector(obj.settings.url) ) { obj._box.build( obj, document.querySelector(obj.settings.url).cloneNode(true) ); } else { obj._box.build( obj, null ); } } else { // Ajax. this.ajax( obj ); } } else { obj._box.build( obj, null ); } }, create: function ( obj ) { var styles = {}; if ( obj._isIE() ) { styles.zIndex = parseFloat(obj.settings.zIndex) + 2; } else { styles['z-index'] = parseFloat(obj.settings.zIndex) + 2; } var modal = obj._create({ id: 'modal', eClass: 'modal ' + obj._box.effect( obj ) + ( obj.settings.customClass ? ' ' + obj.settings.customClass : '' ) }, styles), content = obj._create({ id: 'modal-content', eClass: 'modal-content' }, { 'transition-duration': obj.settings.speed + 'ms' }); // Insert modal to the content. modal.appendChild(content); // Insert modal just after the body. document.body.insertBefore(modal, document.body.firstChild); // Create overlay after the modal content. if ( obj.settings.overlay ) { obj._overlay(); } return [modal, content]; }, effect: function ( obj ) { var position = ['slide','flip','rotate'], perspective = ['letmein','makeway','slip','blur'], effect = cb + '-' + obj.settings.effect, effectClose = ''; // Check if is array. if ( obj.settings.position !== null && obj.settings.position.indexOf(',') !== -1 ) { // Convert the string to array. obj.settings.position = obj.settings.position.split(','); if( obj.settings.position.length > 1 ) { effectClose = ' ' + cb + '-' + obj.settings.effect + '-' + obj.settings.position[0].replace(/^\s+|\s+$/g, '') + '-' + obj.settings.position[1].replace(/^\s+|\s+$/g, ''); } } // Position. for ( var i = 0, len1 = position.length; i < len1; i++ ) { if ( position[i] === obj.settings.effect ) { effect = cb + '-' + obj.settings.effect + '-' + ( effectClose !== '' ? obj.settings.position[0] : obj.settings.position ) + effectClose; } } // HTML head. for ( var x = 0, len2 = perspective.length; x < len2; x++ ) { if ( perspective[x] === obj.settings.effect ) { if ( obj.settings.effect !== 'blur' ) { // Add class. obj._addClass( document.getElementsByTagName( 'html' )[0], 'perspective' ); } var div = document.createElement('div'); div.className = cb + '-container'; // Move the body's children into this wrapper while ( document.body.firstChild ) { div.appendChild(document.body.firstChild); } // Append the wrapper to the body document.body.appendChild(div); } } return effect; }, build: function ( obj, modal ) { var body = document.body, html = document.documentElement, top = ( html && html.scrollTop || body && body.scrollTop || 0 ); if ( obj.settings.error !== false && typeof obj.settings.error === 'string' ) { // If is null, show message error. if ( modal === null ) { modal = document.createElement('div'); obj._addClass( modal, 'error' ); modal.innerHTML = obj.settings.error; } // [0] => modal // [1] => content var tmp = obj._box.create( obj ); // Insert content to the modal. tmp[1].appendChild(modal); // Show the content. modal.style.display = 'block'; // Set scroll. tmp[0].setAttribute('data-' + cb + '-scroll', top); // Temporal sizes. var tmpSize = { width: parseInt(obj.settings.width, 0), height: parseInt(obj.settings.height, 0) }; // Check width: If it is a number and if not null. if ( !isNaN( tmpSize.width ) && tmpSize.width === obj.settings.width && tmpSize.width.toString() === obj.settings.width.toString() && tmpSize.width !== null ) { modal.style.width = tmpSize.width + 'px'; } // Check height: If it is a number and if not null. if ( !isNaN( tmpSize.height ) && tmpSize.height === obj.settings.height && tmpSize.height.toString() === obj.settings.height.toString() && tmpSize.height !== null ) { modal.style.height = tmpSize.height + 'px'; } var offw = modal.offsetWidth, position = { 'margin-left': - offw / 2 + 'px', 'width': offw + 'px' }; // IE8 not supported: translateY(-50%). if ( obj._isIE() ) { var offh = modal.offsetHeight; position['margin-top'] = - offh / 2 + 'px'; position['height'] = offh + 'px'; } // If position top? if ( obj.settings.position !== null && obj.settings.position.indexOf('top') !== -1 ) { position['transform'] = 'none'; } // Center modal. obj._create( {}, position, tmp[0] ); // Check if scrollbar is visible. var wsize = { width: 'innerWidth' in window ? window.innerWidth : document.documentElement.offsetWidth, height: 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight }; if ( !obj.settings.scrollbar ) { if ( modal.offsetHeight < wsize.height && body.offsetHeight > wsize.height ) { var outer = obj._create({},{ visibility: 'hidden', width: '100px' }); // Append outer. body.appendChild(outer); // Save the width without scrollbar. var widthNoScroll = outer.offsetWidth; // Force scrollbars outer.style.overflow = 'scroll'; // Add inner div. var inner = obj._create({},{ width: '100%' }); // Append inner. outer.appendChild(inner); // Save the width with scrollbar. var widthWithScroll = inner.offsetWidth; // Remove divs outer.parentNode.removeChild(outer); // Hide scrollbar. body.style.marginRight = widthNoScroll - widthWithScroll + 'px'; obj._addClass( document.getElementsByTagName( 'html' )[0], 'hide-scrollbar' ); } else { obj._scrollbar(tmp[0]); } } else { obj._scrollbar(tmp[0]); } // Launch responsive. if ( obj.settings.responsive ) { obj._box.responsive(obj, tmp, modal, wsize); } // Show modal. setTimeout( function () { // Init listeners. obj._listeners( top ); // Show modal. tmp[0].className += ' ' + cb + '-show'; var script = tmp[1].getElementsByTagName('script'); // Execute the scripts. for ( var i = 0, len = script.length; i < len; i++ ) { new Function( script[i].text )(); } if ( window.attachEvent ) { setTimeout( function () { // Check if callback 'complete'. if ( obj.settings.complete && typeof obj.settings.complete === 'function' ) { obj.settings.complete( undefined !== arguments[0] ? arguments[0] : '' ); } }, obj.settings.speed ); } else { var stop = true; tmp[0].addEventListener(obj._crossBrowser(), function () { if ( stop ) { stop = false; // Check if callback 'complete'. if ( obj.settings.complete && typeof obj.settings.complete === 'function' ) { obj.settings.complete( undefined !== arguments[0] ? arguments[0] : '' ); } } }, false); } }, ( obj.settings.overlay ? obj.settings.overlaySpeed : 200 ) ); } }, responsive: function ( obj, tmp, modal, wsize ) { // Store width. modal.setAttribute('data-' + cb + '-width', modal.offsetWidth); // Prepare responsive. obj._create( {}, { width: 'auto' }, modal ); // The first time. if ( wsize.width < modal.offsetWidth ) { obj._create( {}, { width: wsize.width - 40 + 'px', 'margin-left': '20px', 'margin-right': '20px', 'left': 0 }, tmp[0] ); } var supportsOrientationChange = 'onorientationchange' in window, orientationEvent = supportsOrientationChange ? 'orientationchange' : 'resize'; if ( window.attachEvent ) { window.attachEvent(orientationEvent, function () { modalResize(this); }, false); } else { window.addEventListener(orientationEvent, function () { modalResize(this); }, false); } var modalResize = function ( e ) { if ( typeof window.orientation === 'undefined' ) { if ( modal.getAttribute('data-' + cb + '-width') !== null ) { var wm = modal.getAttribute('data-' + cb + '-width'); if ( wm > e.innerWidth ) { obj._create( {}, { width: e.innerWidth - 40 + 'px', 'margin-left': '20px', 'margin-right': '20px', left: 0 }, tmp[0] ); } else { obj._create( {}, { width: wm + 'px', 'margin-left': - wm / 2 + 'px', 'left': '50%' }, tmp[0] ); } } } else { obj._create( null, { width: e.innerWidth - 40 + 'px', 'margin-left': '20px', 'margin-right': '20px', left: 0 }, tmp[0] ); } }; }, ajax: function ( obj ) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () {// 有关ajax的事件监听等机理??? var completed = 4; if( xhr.readyState === completed ) { if( xhr.status === 200 ) { var modal = document.createElement('div'); modal.innerHTML = xhr.responseText; obj._box.build( obj, modal ); } else { obj._box.build( obj, null ); } } }; xhr.open('GET', obj.settings.url + ( !obj.settings.cache ? '?_=' + new Date().getTime() : '' ), true); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(null); } }, _close: function () { var obj = this; // Clean custombox. setTimeout(function () { // Remove classes. obj._removeClass( document.getElementsByTagName( 'html' )[0], cb + '-hide-scrollbar' ); // Reset properties scrollbar. document.getElementsByTagName( 'body' )[0].style.marginRight = 0; // Remove modal. var modal = ( obj._isIE() ? document.querySelectorAll('.' + cb + '-modal')[0] : document.getElementsByClassName(cb + '-modal')[0] ); obj._remove( modal ); // Remove overlay. if ( obj.settings.overlay ) { obj._remove( ( obj._isIE() ? document.querySelectorAll('.' + cb + '-overlay')[0] : document.getElementsByClassName(cb + '-overlay')[0] ) ); } // Check if callback 'close'. if ( obj.settings.close && typeof obj.settings.close === 'function' ) { obj.settings.close( undefined !== arguments[0] ? arguments[0] : '' ); } else if ( typeof modal !== 'undefined' && modal.getAttribute('data-' + cb) !== null ) { // Check if callback 'close' when the method is public. var onClose = modal.getAttribute('data-' + cb), onCloseLaunch = new Function ( 'onClose', 'return ' + onClose )(onClose); onCloseLaunch(); } // Go to te last position scroll. window.top.scroll( 0, modal.getAttribute('data-' + cb + '-scroll') ); }, obj.settings.speed ); // Add class close for animation close. obj._addClass( ( obj._isIE() ? document.querySelectorAll('.' + cb + '-modal')[0] : document.getElementsByClassName(cb + '-modal')[0] ), 'close' ); // Remove the remaining classes. obj._removeClass( ( obj._isIE() ? document.querySelectorAll('.' + cb + '-modal')[0] : document.getElementsByClassName(cb + '-modal')[0] ), cb + '-show' ); obj._removeClass( document.getElementsByTagName( 'html' )[0], cb + '-perspective' ); }, _listeners: function () { var obj = this; // Listener overlay. if ( obj._isIE() ) { if ( typeof document.querySelectorAll('.' + cb + '-overlay')[0] !== 'undefined' && obj.settings.overlayClose ) { document.querySelectorAll('.' + cb + '-overlay')[0].attachEvent('onclick', function () { obj._close(); }); } } else { if ( typeof document.getElementsByClassName(cb + '-overlay')[0] !== 'undefined' && obj.settings.overlayClose ) { document.getElementsByClassName(cb + '-overlay')[0].addEventListener('click', function () { obj._close(); }, false ); } } // Listener on tab key esc. if ( obj.settings.escKey ) { document.onkeydown = function ( evt ) { evt = evt || window.event; if ( evt.keyCode === 27 ) { obj._close(); } }; } // Listener on element close. if ( obj.settings.eClose !== null && typeof obj.settings.eClose === 'string' && obj.settings.eClose.charAt(0) === '#' || typeof obj.settings.eClose === 'string' && obj.settings.eClose.charAt(0) === '.' && document.querySelector(obj.settings.eClose) ) { document.querySelector(obj.settings.eClose).addEventListener('click', function () { obj._close(); }, false ); } // Check if callback 'close'. if ( obj.settings.close && typeof obj.settings.close === 'function' ) { var store = obj.settings.close; var modal = ( obj._isIE() ? document.querySelectorAll('.' + cb + '-modal')[0] : document.getElementsByClassName(cb + '-modal')[0] ); modal.setAttribute('data-' + cb, store); } }, /* ---------------------------- Utilities ---------------------------- _extend()扩展对象,无深拷贝功能; _create(attr,styles,element)创建元素或为已存在的元素添加attr.id、attr.class,以及具体的样式; _hexToRgb(hex)将rgb代码值转化r、g、b值,16进制; _addClass(element,calss)添加样式; _removeClass(element,calss)移除样式; _hasClass(element,calss)有否样式; _remove(element)移除元素; _zIndex获取dom元素最大的z-index值; _isIE判断是否IE浏览器; _crossBrowser通过能力检测获取浏览器的transitionend或webkitTransitionEnd属性; _scrollbar(modal)调用_create方法为modal元素根据setting.position设置绝对定位、top、margin-top属性; */ _extend: function () { for( var i = 1, arg = arguments.length; i < arg; i++ ) { for( var key in arguments[i] ) { if( arguments[i].hasOwnProperty(key) ) { arguments[0][key] = arguments[i][key]; } } } return arguments[0]; }, _create: function ( attr, styles, element ) { var div = ( element === undefined || element === null ? document.createElement('div') : element ); // Compatibility ECMAScript 5 Objects and Properties. Object.keys = Object.keys || function( o ) { var result = []; for ( var name in o ) { if ( o.hasOwnProperty(name) ) { result.push(name); } } return result; }; if ( attr !== null && Object.keys(attr).length !== 0 ) { // Add the id. if ( attr.id !== null ) { div.id = cb + '-' + attr.id; } // Add the class. if ( attr.eClass !== null ) { this._addClass( div, attr.eClass ); } } if ( styles !== null ) { // Loop with styles (obj). for ( var obj in styles ) { if ( styles.hasOwnProperty(obj) ) { // Insert browser dependent styles. if ( this._isIE() ) { var camelCase = obj.split('-'); if ( camelCase.length > 1 ) { camelCase = camelCase[0] + camelCase[1].replace(/(?:^|\s)\w/g, function( match ) { return match.toUpperCase(); }); } div.style[camelCase] = styles[obj]; } else { div.style.setProperty( obj, styles[obj], null ); } if ( ( obj.indexOf('transition') !== -1 || obj === 'transform' !== -1 ) && !this._isIE() ) { var prefix = [ '-webkit-', '-ms-']; // Insert prefix. for ( var x = 0, pre = prefix.length; x < pre; x++ ) { div.style.setProperty( prefix[x] + obj, styles[obj], null ); } } } } } return div; }, _hexToRgb: function ( hex ) { // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; }); var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; }, _addClass: function ( element, eClass ) { if ( !this._hasClass( element, eClass ) ) { element.className = ( element.className.length && element.className !== ' ' ? element.className + ' ' + cb + '-' + eClass : cb + '-' + eClass ); } }, _removeClass: function ( element, eClass ) { if ( this._hasClass( element, eClass ) ) { var reg = new RegExp('(\\s|^)' + eClass + '(\\s|$)'); element.className = element.className.replace(reg,' '); } }, _hasClass: function ( element, eClass ) { return ( element !== undefined ? element.className.match(new RegExp('(\\s|^)' + eClass + '(\\s|$)')) : false ); }, _remove: function ( element ) { if ( element !== undefined ) { element.parentNode.removeChild(element); } }, _zIndex: function () { var d = document, elems = d.getElementsByTagName('*'), zIndexMax = 0; for ( var i = 0, etotal = elems.length; i < etotal; i++ ) { var zindex = d.defaultView.getComputedStyle(elems[i],null).getPropertyValue('z-index'); if ( zindex > zIndexMax && zindex !== 'auto' ) { zIndexMax = zindex; } } return zIndexMax; }, _isIE: function () { return navigator.appVersion.indexOf('MSIE 9.') != -1 || navigator.appVersion.indexOf('MSIE 8.') != -1; }, _crossBrowser: function () { var el = document.createElement('fakeelement'), transitions = { transition: 'transitionend', WebkitTransition: 'webkitTransitionEnd' }, transition; // Check transition. for( var t in transitions ) { if ( transitions.hasOwnProperty(t) && el.style[t] !== undefined ) { transition = transitions[t]; } } return transition; }, _scrollbar: function ( modal ) { var obj = this; // Go to te last position scroll. setTimeout( function () { window.scrollTo( 0, 0 ); }, ( obj.settings.overlay ? obj.settings.overlaySpeed : 200 ) ); var position = { 'position': 'absolute' }; if ( obj.settings.position !== null && obj.settings.position.indexOf('top') !== -1 ) { position['top'] = 0; position['margin-top'] = '20px'; } // Change property position obj._create( {}, position, modal ); }, /* ---------------------------- Public methods ---------------------------- */ close: function () { this._close(); } }; // A really lightweight plugin wrapper around the constructor, // preventing against multiple instantiations with jQuery. $.fn[ cb ] = function ( options ) { var args = arguments, isElement = typeof HTMLElement === 'object' ? options instanceof HTMLElement : options && typeof options === 'object' && options !== null && options.nodeType === 1 && typeof options.nodeName === 'string'; if ( options === undefined || typeof options === 'object' ) { if ( isElement ) { if ( navigator.appName === 'Microsoft Internet Explorer' ) { // Write a new regEx to find the version number. var re = new RegExp('MSIE ([0-9]{1,}[.0-9]{0,})'); // If the regEx through the userAgent is not null. if ( re.exec(navigator.userAgent) != null ) { //Set the IE version var version = parseInt(RegExp.$1); } } if ( typeof version === 'undefined' || version >= 10 ) { // Check time to avoid double click. if ( options.getAttribute('data-' + cb) !== null && parseInt(options.getAttribute('data-' + cb)) + 1 > Math.round( new Date().getTime() / 1000 ) ) { return; } // Set time to avoid double click. options.setAttribute('data-' + cb, Math.round( new Date().getTime() / 1000 ) ); } $(options).each( function () { $.data( this, cb, new Plugin( this, args[1] ) ); }); } else { new Plugin( null, args[0] ); } } else if ( typeof options === 'string' && options === 'close' ) { $.data( this, cb, new Plugin( args[0], args[1] ) ); } }; })( jQuery, window, document );