diff --git a/static/layui/css/layui.css b/static/layui/css/layui.css new file mode 100644 index 0000000..a8085e6 --- /dev/null +++ b/static/layui/css/layui.css @@ -0,0 +1,1525 @@ + +/** + * Layui + * Classic modular Front-End UI library + * MIT Licensed + */ + + +/** 初始化 **/ +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,input,button,textarea,p,blockquote,th,td,form,pre{margin: 0; padding: 0; -webkit-tap-highlight-color:rgba(0,0,0,0);} +a:active,a:hover{outline:0} +img{display: inline-block; border: none; vertical-align: middle;} +li{list-style:none;} +table{border-collapse: collapse; border-spacing: 0;} +h1,h2,h3{font-weight: 400;} +h4, h5, h6{font-size: 100%; font-weight: 400;} +button,input,select,textarea{font-size: 100%; } +input,button,textarea,select,optgroup,option{font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; outline: 0;} +pre{white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;} + +/** 初始化全局标签 **/ +body{line-height: 1.6; color: #333; color: rgba(0,0,0,.85); font: 14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;} +hr{height: 0; line-height: 0; margin: 10px 0; padding: 0; border: none!important; border-bottom: 1px solid #eee !important; clear: both; overflow: hidden; background: none;} +a{color: #333; text-decoration:none;} +a:hover{color: #777;} +a cite{font-style: normal; *cursor:pointer;} + +/** 基础通用 **/ +.layui-border-box, .layui-border-box *{box-sizing: border-box;} +/* 消除第三方ui可能造成的冲突 */.layui-box, .layui-box *{box-sizing: content-box;} +.layui-clear{clear: both; *zoom: 1;} +.layui-clear:after{content:'\20'; clear:both; *zoom:1; display:block; height:0;} +.layui-inline{position: relative; display: inline-block; *display:inline; *zoom:1; vertical-align: middle;} +/* 三角形 */.layui-edge{position: relative; display: inline-block; vertical-align: middle; width: 0; height: 0; border-width: 6px; border-style: dashed; border-color: transparent; overflow: hidden;} +.layui-edge-top{top: -4px; border-bottom-color: #999; border-bottom-style: solid;} +.layui-edge-right{border-left-color: #999; border-left-style: solid;} +.layui-edge-bottom{top: 2px; border-top-color: #999; border-top-style: solid;} +.layui-edge-left{border-right-color: #999; border-right-style: solid;} +/* 单行溢出省略 */.layui-elip{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} +/* 屏蔽选中 */.layui-unselect,.layui-icon, .layui-disabled{-moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} +/* 禁用 */.layui-disabled,.layui-disabled:hover{color: #d2d2d2 !important; cursor: not-allowed !important;} +/* 纯圆角 */.layui-circle{border-radius: 100%;} +.layui-show{display: block !important;} +.layui-hide{display: none !important;} +.layui-show-v{visibility: visible !important;} +.layui-hide-v{visibility: hidden !important;} + +/** 图标字体 **/ +@font-face { + font-family: 'layui-icon'; + src: url('../font/iconfont.eot?v=256'); + src: url('../font/iconfont.eot?v=256#iefix') format('embedded-opentype'), + url('../font/iconfont.woff2?v=256') format('woff2'), + url('../font/iconfont.woff?v=256') format('woff'), + url('../font/iconfont.ttf?v=256') format('truetype'), + url('../font/iconfont.svg?v=256#layui-icon') format('svg'); +} + +.layui-icon{ + font-family:"layui-icon" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* font-class */ +.layui-icon-reply-fill:before{content:"\e611"} +.layui-icon-set-fill:before{content:"\e614"} +.layui-icon-menu-fill:before{content:"\e60f"} +.layui-icon-search:before{content:"\e615"} +.layui-icon-share:before{content:"\e641"} +.layui-icon-set-sm:before{content:"\e620"} +.layui-icon-engine:before{content:"\e628"} +.layui-icon-close:before{content:"\1006"} +.layui-icon-close-fill:before{content:"\1007"} +.layui-icon-chart-screen:before{content:"\e629"} +.layui-icon-star:before{content:"\e600"} +.layui-icon-circle-dot:before{content:"\e617"} +.layui-icon-chat:before{content:"\e606"} +.layui-icon-release:before{content:"\e609"} +.layui-icon-list:before{content:"\e60a"} +.layui-icon-chart:before{content:"\e62c"} +.layui-icon-ok-circle:before{content:"\1005"} +.layui-icon-layim-theme:before{content:"\e61b"} +.layui-icon-table:before{content:"\e62d"} +.layui-icon-right:before{content:"\e602"} +.layui-icon-left:before{content:"\e603"} +.layui-icon-cart-simple:before{content:"\e698"} +.layui-icon-face-cry:before{content:"\e69c"} +.layui-icon-face-smile:before{content:"\e6af"} +.layui-icon-survey:before{content:"\e6b2"} +.layui-icon-tree:before{content:"\e62e"} +.layui-icon-ie:before{content:"\e7bb"} +.layui-icon-upload-circle:before{content:"\e62f"} +.layui-icon-add-circle:before{content:"\e61f"} +.layui-icon-download-circle:before{content:"\e601"} +.layui-icon-templeate-1:before{content:"\e630"} +.layui-icon-util:before{content:"\e631"} +.layui-icon-face-surprised:before{content:"\e664"} +.layui-icon-edit:before{content:"\e642"} +.layui-icon-speaker:before{content:"\e645"} +.layui-icon-down:before{content:"\e61a"} +.layui-icon-file:before{content:"\e621"} +.layui-icon-layouts:before{content:"\e632"} +.layui-icon-rate-half:before{content:"\e6c9"} +.layui-icon-add-circle-fine:before{content:"\e608"} +.layui-icon-prev-circle:before{content:"\e633"} +.layui-icon-read:before{content:"\e705"} +.layui-icon-404:before{content:"\e61c"} +.layui-icon-carousel:before{content:"\e634"} +.layui-icon-help:before{content:"\e607"} +.layui-icon-code-circle:before{content:"\e635"} +.layui-icon-windows:before{content:"\e67f"} +.layui-icon-water:before{content:"\e636"} +.layui-icon-username:before{content:"\e66f"} +.layui-icon-find-fill:before{content:"\e670"} +.layui-icon-about:before{content:"\e60b"} +.layui-icon-location:before{content:"\e715"} +.layui-icon-up:before{content:"\e619"} +.layui-icon-pause:before{content:"\e651"} +.layui-icon-date:before{content:"\e637"} +.layui-icon-layim-uploadfile:before{content:"\e61d"} +.layui-icon-delete:before{content:"\e640"} +.layui-icon-play:before{content:"\e652"} +.layui-icon-top:before{content:"\e604"} +.layui-icon-firefox:before{content:"\e686"} +.layui-icon-friends:before{content:"\e612"} +.layui-icon-refresh-3:before{content:"\e9aa"} +.layui-icon-ok:before{content:"\e605"} +.layui-icon-layer:before{content:"\e638"} +.layui-icon-face-smile-fine:before{content:"\e60c"} +.layui-icon-dollar:before{content:"\e659"} +.layui-icon-group:before{content:"\e613"} +.layui-icon-layim-download:before{content:"\e61e"} +.layui-icon-picture-fine:before{content:"\e60d"} +.layui-icon-link:before{content:"\e64c"} +.layui-icon-diamond:before{content:"\e735"} +.layui-icon-log:before{content:"\e60e"} +.layui-icon-key:before{content:"\e683"} +.layui-icon-rate-solid:before{content:"\e67a"} +.layui-icon-fonts-del:before{content:"\e64f"} +.layui-icon-unlink:before{content:"\e64d"} +.layui-icon-fonts-clear:before{content:"\e639"} +.layui-icon-triangle-r:before{content:"\e623"} +.layui-icon-circle:before{content:"\e63f"} +.layui-icon-radio:before{content:"\e643"} +.layui-icon-align-center:before{content:"\e647"} +.layui-icon-align-right:before{content:"\e648"} +.layui-icon-align-left:before{content:"\e649"} +.layui-icon-loading-1:before{content:"\e63e"} +.layui-icon-return:before{content:"\e65c"} +.layui-icon-fonts-strong:before{content:"\e62b"} +.layui-icon-upload:before{content:"\e67c"} +.layui-icon-dialogue:before{content:"\e63a"} +.layui-icon-video:before{content:"\e6ed"} +.layui-icon-headset:before{content:"\e6fc"} +.layui-icon-cellphone-fine:before{content:"\e63b"} +.layui-icon-add-1:before{content:"\e654"} +.layui-icon-face-smile-b:before{content:"\e650"} +.layui-icon-fonts-html:before{content:"\e64b"} +.layui-icon-screen-full:before{content:"\e622"} +.layui-icon-form:before{content:"\e63c"} +.layui-icon-cart:before{content:"\e657"} +.layui-icon-camera-fill:before{content:"\e65d"} +.layui-icon-tabs:before{content:"\e62a"} +.layui-icon-heart-fill:before{content:"\e68f"} +.layui-icon-fonts-code:before{content:"\e64e"} +.layui-icon-ios:before{content:"\e680"} +.layui-icon-at:before{content:"\e687"} +.layui-icon-fire:before{content:"\e756"} +.layui-icon-set:before{content:"\e716"} +.layui-icon-fonts-u:before{content:"\e646"} +.layui-icon-triangle-d:before{content:"\e625"} +.layui-icon-tips:before{content:"\e702"} +.layui-icon-picture:before{content:"\e64a"} +.layui-icon-more-vertical:before{content:"\e671"} +.layui-icon-bluetooth:before{content:"\e689"} +.layui-icon-flag:before{content:"\e66c"} +.layui-icon-loading:before{content:"\e63d"} +.layui-icon-fonts-i:before{content:"\e644"} +.layui-icon-refresh-1:before{content:"\e666"} +.layui-icon-rmb:before{content:"\e65e"} +.layui-icon-addition:before{content:"\e624"} +.layui-icon-home:before{content:"\e68e"} +.layui-icon-time:before{content:"\e68d"} +.layui-icon-user:before{content:"\e770"} +.layui-icon-notice:before{content:"\e667"} +.layui-icon-chrome:before{content:"\e68a"} +.layui-icon-edge:before{content:"\e68b"} +.layui-icon-login-weibo:before{content:"\e675"} +.layui-icon-voice:before{content:"\e688"} +.layui-icon-upload-drag:before{content:"\e681"} +.layui-icon-login-qq:before{content:"\e676"} +.layui-icon-snowflake:before{content:"\e6b1"} +.layui-icon-heart:before{content:"\e68c"} +.layui-icon-logout:before{content:"\e682"} +.layui-icon-file-b:before{content:"\e655"} +.layui-icon-template:before{content:"\e663"} +.layui-icon-transfer:before{content:"\e691"} +.layui-icon-auz:before{content:"\e672"} +.layui-icon-console:before{content:"\e665"} +.layui-icon-app:before{content:"\e653"} +.layui-icon-prev:before{content:"\e65a"} +.layui-icon-website:before{content:"\e7ae"} +.layui-icon-next:before{content:"\e65b"} +.layui-icon-component:before{content:"\e857"} +.layui-icon-android:before{content:"\e684"} +.layui-icon-more:before{content:"\e65f"} +.layui-icon-login-wechat:before{content:"\e677"} +.layui-icon-shrink-right:before{content:"\e668"} +.layui-icon-spread-left:before{content:"\e66b"} +.layui-icon-camera:before{content:"\e660"} +.layui-icon-note:before{content:"\e66e"} +.layui-icon-refresh:before{content:"\e669"} +.layui-icon-female:before{content:"\e661"} +.layui-icon-male:before{content:"\e662"} +.layui-icon-screen-restore:before{content:"\e758"} +.layui-icon-password:before{content:"\e673"} +.layui-icon-senior:before{content:"\e674"} +.layui-icon-theme:before{content:"\e66a"} +.layui-icon-tread:before{content:"\e6c5"} +.layui-icon-praise:before{content:"\e6c6"} +.layui-icon-star-fill:before{content:"\e658"} +.layui-icon-rate:before{content:"\e67b"} +.layui-icon-template-1:before{content:"\e656"} +.layui-icon-vercode:before{content:"\e679"} +.layui-icon-service:before{content:"\e626"} +.layui-icon-cellphone:before{content:"\e678"} +.layui-icon-print:before{content:"\e66d"} +.layui-icon-cols:before{content:"\e610"} +.layui-icon-wifi:before{content:"\e7e0"} +.layui-icon-export:before{content:"\e67d"} +.layui-icon-rss:before{content:"\e808"} +.layui-icon-slider:before{content:"\e714"} +.layui-icon-email:before{content:"\e618"} +.layui-icon-subtraction:before{content:"\e67e"} +.layui-icon-mike:before{content:"\e6dc"} +.layui-icon-light:before{content:"\e748"} +.layui-icon-gift:before{content:"\e627"} +.layui-icon-mute:before{content:"\e685"} +.layui-icon-reduce-circle:before{content:"\e616"} +.layui-icon-music:before{content:"\e690"} + +/* 基本布局 */ +.layui-main{position: relative; width: 1140px; margin: 0 auto;} +.layui-header{position: relative; z-index: 1000; height: 60px;} +.layui-header a:hover{transition: all .5s; -webkit-transition: all .5s;} +.layui-side{position: fixed; left: 0; top: 0; bottom: 0; z-index: 999; width: 200px; overflow-x: hidden;} +.layui-side-scroll{position: relative; width: 220px; height: 100%; overflow-x: hidden;} +.layui-body{position: relative; left: 200px; right: 0; top: 0; bottom: 0; z-index: 900; width: auto; box-sizing: border-box;} + +/* 后台框架大布局 */ +.layui-layout-body{overflow-x: hidden;} +.layui-layout-admin .layui-header{position: fixed; top: 0; left: 0; right: 0; background-color: #23262E;} +.layui-layout-admin .layui-side{top: 60px; width: 200px; overflow-x: hidden;} +.layui-layout-admin .layui-body{position: absolute; top: 60px; padding-bottom: 44px;} +.layui-layout-admin .layui-main{width: auto; margin: 0 15px;} +.layui-layout-admin .layui-footer{position: fixed; left: 200px; right: 0; bottom: 0; z-index: 990; height: 44px; line-height: 44px; padding: 0 15px; box-shadow: -1px 0 4px rgb(0 0 0 / 12%); background-color: #FAFAFA;} +.layui-layout-admin .layui-logo{position: absolute; left: 0; top: 0; width: 200px; height: 100%; line-height: 60px; text-align: center; color: #009688; font-size: 16px; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 15%);} +.layui-layout-admin .layui-header .layui-nav{background: none;} +.layui-layout-left{position: absolute !important; left: 200px; top: 0;} +.layui-layout-right{position: absolute !important; right: 0; top: 0;} + + +/* 栅格布局 */ +.layui-container{position: relative; margin: 0 auto; padding: 0 15px; box-sizing: border-box;} +.layui-fluid{position: relative; margin: 0 auto; padding: 0 15px;} + +.layui-row:before, .layui-row:after{content: ""; display: block; clear: both;} +.layui-col-xs1, .layui-col-xs2, .layui-col-xs3, .layui-col-xs4, .layui-col-xs5, .layui-col-xs6, .layui-col-xs7, .layui-col-xs8, .layui-col-xs9, .layui-col-xs10, .layui-col-xs11, .layui-col-xs12 +,.layui-col-sm1, .layui-col-sm2, .layui-col-sm3, .layui-col-sm4, .layui-col-sm5, .layui-col-sm6, .layui-col-sm7, .layui-col-sm8, .layui-col-sm9, .layui-col-sm10, .layui-col-sm11, .layui-col-sm12 +,.layui-col-md1, .layui-col-md2, .layui-col-md3, .layui-col-md4, .layui-col-md5, .layui-col-md6, .layui-col-md7, .layui-col-md8, .layui-col-md9, .layui-col-md10, .layui-col-md11, .layui-col-md12 +,.layui-col-lg1, .layui-col-lg2, .layui-col-lg3, .layui-col-lg4, .layui-col-lg5, .layui-col-lg6, .layui-col-lg7, .layui-col-lg8, .layui-col-lg9, .layui-col-lg10, .layui-col-lg11, .layui-col-lg12 +{position: relative; display: block; box-sizing: border-box;} + +.layui-col-xs1, .layui-col-xs2, .layui-col-xs3, .layui-col-xs4, .layui-col-xs5, .layui-col-xs6, .layui-col-xs7, .layui-col-xs8, .layui-col-xs9, .layui-col-xs10, .layui-col-xs11, .layui-col-xs12{float: left;} +.layui-col-xs1{width: 8.33333333%;} +.layui-col-xs2{width: 16.66666667%;} +.layui-col-xs3{width: 25%;} +.layui-col-xs4{width: 33.33333333%;} +.layui-col-xs5{width: 41.66666667%;} +.layui-col-xs6{width: 50%;} +.layui-col-xs7{width: 58.33333333%;} +.layui-col-xs8{width: 66.66666667%;} +.layui-col-xs9{width: 75%;} +.layui-col-xs10{width: 83.33333333%;} +.layui-col-xs11{width: 91.66666667%;} +.layui-col-xs12{width: 100%;} + +.layui-col-xs-offset1{margin-left: 8.33333333%;} +.layui-col-xs-offset2{margin-left: 16.66666667%;} +.layui-col-xs-offset3{margin-left: 25%;} +.layui-col-xs-offset4{margin-left: 33.33333333%;} +.layui-col-xs-offset5{margin-left: 41.66666667%;} +.layui-col-xs-offset6{margin-left: 50%;} +.layui-col-xs-offset7{margin-left: 58.33333333%;} +.layui-col-xs-offset8{margin-left: 66.66666667%;} +.layui-col-xs-offset9{margin-left: 75%;} +.layui-col-xs-offset10{margin-left: 83.33333333%;} +.layui-col-xs-offset11{margin-left: 91.66666667%;} +.layui-col-xs-offset12{margin-left: 100%;} + +/* 超小屏幕(手机) */ +@media screen and (max-width: 768px) { + .layui-hide-xs{display: none!important;} + .layui-show-xs-block{display: block!important;} + .layui-show-xs-inline{display: inline!important;} + .layui-show-xs-inline-block{display: inline-block!important;} +} + +/* 小型屏幕(平板) */ +@media screen and (min-width: 768px) { + .layui-container{width: 750px;} + .layui-hide-sm{display: none!important;} + .layui-show-sm-block{display: block!important;} + .layui-show-sm-inline{display: inline!important;} + .layui-show-sm-inline-block{display: inline-block!important;} + + .layui-col-sm1, .layui-col-sm2, .layui-col-sm3, .layui-col-sm4, .layui-col-sm5, .layui-col-sm6, .layui-col-sm7, .layui-col-sm8, .layui-col-sm9, .layui-col-sm10, .layui-col-sm11, .layui-col-sm12{float: left;} + .layui-col-sm1{width: 8.33333333%;} + .layui-col-sm2{width: 16.66666667%;} + .layui-col-sm3{width: 25%;} + .layui-col-sm4{width: 33.33333333%;} + .layui-col-sm5{width: 41.66666667%;} + .layui-col-sm6{width: 50%;} + .layui-col-sm7{width: 58.33333333%;} + .layui-col-sm8{width: 66.66666667%;} + .layui-col-sm9{width: 75%;} + .layui-col-sm10{width: 83.33333333%;} + .layui-col-sm11{width: 91.66666667%;} + .layui-col-sm12{width: 100%;} + /* 列偏移 */ + .layui-col-sm-offset1{margin-left: 8.33333333%;} + .layui-col-sm-offset2{margin-left: 16.66666667%;} + .layui-col-sm-offset3{margin-left: 25%;} + .layui-col-sm-offset4{margin-left: 33.33333333%;} + .layui-col-sm-offset5{margin-left: 41.66666667%;} + .layui-col-sm-offset6{margin-left: 50%;} + .layui-col-sm-offset7{margin-left: 58.33333333%;} + .layui-col-sm-offset8{margin-left: 66.66666667%;} + .layui-col-sm-offset9{margin-left: 75%;} + .layui-col-sm-offset10{margin-left: 83.33333333%;} + .layui-col-sm-offset11{margin-left: 91.66666667%;} + .layui-col-sm-offset12{margin-left: 100%;} +} +/* 中型屏幕(桌面) */ +@media screen and (min-width: 992px) { + .layui-container{width: 970px;} + .layui-hide-md{display: none!important;} + .layui-show-md-block{display: block!important;} + .layui-show-md-inline{display: inline!important;} + .layui-show-md-inline-block{display: inline-block!important;} + + .layui-col-md1, .layui-col-md2, .layui-col-md3, .layui-col-md4, .layui-col-md5, .layui-col-md6, .layui-col-md7, .layui-col-md8, .layui-col-md9, .layui-col-md10, .layui-col-md11, .layui-col-md12{float: left;} + .layui-col-md1{width: 8.33333333%;} + .layui-col-md2{width: 16.66666667%;} + .layui-col-md3{width: 25%;} + .layui-col-md4{width: 33.33333333%;} + .layui-col-md5{width: 41.66666667%;} + .layui-col-md6{width: 50%;} + .layui-col-md7{width: 58.33333333%;} + .layui-col-md8{width: 66.66666667%;} + .layui-col-md9{width: 75%;} + .layui-col-md10{width: 83.33333333%;} + .layui-col-md11{width: 91.66666667%;} + .layui-col-md12{width: 100%;} + /* 列偏移 */ + .layui-col-md-offset1{margin-left: 8.33333333%;} + .layui-col-md-offset2{margin-left: 16.66666667%;} + .layui-col-md-offset3{margin-left: 25%;} + .layui-col-md-offset4{margin-left: 33.33333333%;} + .layui-col-md-offset5{margin-left: 41.66666667%;} + .layui-col-md-offset6{margin-left: 50%;} + .layui-col-md-offset7{margin-left: 58.33333333%;} + .layui-col-md-offset8{margin-left: 66.66666667%;} + .layui-col-md-offset9{margin-left: 75%;} + .layui-col-md-offset10{margin-left: 83.33333333%;} + .layui-col-md-offset11{margin-left: 91.66666667%;} + .layui-col-md-offset12{margin-left: 100%;} +} +/* 大型屏幕(桌面) */ +@media screen and (min-width: 1200px) { + .layui-container{width: 1170px;} + .layui-hide-lg{display: none!important;} + .layui-show-lg-block{display: block!important;} + .layui-show-lg-inline{display: inline!important;} + .layui-show-lg-inline-block{display: inline-block!important;} + + .layui-col-lg1, .layui-col-lg2, .layui-col-lg3, .layui-col-lg4, .layui-col-lg5, .layui-col-lg6, .layui-col-lg7, .layui-col-lg8, .layui-col-lg9, .layui-col-lg10, .layui-col-lg11, .layui-col-lg12{float: left;} + .layui-col-lg1{width: 8.33333333%;} + .layui-col-lg2{width: 16.66666667%;} + .layui-col-lg3{width: 25%;} + .layui-col-lg4{width: 33.33333333%;} + .layui-col-lg5{width: 41.66666667%;} + .layui-col-lg6{width: 50%;} + .layui-col-lg7{width: 58.33333333%;} + .layui-col-lg8{width: 66.66666667%;} + .layui-col-lg9{width: 75%;} + .layui-col-lg10{width: 83.33333333%;} + .layui-col-lg11{width: 91.66666667%;} + .layui-col-lg12{width: 100%;} + /* 列偏移 */ + .layui-col-lg-offset1{margin-left: 8.33333333%;} + .layui-col-lg-offset2{margin-left: 16.66666667%;} + .layui-col-lg-offset3{margin-left: 25%;} + .layui-col-lg-offset4{margin-left: 33.33333333%;} + .layui-col-lg-offset5{margin-left: 41.66666667%;} + .layui-col-lg-offset6{margin-left: 50%;} + .layui-col-lg-offset7{margin-left: 58.33333333%;} + .layui-col-lg-offset8{margin-left: 66.66666667%;} + .layui-col-lg-offset9{margin-left: 75%;} + .layui-col-lg-offset10{margin-left: 83.33333333%;} + .layui-col-lg-offset11{margin-left: 91.66666667%;} + .layui-col-lg-offset12{margin-left: 100%;} +} + +/* 列间隔 */ +.layui-col-space1{margin: -0.5px;} +.layui-col-space1>*{padding: 0.5px;} +.layui-col-space2{margin: -1px;} +.layui-col-space2>*{padding: 1px;} +.layui-col-space4{margin: -2px;} +.layui-col-space4>*{padding: 2px;} +.layui-col-space5{margin: -2.5px;} +.layui-col-space5>*{padding: 2.5px;} +.layui-col-space6{margin: -3px;} +.layui-col-space6>*{padding: 3px;} +.layui-col-space8{margin: -4px;} +.layui-col-space8>*{padding: 4px;} +.layui-col-space10{margin: -5px;} +.layui-col-space10>*{padding: 5px;} +.layui-col-space12{margin: -6px;} +.layui-col-space12>*{padding: 6px;} +.layui-col-space14{margin: -7px;} +.layui-col-space14>*{padding: 7px;} +.layui-col-space15{margin: -7.5px;} +.layui-col-space15>*{padding: 7.5px;} +.layui-col-space16{margin: -8px;} +.layui-col-space16>*{padding: 8px;} +.layui-col-space18{margin: -9px;} +.layui-col-space18>*{padding: 9px;} +.layui-col-space20{margin: -10px;} +.layui-col-space20>*{padding: 10px;} +.layui-col-space22{margin: -11px;} +.layui-col-space22>*{padding: 11px;} +.layui-col-space24{margin: -12px;} +.layui-col-space24>*{padding: 12px;} +.layui-col-space25{margin: -12.5px;} +.layui-col-space25>*{padding: 12.5px;} +.layui-col-space26{margin: -13px;} +.layui-col-space26>*{padding: 13px;} +.layui-col-space28{margin: -14px;} +.layui-col-space28>*{padding: 14px;} +.layui-col-space30{margin: -15px;} +.layui-col-space30>*{padding: 15px;} + + +/** 页面元素 **/ +.layui-btn, .layui-input, .layui-textarea, .layui-upload-button, .layui-select{outline: none; -webkit-appearance: none; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box;} + +/* 引用 */.layui-elem-quote{margin-bottom: 10px; padding: 15px; line-height: 1.6; border-left: 5px solid #5FB878; border-radius: 0 2px 2px 0; background-color: #FAFAFA;} +.layui-quote-nm{border-style: solid; border-width: 1px; border-left-width: 5px; background: none;} +/* 字段集合 */.layui-elem-field{margin-bottom: 10px; padding: 0; border-width: 1px; border-style: solid;} +.layui-elem-field legend{margin-left: 20px; padding: 0 10px; font-size: 20px; font-weight: 300;} +.layui-field-title{margin: 10px 0 20px; border-width: 0; border-top-width: 1px;} +.layui-field-box{padding: 15px;} +.layui-field-title .layui-field-box{padding: 10px 0;} + +/* 进度条 */ +.layui-progress{position: relative; height: 6px; border-radius: 20px; background-color: #eee;} +.layui-progress-bar{position: absolute; left: 0; top: 0; width: 0; max-width: 100%; height: 6px; border-radius: 20px; text-align: right; background-color: #5FB878; transition: all .3s; -webkit-transition: all .3s;} +.layui-progress-big, +.layui-progress-big .layui-progress-bar{height: 18px; line-height: 18px;} +.layui-progress-text{position: relative; top: -20px; line-height: 18px; font-size: 12px; color: #666} +.layui-progress-big .layui-progress-text{position: static; padding: 0 10px; color: #fff;} + + +/* + + 面板 + +*/ + + +/* 折叠面板 */ +.layui-collapse{border-width: 1px; border-style: solid; border-radius: 2px;} +.layui-colla-item, +.layui-colla-content{border-top-width: 1px; border-top-style: solid;} +.layui-colla-item:first-child{border-top: none;} +.layui-colla-title{position: relative; height: 42px; line-height: 42px; padding: 0 15px 0 35px; color: #333; background-color: #FAFAFA; cursor: pointer; font-size: 14px; overflow: hidden;} +.layui-colla-content{display: none; padding: 10px 15px; line-height: 1.6; color: #666;} +.layui-colla-icon{position: absolute; left: 15px; top: 0; font-size: 14px;} + +/* 卡片面板 */ +.layui-card{margin-bottom: 15px; border-radius: 2px; background-color: #fff; box-shadow: 0 1px 2px 0 rgba(0,0,0,.05);} +.layui-card:last-child{margin-bottom: 0;} +.layui-card-header{position: relative; height: 42px; line-height: 42px; padding: 0 15px; border-bottom: 1px solid #f6f6f6; color: #333; border-radius: 2px 2px 0 0; font-size: 14px;} +.layui-card-body{position: relative; padding: 10px 15px; line-height: 24px;} +.layui-card-body[pad15]{padding: 15px;} +.layui-card-body[pad20]{padding: 20px;} +.layui-card-body .layui-table{margin: 5px 0;} +.layui-card .layui-tab{margin: 0;} + +/* 常规面板 */ +.layui-panel{position: relative; border-width: 1px; border-style: solid; border-radius: 2px; box-shadow: 1px 1px 4px rgb(0 0 0 / 8%); background-color: #fff; color: #666;} + +/* 窗口面板 */ +.layui-panel-window{position: relative; padding: 15px; border-radius: 0; border-top: 5px solid #eee; background-color: #fff;} + +/* 其它辅助 */ +.layui-auxiliar-moving{position: fixed; left: 0; right: 0; top: 0; bottom: 0; width: 100%; height: 100%; background: none; z-index: 9999999999;} + + +/* + + 默认主题 + +*/ + + +/* 背景颜色 */ +.layui-bg-red{background-color: #FF5722 !important; color: #fff!important;} /*赤*/ +.layui-bg-orange{background-color: #FFB800!important; color: #fff!important;} /*橙*/ +.layui-bg-green{background-color: #009688!important; color: #fff!important;} /*绿*/ +.layui-bg-cyan{background-color: #2F4056!important; color: #fff!important;} /*青*/ +.layui-bg-blue{background-color: #1E9FFF!important; color: #fff!important;} /*蓝*/ +.layui-bg-black{background-color: #393D49!important; color: #fff!important;} /*黑*/ +.layui-bg-gray{background-color: #FAFAFA!important; color: #666!important;} /*灰*/ + +/* 边框 */ +.layui-border, +.layui-quote-nm, +.layui-elem-field, +.layui-collapse, +.layui-panel, +.layui-colla-item, +.layui-colla-content, +.layui-badge-rim, +.layui-tab-title, +.layui-tab-title .layui-this:after, +.layui-tab-bar, +.layui-tab-card, + +.layui-input, .layui-textarea, .layui-select, +.layui-form-pane .layui-form-label, +.layui-form-pane .layui-form-item[pane], +.layui-layedit, .layui-layedit-tool{border-color: #eee;} + +.layui-border{border-width: 1px; border-style: solid; color: #666!important;} +.layui-border-red{border-width: 1px; border-style: solid; border-color: #FF5722!important; color: #FF5722!important;} +.layui-border-orange{border-width: 1px; border-style: solid; border-color: #FFB800!important; color: #FFB800!important;} +.layui-border-green{border-width: 1px; border-style: solid; border-color: #009688!important; color: #009688!important;} +.layui-border-cyan{border-width: 1px; border-style: solid; border-color: #2F4056!important; color: #2F4056!important;} +.layui-border-blue{border-width: 1px; border-style: solid; border-color: #1E9FFF!important; color: #1E9FFF!important;} +.layui-border-black{border-width: 1px; border-style: solid; border-color: #393D49!important; color: #393D49!important;} + +/* 背景边框 */ +.layui-timeline-item:before{background-color: #eee;} + +/* 文本区域 */ +.layui-text{line-height: 1.6; font-size: 14px; color: #666;} +.layui-text h1, +.layui-text h2, +.layui-text h3{font-weight: 500; color: #333;} +.layui-text h1{font-size: 30px;} +.layui-text h2{font-size: 24px;} +.layui-text h3{font-size: 18px;} +.layui-text a:not(.layui-btn){color: #01AAED;} +.layui-text a:not(.layui-btn):hover{text-decoration: underline;} +.layui-text ul{padding: 5px 0 5px 15px;} +.layui-text ul li{margin-top: 5px; list-style-type: disc;} +.layui-text em, +.layui-word-aux{color: #999 !important; padding-left: 5px !important; padding-right: 5px !important;} +.layui-text p{margin: 10px 0;} +.layui-text p:first-child{margin-top: 0;} + +/* 字体大小及颜色 */ +.layui-font-12{font-size: 12px !important;;} +.layui-font-14{font-size: 14px !important;} +.layui-font-16{font-size: 16px !important;} +.layui-font-18{font-size: 18px !important;} +.layui-font-20{font-size: 20px !important;} + +.layui-font-red{color: #FF5722 !important;} /*赤*/ +.layui-font-orange{color: #FFB800!important;} /*橙*/ +.layui-font-green{color: #009688!important;} /*绿*/ +.layui-font-cyan{color: #2F4056!important;} /*青*/ +.layui-font-blue{color: #01AAED!important;} /*蓝*/ +.layui-font-black{color: #000!important;} /*黑*/ +.layui-font-gray{color: #c2c2c2!important;} /*灰*/ + + + +/* + + 按钮 + +*/ + +.layui-btn{display: inline-block; vertical-align: middle; height: 38px; line-height: 38px; border: 1px solid transparent; padding: 0 18px; background-color: #009688; color: #fff; white-space: nowrap; text-align: center; font-size: 14px; border-radius: 2px; cursor: pointer; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} +.layui-btn:hover{opacity: 0.8; filter:alpha(opacity=80); color: #fff;} +.layui-btn:active{opacity: 1; filter:alpha(opacity=100);} +.layui-btn+.layui-btn{margin-left: 10px;} + +/* 按钮容器 */ +.layui-btn-container{font-size: 0;} +.layui-btn-container .layui-btn{margin-right: 10px; margin-bottom: 10px;} +.layui-btn-container .layui-btn+.layui-btn{margin-left: 0;} +.layui-table .layui-btn-container .layui-btn{margin-bottom: 9px;} + + +/* 圆角 */.layui-btn-radius{border-radius: 100px;} +.layui-btn .layui-icon{padding: 0 2px; vertical-align: middle\0; vertical-align: bottom;} + +/* 原始 */.layui-btn-primary{border-color: #d2d2d2; background: none; color: #666;} +.layui-btn-primary:hover{border-color: #009688; color: #333;} +/* 百搭 */.layui-btn-normal{background-color: #1E9FFF;} +/* 暖色 */.layui-btn-warm{background-color: #FFB800;} +/* 警告 */.layui-btn-danger{background-color: #FF5722;} +/* 选中 */.layui-btn-checked{background-color: #5FB878;} +/* 禁用 */.layui-btn-disabled, .layui-btn-disabled:hover, .layui-btn-disabled:active{border-color: #eee !important; background-color: #FBFBFB !important; color: #d2d2d2 !important; cursor: not-allowed !important; opacity: 1;} + +/* 大型 */.layui-btn-lg{height: 44px; line-height: 44px; padding: 0 25px; font-size: 16px;} +/* 小型 */.layui-btn-sm{height: 30px; line-height: 30px; padding: 0 10px; font-size: 12px;} +/* 超小 */.layui-btn-xs{height: 22px; line-height: 22px; padding: 0 5px; font-size: 12px;} +.layui-btn-xs i{font-size: 12px !important;} +/* 按钮组 */.layui-btn-group{display: inline-block; vertical-align: middle; font-size: 0;} +.layui-btn-group .layui-btn{margin-left: 0!important; margin-right: 0!important; border-left: 1px solid rgba(255,255,255,.5); border-radius: 0;} +.layui-btn-group .layui-btn-primary{border-left: none;} +.layui-btn-group .layui-btn-primary:hover{border-color: #d2d2d2; color: #009688;} +.layui-btn-group .layui-btn:first-child{border-left: none; border-radius: 2px 0 0 2px;} +.layui-btn-group .layui-btn-primary:first-child{border-left: 1px solid #d2d2d2;} +.layui-btn-group .layui-btn:last-child{border-radius: 0 2px 2px 0;} +.layui-btn-group .layui-btn+.layui-btn{margin-left: 0;} +.layui-btn-group+.layui-btn-group{margin-left: 10px;} +/* 流体 */.layui-btn-fluid{width: 100%;} + +/** 表单 **/ +.layui-input, .layui-textarea, .layui-select{height: 38px; line-height: 1.3; line-height: 38px\9; border-width: 1px; border-style: solid; background-color: #fff; color: rgba(0,0,0,.85); border-radius: 2px;} +.layui-input::-webkit-input-placeholder, +.layui-textarea::-webkit-input-placeholder, +.layui-select::-webkit-input-placeholder{line-height: 1.3;} +.layui-input, .layui-textarea{display: block; width: 100%; padding-left: 10px;} +.layui-input:hover, .layui-textarea:hover{border-color: #eee !important;} +.layui-input:focus, .layui-textarea:focus{border-color: #d2d2d2 !important;} +.layui-textarea{position: relative; min-height: 100px; height: auto; line-height: 20px; padding: 6px 10px; resize: vertical;} +.layui-select{padding: 0 10px;} +.layui-form select, +.layui-form input[type=checkbox], +.layui-form input[type=radio]{display: none;} +.layui-form *[lay-ignore]{display: initial;} + +.layui-form-item{margin-bottom: 15px; clear: both; *zoom: 1;} +.layui-form-item:after{content:'\20'; clear: both; *zoom: 1; display: block; height:0;} +.layui-form-label{position: relative; float: left; display: block; padding: 9px 15px; width: 80px; font-weight: 400; line-height: 20px; text-align: right;} +.layui-form-label-col{display: block; float: none; padding: 9px 0; line-height: 20px; text-align: left;} +.layui-form-item .layui-inline{margin-bottom: 5px; margin-right: 10px;} +.layui-input-block, .layui-input-inline{position: relative;} +.layui-input-block{margin-left: 110px; min-height: 36px;} +.layui-input-inline{display: inline-block; vertical-align: middle;} +.layui-form-item .layui-input-inline{float: left; width: 190px; margin-right: 10px;} +.layui-form-text .layui-input-inline{width: auto;} + +/* 分割块 */.layui-form-mid{position: relative; float: left; display: block; padding: 9px 0 !important; line-height: 20px; margin-right: 10px;} +/* 警告域 */.layui-form-danger:focus +,.layui-form-danger+.layui-form-select .layui-input{border-color: #FF5722 !important;} + + +/* 下拉选择 */.layui-form-select{position: relative;} +.layui-form-select .layui-input{padding-right: 30px; cursor: pointer;} +.layui-form-select .layui-edge{position: absolute; right: 10px; top: 50%; margin-top: -3px; cursor: pointer; border-width: 6px; border-top-color: #c2c2c2; border-top-style: solid; transition: all .3s; -webkit-transition: all .3s;} +.layui-form-select dl{display: none; position: absolute; left: 0; top: 42px; padding: 5px 0; z-index: 899; min-width: 100%; border: 1px solid #eee; max-height: 300px; overflow-y: auto; background-color: #fff; border-radius: 2px; box-shadow: 1px 1px 4px rgb(0 0 0 / 8%); box-sizing: border-box;} +.layui-form-select dl dt, +.layui-form-select dl dd{padding: 0 10px; line-height: 36px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;} +.layui-form-select dl dt{font-size: 12px; color: #999;} +.layui-form-select dl dd{cursor: pointer;} +.layui-form-select dl dd:hover{background-color: #F6F6F6; -webkit-transition: .5s all; transition: .5s all;} +.layui-form-select .layui-select-group dd{padding-left: 20px;} +.layui-form-select dl dd.layui-select-tips{padding-left: 10px !important; color: #999;} +.layui-form-select dl dd.layui-this{background-color: #5FB878; color: #fff;} +/*.layui-form-select dl dd.layui-this{background-color: #F6F6F6; color: #5FB878; font-weight: 700;}*/ +.layui-form-select dl dd.layui-disabled{background-color: #fff;} +.layui-form-selected dl{display: block;} +.layui-form-selected .layui-edge{margin-top: -9px; -webkit-transform:rotate(180deg); transform: rotate(180deg);} +.layui-form-selected .layui-edge{margin-top: -3px\0; } +:root .layui-form-selected .layui-edge{margin-top: -9px\0/IE9;} +.layui-form-selectup dl{top: auto; bottom: 42px;} +.layui-select-none{margin: 5px 0; text-align: center; color: #999;} + +.layui-select-disabled .layui-disabled{border-color: #eee !important;} +.layui-select-disabled .layui-edge{border-top-color: #d2d2d2} + +/* 复选框 */.layui-form-checkbox{position: relative; display: inline-block; vertical-align: middle; height: 30px; line-height: 30px; margin-right: 10px; padding-right: 30px; background-color: #fff; cursor: pointer; font-size: 0; -webkit-transition: .1s linear; transition: .1s linear; box-sizing: border-box;} +.layui-form-checkbox:hover{} +.layui-form-checkbox *{display: inline-block; vertical-align: middle;} +.layui-form-checkbox span{padding: 0 10px; height: 100%; font-size: 14px; border-radius: 2px 0 0 2px; background-color: #d2d2d2; color: #fff; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;} +.layui-form-checkbox:hover span{background-color: #c2c2c2;} +.layui-form-checkbox i{position: absolute; right: 0; top: 0; width: 30px; height: 28px; border: 1px solid #d2d2d2; border-left: none; border-radius: 0 2px 2px 0; color: #fff; font-size: 20px; text-align: center;} +.layui-form-checkbox:hover i{border-color: #c2c2c2; color: #c2c2c2;} +.layui-form-checked, .layui-form-checked:hover{border-color: #5FB878;} +.layui-form-checked span, .layui-form-checked:hover span{background-color: #5FB878;} +.layui-form-checked i, .layui-form-checked:hover i{color: #5FB878;} +.layui-form-item .layui-form-checkbox{margin-top: 4px;} + +/* 复选框-原始风格 */.layui-form-checkbox[lay-skin="primary"]{height: auto!important; line-height: normal!important; min-width: 18px; min-height: 18px; border: none!important; margin-right: 0; padding-left: 28px; padding-right: 0; background: none;} +.layui-form-checkbox[lay-skin="primary"] span{padding-left: 0; padding-right: 15px; line-height: 18px; background: none; color: #666;} +.layui-form-checkbox[lay-skin="primary"] i{right: auto; left: 0; width: 16px; height: 16px; line-height: 16px; border: 1px solid #d2d2d2; font-size: 12px; border-radius: 2px; background-color: #fff; -webkit-transition: .1s linear; transition: .1s linear;} +.layui-form-checkbox[lay-skin="primary"]:hover i{border-color: #5FB878; color: #fff;} +.layui-form-checked[lay-skin="primary"] i{border-color: #5FB878 !important; background-color: #5FB878; color: #fff;} +.layui-checkbox-disabled[lay-skin="primary"] span{background: none!important; color: #c2c2c2!important;} +.layui-checkbox-disabled[lay-skin="primary"]:hover i{border-color: #d2d2d2;} +.layui-form-item .layui-form-checkbox[lay-skin="primary"]{margin-top: 10px;} + +/* 复选框-开关风格 */.layui-form-switch{position: relative; display: inline-block; vertical-align: middle; height: 22px; line-height: 22px; min-width: 35px; padding: 0 5px; margin-top: 8px; border: 1px solid #d2d2d2; border-radius: 20px; cursor: pointer; background-color: #fff; -webkit-transition: .1s linear; transition: .1s linear;} +.layui-form-switch i{position: absolute; left: 5px; top: 3px; width: 16px; height: 16px; border-radius: 20px; background-color: #d2d2d2; -webkit-transition: .1s linear; transition: .1s linear;} +.layui-form-switch em{position: relative; top: 0; width: 25px; margin-left: 21px; padding: 0!important; text-align: center!important; color: #999!important; font-style: normal!important; font-size: 12px;} +.layui-form-onswitch{border-color: #5FB878; background-color: #5FB878;} +.layui-form-onswitch i{left: 100%; margin-left: -21px; background-color: #fff;} +.layui-form-onswitch em{margin-left: 5px; margin-right: 21px; color: #fff!important;} + +.layui-checkbox-disabled{border-color: #eee !important;} +.layui-checkbox-disabled span{background-color: #eee !important;} +.layui-checkbox-disabled i{border-color: #eee !important;} +.layui-checkbox-disabled em{color: #d2d2d2 !important;} +.layui-checkbox-disabled:hover i{color: #fff !important;} + +/* 单选框 */ +*[lay-radio]{display: none;} +.layui-form-radio{display: inline-block; vertical-align: middle; line-height: 28px; margin: 6px 10px 0 0; padding-right: 10px; cursor: pointer; font-size: 0;} +.layui-form-radio *{display: inline-block; vertical-align: middle; font-size: 14px;} +.layui-form-radio>i{margin-right: 8px; font-size: 22px; color: #c2c2c2;} +.layui-form-radioed, +.layui-form-radioed>i, +.layui-form-radio:hover *{color: #5FB878;} +.layui-radio-disabled>i{color: #eee !important;} +.layui-radio-disabled *{color: #c2c2c2!important;} + +/* 表单方框风格 */.layui-form-pane .layui-form-label{width: 110px; padding: 8px 15px; height: 38px; line-height: 20px; border-width: 1px; border-style: solid; border-radius: 2px 0 0 2px; text-align: center; background-color: #FAFAFA; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; box-sizing: border-box;} +.layui-form-pane .layui-input-inline{margin-left: -1px;} +.layui-form-pane .layui-input-block{margin-left: 110px; left: -1px;} +.layui-form-pane .layui-input{border-radius: 0 2px 2px 0;} +.layui-form-pane .layui-form-text .layui-form-label{float: none; width: 100%; border-radius: 2px; box-sizing: border-box; text-align: left;} +.layui-form-pane .layui-form-text .layui-input-inline{display: block; margin: 0; top: -1px; clear: both;} +.layui-form-pane .layui-form-text .layui-input-block{margin: 0; left: 0; top: -1px;} +.layui-form-pane .layui-form-text .layui-textarea{min-height: 100px; border-radius: 0 0 2px 2px;} +.layui-form-pane .layui-form-checkbox{margin: 4px 0 4px 10px;} +.layui-form-pane .layui-form-switch, +.layui-form-pane .layui-form-radio{margin-top: 6px; margin-left: 10px; } +.layui-form-pane .layui-form-item[pane]{position: relative; border-width: 1px; border-style: solid;} +.layui-form-pane .layui-form-item[pane] .layui-form-label{position: absolute; left: 0; top: 0; height: 100%; border-width: 0px; border-right-width: 1px;} +.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left: 110px;} + +/** 表单响应式 **/ +@media screen and (max-width: 450px) { + .layui-form-item .layui-form-label{text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} + .layui-form-item .layui-inline{display: block; margin-right: 0; margin-bottom: 20px; clear: both;} + .layui-form-item .layui-inline:after{content:'\20'; clear:both; display:block; height:0;} + .layui-form-item .layui-input-inline{display: block; float: none; left: -3px; width: auto !important; margin: 0 0 10px 112px; } + .layui-form-item .layui-input-inline+.layui-form-mid{margin-left: 110px; top: -5px; padding: 0;} + .layui-form-item .layui-form-checkbox{margin-right: 5px; margin-bottom: 5px;} +} + +/** 富文本编辑器 **/ +.layui-layedit{border-width: 1px; border-style: solid; border-radius: 2px;} +.layui-layedit-tool{padding: 3px 5px; border-bottom-width: 1px; border-bottom-style: solid; font-size: 0;} +.layedit-tool-fixed{position: fixed; top: 0; border-top: 1px solid #eee;} +.layui-layedit-tool .layedit-tool-mid, +.layui-layedit-tool .layui-icon{display: inline-block; vertical-align: middle; text-align: center; font-size: 14px;} +.layui-layedit-tool .layui-icon{position: relative; width: 32px; height: 30px; line-height: 30px; margin: 3px 5px; border-radius: 2px; color: #777; cursor: pointer; border-radius: 2px;} +.layui-layedit-tool .layui-icon:hover{color: #393D49;} +.layui-layedit-tool .layui-icon:active{color: #000;} +.layui-layedit-tool .layedit-tool-active{background-color: #eee; color: #000;} +.layui-layedit-tool .layui-disabled, +.layui-layedit-tool .layui-disabled:hover{color: #d2d2d2; cursor: not-allowed;} +.layui-layedit-tool .layedit-tool-mid{width: 1px; height: 18px; margin: 0 10px; background-color: #d2d2d2;} + +.layedit-tool-html{width: 50px !important; font-size: 30px !important;} +.layedit-tool-b, +.layedit-tool-code, +.layedit-tool-help{font-size: 16px !important;} +.layedit-tool-d, +.layedit-tool-unlink, +.layedit-tool-face, +.layedit-tool-image{font-size: 18px !important;} +.layedit-tool-image input{position: absolute; font-size: 0; left: 0; top: 0; width: 100%; height: 100%; opacity: 0.01; filter: Alpha(opacity=1); cursor: pointer;} + +.layui-layedit-iframe iframe{display: block; width: 100%;} +#LAY_layedit_code{overflow: hidden;} + +/** 分页 **/ +.layui-laypage{display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; margin: 10px 0; font-size: 0;} +.layui-laypage>a:first-child, +.layui-laypage>a:first-child em{border-radius: 2px 0 0 2px;} +.layui-laypage>a:last-child, +.layui-laypage>a:last-child em{border-radius: 0 2px 2px 0;} +.layui-laypage>*:first-child{margin-left: 0!important;} +.layui-laypage>*:last-child{margin-right: 0!important;} +.layui-laypage a, +.layui-laypage span, +.layui-laypage input, +.layui-laypage button, +.layui-laypage select{border: 1px solid #eee;} +.layui-laypage a, +.layui-laypage span{display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; padding: 0 15px; height: 28px; line-height: 28px; margin: 0 -1px 5px 0; background-color: #fff; color: #333; font-size: 12px;} +.layui-laypage a:hover{color: #009688;} +.layui-laypage em{font-style: normal;} +.layui-laypage .layui-laypage-spr{color:#999; font-weight: 700;} +.layui-laypage a{ text-decoration: none;} +.layui-laypage .layui-laypage-curr{position: relative;} +.layui-laypage .layui-laypage-curr em{position: relative; color: #fff;} +.layui-laypage .layui-laypage-curr .layui-laypage-em{position: absolute; left: -1px; top: -1px; padding: 1px; width: 100%; height: 100%; background-color: #009688; } +.layui-laypage-em{border-radius: 2px;} +.layui-laypage-prev em, +.layui-laypage-next em{font-family: Sim sun; font-size: 16px;} + +.layui-laypage .layui-laypage-count, +.layui-laypage .layui-laypage-limits, +.layui-laypage .layui-laypage-refresh, +.layui-laypage .layui-laypage-skip{margin-left: 10px; margin-right: 10px; padding: 0; border: none;} +.layui-laypage .layui-laypage-limits, +.layui-laypage .layui-laypage-refresh{vertical-align: top;} +.layui-laypage .layui-laypage-refresh i{font-size: 18px; cursor: pointer;} +.layui-laypage select{height: 22px; padding: 3px; border-radius: 2px; cursor: pointer;} +.layui-laypage .layui-laypage-skip{height: 30px; line-height: 30px; color: #999;} +.layui-laypage input, .layui-laypage button{height: 30px; line-height: 30px; border-radius: 2px; vertical-align: top; background-color: #fff; box-sizing: border-box;} +.layui-laypage input{display: inline-block; width: 40px; margin: 0 10px; padding: 0 3px; text-align: center;} +.layui-laypage input:focus, +.layui-laypage select:focus{border-color: #009688!important;} +.layui-laypage button{margin-left: 10px; padding: 0 10px; cursor: pointer;} + +/** 流加载 **/ +.layui-flow-more{margin: 10px 0; text-align: center; color: #999; font-size: 14px;} +.layui-flow-more a{ height: 32px; line-height: 32px; } +.layui-flow-more a *{display: inline-block; vertical-align: top;} +.layui-flow-more a cite{padding: 0 20px; border-radius: 3px; background-color: #eee; color: #333; font-style: normal;} +.layui-flow-more a cite:hover{opacity: 0.8;} +.layui-flow-more a i{font-size: 30px; color: #737383;} + +/** 表格 **/ +.layui-table{width: 100%; margin: 10px 0; background-color: #fff; color: #666;} +.layui-table tr{transition: all .3s; -webkit-transition: all .3s;} +.layui-table th{text-align: left; font-weight: 400;} + +.layui-table thead tr, +.layui-table-header, +.layui-table-tool, +.layui-table-total, +.layui-table-total tr, +.layui-table-patch, +.layui-table-mend, +.layui-table[lay-even] tr:nth-child(even), +.layui-table tbody tr:hover, +.layui-table-hover, +.layui-table-click{background-color: #FAFAFA;} + +.layui-table th, +.layui-table td, +.layui-table[lay-skin="line"], +.layui-table[lay-skin="row"], +.layui-table-view, +.layui-table-tool, +.layui-table-header, +.layui-table-col-set, +.layui-table-total, +.layui-table-page, +.layui-table-fixed-r, +.layui-table-tips-main, +.layui-table-grid-down{border-width: 1px; border-style: solid; border-color: #eee;} + +.layui-table th, .layui-table td{position: relative; padding: 9px 15px; min-height: 20px; line-height: 20px; font-size: 14px;} + +.layui-table[lay-skin="line"] th, .layui-table[lay-skin="line"] td{border-width: 0; border-bottom-width: 1px;} +.layui-table[lay-skin="row"] th, .layui-table[lay-skin="row"] td{border-width: 0;border-right-width: 1px;} +.layui-table[lay-skin="nob"] th, .layui-table[lay-skin="nob"] td{border: none;} + +.layui-table img{max-width:100px;} + +/* 大表格 */.layui-table[lay-size="lg"] th, +.layui-table[lay-size="lg"] td{padding-top: 15px; padding-right: 30px; padding-bottom: 15px; padding-left: 30px;} +.layui-table-view .layui-table[lay-size="lg"] .layui-table-cell{height: 40px; line-height: 40px;} +/* 小表格 */.layui-table[lay-size="sm"] th, +.layui-table[lay-size="sm"] td{padding-top: 5px; padding-right: 10px; padding-bottom: 5px; padding-left: 10px; font-size: 12px;} +.layui-table-view .layui-table[lay-size="sm"] .layui-table-cell{height: 20px; line-height: 20px;} + +/* 数据表格 */ +.layui-table[lay-data]{display: none;} +.layui-table-box{position: relative; overflow: hidden;} +.layui-table-view{margin: 10px 0;} +.layui-table-view .layui-table{position: relative; width: auto; margin: 0;} +.layui-table-view .layui-table[lay-skin="line"]{border-width: 0; border-right-width: 1px;} +.layui-table-view .layui-table[lay-skin="row"]{border-width: 0; border-bottom-width: 1px;} +.layui-table-view .layui-table th, +.layui-table-view .layui-table td{padding: 5px 0; border-top: none; border-left: none;} +.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor: pointer;} +.layui-table-view .layui-table td{cursor: default;} +.layui-table-view .layui-table td[data-edit="text"]{cursor: text;} +.layui-table-view .layui-form-checkbox[lay-skin="primary"] i{width: 18px; height: 18px;} +.layui-table-view .layui-form-radio{line-height: 0; padding: 0;} +.layui-table-view .layui-form-radio>i{margin: 0; font-size: 20px;} +.layui-table-init{position: absolute; left: 0; top: 0; width: 100%; height: 100%; text-align: center; z-index: 110;} +.layui-table-init .layui-icon{position: absolute; left: 50%; top: 50%; margin: -15px 0 0 -15px; font-size: 30px; color: #c2c2c2;} +.layui-table-header{border-width: 0; border-bottom-width: 1px; overflow: hidden;} +.layui-table-header .layui-table{margin-bottom: -1px;} + +.layui-table-tool .layui-inline[lay-event]{position: relative; width: 26px; height: 26px; padding: 5px; line-height: 16px; margin-right: 10px; text-align: center; color: #333; border: 1px solid #ccc; cursor: pointer; -webkit-transition: .5s all; transition: .5s all;} +.layui-table-tool .layui-inline[lay-event]:hover{border: 1px solid #999;} +.layui-table-tool-temp{padding-right: 120px;} +.layui-table-tool-self{position: absolute; right: 17px; top: 10px;} +.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin: 0 0 0 10px;} +.layui-table-tool-panel{position: absolute; top: 29px; left: -1px; padding: 5px 0; min-width: 150px; min-height: 40px; border: 1px solid #d2d2d2; text-align: left; overflow-y: auto; background-color: #fff; box-shadow: 0 2px 4px rgba(0,0,0,.12);} +.layui-table-tool-panel li{padding: 0 10px; line-height: 30px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; -webkit-transition: .5s all; transition: .5s all;} +.layui-table-tool-panel li .layui-form-checkbox[lay-skin="primary"]{width: 100%;} +.layui-table-tool-panel li:hover{background-color: #F6F6F6;} +.layui-table-tool-panel li .layui-form-checkbox[lay-skin="primary"]{padding-left: 28px;} +.layui-table-tool-panel li .layui-form-checkbox[lay-skin="primary"] i{position: absolute; left: 0; top: 0;} +.layui-table-tool-panel li .layui-form-checkbox[lay-skin="primary"] span{padding: 0;} +.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left: auto; right: -1px;} + +.layui-table-col-set{position: absolute; right: 0; top: 0; width: 20px; height: 100%; border-width: 0; border-left-width: 1px; background-color: #fff;} + +.layui-table-sort{width: 10px; height: 20px; margin-left: 5px; cursor: pointer!important;} +.layui-table-sort .layui-edge{position: absolute; left: 5px; border-width: 5px;} +.layui-table-sort .layui-table-sort-asc{top: 3px; border-top: none; border-bottom-style: solid; border-bottom-color: #b2b2b2;} +.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color: #666;} +.layui-table-sort .layui-table-sort-desc{bottom: 5px; border-bottom: none; border-top-style: solid; border-top-color: #b2b2b2;} +.layui-table-sort .layui-table-sort-desc:hover{border-top-color: #666;} +.layui-table-sort[lay-sort="asc"] .layui-table-sort-asc{border-bottom-color: #000;} +.layui-table-sort[lay-sort="desc"] .layui-table-sort-desc{border-top-color: #000;} + +.layui-table-cell{height: 28px; line-height: 28px; padding: 0 15px; position: relative; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box;} +.layui-table-cell .layui-form-checkbox[lay-skin="primary"]{top: -1px; padding: 0;} +.layui-table-cell .layui-table-link{color: #01AAED;} + +.laytable-cell-checkbox, +.laytable-cell-radio, +.laytable-cell-space, +.laytable-cell-numbers{padding: 0; text-align: center;} + +.layui-table-body{position: relative; overflow: auto; margin-right: -1px; margin-bottom: -1px;} +.layui-table-body .layui-none{line-height: 26px; padding: 30px 15px; text-align: center; color: #999;} +.layui-table-fixed{position: absolute; left: 0; top: 0; z-index: 101;} +.layui-table-fixed .layui-table-body{overflow: hidden;} +.layui-table-fixed-l{box-shadow: 1px 0 8px rgba(0,0,0,.08);} +.layui-table-fixed-r{left: auto; right: -1px; border-width: 0; border-left-width: 1px; box-shadow: -1px 0 8px rgba(0,0,0,.08);} +.layui-table-fixed-r .layui-table-header{position: relative; overflow: visible;} +.layui-table-mend{position: absolute; right: -49px; top: 0; height: 100%; width: 50px;} + +.layui-table-tool{position: relative; z-index: 890; width: 100%; min-height: 50px; line-height: 30px; padding: 10px 15px; border-width: 0; border-bottom-width: 1px; /*box-shadow: 0 1px 8px 0 rgb(0 0 0 / 8%);*/} +.layui-table-tool .layui-btn-container{margin-bottom: -10px;} + +.layui-table-total{margin-bottom: -1px; border-width: 0; border-top-width: 1px; overflow: hidden;} + + +.layui-table-page{position: relative; width: 100%; padding: 7px 7px 0; border-width: 0; border-top-width: 1px; height: 41px; margin-bottom: -1px; font-size: 12px; white-space: nowrap; overflow: hidden;} +.layui-table-page>div{height: 26px;} +.layui-table-page .layui-laypage{margin: 0;} +.layui-table-page .layui-laypage a, +.layui-table-page .layui-laypage span{height: 26px; line-height: 26px; margin-bottom: 10px; border: none; background: none;} +.layui-table-page .layui-laypage a, +.layui-table-page .layui-laypage span.layui-laypage-curr{padding: 0 12px;} +.layui-table-page .layui-laypage span{margin-left: 0; padding: 0;} +.layui-table-page .layui-laypage .layui-laypage-prev{margin-left: -7px!important;} +.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left: 0; top: 0; padding: 0;} +.layui-table-page .layui-laypage input, +.layui-table-page .layui-laypage button{height: 26px; line-height: 26px; } +.layui-table-page .layui-laypage input{width: 40px;} +.layui-table-page .layui-laypage button{padding: 0 10px;} +.layui-table-page select{height: 18px;} +.layui-table-view select[lay-ignore]{display: inline-block;} + +.layui-table-patch .layui-table-cell{padding: 0; width: 30px;} + +.layui-table-edit{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding: 0 14px 1px; border-radius: 0; box-shadow: 1px 1px 20px rgba(0,0,0,.15)} +.layui-table-edit:focus{border-color: #5FB878!important;} +select.layui-table-edit{padding: 0 0 0 10px; border-color: #d2d2d2;} +.layui-table-view .layui-form-switch, +.layui-table-view .layui-form-checkbox, +.layui-table-view .layui-form-radio{top: 0; margin: 0; box-sizing: content-box;} +.layui-table-view .layui-form-checkbox{top: -1px; height: 26px; line-height: 26px;} +.layui-table-view .layui-form-checkbox i{height: 26px;} + +/* 展开溢出的单元格 */ +.layui-table-grid .layui-table-cell{overflow: visible;} +.layui-table-grid-down{position: absolute; top: 0; right: 0; width: 26px; height: 100%; padding: 5px 0; border-width: 0; border-left-width: 1px; text-align: center; background-color: #fff; color: #999; cursor: pointer;} +.layui-table-grid-down .layui-icon{position: absolute; top: 50%; left: 50%; margin: -8px 0 0 -8px;} +.layui-table-grid-down:hover{background-color: #fbfbfb;} + +body .layui-table-tips .layui-layer-content{background: none; padding: 0; box-shadow: 0 1px 6px rgba(0,0,0,.12);} +.layui-table-tips-main{margin: -44px 0 0 -1px; max-height: 150px; padding: 8px 15px; font-size: 14px; overflow-y: scroll; background-color: #fff; color: #666;} +.layui-table-tips-c{position: absolute; right: -3px; top: -13px; width: 20px; height: 20px; padding: 3px; cursor: pointer; background-color: #666; border-radius: 50%; color: #fff;} +.layui-table-tips-c:hover{background-color: #777;} +.layui-table-tips-c:before{position: relative; right: -2px;} + +/** 文件上传 **/ +.layui-upload-file{display: none!important; opacity: .01; filter: Alpha(opacity=1);} +.layui-upload-list{margin: 10px 0;} +.layui-upload-choose{max-width: 200px; padding: 0 10px; color: #999; font-size: 14px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} +.layui-upload-drag{position: relative; display: inline-block; padding: 30px; border: 1px dashed #e2e2e2; background-color: #fff; text-align: center; cursor: pointer; color: #999;} +.layui-upload-drag .layui-icon{font-size: 50px; color: #009688;} +.layui-upload-drag[lay-over]{border-color: #009688} +.layui-upload-form{display: inline-block;} +.layui-upload-iframe{position: absolute; width: 0; height: 0; border: 0; visibility: hidden} +.layui-upload-wrap{position: relative; display: inline-block; vertical-align: middle;} +.layui-upload-wrap .layui-upload-file{display: block!important; position: absolute; left: 0; top: 0; z-index: 10; font-size: 100px; width: 100%; height: 100%; opacity: .01; filter: Alpha(opacity=1); cursor: pointer;} +.layui-btn-container .layui-upload-choose{padding-left: 0;} + + +/* 基础菜单元素 */ +.layui-menu{position: relative; margin: 5px 0; background-color: #fff; box-sizing: border-box;} +.layui-menu *{box-sizing: border-box;} +.layui-menu li, +.layui-menu-body-title a{padding: 5px 15px;} +.layui-menu li{position: relative; margin: 1px 0; width: calc(100% + 1px); line-height: 26px; color: rgba(0,0,0,.8); font-size: 14px; white-space: nowrap; cursor: pointer; transition: all .3s;} +.layui-menu li:hover{background-color: #F6F6F6; } + +.layui-menu-item-parent:hover>.layui-menu-body-panel{display: block; animation-name: layui-fadein; animation-duration: 0.3s; animation-fill-mode: both; animation-delay:.2s;} +.layui-menu-item-parent .layui-menu-body-title, +.layui-menu-item-group .layui-menu-body-title{padding-right: 25px;} + +.layui-menu .layui-menu-item-group:hover, +.layui-menu .layui-menu-item-none:hover, +.layui-menu .layui-menu-item-divider:hover{background: none; cursor: default;} +.layui-menu .layui-menu-item-group>ul{margin: 5px 0 -5px;} +.layui-menu .layui-menu-item-group>.layui-menu-body-title{color: rgba(0,0,0,.35); user-select: none;} +.layui-menu .layui-menu-item-none{color: rgba(0,0,0,.35); cursor: default;} + +.layui-menu .layui-menu-item-none{text-align: center;} +.layui-menu .layui-menu-item-divider{margin: 5px 0; padding: 0; height: 0; line-height: 0; border-bottom: 1px solid #eee; overflow: hidden;} + +.layui-menu .layui-menu-item-up:hover, +.layui-menu .layui-menu-item-down:hover{cursor: pointer;} +.layui-menu .layui-menu-item-up>.layui-menu-body-title{ color: rgba(0,0,0,.8);} +.layui-menu .layui-menu-item-up>ul{visibility: hidden; height: 0; overflow: hidden;} +.layui-menu .layui-menu-item-up>.layui-menu-body-title:hover>.layui-icon, +.layui-menu .layui-menu-item-down:hover>.layui-menu-body-title>.layui-icon{color: rgba(0,0,0,1);} +.layui-menu .layui-menu-item-down>ul{visibility: visible; height: auto;} + +.layui-menu .layui-menu-item-checked, +.layui-menu .layui-menu-item-checked2{background-color: #F6F6F6!important; color: #5FB878;} +.layui-menu .layui-menu-item-checked a, +.layui-menu .layui-menu-item-checked2 a{color: #5FB878;} +.layui-menu .layui-menu-item-checked:after{position: absolute; right: 0; top: 0; bottom: 0; border-right: 3px solid #5FB878; content: "";} + +.layui-menu-body-title{position: relative; overflow: hidden; text-overflow: ellipsis;} +.layui-menu-body-title a{display: block; margin: -5px -15px; color: rgba(0,0,0,.8);} +.layui-menu-body-title a:hover{transition: all .3s;} +.layui-menu-body-title>.layui-icon{position: absolute; right: 0; top: 0; font-size: 14px;} +.layui-menu-body-title>.layui-icon:hover{transition: all .3s;} +.layui-menu-body-title>.layui-icon-right{right: -1px;} +.layui-menu-body-panel{display: none; position: absolute; top: -7px; left: 100%; z-index: 1000; margin-left: 13px; padding: 5px 0;} +.layui-menu-body-panel:before{content: ""; position: absolute; width: 20px; left: -16px; top: 0; bottom: 0;} +.layui-menu-body-panel-left{left: auto; right: 100%; margin: 0 13px 0;} +.layui-menu-body-panel-left:before{left: auto; right: -16px;} + +.layui-menu-lg li{line-height: 32px;} +.layui-menu-lg li:hover, +.layui-menu-lg .layui-menu-body-title a:hover{background: none; color: #5FB878;} +.layui-menu-lg li .layui-menu-body-panel{margin-left: 14px} +.layui-menu-lg li .layui-menu-body-panel-left{margin: 0 15px 0;} + + +/* 下拉菜单 */ +.layui-dropdown{position: absolute; left: -999999px; top: -999999px; z-index: 66666666; margin: 5px 0; min-width: 100px;} +.layui-dropdown:before{content:""; position: absolute; width: 100%; height: 6px; left: 0; top: -6px;} + + + +/** 导航菜单 **/ +.layui-nav{position: relative; padding: 0 20px; background-color: #393D49; color: #fff; border-radius: 2px; font-size: 0; box-sizing: border-box;} +.layui-nav *{font-size: 14px;} +.layui-nav .layui-nav-item{position: relative; display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; line-height: 60px;} +.layui-nav .layui-nav-item a{display: block; padding: 0 20px; color: #fff; color: rgba(255,255,255,.7); transition: all .3s; -webkit-transition: all .3s;} +.layui-nav-bar, +.layui-nav .layui-this:after{content: ""; position: absolute; left: 0; top: 0; width: 0; height: 5px; background-color: #5FB878; transition: all .2s; -webkit-transition: all .2s; pointer-events: none;} +.layui-nav-bar{z-index: 1000;} +.layui-nav[lay-bar="disabled"] .layui-nav-bar{display: none;} +.layui-nav[lay-bar="disabled"].layui-this:after{} +.layui-nav .layui-this a +,.layui-nav .layui-nav-item a:hover{color: #fff;} +.layui-nav .layui-this:after{top: auto; bottom: 0; width: 100%;} +.layui-nav-img{width: 30px; height: 30px; margin-right: 10px; border-radius: 50%;} + +.layui-nav .layui-nav-more{position: absolute; top: 0; right: 3px; left: auto !important; margin-top: 0; font-size: 12px; cursor: pointer; transition: all .2s; -webkit-transition: all .2s;} +.layui-nav .layui-nav-mored, +.layui-nav-itemed > a .layui-nav-more{transform: rotate(180deg);} + + +.layui-nav-child{display: none; position: absolute; left: 0; top: 65px; min-width: 100%; line-height: 36px; padding: 5px 0; box-shadow: 0 2px 4px rgba(0,0,0,.12); border: 1px solid #eee; background-color: #fff; z-index: 100; border-radius: 2px; white-space: nowrap;} +.layui-nav .layui-nav-child a{color: #666; color: rgba(0,0,0,.8);} +.layui-nav .layui-nav-child a:hover{background-color: #F6F6F6; color: rgba(0,0,0,.8);} +.layui-nav-child dd{margin: 1px 0; position: relative;} +.layui-nav-child dd.layui-this{background-color: #F6F6F6; color: #000;} +.layui-nav-child dd.layui-this:after{display: none;} +.layui-nav-child-r{left: auto; right: 0;} +.layui-nav-child-c{text-align: center;} + +/* 垂直导航菜单 */.layui-nav-tree{width: 200px; padding: 0;} +.layui-nav-tree .layui-nav-item{display: block; width: 100%; line-height: 40px;} +.layui-nav-tree .layui-nav-item a{position: relative; height: 40px; line-height: 40px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} +.layui-nav-tree .layui-nav-item>a{padding-top: 5px; padding-bottom: 5px;} +.layui-nav-tree .layui-nav-more{right: 15px;} +.layui-nav-tree .layui-nav-item>a .layui-nav-more{padding: 5px 0;} +.layui-nav-tree .layui-nav-bar{width: 5px; height: 0;} +.layui-side .layui-nav-tree .layui-nav-bar{width: 2px;} +.layui-nav-tree .layui-this, +.layui-nav-tree .layui-this>a, +.layui-nav-tree .layui-this>a:hover, +.layui-nav-tree .layui-nav-child dd.layui-this, +.layui-nav-tree .layui-nav-child dd.layui-this a{background-color: #009688; color: #fff;} +.layui-nav-tree .layui-this:after{display: none;} +.layui-nav-tree .layui-nav-title a, +.layui-nav-tree .layui-nav-title a:hover, +.layui-nav-itemed>a{color: #fff !important;} +.layui-nav-tree .layui-nav-bar{background-color: #009688;} + +.layui-nav-tree .layui-nav-child{position: relative; z-index: 0; top: 0; border: none; box-shadow: none;} +.layui-nav-tree .layui-nav-child dd{margin: 0;} +.layui-nav-tree .layui-nav-child a{color: #fff; color: rgba(255,255,255,.7);} +.layui-nav-tree .layui-nav-child a:hover, +.layui-nav-tree .layui-nav-child{background: none; color: #fff;} + +.layui-nav-itemed>.layui-nav-child{display: block; background-color: rgba(0,0,0,.3) !important;} +.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display: block;} + +/* 侧边 */.layui-nav-side{position: fixed; top: 0; bottom: 0; left: 0; overflow-x: hidden; z-index: 999;} + + +/** 面包屑 **/ +.layui-breadcrumb{visibility: hidden; font-size: 0;} +.layui-breadcrumb>*{font-size: 14px;} +.layui-breadcrumb a{color: #999 !important;} +.layui-breadcrumb a:hover{color: #5FB878 !important;} +.layui-breadcrumb a cite{color: #666; font-style: normal;} +.layui-breadcrumb span[lay-separator]{margin: 0 10px; color: #999;} + +/** Tab 选项卡 **/ +.layui-tab{margin: 10px 0; text-align: left !important;} +.layui-tab[overflow]>.layui-tab-title{overflow: hidden;} +.layui-tab-title{position: relative; left: 0; height: 40px; white-space: nowrap; font-size: 0; border-bottom-width: 1px; border-bottom-style: solid; transition: all .2s; -webkit-transition: all .2s;} +.layui-tab-title li{display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; font-size: 14px; transition: all .2s; -webkit-transition: all .2s;} +.layui-tab-title li{position: relative; line-height: 40px; min-width: 65px; padding: 0 15px; text-align: center; cursor: pointer;} +.layui-tab-title li a{display: block; padding: 0 15px; margin: 0 -15px;} +.layui-tab-title .layui-this{color: #000;} + +.layui-tab-title .layui-this:after{position: absolute; left:0; top: 0; content: ""; width:100%; height: 41px; border-width: 1px; border-style: solid; border-bottom-color: #fff; border-radius: 2px 2px 0 0; box-sizing: border-box; pointer-events: none;} +.layui-tab-bar{position: absolute; right: 0; top: 0; z-index: 10; width: 30px; height: 39px; line-height: 39px; border-width: 1px; border-style: solid; border-radius: 2px; text-align: center; background-color: #fff; cursor: pointer;} +.layui-tab-bar .layui-icon{position: relative; display: inline-block; top: 3px; transition: all .3s; -webkit-transition: all .3s;} +.layui-tab-item{display: none;} +.layui-tab-more{padding-right: 30px; height: auto !important; white-space: normal !important;} +.layui-tab-more li.layui-this:after{border-bottom-color: #eee; border-radius: 2px;} +.layui-tab-more .layui-tab-bar .layui-icon{top: -2px; top: 3px\0; -webkit-transform: rotate(180deg); transform: rotate(180deg);} +:root .layui-tab-more .layui-tab-bar .layui-icon{top: -2px\0/IE9;} + +.layui-tab-content{padding: 15px 0;} + +/* Tab 关闭 */.layui-tab-title li .layui-tab-close{position: relative; display: inline-block; width: 18px; height: 18px; line-height: 20px; margin-left: 8px; top: 1px; text-align: center; font-size: 14px; color: #c2c2c2; transition: all .2s; -webkit-transition: all .2s;} +.layui-tab-title li .layui-tab-close:hover{border-radius: 2px; background-color: #FF5722; color: #fff;} + +/* Tab 简洁风格 */.layui-tab-brief > .layui-tab-title .layui-this{color: #009688;} +.layui-tab-brief > .layui-tab-title .layui-this:after +,.layui-tab-brief > .layui-tab-more li.layui-this:after{border: none; border-radius: 0; border-bottom: 2px solid #5FB878;} +.layui-tab-brief[overflow] > .layui-tab-title .layui-this:after{top: -1px;} + +/* Tab 卡片风格 */.layui-tab-card{border-width: 1px; border-style: solid; border-radius: 2px; box-shadow: 0 2px 5px 0 rgba(0,0,0,.1);} +.layui-tab-card > .layui-tab-title{background-color: #FAFAFA;} +.layui-tab-card > .layui-tab-title li{margin-right: -1px; margin-left: -1px;} +.layui-tab-card > .layui-tab-title .layui-this{background-color: #fff; } +.layui-tab-card > .layui-tab-title .layui-this:after{border-top: none; border-width: 1px; border-bottom-color: #fff;} +.layui-tab-card > .layui-tab-title .layui-tab-bar{height: 40px; line-height: 40px; border-radius: 0; border-top: none; border-right: none;} +.layui-tab-card > .layui-tab-more .layui-this{background: none; color: #5FB878;} +.layui-tab-card > .layui-tab-more .layui-this:after{border: none;} + +/* 时间线 */ +.layui-timeline{padding-left: 5px;} +.layui-timeline-item{position: relative; padding-bottom: 20px;} +.layui-timeline-axis{position: absolute; left: -5px; top: 0; z-index: 10; width: 20px; height: 20px; line-height: 20px; background-color: #fff; color: #5FB878; border-radius: 50%; text-align: center; cursor: pointer;} +.layui-timeline-axis:hover{color: #FF5722;} +.layui-timeline-item:before{content: ""; position: absolute; left: 5px; top: 0; z-index: 0; width: 1px; height: 100%;} + +.layui-timeline-item:first-child:before{display: block;} +.layui-timeline-item:last-child:before{display: none;} +.layui-timeline-content{padding-left: 25px;;} +.layui-timeline-title{position: relative; margin-bottom: 10px; line-height: 22px;} + +/* 小徽章 */ +.layui-badge, +.layui-badge-dot, +.layui-badge-rim{position:relative; display: inline-block; padding: 0 6px; font-size: 12px; text-align: center; background-color: #FF5722; color: #fff; border-radius: 2px;} +.layui-badge{height: 18px; line-height: 18px;} +.layui-badge-dot{width: 8px; height: 8px; padding: 0; border-radius: 50%;} +.layui-badge-rim{height: 18px; line-height: 18px; border-width: 1px; border-style: solid; background-color: #fff; color: #666;} + +.layui-btn .layui-badge, +.layui-btn .layui-badge-dot{margin-left: 5px;} +.layui-nav .layui-badge, +.layui-nav .layui-badge-dot{position: absolute; top: 50%; margin: -5px 6px 0;} +.layui-nav .layui-badge{margin-top: -10px;} +.layui-tab-title .layui-badge, +.layui-tab-title .layui-badge-dot{left: 5px; top: -2px;} + +/* carousel 轮播 */ +.layui-carousel{position: relative; left: 0; top: 0; background-color: #f8f8f8;} +.layui-carousel>*[carousel-item]{position: relative; width: 100%; height: 100%; overflow: hidden;} +.layui-carousel>*[carousel-item]:before{position: absolute; content: '\e63d'; left: 50%; top: 50%; width: 100px; line-height: 20px; margin: -10px 0 0 -50px; text-align: center; color: #c2c2c2; font-family:"layui-icon" !important; font-size: 30px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;} +.layui-carousel>*[carousel-item] > *{display: none; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #f8f8f8; transition-duration: .3s; -webkit-transition-duration: .3s;} +.layui-carousel-updown > *{-webkit-transition: .3s ease-in-out up; transition: .3s ease-in-out up;} +.layui-carousel-arrow{display: none\0; opacity: 0; position: absolute; left: 10px; top: 50%; margin-top: -18px; width: 36px; height: 36px; line-height: 36px; text-align: center; font-size: 20px; border: none 0; border-radius: 50%; background-color: rgba(0,0,0,.2); color: #fff; -webkit-transition-duration: .3s; transition-duration: .3s; cursor: pointer;} +.layui-carousel-arrow[lay-type="add"]{left: auto!important; right: 10px;} +.layui-carousel[lay-arrow="always"] .layui-carousel-arrow{opacity: 1; left: 20px;} +.layui-carousel[lay-arrow="always"] .layui-carousel-arrow[lay-type="add"]{right: 20px;} +.layui-carousel[lay-arrow="none"] .layui-carousel-arrow{display: none;} +.layui-carousel-arrow:hover, +.layui-carousel-ind ul:hover{background-color: rgba(0,0,0,.35);} +.layui-carousel:hover .layui-carousel-arrow{display: block\0; opacity: 1; left: 20px;} +.layui-carousel:hover .layui-carousel-arrow[lay-type="add"]{right: 20px;} +.layui-carousel-ind{position: relative; top: -35px; width: 100%; line-height: 0!important; text-align: center; font-size: 0;} +.layui-carousel[lay-indicator="outside"]{margin-bottom: 30px;} +.layui-carousel[lay-indicator="outside"] .layui-carousel-ind{top: 10px;} +.layui-carousel[lay-indicator="outside"] .layui-carousel-ind ul{background-color: rgba(0,0,0,.5);} +.layui-carousel[lay-indicator="none"] .layui-carousel-ind{display: none;} +.layui-carousel-ind ul{display: inline-block; padding: 5px; background-color: rgba(0,0,0,.2); border-radius: 10px; -webkit-transition-duration: .3s; transition-duration: .3s;} +.layui-carousel-ind li{display: inline-block; width: 10px; height: 10px; margin: 0 3px; font-size: 14px; background-color: #eee; background-color: rgba(255,255,255,.5); border-radius: 50%; cursor: pointer; -webkit-transition-duration: .3s; transition-duration: .3s;} +.layui-carousel-ind li:hover{background-color: rgba(255,255,255,.7);} +.layui-carousel-ind li.layui-this{background-color: #fff;} +.layui-carousel>*[carousel-item]>.layui-this, +.layui-carousel>*[carousel-item]>.layui-carousel-prev, +.layui-carousel>*[carousel-item]>.layui-carousel-next{display: block} +.layui-carousel>*[carousel-item]>.layui-this{left: 0;} +.layui-carousel>*[carousel-item]>.layui-carousel-prev{left: -100%;} +.layui-carousel>*[carousel-item]>.layui-carousel-next{left: 100%;} +.layui-carousel>*[carousel-item]>.layui-carousel-prev.layui-carousel-right, +.layui-carousel>*[carousel-item]>.layui-carousel-next.layui-carousel-left{left: 0;} +.layui-carousel>*[carousel-item]>.layui-this.layui-carousel-left{left: -100%;} +.layui-carousel>*[carousel-item]>.layui-this.layui-carousel-right{left: 100%;} + +/* 上下切换 */.layui-carousel[lay-anim="updown"] .layui-carousel-arrow{left: 50%!important; top: 20px; margin: 0 0 0 -18px;} +.layui-carousel[lay-anim="updown"] .layui-carousel-arrow[lay-type="add"]{top: auto!important; bottom: 20px;} +.layui-carousel[lay-anim="updown"] .layui-carousel-ind{position: absolute; top: 50%; right: 20px; width: auto; height: auto;} +.layui-carousel[lay-anim="updown"] .layui-carousel-ind ul{padding: 3px 5px;} +.layui-carousel[lay-anim="updown"] .layui-carousel-ind li{display: block; margin: 6px 0;} + +.layui-carousel[lay-anim="updown"]>*[carousel-item]>*{left: 0!important;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-this{top: 0;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-carousel-prev{top: -100%;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-carousel-next{top: 100%;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-carousel-prev.layui-carousel-right, +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-carousel-next.layui-carousel-left{top: 0;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-this.layui-carousel-left{top: -100%;} +.layui-carousel[lay-anim="updown"]>*[carousel-item]>.layui-this.layui-carousel-right{top: 100%;} + +/* 渐显切换 */.layui-carousel[lay-anim="fade"]>*[carousel-item]>*{left: 0!important;} +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-carousel-prev, +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-carousel-next{opacity: 0;} +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-carousel-prev.layui-carousel-right, +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-carousel-next.layui-carousel-left{opacity: 1;} +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-this.layui-carousel-left, +.layui-carousel[lay-anim="fade"]>*[carousel-item]>.layui-this.layui-carousel-right{opacity: 0} + +/** fixbar **/ +.layui-fixbar{position: fixed; right: 15px; bottom: 15px; z-index: 999999;} +.layui-fixbar li{width: 50px; height: 50px; line-height: 50px; margin-bottom: 1px; text-align:center; cursor: pointer; font-size:30px; background-color: #9F9F9F; color:#fff; border-radius: 2px; opacity: 0.95;} +.layui-fixbar li:hover{opacity: 0.85;} +.layui-fixbar li:active{opacity: 1;} +.layui-fixbar .layui-fixbar-top{display: none; font-size: 40px;} + +/** 表情面板 **/ +body .layui-util-face{border: none; background: none;} +body .layui-util-face .layui-layer-content{padding:0; background-color:#fff; color:#666; box-shadow:none} +.layui-util-face .layui-layer-TipsG{display:none;} +.layui-util-face ul{position:relative; width:372px; padding:10px; border:1px solid #D9D9D9; background-color:#fff; box-shadow: 0 0 20px rgba(0,0,0,.2);} +.layui-util-face ul li{cursor: pointer; float: left; border: 1px solid #e8e8e8; height: 22px; width: 26px; overflow: hidden; margin: -1px 0 0 -1px; padding: 4px 2px; text-align: center;} +.layui-util-face ul li:hover{position: relative; z-index: 2; border: 1px solid #eb7350; background: #fff9ec;} + +/** 代码文本修饰 **/ +.layui-code{position: relative; margin: 10px 0; padding: 15px; line-height: 20px; border: 1px solid #eee; border-left-width: 6px; background-color: #FAFAFA; color: #333; font-family: Courier New; font-size: 12px;} + +/** 穿梭框 **/ +.layui-transfer-box, +.layui-transfer-header, +.layui-transfer-search{border-width: 0; border-style: solid; border-color: #eee} +.layui-transfer-box{position: relative; display: inline-block; vertical-align: middle; border-width: 1px; width: 200px; height: 360px; border-radius: 2px; background-color:#fff;} +.layui-transfer-box .layui-form-checkbox{width: 100%; margin: 0 !important;} +.layui-transfer-header{height: 38px; line-height: 38px; padding: 0 10px; border-bottom-width: 1px;} +.layui-transfer-search{position:relative; padding: 10px; border-bottom-width: 1px;} +.layui-transfer-search .layui-input{height: 32px; padding-left: 30px; font-size: 12px;} +.layui-transfer-search .layui-icon-search{position: absolute; left: 20px; top: 50%; margin-top: -8px; color: #666;} +.layui-transfer-active{margin: 0 15px; display: inline-block; vertical-align: middle;} +.layui-transfer-active .layui-btn{display: block; margin: 0; padding: 0 15px; background-color: #5FB878; border-color: #5FB878; color: #fff;} +.layui-transfer-active .layui-btn-disabled{background-color: #FBFBFB; border-color: #eee; color: #d2d2d2;} +.layui-transfer-active .layui-btn:first-child{margin-bottom: 15px;} +.layui-transfer-active .layui-btn .layui-icon{margin: 0; font-size: 14px !important;} +.layui-transfer-data{padding: 5px 0; overflow: auto;} +.layui-transfer-data li{height: 32px; line-height: 32px; padding: 0 10px;} +.layui-transfer-data li:hover{background-color: #F6F6F6; transition: .5s all;} +.layui-transfer-data .layui-none{padding: 15px 10px; text-align: center; color: #999;} + +/** 评分组件 **/ +.layui-rate, +.layui-rate *{display: inline-block; vertical-align: middle;} +.layui-rate{padding: 10px 5px 10px 0; font-size: 0;} +.layui-rate li i.layui-icon{ font-size: 20px; color: #FFB800;} +.layui-rate li i.layui-icon{margin-right: 5px; transition: all .3s; -webkit-transition: all .3s;} +.layui-rate li i:hover{cursor: pointer; transform: scale(1.12); -webkit-transform: scale(1.12);} +.layui-rate[readonly] li i:hover{cursor: default; transform: scale(1);} + +/** 颜色选择器 **/ +.layui-colorpicker{width: 26px; height: 26px; border: 1px solid #eee; padding: 5px; border-radius: 2px; line-height: 24px; display: inline-block; cursor: pointer; transition: all .3s; -webkit-transition: all .3s;} +.layui-colorpicker:hover{border-color: #d2d2d2;} +.layui-colorpicker.layui-colorpicker-lg{width: 34px; height: 34px; line-height: 32px;} +.layui-colorpicker.layui-colorpicker-sm{width: 24px; height: 24px; line-height: 22px;} +.layui-colorpicker.layui-colorpicker-xs{width: 22px; height: 22px; line-height: 20px;} + +.layui-colorpicker-trigger-bgcolor{display: block; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); border-radius: 2px;} +.layui-colorpicker-trigger-span{display: block; height: 100%; box-sizing: border-box; border: 1px solid rgba(0,0,0,.15); border-radius: 2px; text-align: center;} +.layui-colorpicker-trigger-i{display: inline-block; color: #FFF; font-size: 12px;} +.layui-colorpicker-trigger-i.layui-icon-close{color: #999;} + +.layui-colorpicker-main{position: absolute; left: -999999px; top: -999999px; z-index: 66666666; width: 280px; margin: 5px 0; padding: 7px; background: #FFF; border: 1px solid #d2d2d2; border-radius: 2px; box-shadow: 0 2px 4px rgba(0,0,0,.12);} +.layui-colorpicker-main-wrapper{height: 180px; position: relative;} +.layui-colorpicker-basis{width: 260px; height: 100%; position: relative;} +.layui-colorpicker-basis-white{width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: linear-gradient(90deg, #FFF, hsla(0,0%,100%,0));} +.layui-colorpicker-basis-black{width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: linear-gradient(0deg, #000, transparent);} +.layui-colorpicker-basis-cursor{width: 10px; height: 10px; border: 1px solid #FFF; border-radius: 50%; position: absolute; top: -3px; right: -3px; cursor: pointer;} +.layui-colorpicker-side{position: absolute; top: 0; right: 0; width: 12px; height: 100%; background: linear-gradient(#F00, #FF0, #0F0, #0FF, #00F, #F0F, #F00);} +.layui-colorpicker-side-slider{width: 100%; height: 5px; box-shadow: 0 0 1px #888888; box-sizing: border-box; background: #FFF; border-radius: 1px; border: 1px solid #f0f0f0; cursor: pointer; position: absolute; left: 0;} +.layui-colorpicker-main-alpha{display: none; height: 12px; margin-top: 7px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)} +.layui-colorpicker-alpha-bgcolor{height: 100%; position: relative;} +.layui-colorpicker-alpha-slider{width: 5px; height: 100%; box-shadow: 0 0 1px #888888; box-sizing: border-box; background: #FFF; border-radius: 1px; border: 1px solid #f0f0f0; cursor: pointer; position: absolute; top: 0;} +.layui-colorpicker-main-pre{padding-top: 7px; font-size: 0;} +.layui-colorpicker-pre{width: 20px; height: 20px; border-radius: 2px; display: inline-block; margin-left: 6px; margin-bottom: 7px; cursor: pointer;} +.layui-colorpicker-pre:nth-child(11n+1){margin-left: 0;} +.layui-colorpicker-pre-isalpha{background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)} +.layui-colorpicker-pre.layui-this{box-shadow: 0 0 3px 2px rgba(0,0,0,.15);} +.layui-colorpicker-pre > div{height: 100%; border-radius: 2px;} +.layui-colorpicker-main-input{text-align: right; padding-top: 7px;} +.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin: 0 0 0 10px;} +.layui-colorpicker-main-input div.layui-inline{float: left; margin-right: 10px; font-size: 14px;} +.layui-colorpicker-main-input input.layui-input{width: 150px; height: 30px; color: #666;} + +/** 滑块 **/ +.layui-slider{height: 4px; background: #eee; border-radius: 3px; position: relative; cursor: pointer;} +.layui-slider-bar{border-radius: 3px; position: absolute; height: 100%;} +.layui-slider-step{position: absolute; top: 0; width: 4px; height: 4px; border-radius: 50%; background: #FFF; -webkit-transform: translateX(-50%); transform: translateX(-50%);} +.layui-slider-wrap{width: 36px; height: 36px; position: absolute; top: -16px; -webkit-transform: translateX(-50%); transform: translateX(-50%); z-index: 10; text-align: center;} +.layui-slider-wrap-btn{width: 12px; height: 12px; border-radius: 50%; background: #FFF; display: inline-block; vertical-align: middle; cursor: pointer; transition: 0.3s;} +.layui-slider-wrap:after{content: ""; height: 100%; display: inline-block; vertical-align: middle;} +.layui-slider-wrap-btn:hover, +.layui-slider-wrap-btn.layui-slider-hover{transform: scale(1.2);} +.layui-slider-wrap-btn.layui-disabled:hover{transform: scale(1) !important;} +.layui-slider-tips{position: absolute; top: -42px; z-index: 66666666; white-space:nowrap; display: none; -webkit-transform: translateX(-50%); transform: translateX(-50%); color: #FFF; background: #000; border-radius: 3px; height: 25px; line-height: 25px; padding: 0 10px;} +.layui-slider-tips:after{content: ""; position: absolute; bottom: -12px; left: 50%; margin-left: -6px; width: 0; height: 0; border-width: 6px; border-style: solid; border-color: #000 transparent transparent transparent;} +.layui-slider-input{width: 70px; height: 32px; border: 1px solid #eee; border-radius: 3px; font-size: 16px; line-height: 32px; position: absolute; right: 0; top: -14px;} +.layui-slider-input-btn{position: absolute; top: 0; right: 0; width: 20px; height: 100%; border-left: 1px solid #eee;} +.layui-slider-input-btn i{cursor: pointer; position: absolute; right: 0; bottom: 0; width: 20px; height: 50%; font-size: 12px; line-height: 16px; text-align: center; color: #999;} +.layui-slider-input-btn i:first-child{top: 0; border-bottom: 1px solid #eee;} +.layui-slider-input-txt{height: 100%; font-size: 14px;} +.layui-slider-input-txt input{height: 100%; border: none;} +.layui-slider-input-btn i:hover{color: #009688;} +/*垂直滑块*/ +.layui-slider-vertical{width: 4px; margin-left: 33px;} +.layui-slider-vertical .layui-slider-bar{width: 4px;} +.layui-slider-vertical .layui-slider-step{top: auto; left: 0px; -webkit-transform: translateY(50%); transform: translateY(50%);} +.layui-slider-vertical .layui-slider-wrap{top: auto; left: -16px; -webkit-transform: translateY(50%); transform: translateY(50%);} +.layui-slider-vertical .layui-slider-tips{top: auto; left: 2px;} +@media \0screen{ + .layui-slider-wrap-btn{margin-left: -20px;} + .layui-slider-vertical .layui-slider-wrap-btn{margin-left: 0; margin-bottom: -20px;} + .layui-slider-vertical .layui-slider-tips{margin-left: -8px;} + .layui-slider > span{margin-left: 8px;} +} + +/** 树组件 **/ +.layui-tree{line-height: 22px;} +.layui-tree .layui-form-checkbox{margin: 0 !important;} +.layui-tree-set{width: 100%; position: relative;} +.layui-tree-pack{display: none; padding-left: 20px; position: relative;} +.layui-tree-line .layui-tree-pack{padding-left: 27px;} +.layui-tree-line .layui-tree-set .layui-tree-set:after{content: ""; position: absolute; top: 14px; left: -9px; width: 17px; height: 0; border-top: 1px dotted #c0c4cc;} +.layui-tree-entry{position: relative; padding: 3px 0; height: 20px; white-space: nowrap;} +.layui-tree-entry:hover{background-color: #eee;} +.layui-tree-line .layui-tree-entry:hover{background-color: rgba(0,0,0,0);} +.layui-tree-line .layui-tree-entry:hover .layui-tree-txt{color: #999; text-decoration: underline; transition: 0.3s;} +.layui-tree-main{display: inline-block; vertical-align: middle; cursor: pointer; padding-right: 10px;} +.layui-tree-line .layui-tree-set:before{content: ""; position: absolute; top: 0; left: -9px; width: 0; height: 100%; border-left: 1px dotted #c0c4cc;} +.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before{height: 13px;} +.layui-tree-line .layui-tree-set.layui-tree-setHide:before{height: 0;} +.layui-tree-iconClick{display: inline-block; vertical-align: middle; position: relative; height: 20px; line-height: 20px; margin: 0 10px; color: #c0c4cc;} +.layui-tree-icon{height: 12px; line-height: 12px; width: 12px; text-align: center; border: 1px solid #c0c4cc;} +.layui-tree-iconClick .layui-icon{font-size: 18px;} +.layui-tree-icon .layui-icon{font-size: 12px; color: #666;} +.layui-tree-iconArrow{padding: 0 5px;} +.layui-tree-iconArrow:after{content: ""; position: absolute; left: 4px; top: 3px; z-index: 100; width: 0; height: 0; border-width: 5px; border-style: solid; border-color: transparent transparent transparent #c0c4cc; transition: 0.5s;} +.layui-tree-spread>.layui-tree-entry .layui-tree-iconClick>.layui-tree-iconArrow:after{transform: rotate(90deg) translate(3px, 4px);} +.layui-tree-txt{display: inline-block; vertical-align: middle; color: #555;} +.layui-tree-search{margin-bottom: 15px; color: #666;} +.layui-tree-btnGroup{visibility: hidden; display: inline-block; vertical-align: middle; position: relative;} +.layui-tree-btnGroup .layui-icon{display: inline-block; vertical-align: middle; padding: 0 2px; cursor: pointer;} +.layui-tree-btnGroup .layui-icon:hover{color: #999; transition: 0.3s;} +.layui-tree-entry:hover .layui-tree-btnGroup{visibility: visible;} +.layui-tree-editInput{position: relative; display: inline-block; vertical-align: middle; height: 20px; line-height: 20px; padding: 0 3px; border: none; background-color: rgba(0,0,0,0.05);} +.layui-tree-emptyText{text-align: center; color: #999;} + + + + +/** 动画 **/ +.layui-anim{-webkit-animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-duration: 0.3s; animation-fill-mode: both;} +.layui-anim.layui-icon{display: inline-block;} +.layui-anim-loop{-webkit-animation-iteration-count: infinite; animation-iteration-count: infinite;} +.layui-trans, +.layui-trans a{transition: all .2s; -webkit-transition: all .2s;} /* 过度变换 */ + +/* 循环旋转 */ +@-webkit-keyframes layui-rotate{ + from {-webkit-transform: rotate(0deg);} + to {-webkit-transform: rotate(360deg);} +} +@keyframes layui-rotate{ + from {transform: rotate(0deg);} + to {transform: rotate(360deg);} +} +.layui-anim-rotate{-webkit-animation-name: layui-rotate; animation-name: layui-rotate; -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-timing-function: linear; animation-timing-function: linear;} + +/* 从最底部往上滑入 */ +@-webkit-keyframes layui-up{ + from {-webkit-transform: translate3d(0, 100%, 0); opacity: 0.3;} + to {-webkit-transform: translate3d(0, 0, 0); opacity: 1;} +} +@keyframes layui-up{ + from {transform: translate3d(0, 100%, 0); opacity: 0.3;} + to {transform: translate3d(0, 0, 0); opacity: 1;} +} +.layui-anim-up{-webkit-animation-name: layui-up; animation-name: layui-up;} + +/* 微微往上滑入 */ +@-webkit-keyframes layui-upbit{ + from {-webkit-transform: translate3d(0, 15px, 0); opacity: 0.3;} + to {-webkit-transform: translate3d(0, 0, 0); opacity: 1;} +} +@keyframes layui-upbit{ + from {transform: translate3d(0, 15px, 0); opacity: 0.3;} + to {transform: translate3d(0, 0, 0); opacity: 1;} +} +.layui-anim-upbit{-webkit-animation-name: layui-upbit; animation-name: layui-upbit;} + +/* 从最顶部往下滑入 */ +@keyframes layui-down { + 0% {opacity: 0.3; transform: translate3d(0, -100%, 0);} + 100% {opacity: 1; transform: translate3d(0, 0, 0);} +} +.layui-anim-down{animation-name: layui-down;} + +/* 微微往下滑入 */ +@keyframes layui-downbit { + 0% {opacity: 0.3; transform: translate3d(0, -5px, 0);} + 100% {opacity: 1; transform: translate3d(0, 0, 0);} +} +.layui-anim-downbit{animation-name: layui-downbit;} + +/* 放大 */ +@-webkit-keyframes layui-scale { + 0% {opacity: 0.3; -webkit-transform: scale(.5);} + 100% {opacity: 1; -webkit-transform: scale(1);} +} +@keyframes layui-scale { + 0% {opacity: 0.3; -ms-transform: scale(.5); transform: scale(.5);} + 100% {opacity: 1; -ms-transform: scale(1); transform: scale(1);} +} +.layui-anim-scale{-webkit-animation-name: layui-scale; animation-name: layui-scale} + +/* 弹簧式放大 */ +@-webkit-keyframes layui-scale-spring { + 0% {opacity: 0.5; -webkit-transform: scale(.5);} + 80% {opacity: 0.8; -webkit-transform: scale(1.1);} + 100% {opacity: 1; -webkit-transform: scale(1);} +} +@keyframes layui-scale-spring { + 0% {opacity: 0.5; transform: scale(.5);} + 80% {opacity: 0.8; transform: scale(1.1);} + 100% {opacity: 1; transform: scale(1);} +} +.layui-anim-scaleSpring{-webkit-animation-name: layui-scale-spring; animation-name: layui-scale-spring} + +/* 放小 */ +@keyframes layui-scalesmall { + 0% {opacity: 0.3; transform: scale(1.5);} + 100% {opacity: 1; transform: scale(1);} +} +.layui-anim-scalesmall{animation-name: layui-scalesmall} + +/* 弹簧式放小 */ +@keyframes layui-scalesmall-spring { + 0% {opacity: 0.3; transform: scale(1.5);} + 80% {opacity: 0.8; transform: scale(0.9);} + 100% {opacity: 1; transform: scale(1);} +} +.layui-anim-scalesmall-spring{animation-name: layui-scalesmall-spring} + + +/* 渐显 */ +@-webkit-keyframes layui-fadein { + 0% {opacity: 0;} + 100% {opacity: 1;} +} +@keyframes layui-fadein { + 0% {opacity: 0;} + 100% {opacity: 1;} +} +.layui-anim-fadein{-webkit-animation-name: layui-fadein; animation-name: layui-fadein;} + +/* 渐隐 */ +@-webkit-keyframes layui-fadeout { + 0% {opacity: 1;} + 100% {opacity: 0;} +} +@keyframes layui-fadeout { + 0% {opacity: 1;} + 100% {opacity: 0;} +} +.layui-anim-fadeout{-webkit-animation-name: layui-fadeout; animation-name: layui-fadeout} + + + + diff --git a/static/layui/css/modules/code.css b/static/layui/css/modules/code.css new file mode 100644 index 0000000..efb79d2 --- /dev/null +++ b/static/layui/css/modules/code.css @@ -0,0 +1,29 @@ +/** + + @Name: layui.code + @Description:Classic modular front-end UI framework + @License:MIT + + */ + +/* 加载就绪标志 */ +html #layuicss-skincodecss{display:none; position: absolute; width:1989px;} + +/* 默认风格 */ +.layui-code-view{display: block; position: relative; margin: 10px 0; padding: 0; border: 1px solid #eee; border-left-width: 6px; background-color: #FAFAFA; color: #333; font-family: Courier New; font-size: 12px;} +.layui-code-h3{position: relative; padding: 0 10px; height: 40px; line-height: 40px; border-bottom: 1px solid #eee; font-size: 12px;} +.layui-code-h3 a{position: absolute; right: 10px; top: 0; color: #999;} +.layui-code-view .layui-code-ol{position: relative; overflow: auto;} +.layui-code-view .layui-code-ol li{position: relative; margin-left: 45px; line-height: 20px; padding: 0 10px; border-left: 1px solid #e2e2e2; list-style-type: decimal-leading-zero; *list-style-type: decimal; background-color: #fff;} +.layui-code-view .layui-code-ol li:first-child{padding-top: 10px;} +.layui-code-view .layui-code-ol li:last-child{padding-bottom: 10px;} +.layui-code-view pre{margin: 0;} + +/* notepadd++风格 */ +.layui-code-notepad{border: 1px solid #0C0C0C; border-left-color: #3F3F3F; background-color: #0C0C0C; color: #C2BE9E} +.layui-code-notepad .layui-code-h3{border-bottom: none;} +.layui-code-notepad .layui-code-ol li{background-color: #3F3F3F; border-left: none;} + +/* 代码预览 */ +.layui-code-demo .layui-code{visibility: visible !important; margin: -15px; border-top: none; border-right: none; border-bottom: none;} +.layui-code-demo .layui-tab-content{padding: 15px; border-top: none} \ No newline at end of file diff --git a/static/layui/css/modules/laydate/default/font.css b/static/layui/css/modules/laydate/default/font.css new file mode 100644 index 0000000..f429656 --- /dev/null +++ b/static/layui/css/modules/laydate/default/font.css @@ -0,0 +1,16 @@ +/** 图标字体 **/ +@font-face {font-family: 'laydate-icon'; + src: url('./font/iconfont.eot'); + src: url('./font/iconfont.eot#iefix') format('embedded-opentype'), + url('./font/iconfont.svg#iconfont') format('svg'), + url('./font/iconfont.woff') format('woff'), + url('./font/iconfont.ttf') format('truetype'); +} + +.laydate-icon{ + font-family:"laydate-icon" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file diff --git a/static/layui/css/modules/laydate/default/laydate.css b/static/layui/css/modules/laydate/default/laydate.css new file mode 100644 index 0000000..2f54cf9 --- /dev/null +++ b/static/layui/css/modules/laydate/default/laydate.css @@ -0,0 +1,152 @@ +/** + + @Name: laydata + + **/ + + +html #layuicss-laydate{display: none; position: absolute; width: 1989px;} + +/* 初始化 */ +.layui-laydate *{margin: 0; padding: 0;} + +/* 主体结构 */ +.layui-laydate, .layui-laydate *{box-sizing: border-box;} +.layui-laydate{position: absolute; z-index: 66666666; margin: 5px 0; border-radius: 2px; font-size: 14px; -webkit-animation-duration: 0.2s; animation-duration: 0.2s; -webkit-animation-fill-mode: both; animation-fill-mode: both;} +.layui-laydate-main{width: 272px;} +.layui-laydate-header *, +.layui-laydate-content td, +.layui-laydate-list li{transition-duration: .3s; -webkit-transition-duration: .3s;} + +/* 微微往下滑入 */ +@keyframes laydate-downbit { + 0% {opacity: 0.3; transform: translate3d(0, -5px, 0);} + 100% {opacity: 1; transform: translate3d(0, 0, 0);} +} + +.layui-laydate{animation-name: laydate-downbit;} +.layui-laydate-static{ position: relative; z-index: 0; display: inline-block; margin: 0; -webkit-animation: none; animation: none;} + +/* 展开年月列表时 */ +.laydate-ym-show .laydate-prev-m, +.laydate-ym-show .laydate-next-m{display: none !important;} +.laydate-ym-show .laydate-prev-y, +.laydate-ym-show .laydate-next-y{display: inline-block !important;} +.laydate-ym-show .laydate-set-ym span[lay-type="month"]{display: none !important;} + +/* 展开时间列表时 */ +.laydate-time-show .layui-laydate-header .layui-icon, +.laydate-time-show .laydate-set-ym span[lay-type="year"], +.laydate-time-show .laydate-set-ym span[lay-type="month"]{display: none !important;} + +/* 头部结构 */ +.layui-laydate-header{position: relative; line-height:30px; padding: 10px 70px 5px;} +.layui-laydate-header *{display: inline-block; vertical-align: bottom;} +.layui-laydate-header i{position: absolute; top: 10px; padding: 0 5px; color: #999; font-size: 18px; cursor: pointer;} +.layui-laydate-header i.laydate-prev-y{left: 15px;} +.layui-laydate-header i.laydate-prev-m{left: 45px;} +.layui-laydate-header i.laydate-next-y{right: 15px;} +.layui-laydate-header i.laydate-next-m{right: 45px;} +.laydate-set-ym{width: 100%; text-align: center; box-sizing: border-box; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} +.laydate-set-ym span{padding: 0 10px; cursor: pointer;} +.laydate-time-text{cursor: default !important;} + +/* 主体结构 */ +.layui-laydate-content{position: relative; padding: 10px; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} +.layui-laydate-content table{border-collapse: collapse; border-spacing: 0;} +.layui-laydate-content th, +.layui-laydate-content td{width: 36px; height: 30px; padding: 5px; text-align: center;} +.layui-laydate-content th{font-weight: 400;} +.layui-laydate-content td{position: relative; cursor: pointer;} +.laydate-day-mark{position: absolute; left: 0; top: 0; width: 100%; line-height: 30px; font-size: 12px; overflow: hidden;} +.laydate-day-mark::after{position: absolute; content:''; right: 2px; top: 2px; width: 5px; height: 5px; border-radius: 50%;} + +/* 底部结构 */ +.layui-laydate-footer{position: relative; height: 46px; line-height: 26px; padding: 10px;} +.layui-laydate-footer span{display: inline-block; vertical-align: top; height: 26px; line-height: 24px; padding: 0 10px; border: 1px solid #C9C9C9; border-radius: 2px; background-color: #fff; font-size: 12px; cursor: pointer; white-space: nowrap; transition: all .3s;} +.layui-laydate-footer span:hover{color: #5FB878;} +.layui-laydate-footer span.layui-laydate-preview{cursor: default; border-color: transparent !important;} +.layui-laydate-footer span.layui-laydate-preview:hover{color: #666;} +.layui-laydate-footer span:first-child.layui-laydate-preview{padding-left: 0;} +.laydate-footer-btns{position: absolute; right: 10px; top: 10px;} +.laydate-footer-btns span{margin: 0 0 0 -1px;} + +/* 年月列表 */ +.layui-laydate-list{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding: 10px; box-sizing: border-box; background-color: #fff;} +.layui-laydate-list>li{position: relative; display: inline-block; width: 33.3%; height: 36px; line-height: 36px; margin: 3px 0; vertical-align: middle; text-align: center; cursor: pointer;} +.laydate-month-list>li{width: 25%; margin: 17px 0;} +.laydate-time-list{} +.laydate-time-list>li{height: 100%; margin: 0; line-height: normal; cursor: default;} +.laydate-time-list p{position: relative; top: -4px; line-height: 29px;} +.laydate-time-list ol{height: 181px; overflow: hidden;} +.laydate-time-list>li:hover ol{overflow-y: auto;} +.laydate-time-list ol li{width: 130%; padding-left: 33px; height: 30px; line-height: 30px; text-align: left; cursor: pointer;} + +/* 提示 */ +.layui-laydate-hint{position: absolute; top: 115px; left: 50%; width: 250px; margin-left: -125px; line-height: 20px; padding: 15px; text-align: center; font-size: 12px; color: #FF5722;} + + +/* 双日历 */ +.layui-laydate-range{width: 546px;} +.layui-laydate-range .layui-laydate-main{display: inline-block; vertical-align: middle;} +.layui-laydate-range .laydate-main-list-1 .layui-laydate-header, +.layui-laydate-range .laydate-main-list-1 .layui-laydate-content{border-left: 1px solid #e2e2e2;} + + +/* 默认简约主题 */ +.layui-laydate, .layui-laydate-hint{border: 1px solid #d2d2d2; box-shadow: 0 2px 4px rgba(0,0,0,.12); background-color: #fff; color: #666;} +.layui-laydate-header{border-bottom: 1px solid #e2e2e2;} +.layui-laydate-header i:hover, +.layui-laydate-header span:hover{color: #5FB878;} +.layui-laydate-content{border-top: none 0; border-bottom: none 0;} +.layui-laydate-content th{color: #333;} +.layui-laydate-content td{color: #666;} +.layui-laydate-content td.laydate-selected{background-color: #B5FFF8;} +.laydate-selected:hover{background-color: #00F7DE !important;} +.layui-laydate-content td:hover, +.layui-laydate-list li:hover{background-color: #eee; color: #333;} +.laydate-time-list li ol{margin: 0; padding: 0; border: 1px solid #e2e2e2; border-left-width: 0;} +.laydate-time-list li:first-child ol{border-left-width: 1px;} +.laydate-time-list>li:hover{background: none;} +.layui-laydate-content .laydate-day-prev, +.layui-laydate-content .laydate-day-next{color: #d2d2d2;} +.laydate-selected.laydate-day-prev, +.laydate-selected.laydate-day-next{background-color: #f8f8f8 !important;} +.layui-laydate-footer{border-top: 1px solid #e2e2e2;} +.layui-laydate-hint{color: #FF5722;} +.laydate-day-mark::after{background-color: #5FB878;} +.layui-laydate-content td.layui-this .laydate-day-mark::after{display: none;} +.layui-laydate-footer span[lay-type="date"]{color: #5FB878;} +.layui-laydate .layui-this{background-color: #009688 !important; color: #fff !important;} +.layui-laydate .laydate-disabled, +.layui-laydate .laydate-disabled:hover{background:none !important; color: #d2d2d2 !important; cursor: not-allowed !important; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} + +/* 墨绿/自定义背景色主题 */ +.laydate-theme-molv{border: none;} +.laydate-theme-molv.layui-laydate-range{width: 548px} +.laydate-theme-molv .layui-laydate-main{width: 274px;} +.laydate-theme-molv .layui-laydate-header{border: none; background-color: #009688;} +.laydate-theme-molv .layui-laydate-header i, +.laydate-theme-molv .layui-laydate-header span{color: #f6f6f6;} +.laydate-theme-molv .layui-laydate-header i:hover, +.laydate-theme-molv .layui-laydate-header span:hover{color: #fff;} +.laydate-theme-molv .layui-laydate-content{border: 1px solid #e2e2e2; border-top: none; border-bottom: none;} +.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content{border-left: none;} +.laydate-theme-molv .layui-laydate-footer{border: 1px solid #e2e2e2;} + +/* 格子主题 */ +.laydate-theme-grid .layui-laydate-content td, +.laydate-theme-grid .layui-laydate-content thead, +.laydate-theme-grid .laydate-year-list>li, +.laydate-theme-grid .laydate-month-list>li{border: 1px solid #e2e2e2;} +.laydate-theme-grid .laydate-selected, +.laydate-theme-grid .laydate-selected:hover{background-color: #f2f2f2 !important; color: #009688 !important;} +.laydate-theme-grid .laydate-selected.laydate-day-prev, +.laydate-theme-grid .laydate-selected.laydate-day-next{color: #d2d2d2 !important;} +.laydate-theme-grid .laydate-year-list, +.laydate-theme-grid .laydate-month-list{margin: 1px 0 0 1px;} +.laydate-theme-grid .laydate-year-list>li, +.laydate-theme-grid .laydate-month-list>li{margin: 0 -1px -1px 0;} +.laydate-theme-grid .laydate-year-list>li{height: 43px; line-height: 43px;} +.laydate-theme-grid .laydate-month-list>li{height: 71px; line-height: 71px;} + diff --git a/static/layui/css/modules/layer/default/icon-ext.png b/static/layui/css/modules/layer/default/icon-ext.png new file mode 100644 index 0000000..bbbb669 Binary files /dev/null and b/static/layui/css/modules/layer/default/icon-ext.png differ diff --git a/static/layui/css/modules/layer/default/icon.png b/static/layui/css/modules/layer/default/icon.png new file mode 100644 index 0000000..3e17da8 Binary files /dev/null and b/static/layui/css/modules/layer/default/icon.png differ diff --git a/static/layui/css/modules/layer/default/layer.css b/static/layui/css/modules/layer/default/layer.css new file mode 100644 index 0000000..54a6aee --- /dev/null +++ b/static/layui/css/modules/layer/default/layer.css @@ -0,0 +1,179 @@ +/** + + @Name: layer + + **/ + +/* *html{background-image: url(about:blank); background-attachment: fixed;} */ +html #layuicss-layer{display: none; position: absolute; width: 1989px;} + +/* common */ +.layui-layer-shade, .layui-layer{position:fixed; _position:absolute; pointer-events: auto;} +.layui-layer-shade{top:0; left:0; width:100%; height:100%; _height:expression(document.body.offsetHeight+"px");} +.layui-layer{-webkit-overflow-scrolling: touch;} +.layui-layer{top:150px; left: 0; margin:0; padding:0; background-color:#fff; -webkit-background-clip: content; border-radius: 2px; box-shadow: 1px 1px 50px rgba(0,0,0,.3);} +.layui-layer-close{position:absolute;} +.layui-layer-content{position:relative;} +.layui-layer-border{border: 1px solid #B2B2B2; border: 1px solid rgba(0,0,0,.1); box-shadow: 1px 1px 5px rgba(0,0,0,.2);} +.layui-layer-load{background:url(loading-1.gif) #eee center center no-repeat;} +.layui-layer-ico{ background:url(icon.png) no-repeat;} +.layui-layer-dialog .layui-layer-ico, +.layui-layer-setwin a, +.layui-layer-btn a{display:inline-block; *display:inline; *zoom:1; vertical-align:top;} + +.layui-layer-move{display: none; position: fixed; *position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; cursor: move; opacity: 0; filter:alpha(opacity=0); background-color: #fff; z-index: 2147483647;} +.layui-layer-resize{position: absolute; width: 15px; height: 15px; right: 0; bottom: 0; cursor: se-resize;} + +/* 动画 */ +.layer-anim{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.3s; animation-duration:.3s;} + +@-webkit-keyframes layer-bounceIn { /* 默认 */ + 0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)} + 100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)} +} +@keyframes layer-bounceIn { + 0% {opacity: 0; -webkit-transform: scale(.5); -ms-transform: scale(.5); transform: scale(.5)} + 100% {opacity: 1; -webkit-transform: scale(1); -ms-transform: scale(1); transform: scale(1)} +} +.layer-anim-00{-webkit-animation-name: layer-bounceIn;animation-name: layer-bounceIn} + +@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown} + +@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig} + +@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft} + +@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0px) rotate(0deg);-ms-transform:translateX(0px) rotate(0deg);transform:translateX(0px) rotate(0deg)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn} + +@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn} + +@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}} + +/* 标题栏 */ +.layui-layer-title{padding:0 80px 0 20px; height: 50px; line-height: 50px; border-bottom:1px solid #F0F0F0; font-size: 14px; color:#333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 2px 2px 0 0;} +.layui-layer-setwin{position:absolute; right: 15px; *right:0; top: 17px; font-size:0; line-height: initial;} +.layui-layer-setwin a{position:relative; width: 16px; height:16px; margin-left:10px; font-size:12px; _overflow:hidden;} +.layui-layer-setwin .layui-layer-min cite{position:absolute; width:14px; height:2px; left:0; top:50%; margin-top:-1px; background-color:#2E2D3C; cursor:pointer; _overflow:hidden;} +.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA; } +.layui-layer-setwin .layui-layer-max{background-position:-32px -40px;} +.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px;} +.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px;} +.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px;} +.layui-layer-setwin .layui-layer-close1{background-position: 1px -40px; cursor: pointer;} +.layui-layer-setwin .layui-layer-close1:hover{opacity:0.7;} +.layui-layer-setwin .layui-layer-close2{position:absolute; right:-28px; top:-28px; width:30px; height:30px; margin-left:0; background-position:-149px -31px; *right:-18px; _display:none;} +.layui-layer-setwin .layui-layer-close2:hover{ background-position:-180px -31px;} + +/* 按钮栏 */ +.layui-layer-btn{text-align: right; padding: 0 15px 12px; pointer-events: auto; user-select: none; -webkit-user-select: none;} +.layui-layer-btn a{height: 28px; line-height: 28px; margin: 5px 5px 0; padding: 0 15px; border: 1px solid #dedede; background-color:#fff; color: #333; border-radius: 2px; font-weight:400; cursor:pointer; text-decoration: none;} +.layui-layer-btn a:hover{opacity: 0.9; text-decoration: none;} +.layui-layer-btn a:active{opacity: 0.8;} +.layui-layer-btn .layui-layer-btn0{border-color: #1E9FFF; background-color: #1E9FFF; color:#fff;} +.layui-layer-btn-l{text-align: left;} +.layui-layer-btn-c{text-align: center;} + +/* 定制化 */ +.layui-layer-dialog{min-width: 300px;} +.layui-layer-dialog .layui-layer-content{position: relative; padding:20px; line-height:24px; word-break: break-all; overflow:hidden; font-size:14px; overflow-x: hidden; overflow-y:auto;} +.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute; top:16px; left:15px; _left:-40px; width:30px; height:30px;} +.layui-layer-ico1{background-position:-30px 0 } +.layui-layer-ico2{background-position:-60px 0;} +.layui-layer-ico3{background-position:-90px 0;} +.layui-layer-ico4{background-position:-120px 0;} +.layui-layer-ico5{background-position:-150px 0;} +.layui-layer-ico6{background-position:-180px 0;} +.layui-layer-rim{border:6px solid #8D8D8D; border:6px solid rgba(0,0,0,.3); border-radius:5px; box-shadow: none;} +.layui-layer-msg{min-width:180px; border:1px solid #D3D4D3; box-shadow: none;} +.layui-layer-hui{min-width:100px; background-color: #000; filter:alpha(opacity=60); background-color: rgba(0,0,0,0.6); color: #fff; border:none;} +.layui-layer-hui .layui-layer-content{padding:12px 25px; text-align:center;} +.layui-layer-dialog .layui-layer-padding{padding: 20px 20px 20px 55px; text-align: left;} +.layui-layer-page .layui-layer-content{position:relative; overflow:auto;} +.layui-layer-page .layui-layer-btn,.layui-layer-iframe .layui-layer-btn{padding-top:10px;} +.layui-layer-nobg{background:none;} +.layui-layer-iframe iframe{display: block; width: 100%;} + +.layui-layer-loading{border-radius:100%; background:none; box-shadow:none; border:none;} +.layui-layer-loading .layui-layer-content{width:60px; height:24px; background:url(loading-0.gif) no-repeat;} +.layui-layer-loading .layui-layer-loading1{width:37px; height:37px; background:url(loading-1.gif) no-repeat;} +.layui-layer-loading .layui-layer-loading2, .layui-layer-ico16{width:32px; height:32px; background:url(loading-2.gif) no-repeat;} +.layui-layer-tips{background: none; box-shadow:none; border:none;} +.layui-layer-tips .layui-layer-content{position: relative; line-height: 22px; min-width: 12px; padding: 8px 15px; font-size: 12px; _float:left; border-radius: 2px; box-shadow: 1px 1px 3px rgba(0,0,0,.2); background-color: #000; color: #fff;} +.layui-layer-tips .layui-layer-close{right:-2px; top:-1px;} +.layui-layer-tips i.layui-layer-TipsG{ position:absolute; width:0; height:0; border-width:8px; border-color:transparent; border-style:dashed; *overflow:hidden;} +.layui-layer-tips i.layui-layer-TipsT, .layui-layer-tips i.layui-layer-TipsB{left:5px; border-right-style:solid; border-right-color: #000;} +.layui-layer-tips i.layui-layer-TipsT{bottom:-8px;} +.layui-layer-tips i.layui-layer-TipsB{top:-8px;} +.layui-layer-tips i.layui-layer-TipsR, .layui-layer-tips i.layui-layer-TipsL{top: 5px; border-bottom-style:solid; border-bottom-color: #000;} +.layui-layer-tips i.layui-layer-TipsR{left:-8px;} +.layui-layer-tips i.layui-layer-TipsL{right:-8px;} + +/* skin */ +.layui-layer-lan[type="dialog"]{min-width:280px;} +.layui-layer-lan .layui-layer-title{background:#4476A7; color:#fff; border: none;} +.layui-layer-lan .layui-layer-btn{padding: 5px 10px 10px; text-align: right; border-top:1px solid #E9E7E7} +.layui-layer-lan .layui-layer-btn a{background: #fff; border-color: #E9E7E7; color: #333;} +.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5;} +.layui-layer-molv .layui-layer-title{background: #009f95; color:#fff; border: none;} +.layui-layer-molv .layui-layer-btn a{background: #009f95; border-color: #009f95;} +.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1;} + + +/** + + @Name: layer拓展样式 + + */ + +.layui-layer-iconext{background:url(icon-ext.png) no-repeat;} + +/* prompt模式 */ +.layui-layer-prompt .layui-layer-input{display: block; width: 260px; height: 36px; margin: 0 auto; line-height: 30px; padding-left: 10px; border: 1px solid #e6e6e6; color: #333;} +.layui-layer-prompt textarea.layui-layer-input{width: 300px; height: 100px; line-height: 20px; padding: 6px 10px;} +.layui-layer-prompt .layui-layer-content{padding: 20px;} +.layui-layer-prompt .layui-layer-btn{padding-top: 0;} + +/* tab模式 */ +.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4);} +.layui-layer-tab .layui-layer-title{padding-left:0; overflow: visible;} +.layui-layer-tab .layui-layer-title span{position:relative; float:left; min-width:80px; max-width: 300px; padding:0 20px; text-align:center; cursor:default; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; cursor: pointer;} +.layui-layer-tab .layui-layer-title span.layui-this{height: 51px; border-left: 1px solid #eee; border-right: 1px solid #eee; background-color: #fff; z-index: 10;} +.layui-layer-tab .layui-layer-title span:first-child{border-left:none;} +.layui-layer-tabmain{line-height:24px; clear:both;} +.layui-layer-tabmain .layui-layer-tabli{display:none;} +.layui-layer-tabmain .layui-layer-tabli.layui-this{display: block;} + +/* photo模式 */ +.layui-layer-photos{background: none; box-shadow: none;} +.layui-layer-photos .layui-layer-content{overflow:hidden; text-align: center;} +.layui-layer-photos .layui-layer-phimg img{position: relative; width:100%; display: inline-block; *display:inline; *zoom:1; vertical-align:top;} +.layui-layer-imgprev, .layui-layer-imgnext{position: fixed; top: 50%; width: 27px; _width: 44px; height: 44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());} +.layui-layer-imgprev{left: 30px; background-position:-5px -5px; _background-position:-70px -5px;} +.layui-layer-imgprev:hover{background-position:-33px -5px; _background-position:-120px -5px;} +.layui-layer-imgnext{right: 30px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;} +.layui-layer-imgnext:hover{background-position: -33px -50px; _background-position: -120px -50px;} +.layui-layer-imgbar{position: fixed; left:0; right: 0; bottom:0; width:100%; height: 40px; line-height: 40px; background-color:#000\9; filter:Alpha(opacity=60); background-color: rgba(2,0,0,.35); color: #fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;} +.layui-layer-imgtit{/*position:absolute; left:20px;*/} +.layui-layer-imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;} +.layui-layer-imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;} +.layui-layer-imgtit a:hover{color:#fff; text-decoration:underline;} +.layui-layer-imgtit em{padding-left:10px; font-style: normal;} + +/* 关闭动画 */ +@-webkit-keyframes layer-bounceOut { + 100% {opacity: 0; -webkit-transform: scale(.7); transform: scale(.7)} + 30% {-webkit-transform: scale(1.05); transform: scale(1.05)} + 0% {-webkit-transform: scale(1); transform: scale(1);} +} +@keyframes layer-bounceOut { + 100% {opacity: 0; -webkit-transform: scale(.7); -ms-transform: scale(.7); transform: scale(.7);} + 30% {-webkit-transform: scale(1.05); -ms-transform: scale(1.05); transform: scale(1.05);} + 0% {-webkit-transform: scale(1); -ms-transform: scale(1);transform: scale(1);} +} +.layer-anim-close{-webkit-animation-name: layer-bounceOut; animation-name: layer-bounceOut; -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration:.2s; animation-duration:.2s;} + +@media screen and (max-width: 1100px) { + .layui-layer-iframe{overflow-y: auto; -webkit-overflow-scrolling: touch;} +} + + diff --git a/static/layui/css/modules/layer/default/loading-0.gif b/static/layui/css/modules/layer/default/loading-0.gif new file mode 100644 index 0000000..6f3c953 Binary files /dev/null and b/static/layui/css/modules/layer/default/loading-0.gif differ diff --git a/static/layui/css/modules/layer/default/loading-1.gif b/static/layui/css/modules/layer/default/loading-1.gif new file mode 100644 index 0000000..db3a483 Binary files /dev/null and b/static/layui/css/modules/layer/default/loading-1.gif differ diff --git a/static/layui/css/modules/layer/default/loading-2.gif b/static/layui/css/modules/layer/default/loading-2.gif new file mode 100644 index 0000000..5bb90fd Binary files /dev/null and b/static/layui/css/modules/layer/default/loading-2.gif differ diff --git a/static/layui/font/iconfont.eot b/static/layui/font/iconfont.eot new file mode 100644 index 0000000..622d7ec Binary files /dev/null and b/static/layui/font/iconfont.eot differ diff --git a/static/layui/font/iconfont.svg b/static/layui/font/iconfont.svg new file mode 100644 index 0000000..999ca1f --- /dev/null +++ b/static/layui/font/iconfont.svg @@ -0,0 +1,554 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/layui/font/iconfont.ttf b/static/layui/font/iconfont.ttf new file mode 100644 index 0000000..06e30f9 Binary files /dev/null and b/static/layui/font/iconfont.ttf differ diff --git a/static/layui/font/iconfont.woff b/static/layui/font/iconfont.woff new file mode 100644 index 0000000..66a1783 Binary files /dev/null and b/static/layui/font/iconfont.woff differ diff --git a/static/layui/font/iconfont.woff2 b/static/layui/font/iconfont.woff2 new file mode 100644 index 0000000..47e9980 Binary files /dev/null and b/static/layui/font/iconfont.woff2 differ diff --git a/static/layui/layui.js b/static/layui/layui.js new file mode 100644 index 0000000..a35f391 --- /dev/null +++ b/static/layui/layui.js @@ -0,0 +1,754 @@ + +/*! + * Layui + * Classic modular Front-End UI library + * MIT Licensed + */ + +;!function(win){ + "use strict"; + + var doc = win.document, config = { + modules: {} //记录模块物理路径 + ,status: {} //记录模块加载状态 + ,timeout: 10 //符合规范的模块请求最长等待秒数 + ,event: {} //记录模块自定义事件 + } + + ,Layui = function(){ + this.v = '2.6.8'; // layui 版本号 + } + + //识别预先可能定义的指定全局对象 + ,GLOBAL = win.LAYUI_GLOBAL || {} + + //获取 layui 所在目录 + ,getPath = function(){ + var jsPath = doc.currentScript ? doc.currentScript.src : function(){ + var js = doc.scripts + ,last = js.length - 1 + ,src; + for(var i = last; i > 0; i--){ + if(js[i].readyState === 'interactive'){ + src = js[i].src; + break; + } + } + return src || js[last].src; + }(); + + return config.dir = GLOBAL.dir || jsPath.substring(0, jsPath.lastIndexOf('/') + 1); + }() + + //异常提示 + ,error = function(msg, type){ + type = type || 'log'; + win.console && console[type] && console[type]('layui error hint: ' + msg); + } + + ,isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]' + + //内置模块 + ,modules = config.builtin = { + lay: 'lay' //基础 DOM 操作 + ,layer: 'layer' //弹层 + ,laydate: 'laydate' //日期 + ,laypage: 'laypage' //分页 + ,laytpl: 'laytpl' //模板引擎 + ,layedit: 'layedit' //富文本编辑器 + ,form: 'form' //表单集 + ,upload: 'upload' //上传 + ,dropdown: 'dropdown' //下拉菜单 + ,transfer: 'transfer' //穿梭框 + ,tree: 'tree' //树结构 + ,table: 'table' //表格 + ,element: 'element' //常用元素操作 + ,rate: 'rate' //评分组件 + ,colorpicker: 'colorpicker' //颜色选择器 + ,slider: 'slider' //滑块 + ,carousel: 'carousel' //轮播 + ,flow: 'flow' //流加载 + ,util: 'util' //工具块 + ,code: 'code' //代码修饰器 + ,jquery: 'jquery' //DOM 库(第三方) + + ,all: 'all' + ,'layui.all': 'layui.all' //聚合标识(功能性的,非真实模块) + }; + + //记录基础数据 + Layui.prototype.cache = config; + + //定义模块 + Layui.prototype.define = function(deps, factory){ + var that = this + ,type = typeof deps === 'function' + ,callback = function(){ + var setApp = function(app, exports){ + layui[app] = exports; + config.status[app] = true; + }; + typeof factory === 'function' && factory(function(app, exports){ + setApp(app, exports); + config.callback[app] = function(){ + factory(setApp); + } + }); + return this; + }; + + type && ( + factory = deps, + deps = [] + ); + + that.use(deps, callback, null, 'define'); + return that; + }; + + //使用特定模块 + Layui.prototype.use = function(apps, callback, exports, from){ + var that = this + ,dir = config.dir = config.dir ? config.dir : getPath + ,head = doc.getElementsByTagName('head')[0]; + + apps = function(){ + if(typeof apps === 'string'){ + return [apps]; + } + //当第一个参数为 function 时,则自动加载所有内置模块,且执行的回调即为该 function 参数; + else if(typeof apps === 'function'){ + callback = apps; + return ['all']; + } + return apps; + }(); + + //如果页面已经存在 jQuery 1.7+ 库且所定义的模块依赖 jQuery,则不加载内部 jquery 模块 + if(win.jQuery && jQuery.fn.on){ + that.each(apps, function(index, item){ + if(item === 'jquery'){ + apps.splice(index, 1); + } + }); + layui.jquery = layui.$ = jQuery; + } + + var item = apps[0] + ,timeout = 0; + exports = exports || []; + + //静态资源host + config.host = config.host || (dir.match(/\/\/([\s\S]+?)\//)||['//'+ location.host +'/'])[0]; + + //加载完毕 + function onScriptLoad(e, url){ + var readyRegExp = navigator.platform === 'PLaySTATION 3' ? /^complete$/ : /^(complete|loaded)$/ + if (e.type === 'load' || (readyRegExp.test((e.currentTarget || e.srcElement).readyState))) { + config.modules[item] = url; + head.removeChild(node); + (function poll() { + if(++timeout > config.timeout * 1000 / 4){ + return error(item + ' is not a valid module', 'error'); + }; + config.status[item] ? onCallback() : setTimeout(poll, 4); + }()); + } + } + + //回调 + function onCallback(){ + exports.push(layui[item]); + apps.length > 1 ? + that.use(apps.slice(1), callback, exports, from) + : ( typeof callback === 'function' && function(){ + //保证文档加载完毕再执行回调 + if(layui.jquery && typeof layui.jquery === 'function' && from !== 'define'){ + return layui.jquery(function(){ + callback.apply(layui, exports); + }); + } + callback.apply(layui, exports); + }() ); + } + + //如果引入了聚合板,内置的模块则不必重复加载 + if( apps.length === 0 || (layui['layui.all'] && modules[item]) ){ + return onCallback(), that; + } + + //获取加载的模块 URL + //如果是内置模块,则按照 dir 参数拼接模块路径 + //如果是扩展模块,则判断模块路径值是否为 {/} 开头, + //如果路径值是 {/} 开头,则模块路径即为后面紧跟的字符。 + //否则,则按照 base 参数拼接模块路径 + + var url = ( modules[item] ? (dir + 'modules/') + : (/^\{\/\}/.test(that.modules[item]) ? '' : (config.base || '')) + ) + (that.modules[item] || item) + '.js'; + url = url.replace(/^\{\/\}/, ''); + + //如果扩展模块(即:非内置模块)对象已经存在,则不必再加载 + if(!config.modules[item] && layui[item]){ + config.modules[item] = url; //并记录起该扩展模块的 url + } + + //首次加载模块 + if(!config.modules[item]){ + var node = doc.createElement('script'); + + node.async = true; + node.charset = 'utf-8'; + node.src = url + function(){ + var version = config.version === true + ? (config.v || (new Date()).getTime()) + : (config.version||''); + return version ? ('?v=' + version) : ''; + }(); + + head.appendChild(node); + + if(node.attachEvent && !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && !isOpera){ + node.attachEvent('onreadystatechange', function(e){ + onScriptLoad(e, url); + }); + } else { + node.addEventListener('load', function(e){ + onScriptLoad(e, url); + }, false); + } + + config.modules[item] = url; + } else { //缓存 + (function poll() { + if(++timeout > config.timeout * 1000 / 4){ + return error(item + ' is not a valid module', 'error'); + }; + (typeof config.modules[item] === 'string' && config.status[item]) + ? onCallback() + : setTimeout(poll, 4); + }()); + } + + return that; + }; + + //获取节点的 style 属性值 + Layui.prototype.getStyle = function(node, name){ + var style = node.currentStyle ? node.currentStyle : win.getComputedStyle(node, null); + return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name); + }; + + //css外部加载器 + Layui.prototype.link = function(href, fn, cssname){ + var that = this + ,head = doc.getElementsByTagName('head')[0] + ,link = doc.createElement('link'); + + if(typeof fn === 'string') cssname = fn; + + var app = (cssname || href).replace(/\.|\//g, '') + ,id = link.id = 'layuicss-'+ app + ,STAUTS_NAME = 'creating' + ,timeout = 0; + + link.rel = 'stylesheet'; + link.href = href + (config.debug ? '?v='+new Date().getTime() : ''); + link.media = 'all'; + + if(!doc.getElementById(id)){ + head.appendChild(link); + } + + if(typeof fn !== 'function') return that; + + //轮询 css 是否加载完毕 + (function poll(status) { + var delay = 100 + ,getLinkElem = doc.getElementById(id); //获取动态插入的 link 元素 + + //如果轮询超过指定秒数,则视为请求文件失败或 css 文件不符合规范 + if(++timeout > config.timeout * 1000 / delay){ + return error(href + ' timeout'); + }; + + //css 加载就绪 + if(parseInt(that.getStyle(getLinkElem, 'width')) === 1989){ + //如果参数来自于初始轮询(即未加载就绪时的),则移除 link 标签状态 + if(status === STAUTS_NAME) getLinkElem.removeAttribute('lay-status'); + //如果 link 标签的状态仍为「创建中」,则继续进入轮询,直到状态改变,则执行回调 + getLinkElem.getAttribute('lay-status') === STAUTS_NAME ? setTimeout(poll, delay) : fn(); + } else { + getLinkElem.setAttribute('lay-status', STAUTS_NAME); + setTimeout(function(){ + poll(STAUTS_NAME); + }, delay); + } + }()); + + //轮询css是否加载完毕 + /* + (function poll() { + if(++timeout > config.timeout * 1000 / 100){ + return error(href + ' timeout'); + }; + parseInt(that.getStyle(doc.getElementById(id), 'width')) === 1989 ? function(){ + fn(); + }() : setTimeout(poll, 100); + }()); + */ + + return that; + }; + + //css 内部加载器 + Layui.prototype.addcss = function(firename, fn, cssname){ + return layui.link(config.dir + 'css/' + firename, fn, cssname); + }; + + //存储模块的回调 + config.callback = {}; + + //重新执行模块的工厂函数 + Layui.prototype.factory = function(modName){ + if(layui[modName]){ + return typeof config.callback[modName] === 'function' + ? config.callback[modName] + : null; + } + }; + + //图片预加载 + Layui.prototype.img = function(url, callback, error) { + var img = new Image(); + img.src = url; + if(img.complete){ + return callback(img); + } + img.onload = function(){ + img.onload = null; + typeof callback === 'function' && callback(img); + }; + img.onerror = function(e){ + img.onerror = null; + typeof error === 'function' && error(e); + }; + }; + + //全局配置 + Layui.prototype.config = function(options){ + options = options || {}; + for(var key in options){ + config[key] = options[key]; + } + return this; + }; + + //记录全部模块 + Layui.prototype.modules = function(){ + var clone = {}; + for(var o in modules){ + clone[o] = modules[o]; + } + return clone; + }(); + + //拓展模块 + Layui.prototype.extend = function(options){ + var that = this; + + //验证模块是否被占用 + options = options || {}; + for(var o in options){ + if(that[o] || that.modules[o]){ + error(o+ ' Module already exists', 'error'); + } else { + that.modules[o] = options[o]; + } + } + + return that; + }; + + // location.hash 路由解析 + Layui.prototype.router = function(hash){ + var that = this + ,hash = hash || location.hash + ,data = { + path: [] + ,search: {} + ,hash: (hash.match(/[^#](#.*$)/) || [])[1] || '' + }; + + if(!/^#\//.test(hash)) return data; //禁止非路由规范 + hash = hash.replace(/^#\//, ''); + data.href = '/' + hash; + hash = hash.replace(/([^#])(#.*$)/, '$1').split('/') || []; + + //提取 Hash 结构 + that.each(hash, function(index, item){ + /^\w+=/.test(item) ? function(){ + item = item.split('='); + data.search[item[0]] = item[1]; + }() : data.path.push(item); + }); + + return data; + }; + + //URL 解析 + Layui.prototype.url = function(href){ + var that = this + ,data = { + //提取 url 路径 + pathname: function(){ + var pathname = href + ? function(){ + var str = (href.match(/\.[^.]+?\/.+/) || [])[0] || ''; + return str.replace(/^[^\/]+/, '').replace(/\?.+/, ''); + }() + : location.pathname; + return pathname.replace(/^\//, '').split('/'); + }() + + //提取 url 参数 + ,search: function(){ + var obj = {} + ,search = (href + ? function(){ + var str = (href.match(/\?.+/) || [])[0] || ''; + return str.replace(/\#.+/, ''); + }() + : location.search + ).replace(/^\?+/, '').split('&'); //去除 ?,按 & 分割参数 + + //遍历分割后的参数 + that.each(search, function(index, item){ + var _index = item.indexOf('=') + ,key = function(){ //提取 key + if(_index < 0){ + return item.substr(0, item.length); + } else if(_index === 0){ + return false; + } else { + return item.substr(0, _index); + } + }(); + //提取 value + if(key){ + obj[key] = _index > 0 ? item.substr(_index + 1) : null; + } + }); + + return obj; + }() + + //提取 Hash + ,hash: that.router(function(){ + return href + ? ((href.match(/#.+/) || [])[0] || '/') + : location.hash; + }()) + }; + + return data; + }; + + //本地持久性存储 + Layui.prototype.data = function(table, settings, storage){ + table = table || 'layui'; + storage = storage || localStorage; + + if(!win.JSON || !win.JSON.parse) return; + + //如果settings为null,则删除表 + if(settings === null){ + return delete storage[table]; + } + + settings = typeof settings === 'object' + ? settings + : {key: settings}; + + try{ + var data = JSON.parse(storage[table]); + } catch(e){ + var data = {}; + } + + if('value' in settings) data[settings.key] = settings.value; + if(settings.remove) delete data[settings.key]; + storage[table] = JSON.stringify(data); + + return settings.key ? data[settings.key] : data; + }; + + //本地会话性存储 + Layui.prototype.sessionData = function(table, settings){ + return this.data(table, settings, sessionStorage); + } + + //设备信息 + Layui.prototype.device = function(key){ + var agent = navigator.userAgent.toLowerCase() + + //获取版本号 + ,getVersion = function(label){ + var exp = new RegExp(label + '/([^\\s\\_\\-]+)'); + label = (agent.match(exp)||[])[1]; + return label || false; + } + + //返回结果集 + ,result = { + os: function(){ //底层操作系统 + if(/windows/.test(agent)){ + return 'windows'; + } else if(/linux/.test(agent)){ + return 'linux'; + } else if(/iphone|ipod|ipad|ios/.test(agent)){ + return 'ios'; + } else if(/mac/.test(agent)){ + return 'mac'; + } + }() + ,ie: function(){ //ie版本 + return (!!win.ActiveXObject || "ActiveXObject" in win) ? ( + (agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识 + ) : false; + }() + ,weixin: getVersion('micromessenger') //是否微信 + }; + + //任意的key + if(key && !result[key]){ + result[key] = getVersion(key); + } + + //移动设备 + result.android = /android/.test(agent); + result.ios = result.os === 'ios'; + result.mobile = (result.android || result.ios) ? true : false; + + return result; + }; + + //提示 + Layui.prototype.hint = function(){ + return { + error: error + }; + }; + + //typeof 类型细分 -> string/number/boolean/undefined/null、object/array/function/… + Layui.prototype._typeof = function(operand){ + if(operand === null) return String(operand); + + //细分引用类型 + return (typeof operand === 'object' || typeof operand === 'function') ? function(){ + var type = Object.prototype.toString.call(operand).match(/\s(.+)\]$/) || [] //匹配类型字符 + ,classType = 'Function|Array|Date|RegExp|Object|Error|Symbol'; //常见类型字符 + + type = type[1] || 'Object'; + + //除匹配到的类型外,其他对象均返回 object + return new RegExp('\\b('+ classType + ')\\b').test(type) + ? type.toLowerCase() + : 'object'; + }() : typeof operand; + }; + + //对象是否具备数组结构(此处为兼容 jQuery 对象) + Layui.prototype._isArray = function(obj){ + var that = this + ,len + ,type = that._typeof(obj); + + if(!obj || (typeof obj !== 'object') || obj === win) return false; + + len = 'length' in obj && obj.length; //兼容 ie + return type === 'array' || len === 0 || ( + typeof len === 'number' && len > 0 && (len - 1) in obj //兼容 jQuery 对象 + ); + }; + + //遍历 + Layui.prototype.each = function(obj, fn){ + var key + ,that = this + ,callFn = function(key, obj){ //回调 + return fn.call(obj[key], key, obj[key]) + }; + + if(typeof fn !== 'function') return that; + obj = obj || []; + + //优先处理数组结构 + if(that._isArray(obj)){ + for(key = 0; key < obj.length; key++){ + if(callFn(key, obj)) break; + } + } else { + for(key in obj){ + if(callFn(key, obj)) break; + } + } + + return that; + }; + + //将数组中的对象按其某个成员排序 + Layui.prototype.sort = function(obj, key, desc){ + var clone = JSON.parse( + JSON.stringify(obj || []) + ); + + if(!key) return clone; + + //如果是数字,按大小排序;如果是非数字,则按字典序排序 + clone.sort(function(o1, o2){ + var v1 = o1[key] + ,v2 = o2[key] + ,isNum = [ + !isNaN(v1) + ,!isNaN(v2) + ]; + + + //若为数字比较 + if(isNum[0] && isNum[1]){ + if(v1 && (!v2 && v2 !== 0)){ //数字 vs 空 + return 1; + } else if((!v1 && v1 !== 0) && v2){ //空 vs 数字 + return -1; + } else { //数字 vs 数字 + return v1 - v2; + } + }; + + /** + * 字典序排序 + */ + + //若为非数字比较 + if(!isNum[0] && !isNum[1]){ + //字典序比较 + if(v1 > v2){ + return 1; + } else if (v1 < v2) { + return -1; + } else { + return 0; + } + } + + //若为混合比较 + if(isNum[0] || !isNum[1]){ //数字 vs 非数字 + return -1; + } else if(!isNum[0] || isNum[1]) { //非数字 vs 数字 + return 1; + } + + /* + //老版本 + if(v1 && !v2){ + return 1; + } else if(!v1 && v2){ + return -1; + } + + if(v1 > v2){ + return 1; + } else if (v1 < v2) { + return -1; + } else { + return 0; + } + */ + + }); + + desc && clone.reverse(); //倒序 + return clone; + }; + + //阻止事件冒泡 + Layui.prototype.stope = function(thisEvent){ + thisEvent = thisEvent || win.event; + try { thisEvent.stopPropagation() } catch(e){ + thisEvent.cancelBubble = true; + } + }; + + //字符常理 + var EV_REMOVE = 'LAYUI-EVENT-REMOVE'; + + //自定义模块事件 + Layui.prototype.onevent = function(modName, events, callback){ + if(typeof modName !== 'string' + || typeof callback !== 'function') return this; + + return Layui.event(modName, events, null, callback); + }; + + //执行自定义模块事件 + Layui.prototype.event = Layui.event = function(modName, events, params, fn){ + var that = this + ,result = null + ,filter = (events || '').match(/\((.*)\)$/)||[] //提取事件过滤器字符结构,如:select(xxx) + ,eventName = (modName + '.'+ events).replace(filter[0], '') //获取事件名称,如:form.select + ,filterName = filter[1] || '' //获取过滤器名称,,如:xxx + ,callback = function(_, item){ + var res = item && item.call(that, params); + res === false && result === null && (result = false); + }; + + //如果参数传入特定字符,则执行移除事件 + if(params === EV_REMOVE){ + delete (that.cache.event[eventName] || {})[filterName]; + return that; + } + + //添加事件 + if(fn){ + config.event[eventName] = config.event[eventName] || {}; + + //这里不再对重复事件做支持 + //config.event[eventName][filterName] ? config.event[eventName][filterName].push(fn) : + config.event[eventName][filterName] = [fn]; + return this; + } + + //执行事件回调 + layui.each(config.event[eventName], function(key, item){ + //执行当前模块的全部事件 + if(filterName === '{*}'){ + layui.each(item, callback); + return; + } + + //执行指定事件 + key === '' && layui.each(item, callback); + (filterName && key === filterName) && layui.each(item, callback); + }); + + return result; + }; + + //新增模块事件 + Layui.prototype.on = function(events, modName, callback){ + var that = this; + return that.onevent.call(that, modName, events, callback); + } + + //移除模块事件 + Layui.prototype.off = function(events, modName){ + var that = this; + return that.event.call(that, modName, events, EV_REMOVE); + }; + + //exports layui + win.layui = new Layui(); + +}(window); //gulp build: layui-footer + diff --git a/static/layui/modules/all.js b/static/layui/modules/all.js new file mode 100644 index 0000000..6c7aa24 --- /dev/null +++ b/static/layui/modules/all.js @@ -0,0 +1,32 @@ + +/*! + * 用于加载所有内置模块 + * MIT Licensed + */ + +layui.define(function(){ + var mods = [] + ,builtin = layui.cache.builtin; + layui.each(builtin, function(modName){ + (modName === 'all' || modName === 'layui.all') || mods.push(modName); + }); + layui.cache.startTime = new Date().getTime(); + + return mods; +}(), function(exports){ + "use strict"; + + var MOD_NAME = 'all' + + //外部接口 + ,all = { + config: {} + ,time: function(){ + var time = new Date().getTime() - layui.cache.startTime; + delete layui.cache.startTime; + return time; + }() + }; + + exports(MOD_NAME, all); +}); diff --git a/static/layui/modules/carousel.js b/static/layui/modules/carousel.js new file mode 100644 index 0000000..ef1a905 --- /dev/null +++ b/static/layui/modules/carousel.js @@ -0,0 +1,313 @@ + +/*! + * carousel 轮播模块 + * MIT Licensed + */ + +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$ + ,hint = layui.hint() + ,device = layui.device() + + //外部接口 + ,carousel = { + config: {} //全局配置项 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //字符常量 + ,MOD_NAME = 'carousel', ELEM = '.layui-carousel', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled' + + ,ELEM_ITEM = '>*[carousel-item]>*', ELEM_LEFT = 'layui-carousel-left', ELEM_RIGHT = 'layui-carousel-right', ELEM_PREV = 'layui-carousel-prev', ELEM_NEXT = 'layui-carousel-next', ELEM_ARROW = 'layui-carousel-arrow', ELEM_IND = 'layui-carousel-ind' + + //构造器 + ,Class = function(options){ + var that = this; + that.config = $.extend({}, that.config, carousel.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + width: '600px' + ,height: '280px' + ,full: false //是否全屏 + ,arrow: 'hover' //切换箭头默认显示状态:hover/always/none + ,indicator: 'inside' //指示器位置:inside/outside/none + ,autoplay: true //是否自动切换 + ,interval: 3000 //自动切换的时间间隔,不能低于800ms + ,anim: '' //动画类型:default/updown/fade + ,trigger: 'click' //指示器的触发方式:click/hover + ,index: 0 //初始开始的索引 + }; + + //轮播渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + options.elem = $(options.elem); + if(!options.elem[0]) return; + that.elemItem = options.elem.find(ELEM_ITEM); + + if(options.index < 0) options.index = 0; + if(options.index >= that.elemItem.length) options.index = that.elemItem.length - 1; + if(options.interval < 800) options.interval = 800; + + //是否全屏模式 + if(options.full){ + options.elem.css({ + position: 'fixed' + ,width: '100%' + ,height: '100%' + ,zIndex: 9999 + }); + } else { + options.elem.css({ + width: options.width + ,height: options.height + }); + } + + options.elem.attr('lay-anim', options.anim); + + //初始焦点状态 + that.elemItem.eq(options.index).addClass(THIS); + + //指示器等动作 + if(that.elemItem.length <= 1) return; + that.indicator(); + that.arrow(); + that.autoplay(); + that.events(); + }; + + //重置轮播 + Class.prototype.reload = function(options){ + var that = this; + clearInterval(that.timer); + that.config = $.extend({}, that.config, options); + that.render(); + }; + + //获取上一个等待条目的索引 + Class.prototype.prevIndex = function(){ + var that = this + ,options = that.config; + + var prevIndex = options.index - 1; + if(prevIndex < 0){ + prevIndex = that.elemItem.length - 1; + } + return prevIndex; + }; + + //获取下一个等待条目的索引 + Class.prototype.nextIndex = function(){ + var that = this + ,options = that.config; + + var nextIndex = options.index + 1; + if(nextIndex >= that.elemItem.length){ + nextIndex = 0; + } + return nextIndex; + }; + + //索引递增 + Class.prototype.addIndex = function(num){ + var that = this + ,options = that.config; + + num = num || 1; + options.index = options.index + num; + + //index不能超过轮播总数量 + if(options.index >= that.elemItem.length){ + options.index = 0; + } + }; + + //索引递减 + Class.prototype.subIndex = function(num){ + var that = this + ,options = that.config; + + num = num || 1; + options.index = options.index - num; + + //index不能超过轮播总数量 + if(options.index < 0){ + options.index = that.elemItem.length - 1; + } + }; + + //自动轮播 + Class.prototype.autoplay = function(){ + var that = this + ,options = that.config; + + if(!options.autoplay) return; + clearInterval(that.timer); + + that.timer = setInterval(function(){ + that.slide(); + }, options.interval); + }; + + //箭头 + Class.prototype.arrow = function(){ + var that = this + ,options = that.config; + + //模板 + var tplArrow = $([ + '' + ,'' + ].join('')); + + //预设基础属性 + options.elem.attr('lay-arrow', options.arrow); + + //避免重复插入 + if(options.elem.find('.'+ELEM_ARROW)[0]){ + options.elem.find('.'+ELEM_ARROW).remove(); + }; + options.elem.append(tplArrow); + + //事件 + tplArrow.on('click', function(){ + var othis = $(this) + ,type = othis.attr('lay-type') + that.slide(type); + }); + }; + + //指示器 + Class.prototype.indicator = function(){ + var that = this + ,options = that.config; + + //模板 + var tplInd = that.elemInd = $(['
'].join('')); + + //预设基础属性 + options.elem.attr('lay-indicator', options.indicator); + + //避免重复插入 + if(options.elem.find('.'+ELEM_IND)[0]){ + options.elem.find('.'+ELEM_IND).remove(); + }; + options.elem.append(tplInd); + + if(options.anim === 'updown'){ + tplInd.css('margin-top', -(tplInd.height()/2)); + } + + //事件 + tplInd.find('li').on(options.trigger === 'hover' ? 'mouseover' : options.trigger, function(){ + var othis = $(this) + ,index = othis.index(); + if(index > options.index){ + that.slide('add', index - options.index); + } else if(index < options.index){ + that.slide('sub', options.index - index); + } + }); + }; + + //滑动切换 + Class.prototype.slide = function(type, num){ + var that = this + ,elemItem = that.elemItem + ,options = that.config + ,thisIndex = options.index + ,filter = options.elem.attr('lay-filter'); + + if(that.haveSlide) return; + + //滑动方向 + if(type === 'sub'){ + that.subIndex(num); + elemItem.eq(options.index).addClass(ELEM_PREV); + setTimeout(function(){ + elemItem.eq(thisIndex).addClass(ELEM_RIGHT); + elemItem.eq(options.index).addClass(ELEM_RIGHT); + }, 50); + } else { //默认递增滑 + that.addIndex(num); + elemItem.eq(options.index).addClass(ELEM_NEXT); + setTimeout(function(){ + elemItem.eq(thisIndex).addClass(ELEM_LEFT); + elemItem.eq(options.index).addClass(ELEM_LEFT); + }, 50); + }; + + //移除过度类 + setTimeout(function(){ + elemItem.removeClass(THIS + ' ' + ELEM_PREV + ' ' + ELEM_NEXT + ' ' + ELEM_LEFT + ' ' + ELEM_RIGHT); + elemItem.eq(options.index).addClass(THIS); + that.haveSlide = false; //解锁 + }, 300); + + //指示器焦点 + that.elemInd.find('li').eq(options.index).addClass(THIS) + .siblings().removeClass(THIS); + + that.haveSlide = true; + + layui.event.call(this, MOD_NAME, 'change('+ filter +')', { + index: options.index + ,prevIndex: thisIndex + ,item: elemItem.eq(options.index) + }); + }; + + //事件处理 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + + if(options.elem.data('haveEvents')) return; + + //移入移出容器 + options.elem.on('mouseenter', function(){ + clearInterval(that.timer); + }).on('mouseleave', function(){ + that.autoplay(); + }); + + options.elem.data('haveEvents', true); + }; + + //核心入口 + carousel.render = function(options){ + var inst = new Class(options); + return inst; + }; + + exports(MOD_NAME, carousel); +}); + + diff --git a/static/layui/modules/code.js b/static/layui/modules/code.js new file mode 100644 index 0000000..8496e13 --- /dev/null +++ b/static/layui/modules/code.js @@ -0,0 +1,59 @@ + +/** + * code 代码修饰器 + * MIT Licensed + */ + +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$; + + exports('code', function(options){ + var elems = []; + options = options || {}; + options.elem = $(options.elem||'.layui-code'); + options.lang = 'lang' in options ? options.lang : 'code'; + + options.elem.each(function(){ + elems.push(this); + }); + + layui.each(elems.reverse(), function(index, item){ + var othis = $(item), html = othis.html(); + + //转义HTML标签 + if(othis.attr('lay-encode') || options.encode){ + html = html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"') + } + + othis.html('
  1. ' + html.replace(/[\r\t\n]+/g, '
  2. ') + '
') + + if(!othis.find('>.layui-code-h3')[0]){ + othis.prepend('

'+ (othis.attr('lay-title')||options.title||'</>') + ''+ (othis.attr('lay-lang')||options.lang||'') +'' + '

'); + } + + var ol = othis.find('>.layui-code-ol'); + othis.addClass('layui-box layui-code-view'); + + //识别皮肤 + if(othis.attr('lay-skin') || options.skin){ + othis.addClass('layui-code-' +(othis.attr('lay-skin') || options.skin)); + } + + //按行数适配左边距 + if((ol.find('li').length/100|0) > 0){ + ol.css('margin-left', (ol.find('li').length/100|0) + 'px'); + } + + //设置最大高度 + if(othis.attr('lay-height') || options.height){ + ol.css('max-height', othis.attr('lay-height') || options.height); + } + + }); + + }); +}).addcss('modules/code.css?v=2', 'skincodecss'); + diff --git a/static/layui/modules/colorpicker.js b/static/layui/modules/colorpicker.js new file mode 100644 index 0000000..083c1e1 --- /dev/null +++ b/static/layui/modules/colorpicker.js @@ -0,0 +1,691 @@ + +/*! + * colorpicker + * 颜色选择组件 + */ + +layui.define(['jquery', 'lay'], function(exports){ + "use strict"; + + var $ = layui.jquery + ,lay = layui.lay + ,device = layui.device() + ,clickOrMousedown = (device.mobile ? 'click' : 'mousedown') + + //外部接口 + ,colorpicker = { + config: {} + ,index: layui.colorpicker ? (layui.colorpicker.index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, 'colorpicker', events, callback); + } + } + + //操作当前实例 + ,thisColorPicker = function(){ + var that = this + ,options = that.config; + + return { + config: options + } + } + + //字符常量 + ,MOD_NAME = 'colorpicker', SHOW = 'layui-show', THIS = 'layui-this', ELEM = 'layui-colorpicker' + + ,ELEM_MAIN = '.layui-colorpicker-main', ICON_PICKER_DOWN = 'layui-icon-down', ICON_PICKER_CLOSE = 'layui-icon-close' + ,PICKER_TRIG_SPAN = 'layui-colorpicker-trigger-span', PICKER_TRIG_I = 'layui-colorpicker-trigger-i', PICKER_SIDE = 'layui-colorpicker-side', PICKER_SIDE_SLIDER = 'layui-colorpicker-side-slider' + ,PICKER_BASIS = 'layui-colorpicker-basis', PICKER_ALPHA_BG = 'layui-colorpicker-alpha-bgcolor', PICKER_ALPHA_SLIDER = 'layui-colorpicker-alpha-slider', PICKER_BASIS_CUR = 'layui-colorpicker-basis-cursor', PICKER_INPUT = 'layui-colorpicker-main-input' + + //RGB转HSB + ,RGBToHSB = function(rgb){ + var hsb = {h:0, s:0, b:0}; + var min = Math.min(rgb.r, rgb.g, rgb.b); + var max = Math.max(rgb.r, rgb.g, rgb.b); + var delta = max - min; + hsb.b = max; + hsb.s = max != 0 ? 255*delta/max : 0; + if(hsb.s != 0){ + if(rgb.r == max){ + hsb.h = (rgb.g - rgb.b) / delta; + }else if(rgb.g == max){ + hsb.h = 2 + (rgb.b - rgb.r) / delta; + }else{ + hsb.h = 4 + (rgb.r - rgb.g) / delta; + } + }else{ + hsb.h = -1; + }; + if(max == min){ + hsb.h = 0; + }; + hsb.h *= 60; + if(hsb.h < 0) { + hsb.h += 360; + }; + hsb.s *= 100/255; + hsb.b *= 100/255; + return hsb; + } + + //HEX转HSB + ,HEXToHSB = function(hex){ + var hex = hex.indexOf('#') > -1 ? hex.substring(1) : hex; + if(hex.length == 3){ + var num = hex.split(""); + hex = num[0]+num[0]+num[1]+num[1]+num[2]+num[2] + }; + hex = parseInt(hex, 16); + var rgb = {r:hex >> 16, g:(hex & 0x00FF00) >> 8, b:(hex & 0x0000FF)}; + return RGBToHSB(rgb); + } + + //HSB转RGB + ,HSBToRGB = function(hsb){ + var rgb = {}; + var h = hsb.h; + var s = hsb.s*255/100; + var b = hsb.b*255/100; + if(s == 0){ + rgb.r = rgb.g = rgb.b = b; + }else{ + var t1 = b; + var t2 = (255 - s) * b /255; + var t3 = (t1 - t2) * (h % 60) /60; + if(h == 360) h = 0; + if(h < 60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} + else if(h < 120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} + else if(h < 180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} + else if(h < 240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} + else if(h < 300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} + else if(h < 360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} + else {rgb.r=0; rgb.g=0; rgb.b=0} + } + return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; + } + + //HSB转HEX + ,HSBToHEX = function(hsb){ + var rgb = HSBToRGB(hsb); + var hex = [ + rgb.r.toString(16) + ,rgb.g.toString(16) + ,rgb.b.toString(16) + ]; + $.each(hex, function(nr, val){ + if(val.length == 1){ + hex[nr] = '0' + val; + } + }); + return hex.join(''); + } + + //转化成所需rgb格式 + ,RGBSTo = function(rgbs){ + var regexp = /[0-9]{1,3}/g; + var re = rgbs.match(regexp) || []; + return {r:re[0], g:re[1], b:re[2]}; + } + + ,$win = $(window) + ,$doc = $(document) + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++colorpicker.index; + that.config = $.extend({}, that.config, colorpicker.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + color: '' //默认颜色,默认没有 + ,size: null //选择器大小 + ,alpha: false //是否开启透明度 + ,format: 'hex' //颜色显示/输入格式,可选 rgb,hex + ,predefine: false //预定义颜色是否开启 + ,colors: [ //默认预定义颜色列表 + '#009688', '#5FB878', '#1E9FFF', '#FF5722', '#FFB800', '#01AAED', '#999', '#c00', '#ff8c00','#ffd700' + ,'#90ee90', '#00ced1', '#1e90ff', '#c71585', 'rgb(0, 186, 189)', 'rgb(255, 120, 0)', 'rgb(250, 212, 0)', '#393D49', 'rgba(0,0,0,.5)', 'rgba(255, 69, 0, 0.68)', 'rgba(144, 240, 144, 0.5)', 'rgba(31, 147, 255, 0.73)' + ] + }; + + //初始颜色选择框 + Class.prototype.render = function(){ + var that = this + ,options = that.config + + //颜色选择框对象 + ,elemColorBox = $(['
' + ,'' + ,'' + ,'' + ,'' + ,'' + ,'
'].join('')) + + //初始化颜色选择框 + var othis = $(options.elem); + options.size && elemColorBox.addClass('layui-colorpicker-'+ options.size); //初始化颜色选择框尺寸 + + //插入颜色选择框 + othis.addClass('layui-inline').html( + that.elemColorBox = elemColorBox + ); + + //获取背景色值 + that.color = that.elemColorBox.find('.'+ PICKER_TRIG_SPAN)[0].style.background; + + //相关事件 + that.events(); + }; + + //渲染颜色选择器 + Class.prototype.renderPicker = function(){ + var that = this + ,options = that.config + ,elemColorBox = that.elemColorBox[0] + + //颜色选择器对象 + ,elemPicker = that.elemPicker = $(['
' + //颜色面板 + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + + //透明度条块 + ,'
' + ,'
' + ,'
' + ,'
' + ,'
' + + //预设颜色列表 + ,function(){ + if(options.predefine){ + var list = ['
']; + layui.each(options.colors, function(i, v){ + list.push(['
' + ,'
' + ,'
'].join('')); + }); + list.push('
'); + return list.join(''); + } else { + return ''; + } + }() + + //底部表单元素区域 + ,'
' + ,'
' + ,'' + ,'
' + ,'
' + ,'' + ,'' + ,'' + ,'
'].join('')) + + ,elemColorBoxSpan = that.elemColorBox.find('.' + PICKER_TRIG_SPAN)[0]; + + //如果当前点击的颜色盒子已经存在选择器,则关闭 + if($(ELEM_MAIN)[0] && $(ELEM_MAIN).data('index') == that.index){ + that.removePicker(Class.thisElemInd); + } else { //插入颜色选择器 + that.removePicker(Class.thisElemInd); + $('body').append(elemPicker); + } + + Class.thisElemInd = that.index; //记录最新打开的选择器索引 + Class.thisColor = elemColorBox.style.background //记录最新打开的选择器颜色选中值 + + that.position(); + that.pickerEvents(); + }; + + //颜色选择器移除 + Class.prototype.removePicker = function(index){ + var that = this + ,options = that.config; + $('#layui-colorpicker'+ (index || that.index)).remove(); + return that; + }; + + //定位算法 + Class.prototype.position = function(){ + var that = this + ,options = that.config; + lay.position(that.bindElem || that.elemColorBox[0], that.elemPicker[0], { + position: options.position + ,align: 'center' + }); + return that; + }; + + //颜色选择器赋值 + Class.prototype.val = function(){ + var that = this + ,options = that.config + + ,elemColorBox = that.elemColorBox.find('.' + PICKER_TRIG_SPAN) + ,elemPickerInput = that.elemPicker.find('.' + PICKER_INPUT) + ,e = elemColorBox[0] + ,bgcolor = e.style.backgroundColor; + + //判断是否有背景颜色 + if(bgcolor){ + + //转化成hsb格式 + var hsb = RGBToHSB(RGBSTo(bgcolor)) + ,type = elemColorBox.attr('lay-type'); + + //同步滑块的位置及颜色选择器的选择 + that.select(hsb.h, hsb.s, hsb.b); + + //如果格式要求为rgb + if(type === 'torgb'){ + elemPickerInput.find('input').val(bgcolor); + }; + + //如果格式要求为rgba + if(type === 'rgba'){ + var rgb = RGBSTo(bgcolor); + + //如果开启透明度而没有设置,则给默认值 + if((bgcolor.match(/[0-9]{1,3}/g) || []).length == 3){ + elemPickerInput.find('input').val('rgba('+ rgb.r +', '+ rgb.g +', '+ rgb.b +', 1)'); + that.elemPicker.find('.'+ PICKER_ALPHA_SLIDER).css("left", 280); + } else { + elemPickerInput.find('input').val(bgcolor); + var left = bgcolor.slice(bgcolor.lastIndexOf(",") + 1, bgcolor.length - 1) * 280; + that.elemPicker.find('.'+ PICKER_ALPHA_SLIDER).css("left", left); + }; + + //设置span背景色 + that.elemPicker.find('.'+ PICKER_ALPHA_BG)[0].style.background = 'linear-gradient(to right, rgba('+ rgb.r +', '+ rgb.g +', '+ rgb.b +', 0), rgb('+ rgb.r +', '+ rgb.g +', '+ rgb.b +'))'; + }; + + }else{ + //如果没有背景颜色则默认到最初始的状态 + that.select(0,100,100); + elemPickerInput.find('input').val(""); + that.elemPicker.find('.'+ PICKER_ALPHA_BG)[0].style.background = ''; + that.elemPicker.find('.'+ PICKER_ALPHA_SLIDER).css("left", 280); + } + }; + + //颜色选择器滑动 / 点击 + Class.prototype.side = function(){ + var that = this + ,options = that.config + + ,span = that.elemColorBox.find('.' + PICKER_TRIG_SPAN) + ,type = span.attr('lay-type') + + ,side = that.elemPicker.find('.' + PICKER_SIDE) + ,slider = that.elemPicker.find('.' + PICKER_SIDE_SLIDER) + ,basis = that.elemPicker.find('.' + PICKER_BASIS) + ,choose = that.elemPicker.find('.' + PICKER_BASIS_CUR) + ,alphacolor = that.elemPicker.find('.' + PICKER_ALPHA_BG) + ,alphaslider = that.elemPicker.find('.' + PICKER_ALPHA_SLIDER) + + ,_h = slider[0].offsetTop/180*360 + ,_b = 100 - (choose[0].offsetTop + 3)/180*100 + ,_s = (choose[0].offsetLeft + 3)/260*100 + ,_a = Math.round(alphaslider[0].offsetLeft/280*100)/100 + + ,i = that.elemColorBox.find('.' + PICKER_TRIG_I) + ,pre = that.elemPicker.find('.layui-colorpicker-pre').children('div') + + ,change = function(x,y,z,a){ + that.select(x, y, z); + var rgb = HSBToRGB({h:x, s:y, b:z}); + i.addClass(ICON_PICKER_DOWN).removeClass(ICON_PICKER_CLOSE); + span[0].style.background = 'rgb('+ rgb.r +', '+ rgb.g +', '+ rgb.b +')'; + + if(type === 'torgb'){ + that.elemPicker.find('.' + PICKER_INPUT).find('input').val('rgb('+ rgb.r +', '+ rgb.g +', '+ rgb.b +')'); + }; + + if(type === 'rgba'){ + var left = 0; + left = a * 280; + alphaslider.css("left", left); + that.elemPicker.find('.' + PICKER_INPUT).find('input').val('rgba('+ rgb.r +', '+ rgb.g +', '+ rgb.b +', '+ a +')'); + span[0].style.background = 'rgba('+ rgb.r +', '+ rgb.g +', '+ rgb.b +', '+ a +')'; + alphacolor[0].style.background = 'linear-gradient(to right, rgba('+ rgb.r +', '+ rgb.g +', '+ rgb.b +', 0), rgb('+ rgb.r +', '+ rgb.g +', '+ rgb.b +'))' + }; + + //回调更改的颜色 + options.change && options.change(that.elemPicker.find('.' + PICKER_INPUT).find('input').val()); + } + + //拖拽元素 + ,elemMove = $(['
'].join('')) + ,createMoveElem = function(call){ + $('#LAY-colorpicker-moving')[0] || $('body').append(elemMove); + elemMove.on('mousemove', call); + elemMove.on('mouseup', function(){ + elemMove.remove(); + }).on('mouseleave', function(){ + elemMove.remove(); + }); + }; + + //右侧主色选择 + slider.on('mousedown', function(e){ + var oldtop = this.offsetTop + ,oldy = e.clientY; + var move = function(e){ + var top = oldtop + (e.clientY - oldy) + ,maxh = side[0].offsetHeight; + if(top < 0)top = 0; + if(top > maxh)top = maxh; + var h = top/180*360; + _h = h; + change(h, _s, _b, _a); + e.preventDefault(); + }; + + createMoveElem(move); + //layui.stope(e); + e.preventDefault(); + }); + + side.on('click', function(e){ + var top = e.clientY - $(this).offset().top; + if(top < 0)top = 0; + if(top > this.offsetHeight)top = this.offsetHeight; + var h = top/180*360; + _h = h; + change(h, _s, _b, _a); + e.preventDefault(); + }); + + //中间小圆点颜色选择 + choose.on('mousedown', function(e){ + var oldtop = this.offsetTop + ,oldleft = this.offsetLeft + ,oldy = e.clientY + ,oldx = e.clientX; + var move = function(e){ + var top = oldtop + (e.clientY - oldy) + ,left = oldleft + (e.clientX - oldx) + ,maxh = basis[0].offsetHeight - 3 + ,maxw = basis[0].offsetWidth - 3; + if(top < -3)top = -3; + if(top > maxh)top = maxh; + if(left < -3)left = -3; + if(left > maxw)left = maxw; + var s = (left + 3)/260*100 + ,b = 100 - (top + 3)/180*100; + _b = b; + _s = s; + change(_h, s, b, _a); + e.preventDefault(); + }; + layui.stope(e); + createMoveElem(move); + e.preventDefault(); + }); + + basis.on('mousedown', function(e){ + var top = e.clientY - $(this).offset().top - 3 + $win.scrollTop() + ,left = e.clientX - $(this).offset().left - 3 + $win.scrollLeft() + if(top < -3)top = -3; + if(top > this.offsetHeight - 3)top = this.offsetHeight - 3; + if(left < -3)left = -3; + if(left > this.offsetWidth - 3)left = this.offsetWidth - 3; + var s = (left + 3)/260*100 + ,b = 100 - (top + 3)/180*100; + _b = b; + _s = s; + change(_h, s, b, _a); + layui.stope(e); + e.preventDefault(); + choose.trigger(e, 'mousedown'); + }); + + //底部透明度选择 + alphaslider.on('mousedown', function(e){ + var oldleft = this.offsetLeft + ,oldx = e.clientX; + var move = function(e){ + var left = oldleft + (e.clientX - oldx) + ,maxw = alphacolor[0].offsetWidth; + if(left < 0)left = 0; + if(left > maxw)left = maxw; + var a = Math.round(left /280*100) /100; + _a = a; + change(_h, _s, _b, a); + e.preventDefault(); + }; + + createMoveElem(move); + e.preventDefault(); + }); + alphacolor.on('click', function(e){ + var left = e.clientX - $(this).offset().left + if(left < 0)left = 0; + if(left > this.offsetWidth)left = this.offsetWidth; + var a = Math.round(left /280*100) /100; + _a = a; + change(_h, _s, _b, a); + e.preventDefault(); + }); + + //预定义颜色选择 + pre.each(function(){ + $(this).on('click', function(){ + $(this).parent('.layui-colorpicker-pre').addClass('selected').siblings().removeClass('selected'); + var color = this.style.backgroundColor + ,hsb = RGBToHSB(RGBSTo(color)) + ,a = color.slice(color.lastIndexOf(",") + 1, color.length - 1),left; + _h = hsb.h; + _s = hsb.s; + _b = hsb.b; + if((color.match(/[0-9]{1,3}/g) || []).length == 3) a = 1; + _a = a; + left = a * 280; + change(hsb.h, hsb.s, hsb.b, a); + }) + }); + }; + + //颜色选择器hsb转换 + Class.prototype.select = function(h, s, b, type){ + var that = this + ,options = that.config + ,hex = HSBToHEX({h:h, s:100, b:100}) + ,color = HSBToHEX({h:h, s:s, b:b}) + ,sidetop = h/360*180 + ,top = 180 - b/100*180 - 3 + ,left = s/100*260 - 3; + + that.elemPicker.find('.' + PICKER_SIDE_SLIDER).css("top", sidetop); //滑块的top + that.elemPicker.find('.' + PICKER_BASIS)[0].style.background = '#' + hex; //颜色选择器的背景 + + //选择器的top left + that.elemPicker.find('.' + PICKER_BASIS_CUR).css({ + "top": top + ,"left": left + }); + + if(type === 'change') return; + + //选中的颜色 + that.elemPicker.find('.' + PICKER_INPUT).find('input').val('#' + color); + }; + + Class.prototype.pickerEvents = function(){ + var that = this + ,options = that.config + + ,elemColorBoxSpan = that.elemColorBox.find('.' + PICKER_TRIG_SPAN) //颜色盒子 + ,elemPickerInput = that.elemPicker.find('.' + PICKER_INPUT + ' input') //颜色选择器表单 + + ,pickerEvents = { + //清空 + clear: function(othis){ + elemColorBoxSpan[0].style.background =''; + that.elemColorBox.find('.' + PICKER_TRIG_I).removeClass(ICON_PICKER_DOWN).addClass(ICON_PICKER_CLOSE); + that.color = ''; + + options.done && options.done(''); + that.removePicker(); + } + + //确认 + ,confirm: function(othis, change){ + var value = elemPickerInput.val() + ,colorValue = value + ,hsb = {}; + + if(value.indexOf(',') > -1){ + hsb = RGBToHSB(RGBSTo(value)); + that.select(hsb.h, hsb.s, hsb.b); + elemColorBoxSpan[0].style.background = (colorValue = '#' + HSBToHEX(hsb)); + + if((value.match(/[0-9]{1,3}/g) || []).length > 3 && elemColorBoxSpan.attr('lay-type') === 'rgba'){ + var left = value.slice(value.lastIndexOf(",") + 1, value.length - 1) * 280; + that.elemPicker.find('.' + PICKER_ALPHA_SLIDER).css("left", left); + elemColorBoxSpan[0].style.background = value; + colorValue = value; + }; + } else { + hsb = HEXToHSB(value); + elemColorBoxSpan[0].style.background = (colorValue = '#' + HSBToHEX(hsb)); + that.elemColorBox.find('.' + PICKER_TRIG_I).removeClass(ICON_PICKER_CLOSE).addClass(ICON_PICKER_DOWN); + }; + + if(change === 'change'){ + that.select(hsb.h, hsb.s, hsb.b, change); + options.change && options.change(colorValue); + return; + } + that.color = value; + + options.done && options.done(value); + that.removePicker(); + } + }; + + //选择器面板点击事件 + that.elemPicker.on('click', '*[colorpicker-events]', function(){ + var othis = $(this) + ,attrEvent = othis.attr('colorpicker-events'); + pickerEvents[attrEvent] && pickerEvents[attrEvent].call(this, othis); + }); + + //输入框事件 + elemPickerInput.on('keyup', function(e){ + var othis = $(this) + pickerEvents.confirm.call(this, othis, e.keyCode === 13 ? null : 'change'); + }); + } + + //颜色选择器输入 + Class.prototype.events = function(){ + var that = this + ,options = that.config + + ,elemColorBoxSpan = that.elemColorBox.find('.' + PICKER_TRIG_SPAN) + + //弹出颜色选择器 + that.elemColorBox.on('click' , function(){ + that.renderPicker(); + if($(ELEM_MAIN)[0]){ + that.val(); + that.side(); + }; + }); + + if(!options.elem[0] || that.elemColorBox[0].eventHandler) return; + + //绑定关闭控件事件 + $doc.on(clickOrMousedown, function(e){ + //如果点击的元素是颜色框 + if($(e.target).hasClass(ELEM) + || $(e.target).parents('.'+ELEM)[0] + ) return; + + //如果点击的元素是选择器 + if($(e.target).hasClass(ELEM_MAIN.replace(/\./g, '')) + || $(e.target).parents(ELEM_MAIN)[0] + ) return; + + if(!that.elemPicker) return; + + if(that.color){ + var hsb = RGBToHSB(RGBSTo(that.color)); + that.select(hsb.h, hsb.s, hsb.b); + } else { + that.elemColorBox.find('.' + PICKER_TRIG_I).removeClass(ICON_PICKER_DOWN).addClass(ICON_PICKER_CLOSE); + } + elemColorBoxSpan[0].style.background = that.color || ''; + + that.removePicker(); + }); + + //自适应定位 + $win.on('resize', function(){ + if(!that.elemPicker || !$(ELEM_MAIN)[0]){ + return false; + } + that.position(); + }); + + that.elemColorBox[0].eventHandler = true; + }; + + //核心入口 + colorpicker.render = function(options){ + var inst = new Class(options); + return thisColorPicker.call(inst); + }; + + exports(MOD_NAME, colorpicker); +}); diff --git a/static/layui/modules/demo.js b/static/layui/modules/demo.js new file mode 100644 index 0000000..5058d67 --- /dev/null +++ b/static/layui/modules/demo.js @@ -0,0 +1,135 @@ + +/*! + * MODULE_DEMO_NAME 模块组件通用结构 + * MIT Licensed + */ + +layui.define([''], function(exports){ + "use strict"; + + var $ = layui.$ + + //模块名 + ,MOD_NAME = 'MODULE_DEMO_NAME' + ,MOD_INDEX = 'layui_'+ MOD_NAME +'_index' //模块索引名 + + //外部接口 + ,MODULE_DEMO_NAME = { + config: {} + ,index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisModule = function(){ + var that = this + ,options = that.config + ,id = options.id || that.index; + + thisModule.that[id] = that; //记录当前实例对象 + + return { + config: options + //重置实例 + ,reload: function(options){ + that.reload.call(that, options); + } + } + } + + //字符常量 + ,STR_ELEM = 'layui-MODULE_DEMO_NAME', STR_HIDE = 'layui-hide', STR_DISABLED = 'layui-disabled', STR_NONE = 'layui-none' + + //主模板 + ,TPL_MAIN = [''].join('') + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++MODULE_DEMO_NAME.index; + that.config = $.extend({}, that.config, MODULE_DEMO_NAME.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + + }; + + //重载实例 + Class.prototype.reload = function(options){ + var that = this; + + //防止数组深度合并 + layui.each(options, function(key, item){ + if(layui._typeof(item) === 'array') delete that.config[key]; + }); + + that.config = $.extend(true, {}, that.config, options); + that.render(); + }; + + //渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + //解析模板 + var thisElem = that.elem = $(laytpl(TPL_MAIN).render({ + data: options + ,index: that.index //索引 + })); + + var othis = options.elem = $(options.elem); + if(!othis[0]) return; + + + + that.events(); //事件 + }; + + //事件 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + + + }; + + //记录所有实例 + thisModule.that = {}; //记录所有实例对象 + + //获取当前实例对象 + thisModule.getThis = function(id){ + var that = thisModule.that[id]; + if(!that) hint.error(id ? (MOD_NAME +' instance with ID \''+ id +'\' not found') : 'ID argument required'); + return that + }; + + //重载实例 + MODULE_DEMO_NAME.reload = function(id, options){ + var that = thisModule.that[id]; + that.reload(options); + + return thisModule.call(that); + }; + + //核心入口 + MODULE_DEMO_NAME.render = function(options){ + var inst = new Class(options); + return thisModule.call(inst); + }; + + exports(MOD_NAME, MODULE_DEMO_NAME); +}); diff --git a/static/layui/modules/dropdown.js b/static/layui/modules/dropdown.js new file mode 100644 index 0000000..5dae4b5 --- /dev/null +++ b/static/layui/modules/dropdown.js @@ -0,0 +1,528 @@ +/** + + @Name:dropdown 下拉菜单组件 + @License:MIT + + */ + +layui.define(['jquery', 'laytpl', 'lay'], function(exports){ + "use strict"; + + var $ = layui.$ + ,laytpl = layui.laytpl + ,hint = layui.hint() + ,device = layui.device() + ,clickOrMousedown = (device.mobile ? 'click' : 'mousedown') + + //模块名 + ,MOD_NAME = 'dropdown' + ,MOD_INDEX = 'layui_'+ MOD_NAME +'_index' //模块索引名 + + //外部接口 + ,dropdown = { + config: {} + ,index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisModule = function(){ + var that = this + ,options = that.config + ,id = options.id; + + thisModule.that[id] = that; //记录当前实例对象 + + return { + config: options + //重置实例 + ,reload: function(options){ + that.reload.call(that, options); + } + } + } + + //字符常量 + ,STR_ELEM = 'layui-dropdown', STR_HIDE = 'layui-hide', STR_DISABLED = 'layui-disabled', STR_NONE = 'layui-none' + ,STR_ITEM_UP = 'layui-menu-item-up', STR_ITEM_DOWN = 'layui-menu-item-down', STR_MENU_TITLE = 'layui-menu-body-title', STR_ITEM_GROUP = 'layui-menu-item-group', STR_ITEM_PARENT = 'layui-menu-item-parent', STR_ITEM_DIV = 'layui-menu-item-divider', STR_ITEM_CHECKED = 'layui-menu-item-checked', STR_ITEM_CHECKED2 = 'layui-menu-item-checked2', STR_MENU_PANEL = 'layui-menu-body-panel', STR_MENU_PANEL_L = 'layui-menu-body-panel-left' + + ,STR_GROUP_TITLE = '.'+ STR_ITEM_GROUP + '>.'+ STR_MENU_TITLE + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++dropdown.index; + that.config = $.extend({}, that.config, dropdown.config, options); + that.init(); + }; + + //默认配置 + Class.prototype.config = { + trigger: 'click' //事件类型 + ,content: '' //自定义菜单内容 + ,className: '' //自定义样式类名 + ,style: '' //设置面板 style 属性 + ,show: false //是否初始即显示菜单面板 + ,isAllowSpread: true //是否允许菜单组展开收缩 + ,isSpreadItem: true //是否初始展开子菜单 + ,data: [] //菜单数据结构 + ,delay: 300 //延迟关闭的毫秒数,若 trigger 为 hover 时才生效 + }; + + //重载实例 + Class.prototype.reload = function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + that.init(true); + }; + + //初始化准备 + Class.prototype.init = function(rerender){ + var that = this + ,options = that.config + ,elem = options.elem = $(options.elem); + + //若 elem 非唯一 + if(elem.length > 1){ + layui.each(elem, function(){ + dropdown.render($.extend({}, options, { + elem: this + })); + }); + return that; + } + + //若重复执行 render,则视为 reload 处理 + if(!rerender && elem[0] && elem.data(MOD_INDEX)){; + var newThat = thisModule.getThis(elem.data(MOD_INDEX)); + if(!newThat) return; + + return newThat.reload(options); + }; + + //初始化 id 参数 + options.id = ('id' in options) ? options.id : that.index; + + if(options.show) that.render(rerender); //初始即显示 + that.events(); //事件 + }; + + //渲染 + Class.prototype.render = function(rerender){ + var that = this + ,options = that.config + ,elemBody = $('body') + + //默认菜单内容 + ,getDefaultView = function(){ + var elemUl = $(''); + if(options.data.length > 0 ){ + eachItemView(elemUl, options.data) + } else { + elemUl.html('
  • no menu
  • '); + } + return elemUl; + } + + //遍历菜单项 + ,eachItemView = function(views, data){ + //var views = []; + layui.each(data, function(index, item){ + //是否存在子级 + var isChild = item.child && item.child.length > 0 + ,isSpreadItem = ('isSpreadItem' in item) ? item.isSpreadItem : options.isSpreadItem + ,title = item.templet + ? laytpl(item.templet).render(item) + : (options.templet ? laytpl(options.templet).render(item) : item.title) + + //初始类型 + ,type = function(){ + if(isChild){ + item.type = item.type || 'parent'; + } + if(item.type){ + return ({ + group: 'group' + ,parent: 'parent' + ,'-': '-' + })[item.type] || 'parent'; + } + return ''; + }(); + + if(type !== '-' && (!item.title && !item.id && !isChild)) return; + + //列表元素 + var viewLi = $(['' + + //标题区 + ,function(){ + //是否超文本 + var viewText = ('href' in item) ? ( + ''+ title +'' + ) : title; + + //是否存在子级 + if(isChild){ + return '
    '+ viewText + function(){ + if(type === 'parent'){ + return ''; + } else if(type === 'group' && options.isAllowSpread){ + return ''; + } else { + return ''; + } + }() +'
    ' + + } + return '
    '+ viewText +'
    '; + }() + ,''].join('')); + + viewLi.data('item', item); + + //子级区 + if(isChild){ + var elemPanel = $('
    ') + ,elemUl = $('
      '); + + if(type === 'parent'){ + elemPanel.append(eachItemView(elemUl, item.child)); + viewLi.append(elemPanel); + } else { + viewLi.append(eachItemView(elemUl, item.child)); + } + } + + views.append(viewLi); + }); + return views; + } + + //主模板 + ,TPL_MAIN = ['
      ' + ,'
      '].join(''); + + //如果是右键事件,则每次触发事件时,将允许重新渲染 + if(options.trigger === 'contextmenu' || lay.isTopElem(options.elem[0])) rerender = true; + + //判断是否已经打开了下拉菜单面板 + if(!rerender && options.elem.data(MOD_INDEX +'_opened')) return; + + //记录模板对象 + that.elemView = $(TPL_MAIN); + that.elemView.append(options.content || getDefaultView()); + + //初始化某些属性 + if(options.className) that.elemView.addClass(options.className); + if(options.style) that.elemView.attr('style', options.style); + + + //记录当前执行的实例索引 + dropdown.thisId = options.id; + + //插入视图 + that.remove(); //移除非当前绑定元素的面板 + elemBody.append(that.elemView); + options.elem.data(MOD_INDEX +'_opened', true); + + //坐标定位 + that.position(); + thisModule.prevElem = that.elemView; //记录当前打开的元素,以便在下次关闭 + thisModule.prevElem.data('prevElem', options.elem); //将当前绑定的元素,记录在打开元素的 data 对象中 + + //阻止全局事件 + that.elemView.find('.layui-menu').on(clickOrMousedown, function(e){ + layui.stope(e); + }); + + //触发菜单列表事件 + that.elemView.find('.layui-menu li').on('click', function(e){ + var othis = $(this) + ,data = othis.data('item') || {} + ,isChild = data.child && data.child.length > 0; + + if(!isChild && data.type !== '-'){ + that.remove(); + typeof options.click === 'function' && options.click(data, othis); + } + }); + + //触发菜单组展开收缩 + that.elemView.find(STR_GROUP_TITLE).on('click', function(e){ + var othis = $(this) + ,elemGroup = othis.parent() + ,data = elemGroup.data('item') || {} + + if(data.type === 'group' && options.isAllowSpread){ + thisModule.spread(elemGroup); + } + }); + + //如果是鼠标移入事件,则鼠标移出时自动关闭 + if(options.trigger === 'mouseenter'){ + that.elemView.on('mouseenter', function(){ + clearTimeout(thisModule.timer); + }).on('mouseleave', function(){ + that.delayRemove(); + }); + } + + }; + + //位置定位 + Class.prototype.position = function(obj){ + var that = this + ,options = that.config; + + lay.position(options.elem[0], that.elemView[0], { + position: options.position + ,e: that.e + ,clickType: options.trigger === 'contextmenu' ? 'right' : null + ,align: options.align || null + }); + }; + + //删除视图 + Class.prototype.remove = function(){ + var that = this + ,options = that.config + ,elemPrev = thisModule.prevElem; + + //若存在已打开的面板元素,则移除 + if(elemPrev){ + elemPrev.data('prevElem') && ( + elemPrev.data('prevElem').data(MOD_INDEX +'_opened', false) + ); + elemPrev.remove(); + } + }; + + //延迟删除视图 + Class.prototype.delayRemove = function(){ + var that = this + ,options = that.config; + clearTimeout(thisModule.timer); + + thisModule.timer = setTimeout(function(){ + that.remove(); + }, options.delay); + }; + + //事件 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + + //如果传入 hover,则解析为 mouseenter + if(options.trigger === 'hover') options.trigger = 'mouseenter'; + + //解除上一个事件 + if(that.prevElem) that.prevElem.off(options.trigger, that.prevElemCallback); + + //记录被绑定的元素及回调 + that.prevElem = options.elem; + that.prevElemCallback = function(e){ + clearTimeout(thisModule.timer); + that.e = e; + that.render(); + e.preventDefault(); + + //组件打开完毕的时间 + typeof options.ready === 'function' && options.ready(that.elemView, options.elem, that.e.target); + }; + + //触发元素事件 + options.elem.on(options.trigger, that.prevElemCallback); + + //如果是鼠标移入事件 + if(options.trigger === 'mouseenter'){ + //直行鼠标移出事件 + options.elem.on('mouseleave', function(){ + that.delayRemove(); + }); + } + }; + + //记录所有实例 + thisModule.that = {}; //记录所有实例对象 + + //获取当前实例对象 + thisModule.getThis = function(id){ + var that = thisModule.that[id]; + if(!that) hint.error(id ? (MOD_NAME +' instance with ID \''+ id +'\' not found') : 'ID argument required'); + return that; + }; + + //设置菜单组展开和收缩状态 + thisModule.spread = function(othis){ + //菜单组展开和收缩 + var elemIcon = othis.children('.'+ STR_MENU_TITLE).find('.layui-icon'); + if(othis.hasClass(STR_ITEM_UP)){ + othis.removeClass(STR_ITEM_UP).addClass(STR_ITEM_DOWN); + elemIcon.removeClass('layui-icon-down').addClass('layui-icon-up'); + } else { + othis.removeClass(STR_ITEM_DOWN).addClass(STR_ITEM_UP); + elemIcon.removeClass('layui-icon-up').addClass('layui-icon-down') + } + }; + + //全局事件 + ;!function(){ + var _WIN = $(window) + ,_DOC = $(document); + + //自适应定位 + _WIN.on('resize', function(){ + if(!dropdown.thisId) return; + var that = thisModule.getThis(dropdown.thisId); + if(!that) return; + + if(!that.elemView[0] || !$('.'+ STR_ELEM)[0]){ + return false; + } + + var options = that.config; + + if(options.trigger === 'contextmenu'){ + that.remove(); + } else { + that.position(); + } + }); + + + + //点击任意处关闭 + _DOC.on(clickOrMousedown, function(e){ + if(!dropdown.thisId) return; + var that = thisModule.getThis(dropdown.thisId) + if(!that) return; + + var options = that.config; + + //如果触发的是绑定的元素,或者属于绑定元素的子元素,则不关闭 + //满足条件:当前绑定的元素不是 body document,或者不是鼠标右键事件 + if(!(lay.isTopElem(options.elem[0]) || options.trigger === 'contextmenu')){ + if( + e.target === options.elem[0] || + options.elem.find(e.target)[0] || + e.target === that.elemView[0] || + (that.elemView && that.elemView.find(e.target)[0]) + ) return; + } + + that.remove(); + }); + + //基础菜单的静态元素事件 + var ELEM_LI = '.layui-menu:not(.layui-dropdown-menu) li'; + _DOC.on('click', ELEM_LI, function(e){ + var othis = $(this) + ,parent = othis.parents('.layui-menu').eq(0) + ,isChild = othis.hasClass(STR_ITEM_GROUP) || othis.hasClass(STR_ITEM_PARENT) + ,filter = parent.attr('lay-filter') || parent.attr('id') + ,options = lay.options(this); + + //非触发元素 + if(othis.hasClass(STR_ITEM_DIV)) return; + + //非菜单组 + if(!isChild){ + //选中 + parent.find('.'+ STR_ITEM_CHECKED).removeClass(STR_ITEM_CHECKED); //清除选中样式 + parent.find('.'+ STR_ITEM_CHECKED2).removeClass(STR_ITEM_CHECKED2); //清除父级菜单选中样式 + othis.addClass(STR_ITEM_CHECKED); //添加选中样式 + othis.parents('.'+ STR_ITEM_PARENT).addClass(STR_ITEM_CHECKED2); //添加父级菜单选中样式 + + //触发事件 + layui.event.call(this, MOD_NAME, 'click('+ filter +')', options); + } + }); + + //基础菜单的展开收缩事件 + _DOC.on('click', (ELEM_LI + STR_GROUP_TITLE), function(e){ + var othis = $(this) + ,elemGroup = othis.parents('.'+ STR_ITEM_GROUP +':eq(0)') + ,options = lay.options(elemGroup[0]); + + if(('isAllowSpread' in options) ? options.isAllowSpread : true){ + thisModule.spread(elemGroup); + }; + }); + + //判断子级菜单是否超出屏幕 + var ELEM_LI_PAR = '.layui-menu .'+ STR_ITEM_PARENT + _DOC.on('mouseenter', ELEM_LI_PAR, function(e){ + var othis = $(this) + ,elemPanel = othis.find('.'+ STR_MENU_PANEL); + + if(!elemPanel[0]) return; + var rect = elemPanel[0].getBoundingClientRect(); + + //是否超出右侧屏幕 + if(rect.right > _WIN.width()){ + elemPanel.addClass(STR_MENU_PANEL_L); + //不允许超出左侧屏幕 + rect = elemPanel[0].getBoundingClientRect(); + if(rect.left < 0){ + elemPanel.removeClass(STR_MENU_PANEL_L); + } + } + + //是否超出底部屏幕 + if(rect.bottom > _WIN.height()){ + elemPanel.eq(0).css('margin-top', -(rect.bottom - _WIN.height())); + }; + }).on('mouseleave', ELEM_LI_PAR, function(e){ + var othis = $(this) + ,elemPanel = othis.children('.'+ STR_MENU_PANEL); + + elemPanel.removeClass(STR_MENU_PANEL_L); + elemPanel.css('margin-top', 0); + }); + + }(); + + //重载实例 + dropdown.reload = function(id, options){ + var that = thisModule.getThis(id); + if(!that) return this; + + that.reload(options); + return thisModule.call(that); + }; + + //核心入口 + dropdown.render = function(options){ + var inst = new Class(options); + return thisModule.call(inst); + }; + + exports(MOD_NAME, dropdown); +}); diff --git a/static/layui/modules/element.js b/static/layui/modules/element.js new file mode 100644 index 0000000..b5742e2 --- /dev/null +++ b/static/layui/modules/element.js @@ -0,0 +1,510 @@ + +/*! + * element 常用元素操作 + * MIT Licensed + */ + +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$ + ,hint = layui.hint() + ,device = layui.device() + + ,MOD_NAME = 'element', THIS = 'layui-this', SHOW = 'layui-show' + + ,Element = function(){ + this.config = {}; + }; + + //全局设置 + Element.prototype.set = function(options){ + var that = this; + $.extend(true, that.config, options); + return that; + }; + + //表单事件 + Element.prototype.on = function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + }; + + //外部Tab新增 + Element.prototype.tabAdd = function(filter, options){ + var TITLE = '.layui-tab-title' + ,tabElem = $('.layui-tab[lay-filter='+ filter +']') + ,titElem = tabElem.children(TITLE) + ,barElem = titElem.children('.layui-tab-bar') + ,contElem = tabElem.children('.layui-tab-content') + ,li = ' 0) layAttr.unshift(''); //向前插,预留空格 + return layAttr.join(' '); + }() +'>'+ (options.title || 'unnaming') +''; + + barElem[0] ? barElem.before(li) : titElem.append(li); + contElem.append('
      '+ (options.content || '') +'
      '); + call.hideTabMore(true); + call.tabAuto(); + return this; + }; + + //外部Tab删除 + Element.prototype.tabDelete = function(filter, layid){ + var TITLE = '.layui-tab-title' + ,tabElem = $('.layui-tab[lay-filter='+ filter +']') + ,titElem = tabElem.children(TITLE) + ,liElem = titElem.find('>li[lay-id="'+ layid +'"]'); + call.tabDelete(null, liElem); + return this; + }; + + //外部Tab切换 + Element.prototype.tabChange = function(filter, layid){ + var TITLE = '.layui-tab-title' + ,tabElem = $('.layui-tab[lay-filter='+ filter +']') + ,titElem = tabElem.children(TITLE) + ,liElem = titElem.find('>li[lay-id="'+ layid +'"]'); + call.tabClick.call(liElem[0], null, null, liElem); + return this; + }; + + //自定义Tab选项卡 + Element.prototype.tab = function(options){ + options = options || {}; + dom.on('click', options.headerElem, function(e){ + var index = $(this).index(); + call.tabClick.call(this, e, index, null, options); + }); + }; + + + //动态改变进度条 + Element.prototype.progress = function(filter, percent){ + var ELEM = 'layui-progress' + ,elem = $('.'+ ELEM +'[lay-filter='+ filter +']') + ,elemBar = elem.find('.'+ ELEM +'-bar') + ,text = elemBar.find('.'+ ELEM +'-text'); + elemBar.css('width', percent).attr('lay-percent', percent); + text.text(percent); + return this; + }; + + var NAV_ELEM = '.layui-nav', NAV_ITEM = 'layui-nav-item', NAV_BAR = 'layui-nav-bar' + ,NAV_TREE = 'layui-nav-tree', NAV_CHILD = 'layui-nav-child', NAV_CHILD_C = 'layui-nav-child-c' + ,NAV_MORE = 'layui-nav-more', NAV_DOWN = 'layui-icon-down', NAV_ANIM = 'layui-anim layui-anim-upbit' + + //基础事件体 + ,call = { + //Tab 点击 + tabClick: function(e, index, liElem, options){ + options = options || {}; + var othis = liElem || $(this) + ,index = index || othis.parent().children('li').index(othis) + ,parents = options.headerElem ? othis.parent() : othis.parents('.layui-tab').eq(0) + ,item = options.bodyElem ? $(options.bodyElem) : parents.children('.layui-tab-content').children('.layui-tab-item') + ,elemA = othis.find('a') + ,isJump = elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank' //是否存在跳转 + ,unselect = typeof othis.attr('lay-unselect') === 'string' //是否禁用选中 + ,filter = parents.attr('lay-filter'); + + //执行切换 + if(!(isJump || unselect)){ + othis.addClass(THIS).siblings().removeClass(THIS); + item.eq(index).addClass(SHOW).siblings().removeClass(SHOW); + } + + layui.event.call(this, MOD_NAME, 'tab('+ filter +')', { + elem: parents + ,index: index + }); + } + + //Tab删除 + ,tabDelete: function(e, othis){ + var li = othis || $(this).parent(), index = li.index() + ,parents = li.parents('.layui-tab').eq(0) + ,item = parents.children('.layui-tab-content').children('.layui-tab-item') + ,filter = parents.attr('lay-filter'); + + if(li.hasClass(THIS)){ + if(li.next()[0]){ + call.tabClick.call(li.next()[0], null, index + 1); + } else if(li.prev()[0]){ + call.tabClick.call(li.prev()[0], null, index - 1); + } + } + + li.remove(); + item.eq(index).remove(); + setTimeout(function(){ + call.tabAuto(); + }, 50); + + layui.event.call(this, MOD_NAME, 'tabDelete('+ filter +')', { + elem: parents + ,index: index + }); + } + + //Tab自适应 + ,tabAuto: function(){ + var SCROLL = 'layui-tab-scroll', MORE = 'layui-tab-more', BAR = 'layui-tab-bar' + ,CLOSE = 'layui-tab-close', that = this; + + $('.layui-tab').each(function(){ + var othis = $(this) + ,title = othis.children('.layui-tab-title') + ,item = othis.children('.layui-tab-content').children('.layui-tab-item') + ,STOPE = 'lay-stope="tabmore"' + ,span = $(''); + + if(that === window && device.ie != 8){ + call.hideTabMore(true) + } + + //允许关闭 + if(othis.attr('lay-allowClose')){ + title.find('li').each(function(){ + var li = $(this); + if(!li.find('.'+CLOSE)[0]){ + var close = $(''); + close.on('click', call.tabDelete); + li.append(close); + } + }); + } + + if(typeof othis.attr('lay-unauto') === 'string') return; + + //响应式 + if(title.prop('scrollWidth') > title.outerWidth()+1){ + if(title.find('.'+BAR)[0]) return; + title.append(span); + othis.attr('overflow', ''); + span.on('click', function(e){ + title[this.title ? 'removeClass' : 'addClass'](MORE); + this.title = this.title ? '' : '收缩'; + }); + } else { + title.find('.'+BAR).remove(); + othis.removeAttr('overflow'); + } + }); + } + //隐藏更多Tab + ,hideTabMore: function(e){ + var tsbTitle = $('.layui-tab-title'); + if(e === true || $(e.target).attr('lay-stope') !== 'tabmore'){ + tsbTitle.removeClass('layui-tab-more'); + tsbTitle.find('.layui-tab-bar').attr('title',''); + } + } + + //点击一级菜单 + /* + ,clickThis: function(){ + var othis = $(this), parents = othis.parents(NAV_ELEM) + ,filter = parents.attr('lay-filter') + ,elemA = othis.find('a') + ,unselect = typeof othis.attr('lay-unselect') === 'string'; + + if(othis.find('.'+NAV_CHILD)[0]) return; + + if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank') && !unselect){ + parents.find('.'+THIS).removeClass(THIS); + othis.addClass(THIS); + } + + layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis); + } + ) + */ + + //点击菜单 - a标签触发 + ,clickThis: function(){ + var othis = $(this) + ,parents = othis.parents(NAV_ELEM) + ,filter = parents.attr('lay-filter') + ,parent = othis.parent() + ,child = othis.siblings('.'+NAV_CHILD) + ,unselect = typeof parent.attr('lay-unselect') === 'string'; //是否禁用选中 + + if(!(othis.attr('href') !== 'javascript:;' && othis.attr('target') === '_blank') && !unselect){ + if(!child[0]){ + parents.find('.'+THIS).removeClass(THIS); + parent.addClass(THIS); + } + } + + //如果是垂直菜单 + if(parents.hasClass(NAV_TREE)){ + child.removeClass(NAV_ANIM); + + //如果有子菜单,则展开 + if(child[0]){ + parent[child.css('display') === 'none' ? 'addClass': 'removeClass'](NAV_ITEM+'ed'); + if(parents.attr('lay-shrink') === 'all'){ + parent.siblings().removeClass(NAV_ITEM + 'ed'); + } + } + } + + layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis); + } + + //点击子菜单选中 + /* + ,clickChild: function(){ + var othis = $(this), parents = othis.parents(NAV_ELEM) + ,filter = parents.attr('lay-filter'); + parents.find('.'+THIS).removeClass(THIS); + othis.addClass(THIS); + layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis); + } + */ + + //折叠面板 + ,collapse: function(){ + var othis = $(this), icon = othis.find('.layui-colla-icon') + ,elemCont = othis.siblings('.layui-colla-content') + ,parents = othis.parents('.layui-collapse').eq(0) + ,filter = parents.attr('lay-filter') + ,isNone = elemCont.css('display') === 'none'; + + //是否手风琴 + if(typeof parents.attr('lay-accordion') === 'string'){ + var show = parents.children('.layui-colla-item').children('.'+SHOW); + show.siblings('.layui-colla-title').children('.layui-colla-icon').html(''); + show.removeClass(SHOW); + } + + elemCont[isNone ? 'addClass' : 'removeClass'](SHOW); + icon.html(isNone ? '' : ''); + + layui.event.call(this, MOD_NAME, 'collapse('+ filter +')', { + title: othis + ,content: elemCont + ,show: isNone + }); + } + }; + + //初始化元素操作 + Element.prototype.init = function(type, filter){ + var that = this, elemFilter = function(){ + return filter ? ('[lay-filter="' + filter +'"]') : ''; + }(), items = { + + //Tab选项卡 + tab: function(){ + call.tabAuto.call({}); + } + + //导航菜单 + ,nav: function(){ + var TIME = 200, timer = {}, timerMore = {}, timeEnd = {}, NAV_TITLE = 'layui-nav-title' + + //滑块跟随 + ,follow = function(bar, nav, index){ + var othis = $(this), child = othis.find('.'+NAV_CHILD); + if(nav.hasClass(NAV_TREE)){ + //无子菜单时跟随 + if(!child[0]){ + var thisA = othis.children('.'+ NAV_TITLE); + bar.css({ + top: othis.offset().top - nav.offset().top + ,height: (thisA[0] ? thisA : othis).outerHeight() + ,opacity: 1 + }); + } + } else { + child.addClass(NAV_ANIM); + + //若居中对齐 + if(child.hasClass(NAV_CHILD_C)) child.css({ + left: -(child.outerWidth() - othis.width())/2 + }); + + //滑块定位 + if(child[0]){ //若有子菜单,则滑块消失 + bar.css({ + left: bar.position().left + bar.width()/2 + ,width: 0 + ,opacity: 0 + }); + } else { //bar 跟随 + bar.css({ + left: othis.position().left + parseFloat(othis.css('marginLeft')) + ,top: othis.position().top + othis.height() - bar.height() + }); + } + + //渐显滑块并适配宽度 + timer[index] = setTimeout(function(){ + bar.css({ + width: child[0] ? 0 : othis.width() + ,opacity: child[0] ? 0 : 1 + }); + }, device.ie && device.ie < 10 ? 0 : TIME); + + //显示子菜单 + clearTimeout(timeEnd[index]); + if(child.css('display') === 'block'){ + clearTimeout(timerMore[index]); + } + timerMore[index] = setTimeout(function(){ + child.addClass(SHOW); + othis.find('.'+NAV_MORE).addClass(NAV_MORE+'d'); + }, 300); + } + }; + + //遍历导航 + $(NAV_ELEM + elemFilter).each(function(index){ + var othis = $(this) + ,bar = $('') + ,itemElem = othis.find('.'+NAV_ITEM); + + //hover 滑动效果 + if(!othis.find('.'+NAV_BAR)[0]){ + othis.append(bar); + (othis.hasClass(NAV_TREE) + ? itemElem.find('dd,>.'+ NAV_TITLE) + : itemElem).on('mouseenter', function(){ + follow.call(this, bar, othis, index); + }).on('mouseleave', function(){ //鼠标移出 + //是否为垂直导航 + if(othis.hasClass(NAV_TREE)){ + bar.css({ + height: 0 + ,opacity: 0 + }); + } else { + //隐藏子菜单 + clearTimeout(timerMore[index]); + timerMore[index] = setTimeout(function(){ + othis.find('.'+NAV_CHILD).removeClass(SHOW); + othis.find('.'+NAV_MORE).removeClass(NAV_MORE+'d'); + }, 300); + } + }); + othis.on('mouseleave', function(){ + clearTimeout(timer[index]) + timeEnd[index] = setTimeout(function(){ + if(!othis.hasClass(NAV_TREE)){ + bar.css({ + width: 0 + ,left: bar.position().left + bar.width()/2 + ,opacity: 0 + }); + } + }, TIME); + }); + } + + //展开子菜单 + itemElem.find('a').each(function(){ + var thisA = $(this) + ,parent = thisA.parent() + ,child = thisA.siblings('.'+NAV_CHILD); + + //输出小箭头 + if(child[0] && !thisA.children('.'+NAV_MORE)[0]){ + thisA.append(''); + } + + thisA.off('click', call.clickThis).on('click', call.clickThis); //点击菜单 + }); + }); + } + + //面包屑 + ,breadcrumb: function(){ + var ELEM = '.layui-breadcrumb'; + + $(ELEM + elemFilter).each(function(){ + var othis = $(this) + ,ATTE_SPR = 'lay-separator' + ,separator = othis.attr(ATTE_SPR) || '/' + ,aNode = othis.find('a'); + if(aNode.next('span['+ ATTE_SPR +']')[0]) return; + aNode.each(function(index){ + if(index === aNode.length - 1) return; + $(this).after(''+ separator +''); + }); + othis.css('visibility', 'visible'); + }); + } + + //进度条 + ,progress: function(){ + var ELEM = 'layui-progress'; + $('.' + ELEM + elemFilter).each(function(){ + var othis = $(this) + ,elemBar = othis.find('.layui-progress-bar') + ,percent = elemBar.attr('lay-percent'); + + elemBar.css('width', function(){ + return /^.+\/.+$/.test(percent) + ? (new Function('return '+ percent)() * 100) + '%' + : percent; + }()); + + if(othis.attr('lay-showPercent')){ + setTimeout(function(){ + elemBar.html(''+ percent +''); + },350); + } + }); + } + + //折叠面板 + ,collapse: function(){ + var ELEM = 'layui-collapse'; + + $('.' + ELEM + elemFilter).each(function(){ + var elemItem = $(this).find('.layui-colla-item') + elemItem.each(function(){ + var othis = $(this) + ,elemTitle = othis.find('.layui-colla-title') + ,elemCont = othis.find('.layui-colla-content') + ,isNone = elemCont.css('display') === 'none'; + + //初始状态 + elemTitle.find('.layui-colla-icon').remove(); + elemTitle.append(''+ (isNone ? '' : '') +''); + + //点击标题 + elemTitle.off('click', call.collapse).on('click', call.collapse); + }); + + }); + } + }; + + return items[type] ? items[type]() : layui.each(items, function(index, item){ + item(); + }); + }; + + Element.prototype.render = Element.prototype.init; + + var element = new Element(), dom = $(document); + + $(function(){ + element.render(); + }); + + var TITLE = '.layui-tab-title li'; + dom.on('click', TITLE, call.tabClick); //Tab切换 + dom.on('click', call.hideTabMore); //隐藏展开的Tab + $(window).on('resize', call.tabAuto); //自适应 + + exports(MOD_NAME, element); +}); + diff --git a/static/layui/modules/flow.js b/static/layui/modules/flow.js new file mode 100644 index 0000000..a4d12ef --- /dev/null +++ b/static/layui/modules/flow.js @@ -0,0 +1,179 @@ +/** + + @Name flow 流加载组件 + @License:MIT + + */ + + +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$, Flow = function(options){} + ,ELEM_MORE = 'layui-flow-more' + ,ELEM_LOAD = ''; + + //主方法 + Flow.prototype.load = function(options){ + var that = this, page = 0, lock, isOver, lazyimg, timer; + options = options || {}; + + var elem = $(options.elem); if(!elem[0]) return; + var scrollElem = $(options.scrollElem || document); //滚动条所在元素 + var mb = options.mb || 50; //与底部的临界距离 + var isAuto = 'isAuto' in options ? options.isAuto : true; //是否自动滚动加载 + var end = options.end || '没有更多了'; //“末页”显示文案 + + //滚动条所在元素是否为document + var notDocment = options.scrollElem && options.scrollElem !== document; + + //加载更多 + var ELEM_TEXT = '加载更多' + ,more = $(''); + + if(!elem.find('.layui-flow-more')[0]){ + elem.append(more); + } + + //加载下一个元素 + var next = function(html, over){ + html = $(html); + more.before(html); + over = over == 0 ? true : null; + over ? more.html(end) : more.find('a').html(ELEM_TEXT); + isOver = over; + lock = null; + lazyimg && lazyimg(); + }; + + //触发请求 + var done = function(){ + lock = true; + more.find('a').html(ELEM_LOAD); + typeof options.done === 'function' && options.done(++page, next); + }; + + done(); + + //不自动滚动加载 + more.find('a').on('click', function(){ + var othis = $(this); + if(isOver) return; + lock || done(); + }); + + //如果允许图片懒加载 + if(options.isLazyimg){ + var lazyimg = that.lazyimg({ + elem: options.elem + ' img' + ,scrollElem: options.scrollElem + }); + } + + if(!isAuto) return that; + + scrollElem.on('scroll', function(){ + var othis = $(this), top = othis.scrollTop(); + + if(timer) clearTimeout(timer); + if(isOver || !elem.width()) return; //如果已经结束,或者元素处于隐藏状态,则不执行滚动加载 + + timer = setTimeout(function(){ + //计算滚动所在容器的可视高度 + var height = notDocment ? othis.height() : $(window).height(); + + //计算滚动所在容器的实际高度 + var scrollHeight = notDocment + ? othis.prop('scrollHeight') + : document.documentElement.scrollHeight; + + //临界点 + if(scrollHeight - top - height <= mb){ + lock || done(); + } + }, 100); + }); + + return that; + }; + + //图片懒加载 + Flow.prototype.lazyimg = function(options){ + var that = this, index = 0, haveScroll; + options = options || {}; + + var scrollElem = $(options.scrollElem || document); //滚动条所在元素 + var elem = options.elem || 'img'; + + //滚动条所在元素是否为document + var notDocment = options.scrollElem && options.scrollElem !== document; + + //显示图片 + var show = function(item, height){ + var start = scrollElem.scrollTop(), end = start + height; + var elemTop = notDocment ? function(){ + return item.offset().top - scrollElem.offset().top + start; + }() : item.offset().top; + + /* 始终只加载在当前屏范围内的图片 */ + if(elemTop >= start && elemTop <= end){ + if(item.attr('lay-src')){ + var src = item.attr('lay-src'); + layui.img(src, function(){ + var next = that.lazyimg.elem.eq(index); + item.attr('src', src).removeAttr('lay-src'); + + /* 当前图片加载就绪后,检测下一个图片是否在当前屏 */ + next[0] && render(next); + index++; + }, function(){ + var next = that.lazyimg.elem.eq(index); + item.removeAttr('lay-src'); + }); + } + } + }, render = function(othis, scroll){ + + //计算滚动所在容器的可视高度 + var height = notDocment ? (scroll||scrollElem).height() : $(window).height(); + var start = scrollElem.scrollTop(), end = start + height; + + that.lazyimg.elem = $(elem); + + if(othis){ + show(othis, height); + } else { + //计算未加载过的图片 + for(var i = 0; i < that.lazyimg.elem.length; i++){ + var item = that.lazyimg.elem.eq(i), elemTop = notDocment ? function(){ + return item.offset().top - scrollElem.offset().top + start; + }() : item.offset().top; + + show(item, height); + index = i; + + //如果图片的top坐标,超出了当前屏,则终止后续图片的遍历 + if(elemTop > end) break; + } + } + }; + + render(); + + if(!haveScroll){ + var timer; + scrollElem.on('scroll', function(){ + var othis = $(this); + if(timer) clearTimeout(timer) + timer = setTimeout(function(){ + render(null, othis); + }, 50); + }); + haveScroll = true; + } + return render; + }; + + //暴露接口 + exports('flow', new Flow()); +}); diff --git a/static/layui/modules/form.js b/static/layui/modules/form.js new file mode 100644 index 0000000..1bd40c1 --- /dev/null +++ b/static/layui/modules/form.js @@ -0,0 +1,742 @@ + +/*! + * form 表单组件 + * MIT Licensed + */ + +layui.define('layer', function(exports){ + "use strict"; + + var $ = layui.$ + ,layer = layui.layer + ,hint = layui.hint() + ,device = layui.device() + + ,MOD_NAME = 'form', ELEM = '.layui-form', THIS = 'layui-this' + ,SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled' + + ,Form = function(){ + this.config = { + verify: { + required: [ + /[\S]+/ + ,'必填项不能为空' + ] + ,phone: [ + /^1\d{10}$/ + ,'请输入正确的手机号' + ] + ,email: [ + /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/ + ,'邮箱格式不正确' + ] + ,url: [ + /^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/ + ,'链接格式不正确' + ] + ,number: function(value){ + if(!value || isNaN(value)) return '只能填写数字' + } + ,date: [ + /^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/ + ,'日期格式不正确' + ] + ,identity: [ + /(^\d{15}$)|(^\d{17}(x|X|\d)$)/ + ,'请输入正确的身份证号' + ] + } + ,autocomplete: null //全局 autocomplete 状态。null 表示不干预 + }; + }; + + //全局设置 + Form.prototype.set = function(options){ + var that = this; + $.extend(true, that.config, options); + return that; + }; + + //验证规则设定 + Form.prototype.verify = function(settings){ + var that = this; + $.extend(true, that.config.verify, settings); + return that; + }; + + //表单事件 + Form.prototype.on = function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + }; + + //赋值/取值 + Form.prototype.val = function(filter, object){ + var that = this + ,formElem = $(ELEM + '[lay-filter="' + filter +'"]'); + + //遍历 + formElem.each(function(index, item){ + var itemForm = $(this); + + //赋值 + layui.each(object, function(key, value){ + var itemElem = itemForm.find('[name="'+ key +'"]') + ,type; + + //如果对应的表单不存在,则不执行 + if(!itemElem[0]) return; + type = itemElem[0].type; + + //如果为复选框 + if(type === 'checkbox'){ + itemElem[0].checked = value; + } else if(type === 'radio') { //如果为单选框 + itemElem.each(function(){ + if(this.value == value ){ + this.checked = true + } + }); + } else { //其它类型的表单 + itemElem.val(value); + } + }); + }); + + form.render(null, filter); + + //返回值 + return that.getValue(filter); + }; + + //取值 + Form.prototype.getValue = function(filter, itemForm){ + itemForm = itemForm || $(ELEM + '[lay-filter="' + filter +'"]').eq(0); + + var nameIndex = {} //数组 name 索引 + ,field = {} + ,fieldElem = itemForm.find('input,select,textarea') //获取所有表单域 + + layui.each(fieldElem, function(_, item){ + var othis = $(this) + ,init_name; //初始 name + + item.name = (item.name || '').replace(/^\s*|\s*&/, ''); + if(!item.name) return; + + //用于支持数组 name + if(/^.*\[\]$/.test(item.name)){ + var key = item.name.match(/^(.*)\[\]$/g)[0]; + nameIndex[key] = nameIndex[key] | 0; + init_name = item.name.replace(/^(.*)\[\]$/, '$1['+ (nameIndex[key]++) +']'); + } + + if(/^checkbox|radio$/.test(item.type) && !item.checked) return; //复选框和单选框未选中,不记录字段 + field[init_name || item.name] = item.value; + }); + + return field; + }; + + //表单控件渲染 + Form.prototype.render = function(type, filter){ + var that = this + ,options = that.config + ,elemForm = $(ELEM + function(){ + return filter ? ('[lay-filter="' + filter +'"]') : ''; + }()) + ,items = { + //输入框 + input: function(){ + var inputs = elemForm.find('input,textarea'); + + //初始化全局的 autocomplete + options.autocomplete && inputs.attr('autocomplete', options.autocomplete); + } + + //下拉选择框 + ,select: function(){ + var TIPS = '请选择', CLASS = 'layui-form-select', TITLE = 'layui-select-title' + ,NONE = 'layui-select-none', initValue = '', thatInput + ,selects = elemForm.find('select') + + //隐藏 select + ,hide = function(e, clear){ + if(!$(e.target).parent().hasClass(TITLE) || clear){ + $('.'+CLASS).removeClass(CLASS+'ed ' + CLASS+'up'); + thatInput && initValue && thatInput.val(initValue); + } + thatInput = null; + } + + //各种事件 + ,events = function(reElem, disabled, isSearch){ + var select = $(this) + ,title = reElem.find('.' + TITLE) + ,input = title.find('input') + ,dl = reElem.find('dl') + ,dds = dl.children('dd') + ,index = this.selectedIndex //当前选中的索引 + ,nearElem; //select 组件当前选中的附近元素,用于辅助快捷键功能 + + if(disabled) return; + + //展开下拉 + var showDown = function(){ + var top = reElem.offset().top + reElem.outerHeight() + 5 - $win.scrollTop() + ,dlHeight = dl.outerHeight(); + + index = select[0].selectedIndex; //获取最新的 selectedIndex + reElem.addClass(CLASS+'ed'); + dds.removeClass(HIDE); + nearElem = null; + + //初始选中样式 + dds.eq(index).addClass(THIS).siblings().removeClass(THIS); + + //上下定位识别 + if(top + dlHeight > $win.height() && top >= dlHeight){ + reElem.addClass(CLASS + 'up'); + } + + followScroll(); + } + + //隐藏下拉 + ,hideDown = function(choose){ + reElem.removeClass(CLASS+'ed ' + CLASS+'up'); + input.blur(); + nearElem = null; + + if(choose) return; + + notOption(input.val(), function(none){ + var selectedIndex = select[0].selectedIndex; + + //未查询到相关值 + if(none){ + initValue = $(select[0].options[selectedIndex]).html(); //重新获得初始选中值 + + //如果是第一项,且文本值等于 placeholder,则清空初始值 + if(selectedIndex === 0 && initValue === input.attr('placeholder')){ + initValue = ''; + }; + + //如果有选中值,则将输入框纠正为该值。否则清空输入框 + input.val(initValue || ''); + } + }); + } + + //定位下拉滚动条 + ,followScroll = function(){ + var thisDd = dl.children('dd.'+ THIS); + + if(!thisDd[0]) return; + + var posTop = thisDd.position().top + ,dlHeight = dl.height() + ,ddHeight = thisDd.height(); + + //若选中元素在滚动条不可见底部 + if(posTop > dlHeight){ + dl.scrollTop(posTop + dl.scrollTop() - dlHeight + ddHeight - 5); + } + + //若选择玄素在滚动条不可见顶部 + if(posTop < 0){ + dl.scrollTop(posTop + dl.scrollTop() - 5); + } + }; + + //点击标题区域 + title.on('click', function(e){ + reElem.hasClass(CLASS+'ed') ? ( + hideDown() + ) : ( + hide(e, true), + showDown() + ); + dl.find('.'+NONE).remove(); + }); + + //点击箭头获取焦点 + title.find('.layui-edge').on('click', function(){ + input.focus(); + }); + + //select 中 input 键盘事件 + input.on('keyup', function(e){ //键盘松开 + var keyCode = e.keyCode; + + //Tab键展开 + if(keyCode === 9){ + showDown(); + } + }).on('keydown', function(e){ //键盘按下 + var keyCode = e.keyCode; + + //Tab键隐藏 + if(keyCode === 9){ + hideDown(); + } + + //标注 dd 的选中状态 + var setThisDd = function(prevNext, thisElem1){ + var nearDd, cacheNearElem + e.preventDefault(); + + //得到当前队列元素 + var thisElem = function(){ + var thisDd = dl.children('dd.'+ THIS); + + //如果是搜索状态,且按 Down 键,且当前可视 dd 元素在选中元素之前, + //则将当前可视 dd 元素的上一个元素作为虚拟的当前选中元素,以保证递归不中断 + if(dl.children('dd.'+ HIDE)[0] && prevNext === 'next'){ + var showDd = dl.children('dd:not(.'+ HIDE +',.'+ DISABLED +')') + ,firstIndex = showDd.eq(0).index(); + if(firstIndex >=0 && firstIndex < thisDd.index() && !showDd.hasClass(THIS)){ + return showDd.eq(0).prev()[0] ? showDd.eq(0).prev() : dl.children(':last'); + } + } + + if(thisElem1 && thisElem1[0]){ + return thisElem1; + } + if(nearElem && nearElem[0]){ + return nearElem; + } + + return thisDd; + //return dds.eq(index); + }(); + + cacheNearElem = thisElem[prevNext](); //当前元素的附近元素 + nearDd = thisElem[prevNext]('dd:not(.'+ HIDE +')'); //当前可视元素的 dd 元素 + + //如果附近的元素不存在,则停止执行,并清空 nearElem + if(!cacheNearElem[0]) return nearElem = null; + + //记录附近的元素,让其成为下一个当前元素 + nearElem = thisElem[prevNext](); + + //如果附近不是 dd ,或者附近的 dd 元素是禁用状态,则进入递归查找 + if((!nearDd[0] || nearDd.hasClass(DISABLED)) && nearElem[0]){ + return setThisDd(prevNext, nearElem); + } + + nearDd.addClass(THIS).siblings().removeClass(THIS); //标注样式 + followScroll(); //定位滚动条 + }; + + if(keyCode === 38) setThisDd('prev'); //Up 键 + if(keyCode === 40) setThisDd('next'); //Down 键 + + //Enter 键 + if(keyCode === 13){ + e.preventDefault(); + dl.children('dd.'+THIS).trigger('click'); + } + }); + + //检测值是否不属于 select 项 + var notOption = function(value, callback, origin){ + var num = 0; + layui.each(dds, function(){ + var othis = $(this) + ,text = othis.text() + ,not = text.indexOf(value) === -1; + if(value === '' || (origin === 'blur') ? value !== text : not) num++; + origin === 'keyup' && othis[not ? 'addClass' : 'removeClass'](HIDE); + }); + var none = num === dds.length; + return callback(none), none; + }; + + //搜索匹配 + var search = function(e){ + var value = this.value, keyCode = e.keyCode; + + if(keyCode === 9 || keyCode === 13 + || keyCode === 37 || keyCode === 38 + || keyCode === 39 || keyCode === 40 + ){ + return false; + } + + notOption(value, function(none){ + if(none){ + dl.find('.'+NONE)[0] || dl.append('

      无匹配项

      '); + } else { + dl.find('.'+NONE).remove(); + } + }, 'keyup'); + + if(value === ''){ + dl.find('.'+NONE).remove(); + } + + followScroll(); //定位滚动条 + }; + + if(isSearch){ + input.on('keyup', search).on('blur', function(e){ + var selectedIndex = select[0].selectedIndex; + + thatInput = input; //当前的 select 中的 input 元素 + initValue = $(select[0].options[selectedIndex]).html(); //重新获得初始选中值 + + //如果是第一项,且文本值等于 placeholder,则清空初始值 + if(selectedIndex === 0 && initValue === input.attr('placeholder')){ + initValue = ''; + }; + + setTimeout(function(){ + notOption(input.val(), function(none){ + initValue || input.val(''); //none && !initValue + }, 'blur'); + }, 200); + }); + } + + //选择 + dds.on('click', function(){ + var othis = $(this), value = othis.attr('lay-value'); + var filter = select.attr('lay-filter'); //获取过滤器 + + if(othis.hasClass(DISABLED)) return false; + + if(othis.hasClass('layui-select-tips')){ + input.val(''); + } else { + input.val(othis.text()); + othis.addClass(THIS); + } + + othis.siblings().removeClass(THIS); + select.val(value).removeClass('layui-form-danger') + layui.event.call(this, MOD_NAME, 'select('+ filter +')', { + elem: select[0] + ,value: value + ,othis: reElem + }); + + hideDown(true); + return false; + }); + + reElem.find('dl>dt').on('click', function(e){ + return false; + }); + + $(document).off('click', hide).on('click', hide); //点击其它元素关闭 select + } + + selects.each(function(index, select){ + var othis = $(this) + ,hasRender = othis.next('.'+CLASS) + ,disabled = this.disabled + ,value = select.value + ,selected = $(select.options[select.selectedIndex]) //获取当前选中项 + ,optionsFirst = select.options[0]; + + if(typeof othis.attr('lay-ignore') === 'string') return othis.show(); + + var isSearch = typeof othis.attr('lay-search') === 'string' + ,placeholder = optionsFirst ? ( + optionsFirst.value ? TIPS : (optionsFirst.innerHTML || TIPS) + ) : TIPS; + + //替代元素 + var reElem = $(['
      ' + ,'
      ' + ,('') //禁用状态 + ,'
      ' + ,'
      ' + ,function(options){ + var arr = []; + layui.each(options, function(index, item){ + if(index === 0 && !item.value){ + arr.push('
      '+ $.trim(item.innerHTML || TIPS) +'
      '); + } else if(item.tagName.toLowerCase() === 'optgroup'){ + arr.push('
      '+ item.label +'
      '); + } else { + arr.push('
      '+ $.trim(item.innerHTML) +'
      '); + } + }); + arr.length === 0 && arr.push('
      没有选项
      '); + return arr.join(''); + }(othis.find('*')) +'
      ' + ,'
      '].join('')); + + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + othis.after(reElem); + events.call(this, reElem, disabled, isSearch); + }); + } + + //复选框/开关 + ,checkbox: function(){ + var CLASS = { + checkbox: ['layui-form-checkbox', 'layui-form-checked', 'checkbox'] + ,_switch: ['layui-form-switch', 'layui-form-onswitch', 'switch'] + } + ,checks = elemForm.find('input[type=checkbox]') + + ,events = function(reElem, RE_CLASS){ + var check = $(this); + + //勾选 + reElem.on('click', function(){ + var filter = check.attr('lay-filter') //获取过滤器 + ,text = (check.attr('lay-text')||'').split('|'); + + if(check[0].disabled) return; + + check[0].checked ? ( + check[0].checked = false + ,reElem.removeClass(RE_CLASS[1]).find('em').text(text[1]) + ) : ( + check[0].checked = true + ,reElem.addClass(RE_CLASS[1]).find('em').text(text[0]) + ); + + layui.event.call(check[0], MOD_NAME, RE_CLASS[2]+'('+ filter +')', { + elem: check[0] + ,value: check[0].value + ,othis: reElem + }); + }); + } + + checks.each(function(index, check){ + var othis = $(this), skin = othis.attr('lay-skin') + ,text = (othis.attr('lay-text') || '').split('|'), disabled = this.disabled; + if(skin === 'switch') skin = '_'+skin; + var RE_CLASS = CLASS[skin] || CLASS.checkbox; + + if(typeof othis.attr('lay-ignore') === 'string') return othis.show(); + + //替代元素 + var hasRender = othis.next('.' + RE_CLASS[0]) + ,reElem = $(['
      ' + ,function(){ //不同风格的内容 + var title = check.title.replace(/\s/g, '') + ,type = { + //复选框 + checkbox: [ + (title ? (''+ check.title +'') : '') + ,'' + ].join('') + + //开关 + ,_switch: ''+ ((check.checked ? text[0] : text[1]) || '') +'' + }; + return type[skin] || type['checkbox']; + }() + ,'
      '].join('')); + + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + othis.after(reElem); + events.call(this, reElem, RE_CLASS); + }); + } + + //单选框 + ,radio: function(){ + var CLASS = 'layui-form-radio', ICON = ['', ''] + ,radios = elemForm.find('input[type=radio]') + + ,events = function(reElem){ + var radio = $(this), ANIM = 'layui-anim-scaleSpring'; + + reElem.on('click', function(){ + var name = radio[0].name, forms = radio.parents(ELEM); + var filter = radio.attr('lay-filter'); //获取过滤器 + var sameRadio = forms.find('input[name='+ name.replace(/(\.|#|\[|\])/g, '\\$1') +']'); //找到相同name的兄弟 + + if(radio[0].disabled) return; + + layui.each(sameRadio, function(){ + var next = $(this).next('.'+CLASS); + this.checked = false; + next.removeClass(CLASS+'ed'); + next.find('.layui-icon').removeClass(ANIM).html(ICON[1]); + }); + + radio[0].checked = true; + reElem.addClass(CLASS+'ed'); + reElem.find('.layui-icon').addClass(ANIM).html(ICON[0]); + + layui.event.call(radio[0], MOD_NAME, 'radio('+ filter +')', { + elem: radio[0] + ,value: radio[0].value + ,othis: reElem + }); + }); + }; + + radios.each(function(index, radio){ + var othis = $(this), hasRender = othis.next('.' + CLASS), disabled = this.disabled; + + if(typeof othis.attr('lay-ignore') === 'string') return othis.show(); + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + + //替代元素 + var reElem = $(['
      ' //禁用状态 + ,''+ ICON[radio.checked ? 0 : 1] +'' + ,'
      '+ function(){ + var title = radio.title || ''; + if(typeof othis.next().attr('lay-radio') === 'string'){ + title = othis.next().html(); + //othis.next().remove(); + } + return title + }() +'
      ' + ,'
      '].join('')); + + othis.after(reElem); + events.call(this, reElem); + }); + } + }; + type ? ( + items[type] ? items[type]() : hint.error('不支持的 "'+ type + '" 表单渲染') + ) : layui.each(items, function(index, item){ + item(); + }); + return that; + }; + + //表单提交校验 + var submit = function(){ + var stop = null //验证不通过状态 + ,verify = form.config.verify //验证规则 + ,DANGER = 'layui-form-danger' //警示样式 + ,field = {} //字段集合 + ,button = $(this) //当前触发的按钮 + ,elem = button.parents(ELEM).eq(0) //当前所在表单域 + ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 + ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 + ,filter = button.attr('lay-filter'); //获取过滤器 + + + //开始校验 + layui.each(verifyElem, function(_, item){ + var othis = $(this) + ,vers = othis.attr('lay-verify').split('|') + ,verType = othis.attr('lay-verType') //提示方式 + ,value = othis.val(); + + othis.removeClass(DANGER); //移除警示样式 + + //遍历元素绑定的验证规则 + layui.each(vers, function(_, thisVer){ + var isTrue //是否命中校验 + ,errorText = '' //错误提示文本 + ,isFn = typeof verify[thisVer] === 'function'; + + //匹配验证规则 + if(verify[thisVer]){ + var isTrue = isFn ? errorText = verify[thisVer](value, item) : !verify[thisVer][0].test(value) + //是否属于美化替换后的表单元素 + ,isForm2Elem = item.tagName.toLowerCase() === 'select' || /^checkbox|radio$/.test(item.type); + + errorText = errorText || verify[thisVer][1]; + + if(thisVer === 'required'){ + errorText = othis.attr('lay-reqText') || errorText; + } + + //如果是必填项或者非空命中校验,则阻止提交,弹出提示 + if(isTrue){ + //提示层风格 + if(verType === 'tips'){ + layer.tips(errorText, function(){ + if(typeof othis.attr('lay-ignore') !== 'string'){ + if(isForm2Elem){ + return othis.next(); + } + } + return othis; + }(), {tips: 1}); + } else if(verType === 'alert') { + layer.alert(errorText, {title: '提示', shadeClose: true}); + } + //如果返回的为字符或数字,则自动弹出默认提示框;否则由 verify 方法中处理提示 + else if(/\bstring|number\b/.test(typeof errorText)){ + layer.msg(errorText, {icon: 5, shift: 6}); + } + + //非移动设备自动定位焦点 + if(!device.mobile){ + setTimeout(function(){ + (isForm2Elem ? othis.next().find('input') : item).focus(); + }, 7); + } else { //移动设备定位 + $dom.scrollTop(function(){ + try { + return (isForm2Elem ? othis.next() : othis).offset().top - 15 + } catch(e){ + return 0; + } + }()); + } + + othis.addClass(DANGER); + return stop = true; + } + } + }); + if(stop) return stop; + }); + + if(stop) return false; + + //获取当前表单值 + field = form.getValue(null, elem); + + //返回字段 + return layui.event.call(this, MOD_NAME, 'submit('+ filter +')', { + elem: this + ,form: formElem + ,field: field + }); + }; + + //自动完成渲染 + var form = new Form() + ,$dom = $(document), $win = $(window); + + $(function(){ + form.render(); + }); + + //表单reset重置渲染 + $dom.on('reset', ELEM, function(){ + var filter = $(this).attr('lay-filter'); + setTimeout(function(){ + form.render(null, filter); + }, 50); + }); + + //表单提交事件 + $dom.on('submit', ELEM, submit) + .on('click', '*[lay-submit]', submit); + + exports(MOD_NAME, form); +}); + + diff --git a/static/layui/modules/jquery.js b/static/layui/modules/jquery.js new file mode 100644 index 0000000..bc82158 --- /dev/null +++ b/static/layui/modules/jquery.js @@ -0,0 +1,10981 @@ +/*! + * jQuery JavaScript Library v1.12.4 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-05-20T17:17Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Support: Firefox 18+ +// Can't be in strict mode, several libs including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +//"use strict"; +var deletedIds = []; + +var document = window.document; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.12.4", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type( obj ) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + // adding 1 corrects loss of precision from parseFloat (#15100) + var realStringObj = obj && obj.toString(); + return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call( obj, "constructor" ) && + !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + } catch ( e ) { + + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( !support.ownFirst ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); // jscs:ignore requireDotNotation + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[ j ] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +// JSHint would error on this code due to the Symbol not being defined in ES5. +// Defining this global in .jshintrc would create a danger of using the global +// unguarded in another place, it seems safer to just disable JSHint for these +// three lines. +/* jshint ignore: start */ +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ]; +} +/* jshint ignore: end */ + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.2.1 + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2015-10-17 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, nidselect, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; + while ( i-- ) { + groups[i] = nidselect + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( (parent = document.defaultView) && parent.top !== parent ) { + // Support: IE 11 + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + return m ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + docElem.appendChild( div ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( (oldCache = uniqueCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ ); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + } ); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) > -1 ) !== not; + } ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // init accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt( 0 ) === "<" && + selector.charAt( selector.length - 1 ) === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[ 2 ] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[ 0 ] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof root.ready !== "undefined" ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( pos ? + pos.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[ 0 ], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.uniqueSort( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +} ); +var rnotwhite = ( /\S+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = true; + if ( !memory ) { + self.disable(); + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], + [ "notify", "progress", jQuery.Callbacks( "memory" ) ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this === promise ? newDefer.promise() : this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( function() { + + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || + ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. + // If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .progress( updateFunc( i, progressContexts, progressValues ) ) + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +} ); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +} ); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || + window.event.type === "load" || + document.readyState === "complete" ) { + + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called + // after the browser event has already occurred. + // Support: IE6-10 + // Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); + + // If IE event model is used + } else { + + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch ( e ) {} + + if ( top && top.doScroll ) { + ( function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll( "left" ); + } catch ( e ) { + return window.setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + } )(); + } + } + } + return readyList.promise( obj ); +}; + +// Kick off the DOM ready check even if the user does not +jQuery.ready.promise(); + + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownFirst = i === "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery( function() { + + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== "undefined" ) { + + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +} ); + + +( function() { + var div = document.createElement( "div" ); + + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch ( e ) { + support.deleteExpando = false; + } + + // Null elements to avoid leaks in IE. + div = null; +} )(); +var acceptData = function( elem ) { + var noData = jQuery.noData[ ( elem.nodeName + " " ).toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute( "classid" ) === noData; +}; + + + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[ name ] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) && + data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } else { + + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[ i ] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject( thisCache ) : !jQuery.isEmptyObject( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, undefined + } else { + cache[ id ] = undefined; + } +} + +jQuery.extend( { + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + jQuery.data( this, key ); + } ); + } + + return arguments.length > 1 ? + + // Sets one value + this.each( function() { + jQuery.data( this, key, value ); + } ) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each( function() { + jQuery.removeData( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = jQuery._data( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, + // or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); + + +( function() { + var shrinkWrapBlocksVal; + + support.shrinkWrapBlocks = function() { + if ( shrinkWrapBlocksVal != null ) { + return shrinkWrapBlocksVal; + } + + // Will be changed later if needed. + shrinkWrapBlocksVal = false; + + // Minified: var b,c,d + var div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + + // Test fired too early or in an unsupported environment, exit. + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + if ( typeof div.style.zoom !== "undefined" ) { + + // Reset CSS: box-sizing; display; margin; border + div.style.cssText = + + // Support: Firefox<29, Android 2.3 + // Vendor-prefix box-sizing + "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + + "box-sizing:content-box;display:block;margin:0;border:0;" + + "padding:1px;width:1px;zoom:1"; + div.appendChild( document.createElement( "div" ) ).style.width = "5px"; + shrinkWrapBlocksVal = div.offsetWidth !== 3; + } + + body.removeChild( container ); + + return shrinkWrapBlocksVal; + }; + +} )(); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || + !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { return tween.cur(); } : + function() { return jQuery.css( elem, prop, "" ); }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( + elems[ i ], + key, + raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[ 0 ], key ) : emptyGet; +}; +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([\w:-]+)/ ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + +var rleadingWhitespace = ( /^\s+/ ); + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|" + + "details|dialog|figcaption|figure|footer|header|hgroup|main|" + + "mark|meter|nav|output|picture|progress|section|summary|template|time|video"; + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + + +( function() { + var div = document.createElement( "div" ), + fragment = document.createDocumentFragment(), + input = document.createElement( "input" ); + + // Setup + div.innerHTML = "
      a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input = document.createElement( "input" ); + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Cloned elements keep attachEvent handlers, we use addEventListener on IE9+ + support.noCloneEvent = !!div.addEventListener; + + // Support: IE<9 + // Since attributes and properties are the same in IE, + // cleanData must set properties to undefined rather than use removeAttribute + div[ jQuery.expando ] = 1; + support.attributes = !div.getAttribute( jQuery.expando ); +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
      ", "
      " ], + area: [ 1, "", "" ], + + // Support: IE8 + param: [ 1, "", "" ], + thead: [ 1, "", "
      " ], + tr: [ 2, "", "
      " ], + col: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
      ", "
      " ] +}; + +// Support: IE8-IE9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? + context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; + ( elem = elems[ i ] ) != null; + i++ + ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + jQuery._data( + elem, + "globalEval", + !refElements || jQuery._data( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/, + rtbody = / from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[ 1 ] === "
      " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) && + !tbody.childNodes.length ) { + + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; +} + + +( function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events) + for ( i in { submit: true, change: true, focusin: true } ) { + eventName = "on" + i; + + if ( !( support[ i ] = eventName in window ) ) { + + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +} )(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE9 +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && + ( !e || jQuery.event.triggered !== e.type ) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + + // Add elem as a property of the handle fn to prevent a memory leak + // with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && + jQuery._data( cur, "handle" ); + + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( + ( !special._default || + special._default.apply( eventPath.pop(), data ) === false + ) && acceptData( elem ) + ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Support (at least): Chrome, IE9 + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // + // Support: Firefox<=42+ + // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) + if ( delegateCount && cur.nodeType && + ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push( { elem: cur, handlers: matches } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Safari 6-8+ + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + + "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split( " " ), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: ( "button buttons clientX clientY fromElement offsetX offsetY " + + "pageX pageY screenX screenY toElement" ).split( " " ), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - + ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - + ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? + original.toElement : + fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + // Piggyback on a donor event to simulate a different one + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + + // Previously, `originalEvent: {}` was set here, so stopPropagation call + // would not be triggered on donor event, since in our own + // jQuery.event.stopPropagation function we had a check for existence of + // originalEvent.stopPropagation method, so, consequently it would be a noop. + // + // Guard for simulated events was moved to jQuery.event.stopPropagation function + // since `originalEvent` should point to the original event for the + // constancy with other events and for more focused logic + } + ); + + jQuery.event.trigger( e, null, elem ); + + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, + // to properly expose it to GC + if ( typeof elem[ name ] === "undefined" ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( !e || this.isSimulated ) { + return; + } + + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://code.google.com/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +// IE submit delegation +if ( !support.submit ) { + + jQuery.event.special.submit = { + setup: function() { + + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? + + // Support: IE <=8 + // We use jQuery.prop instead of elem.form + // to allow fixing the IE8 delegated submit issue (gh-2332) + // by 3rd party polyfills/workarounds. + jQuery.prop( elem, "form" ) : + undefined; + + if ( form && !jQuery._data( form, "submit" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submitBubble = true; + } ); + jQuery._data( form, "submit", true ); + } + } ); + + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + + // If form was submitted by the user, bubble the event up the tree + if ( event._submitBubble ) { + delete event._submitBubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event ); + } + } + }, + + teardown: function() { + + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.change ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._justChanged = true; + } + } ); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._justChanged && !event.isTrigger ) { + this._justChanged = false; + } + + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event ); + } ); + } + return false; + } + + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "change" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event ); + } + } ); + jQuery._data( elem, "change", true ); + } + } ); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || + ( elem.type !== "radio" && elem.type !== "checkbox" ) ) { + + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Support: Firefox +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome, Safari +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + } ); +} + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + }, + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, + + // Support: IE 10-11, Edge 10240+ + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) ); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName( "tbody" )[ 0 ] || + elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( jQuery.find.attr( elem, "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + return elem; +} + +function cloneCopyEvent( src, dest ) { + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( + ( node.text || node.textContent || node.innerHTML || "" ) + .replace( rcleanScript, "" ) + ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + elems = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = elems[ i ] ) != null; i++ ) { + + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc( elem ) || + !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( ( !support.noCloneEvent || !support.noCloneChecked ) && + ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) { + + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[ i ] ) { + fixCloneNodeIssues( node, destElements[ i ] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) { + cloneCopyEvent( node, destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + cleanData: function( elems, /* internal */ forceAcceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + attributes = support.attributes, + special = jQuery.event.special; + + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + if ( forceAcceptData || acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // Support: IE<9 + // IE does not allow us to delete expando properties from nodes + // IE creates expando attributes along with the property + // IE does not have a removeAttribute function on Document nodes + if ( !attributes && typeof elem.removeAttribute !== "undefined" ) { + elem.removeAttribute( internalKey ); + + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://code.google.com/p/chromium/issues/detail?id=378607 + } else { + elem[ internalKey ] = undefined; + } + + deletedIds.push( id ); + } + } + } + } + } +} ); + +jQuery.fn.extend( { + + // Keep domManip exposed until 3.0 (gh-2225) + domManip: domManip, + + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( + ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) + ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + + // Remove element nodes and prevent memory leaks + elem = this[ i ] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); + + +var iframe, + elemdisplay = { + + // Support: Firefox + // We have to pre-define these values for FF (#10227) + HTML: "block", + BODY: "block" + }; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ + +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + display = jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = ( iframe || jQuery( "' + ,'' + ,''].join('')) + + //编辑器不兼容ie8以下 + if(device.ie && device.ie < 8){ + return textArea.removeClass('layui-hide').addClass(SHOW); + } + + haveBuild[0] && (haveBuild.remove()); + + setIframe.call(that, editor, textArea[0], set) + textArea.addClass('layui-hide').after(editor); + + return that.index; + }; + + //获得编辑器中内容 + Edit.prototype.getContent = function(index){ + var iframeWin = getWin(index); + if(!iframeWin[0]) return; + return toLower(iframeWin[0].document.body.innerHTML); + }; + + //获得编辑器中纯文本内容 + Edit.prototype.getText = function(index){ + var iframeWin = getWin(index); + if(!iframeWin[0]) return; + return $(iframeWin[0].document.body).text(); + }; + /** + * 设置编辑器内容 + * @param {[type]} index 编辑器索引 + * @param {[type]} content 要设置的内容 + * @param {[type]} flag 是否追加模式 + */ + Edit.prototype.setContent = function(index, content, flag){ + var iframeWin = getWin(index); + if(!iframeWin[0]) return; + if(flag){ + $(iframeWin[0].document.body).append(content) + }else{ + $(iframeWin[0].document.body).html(content) + }; + layedit.sync(index) + }; + //将编辑器内容同步到textarea(一般用于异步提交时) + Edit.prototype.sync = function(index){ + var iframeWin = getWin(index); + if(!iframeWin[0]) return; + var textarea = $('#'+iframeWin[1].attr('textarea')); + textarea.val(toLower(iframeWin[0].document.body.innerHTML)); + }; + + //获取编辑器选中内容 + Edit.prototype.getSelection = function(index){ + var iframeWin = getWin(index); + if(!iframeWin[0]) return; + var range = Range(iframeWin[0].document); + return document.selection ? range.text : range.toString(); + }; + + //iframe初始化 + var setIframe = function(editor, textArea, set){ + var that = this, iframe = editor.find('iframe'); + + iframe.css({ + height: set.height + }).on('load', function(){ + var conts = iframe.contents() + ,iframeWin = iframe.prop('contentWindow') + ,head = conts.find('head') + ,style = $([''].join('')) + ,body = conts.find('body'); + + head.append(style); + body.attr('contenteditable', 'true').css({ + 'min-height': set.height + }).html(textArea.value||''); + + hotkey.apply(that, [iframeWin, iframe, textArea, set]); //快捷键处理 + toolActive.call(that, iframeWin, editor, set); //触发工具 + + }); + } + + //获得iframe窗口对象 + ,getWin = function(index){ + var iframe = $('#LAY_layedit_'+ index) + ,iframeWin = iframe.prop('contentWindow'); + return [iframeWin, iframe]; + } + + //IE8下将标签处理成小写 + ,toLower = function(html){ + if(device.ie == 8){ + html = html.replace(/<.+>/g, function(str){ + return str.toLowerCase(); + }); + } + return html; + } + + //快捷键处理 + ,hotkey = function(iframeWin, iframe, textArea, set){ + var iframeDOM = iframeWin.document, body = $(iframeDOM.body); + body.on('keydown', function(e){ + var keycode = e.keyCode; + //处理回车 + if(keycode === 13){ + var range = Range(iframeDOM); + var container = getContainer(range) + ,parentNode = container.parentNode; + + if(parentNode.tagName.toLowerCase() === 'pre'){ + if(e.shiftKey) return + layer.msg('请暂时用shift+enter'); + return false; + } + iframeDOM.execCommand('formatBlock', false, '

      '); + } + }); + + //给textarea同步内容 + $(textArea).parents('form').on('submit', function(){ + var html = body.html(); + //IE8下将标签处理成小写 + if(device.ie == 8){ + html = html.replace(/<.+>/g, function(str){ + return str.toLowerCase(); + }); + } + textArea.value = html; + }); + + //处理粘贴 + body.on('paste', function(e){ + iframeDOM.execCommand('formatBlock', false, '

      '); + setTimeout(function(){ + filter.call(iframeWin, body); + textArea.value = body.html(); + }, 100); + }); + } + + //标签过滤 + ,filter = function(body){ + var iframeWin = this + ,iframeDOM = iframeWin.document; + + //清除影响版面的css属性 + body.find('*[style]').each(function(){ + var textAlign = this.style.textAlign; + this.removeAttribute('style'); + $(this).css({ + 'text-align': textAlign || '' + }) + }); + + //修饰表格 + body.find('table').addClass('layui-table'); + + //移除不安全的标签 + body.find('script,link').remove(); + } + + //Range对象兼容性处理 + ,Range = function(iframeDOM){ + return iframeDOM.selection + ? iframeDOM.selection.createRange() + : iframeDOM.getSelection().getRangeAt(0); + } + + //当前Range对象的endContainer兼容性处理 + ,getContainer = function(range){ + return range.endContainer || range.parentElement().childNodes[0] + } + + //在选区插入内联元素 + ,insertInline = function(tagName, attr, range){ + var iframeDOM = this.document + ,elem = document.createElement(tagName) + for(var key in attr){ + elem.setAttribute(key, attr[key]); + } + elem.removeAttribute('text'); + + if(iframeDOM.selection){ //IE + var text = range.text || attr.text; + if(tagName === 'a' && !text) return; + if(text){ + elem.innerHTML = text; + } + range.pasteHTML($(elem).prop('outerHTML')); + range.select(); + } else { //非IE + var text = range.toString() || attr.text; + if(tagName === 'a' && !text) return; + if(text){ + elem.innerHTML = text; + } + range.deleteContents(); + range.insertNode(elem); + } + } + + //工具选中 + ,toolCheck = function(tools, othis){ + var iframeDOM = this.document + ,CHECK = 'layedit-tool-active' + ,container = getContainer(Range(iframeDOM)) + ,item = function(type){ + return tools.find('.layedit-tool-'+type) + } + + if(othis){ + othis[othis.hasClass(CHECK) ? 'removeClass' : 'addClass'](CHECK); + } + + tools.find('>i').removeClass(CHECK); + item('unlink').addClass(ABLED); + + $(container).parents().each(function(){ + var tagName = this.tagName.toLowerCase() + ,textAlign = this.style.textAlign; + + //文字 + if(tagName === 'b' || tagName === 'strong'){ + item('b').addClass(CHECK) + } + if(tagName === 'i' || tagName === 'em'){ + item('i').addClass(CHECK) + } + if(tagName === 'u'){ + item('u').addClass(CHECK) + } + if(tagName === 'strike'){ + item('d').addClass(CHECK) + } + + //对齐 + if(tagName === 'p'){ + if(textAlign === 'center'){ + item('center').addClass(CHECK); + } else if(textAlign === 'right'){ + item('right').addClass(CHECK); + } else { + item('left').addClass(CHECK); + } + } + + //超链接 + if(tagName === 'a'){ + item('link').addClass(CHECK); + item('unlink').removeClass(ABLED); + } + }); + } + + //触发工具 + ,toolActive = function(iframeWin, editor, set){ + var iframeDOM = iframeWin.document + ,body = $(iframeDOM.body) + ,toolEvent = { + //超链接 + link: function(range){ + var container = getContainer(range) + ,parentNode = $(container).parent(); + + link.call(body, { + href: parentNode.attr('href') + ,target: parentNode.attr('target') + }, function(field){ + var parent = parentNode[0]; + if(parent.tagName === 'A'){ + parent.href = field.url; + } else { + insertInline.call(iframeWin, 'a', { + target: field.target + ,href: field.url + ,text: field.url + }, range); + } + }); + } + //清除超链接 + ,unlink: function(range){ + iframeDOM.execCommand('unlink'); + } + //表情 + ,face: function(range){ + face.call(this, function(img){ + insertInline.call(iframeWin, 'img', { + src: img.src + ,alt: img.alt + }, range); + }); + } + //图片 + ,image: function(range){ + var that = this; + layui.use('upload', function(upload){ + var uploadImage = set.uploadImage || {}; + upload.render({ + url: uploadImage.url + ,method: uploadImage.type + ,elem: $(that).find('input')[0] + ,done: function(res){ + if(res.code == 0){ + res.data = res.data || {}; + insertInline.call(iframeWin, 'img', { + src: res.data.src + ,alt: res.data.title + }, range); + } else { + layer.msg(res.msg||'上传失败'); + } + } + }); + }); + } + //插入代码 + ,code: function(range){ + code.call(body, function(pre){ + insertInline.call(iframeWin, 'pre', { + text: pre.code + ,'lay-lang': pre.lang + }, range); + }); + } + //帮助 + ,help: function(){ + layer.open({ + type: 2 + ,title: '帮助' + ,area: ['600px', '380px'] + ,shadeClose: true + ,shade: 0.1 + ,skin: 'layui-layer-msg' + ,content: ['', 'no'] + }); + } + } + ,tools = editor.find('.layui-layedit-tool') + + ,click = function(){ + var othis = $(this) + ,events = othis.attr('layedit-event') + ,command = othis.attr('lay-command'); + + if(othis.hasClass(ABLED)) return; + + body.focus(); + + var range = Range(iframeDOM) + ,container = range.commonAncestorContainer + + if(command){ + iframeDOM.execCommand(command); + if(/justifyLeft|justifyCenter|justifyRight/.test(command)){ + iframeDOM.execCommand('formatBlock', false, '

      '); + } + setTimeout(function(){ + body.focus(); + }, 10); + } else { + toolEvent[events] && toolEvent[events].call(this, range); + } + toolCheck.call(iframeWin, tools, othis); + } + + ,isClick = /image/ + + tools.find('>i').on('mousedown', function(){ + var othis = $(this) + ,events = othis.attr('layedit-event'); + if(isClick.test(events)) return; + click.call(this) + }).on('click', function(){ + var othis = $(this) + ,events = othis.attr('layedit-event'); + if(!isClick.test(events)) return; + click.call(this) + }); + + //触发内容区域 + body.on('click', function(){ + toolCheck.call(iframeWin, tools); + layer.close(face.index); + }); + } + + //超链接面板 + ,link = function(options, callback){ + var body = this, index = layer.open({ + type: 1 + ,id: 'LAY_layedit_link' + ,area: '350px' + ,shade: 0.05 + ,shadeClose: true + ,moveType: 1 + ,title: '超链接' + ,skin: 'layui-layer-msg' + ,content: ['

        ' + ,'
      • ' + ,'' + ,'
        ' + ,'' + ,'
        ' + ,'
      • ' + ,'
      • ' + ,'' + ,'
        ' + ,'' + ,'' + ,'
        ' + ,'
      • ' + ,'
      • ' + ,'' + ,'' + ,'
      • ' + ,'
      '].join('') + ,success: function(layero, index){ + var eventFilter = 'submit(layedit-link-yes)'; + form.render('radio'); + layero.find('.layui-btn-primary').on('click', function(){ + layer.close(index); + body.focus(); + }); + form.on(eventFilter, function(data){ + layer.close(link.index); + callback && callback(data.field); + }); + } + }); + link.index = index; + } + + //表情面板 + ,face = function(callback){ + //表情库 + var faces = function(){ + var alt = ["[微笑]", "[嘻嘻]", "[哈哈]", "[可爱]", "[可怜]", "[挖鼻]", "[吃惊]", "[害羞]", "[挤眼]", "[闭嘴]", "[鄙视]", "[爱你]", "[泪]", "[偷笑]", "[亲亲]", "[生病]", "[太开心]", "[白眼]", "[右哼哼]", "[左哼哼]", "[嘘]", "[衰]", "[委屈]", "[吐]", "[哈欠]", "[抱抱]", "[怒]", "[疑问]", "[馋嘴]", "[拜拜]", "[思考]", "[汗]", "[困]", "[睡]", "[钱]", "[失望]", "[酷]", "[色]", "[哼]", "[鼓掌]", "[晕]", "[悲伤]", "[抓狂]", "[黑线]", "[阴险]", "[怒骂]", "[互粉]", "[心]", "[伤心]", "[猪头]", "[熊猫]", "[兔子]", "[ok]", "[耶]", "[good]", "[NO]", "[赞]", "[来]", "[弱]", "[草泥马]", "[神马]", "[囧]", "[浮云]", "[给力]", "[围观]", "[威武]", "[奥特曼]", "[礼物]", "[钟]", "[话筒]", "[蜡烛]", "[蛋糕]"], arr = {}; + layui.each(alt, function(index, item){ + arr[item] = layui.cache.dir + 'images/face/'+ index + '.gif'; + }); + return arr; + }(); + face.hide = face.hide || function(e){ + if($(e.target).attr('layedit-event') !== 'face'){ + layer.close(face.index); + } + } + return face.index = layer.tips(function(){ + var content = []; + layui.each(faces, function(key, item){ + content.push('
    • '+ key +'
    • '); + }); + return '
        ' + content.join('') + '
      '; + }(), this, { + tips: 1 + ,time: 0 + ,skin: 'layui-box layui-util-face' + ,maxWidth: 500 + ,success: function(layero, index){ + layero.css({ + marginTop: -4 + ,marginLeft: -10 + }).find('.layui-clear>li').on('click', function(){ + callback && callback({ + src: faces[this.title] + ,alt: this.title + }); + layer.close(index); + }); + $(document).off('click', face.hide).on('click', face.hide); + } + }); + } + + //插入代码面板 + ,code = function(callback){ + var body = this, index = layer.open({ + type: 1 + ,id: 'LAY_layedit_code' + ,area: '550px' + ,shade: 0.05 + ,shadeClose: true + ,moveType: 1 + ,title: '插入代码' + ,skin: 'layui-layer-msg' + ,content: ['
        ' + ,'
      • ' + ,'' + ,'
        ' + ,'' + ,'
        ' + ,'
      • ' + ,'
      • ' + ,'' + ,'
        ' + ,'' + ,'
        ' + ,'
      • ' + ,'
      • ' + ,'' + ,'' + ,'
      • ' + ,'
      '].join('') + ,success: function(layero, index){ + var eventFilter = 'submit(layedit-code-yes)'; + form.render('select'); + layero.find('.layui-btn-primary').on('click', function(){ + layer.close(index); + body.focus(); + }); + form.on(eventFilter, function(data){ + layer.close(code.index); + callback && callback(data.field); + }); + } + }); + code.index = index; + } + + //全部工具 + ,tools = { + html: '' + ,strong: '' + ,italic: '' + ,underline: '' + ,del: '' + + ,'|': '' + + ,left: '' + ,center: '' + ,right: '' + ,link: '' + ,unlink: '' + ,face: '' + ,image: '' + ,code: '' + + ,help: '' + } + + ,edit = new Edit(); + + exports(MOD_NAME, edit); +}); diff --git a/static/layui/modules/layer.js b/static/layui/modules/layer.js new file mode 100644 index 0000000..62b5c3d --- /dev/null +++ b/static/layui/modules/layer.js @@ -0,0 +1,1390 @@ + +/*! + * layer - 通用 Web 弹出层组件 + * MIT Licensed + */ + +;!function(window, undefined){ +"use strict"; + +var isLayui = window.layui && layui.define, $, win, ready = { + getPath: function(){ + var jsPath = document.currentScript ? document.currentScript.src : function(){ + var js = document.scripts + ,last = js.length - 1 + ,src; + for(var i = last; i > 0; i--){ + if(js[i].readyState === 'interactive'){ + src = js[i].src; + break; + } + } + return src || js[last].src; + }() + ,GLOBAL = window.LAYUI_GLOBAL || {}; + return GLOBAL.layer_dir || jsPath.substring(0, jsPath.lastIndexOf('/') + 1); + }(), + + config: {}, end: {}, minIndex: 0, minLeft: [], + btn: ['确定', '取消'], + + //五种原始层模式 + type: ['dialog', 'page', 'iframe', 'loading', 'tips'], + + //获取节点的style属性值 + getStyle: function(node, name){ + var style = node.currentStyle ? node.currentStyle : window.getComputedStyle(node, null); + return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name); + }, + + //载入 CSS 依赖 + link: function(href, fn, cssname){ + //未设置路径,则不主动加载css + if(!layer.path) return; + + var head = document.getElementsByTagName("head")[0] + ,link = document.createElement('link'); + + if(typeof fn === 'string') cssname = fn; + + var app = (cssname || href).replace(/\.|\//g, ''); + var id = 'layuicss-'+ app + ,STAUTS_NAME = 'creating' + ,timeout = 0; + + link.rel = 'stylesheet'; + link.href = layer.path + href; + link.id = id; + + if(!document.getElementById(id)){ + head.appendChild(link); + } + + if(typeof fn !== 'function') return; + + //轮询 css 是否加载完毕 + (function poll(status) { + var delay = 100 + ,getLinkElem = document.getElementById(id); //获取动态插入的 link 元素 + + //如果轮询超过指定秒数,则视为请求文件失败或 css 文件不符合规范 + if(++timeout > 10 * 1000 / delay){ + return window.console && console.error(app +'.css: Invalid'); + }; + + //css 加载就绪 + if(parseInt(ready.getStyle(getLinkElem, 'width')) === 1989){ + //如果参数来自于初始轮询(即未加载就绪时的),则移除 link 标签状态 + if(status === STAUTS_NAME) getLinkElem.removeAttribute('lay-status'); + //如果 link 标签的状态仍为「创建中」,则继续进入轮询,直到状态改变,则执行回调 + getLinkElem.getAttribute('lay-status') === STAUTS_NAME ? setTimeout(poll, delay) : fn(); + } else { + getLinkElem.setAttribute('lay-status', STAUTS_NAME); + setTimeout(function(){ + poll(STAUTS_NAME); + }, delay); + } + + //parseInt(ready.getStyle(document.getElementById(id), 'width')) === 1989 ? fn() : setTimeout(poll, 1000); + }()); + + } +}; + +//默认内置方法。 +var layer = { + v: '3.5.1', + ie: function(){ //ie版本 + var agent = navigator.userAgent.toLowerCase(); + return (!!window.ActiveXObject || "ActiveXObject" in window) ? ( + (agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识 + ) : false; + }(), + index: (window.layer && window.layer.v) ? 100000 : 0, + path: ready.getPath, + config: function(options, fn){ + options = options || {}; + layer.cache = ready.config = $.extend({}, ready.config, options); + layer.path = ready.config.path || layer.path; + typeof options.extend === 'string' && (options.extend = [options.extend]); + + //如果设置了路径,则加载样式 + if(ready.config.path) layer.ready(); + + if(!options.extend) return this; + + isLayui + ? layui.addcss('modules/layer/' + options.extend) + : ready.link('theme/' + options.extend); + + return this; + }, + + //主体CSS等待事件 + ready: function(callback){ + var cssname = 'layer', ver = '' + ,path = (isLayui ? 'modules/layer/' : 'theme/') + 'default/layer.css?v='+ layer.v + ver; + isLayui ? layui.addcss(path, callback, cssname) : ready.link(path, callback, cssname); + return this; + }, + + //各种快捷引用 + alert: function(content, options, yes){ + var type = typeof options === 'function'; + if(type) yes = options; + return layer.open($.extend({ + content: content, + yes: yes + }, type ? {} : options)); + }, + + confirm: function(content, options, yes, cancel){ + var type = typeof options === 'function'; + if(type){ + cancel = yes; + yes = options; + } + return layer.open($.extend({ + content: content, + btn: ready.btn, + yes: yes, + btn2: cancel + }, type ? {} : options)); + }, + + msg: function(content, options, end){ //最常用提示层 + var type = typeof options === 'function', rskin = ready.config.skin; + var skin = (rskin ? rskin + ' ' + rskin + '-msg' : '')||'layui-layer-msg'; + var anim = doms.anim.length - 1; + if(type) end = options; + return layer.open($.extend({ + content: content, + time: 3000, + shade: false, + skin: skin, + title: false, + closeBtn: false, + btn: false, + resize: false, + end: end + }, (type && !ready.config.skin) ? { + skin: skin + ' layui-layer-hui', + anim: anim + } : function(){ + options = options || {}; + if(options.icon === -1 || options.icon === undefined && !ready.config.skin){ + options.skin = skin + ' ' + (options.skin||'layui-layer-hui'); + } + return options; + }())); + }, + + load: function(icon, options){ + return layer.open($.extend({ + type: 3, + icon: icon || 0, + resize: false, + shade: 0.01 + }, options)); + }, + + tips: function(content, follow, options){ + return layer.open($.extend({ + type: 4, + content: [content, follow], + closeBtn: false, + time: 3000, + shade: false, + resize: false, + fixed: false, + maxWidth: 260 + }, options)); + } +}; + +var Class = function(setings){ + var that = this, creat = function(){ + that.creat(); + }; + that.index = ++layer.index; + that.config.maxWidth = $(win).width() - 15*2; //初始最大宽度:当前屏幕宽,左右留 15px 边距 + that.config = $.extend({}, that.config, ready.config, setings); + document.body ? creat() : setTimeout(function(){ + creat(); + }, 30); +}; + +Class.pt = Class.prototype; + +//缓存常用字符 +var doms = ['layui-layer', '.layui-layer-title', '.layui-layer-main', '.layui-layer-dialog', 'layui-layer-iframe', 'layui-layer-content', 'layui-layer-btn', 'layui-layer-close']; +doms.anim = ['layer-anim-00', 'layer-anim-01', 'layer-anim-02', 'layer-anim-03', 'layer-anim-04', 'layer-anim-05', 'layer-anim-06']; + +doms.SHADE = 'layui-layer-shade'; +doms.MOVE = 'layui-layer-move'; + +//默认配置 +Class.pt.config = { + type: 0, + shade: 0.3, + fixed: true, + move: doms[1], + title: '信息', + offset: 'auto', + area: 'auto', + closeBtn: 1, + time: 0, //0表示不自动关闭 + zIndex: 19891014, + maxWidth: 360, + anim: 0, + isOutAnim: true, //退出动画 + minStack: true, //最小化堆叠 + icon: -1, + moveType: 1, + resize: true, + scrollbar: true, //是否允许浏览器滚动条 + tips: 2 +}; + +//容器 +Class.pt.vessel = function(conType, callback){ + var that = this, times = that.index, config = that.config; + var zIndex = config.zIndex + times, titype = typeof config.title === 'object'; + var ismax = config.maxmin && (config.type === 1 || config.type === 2); + var titleHTML = (config.title ? '
      ' + + (titype ? config.title[0] : config.title) + + '
      ' : ''); + + config.zIndex = zIndex; + callback([ + //遮罩 + config.shade ? ('
      ') : '', + + //主体 + '
      ' + + (conType && config.type != 2 ? '' : titleHTML) + + '
      ' + + (config.type == 0 && config.icon !== -1 ? '' : '') + + (config.type == 1 && conType ? '' : (config.content||'')) + + '
      ' + + ''+ function(){ + var closebtn = ismax ? '' : ''; + config.closeBtn && (closebtn += ''); + return closebtn; + }() + '' + + (config.btn ? function(){ + var button = ''; + typeof config.btn === 'string' && (config.btn = [config.btn]); + for(var i = 0, len = config.btn.length; i < len; i++){ + button += ''+ config.btn[i] +'' + } + return '
      '+ button +'
      ' + }() : '') + + (config.resize ? '' : '') + + '
      ' + ], titleHTML, $('
      ')); + return that; +}; + +//创建骨架 +Class.pt.creat = function(){ + var that = this + ,config = that.config + ,times = that.index, nodeIndex + ,content = config.content + ,conType = typeof content === 'object' + ,body = $('body'); + + if(config.id && $('#'+config.id)[0]) return; + + if(typeof config.area === 'string'){ + config.area = config.area === 'auto' ? ['', ''] : [config.area, '']; + } + + //anim兼容旧版shift + if(config.shift){ + config.anim = config.shift; + } + + if(layer.ie == 6){ + config.fixed = false; + } + + switch(config.type){ + case 0: + config.btn = ('btn' in config) ? config.btn : ready.btn[0]; + layer.closeAll('dialog'); + break; + case 2: + var content = config.content = conType ? config.content : [config.content||'', 'auto']; + config.content = ''; + break; + case 3: + delete config.title; + delete config.closeBtn; + config.icon === -1 && (config.icon === 0); + layer.closeAll('loading'); + break; + case 4: + conType || (config.content = [config.content, 'body']); + config.follow = config.content[1]; + config.content = config.content[0] + ''; + delete config.title; + config.tips = typeof config.tips === 'object' ? config.tips : [config.tips, true]; + config.tipsMore || layer.closeAll('tips'); + break; + } + + //建立容器 + that.vessel(conType, function(html, titleHTML, moveElem){ + body.append(html[0]); + conType ? function(){ + (config.type == 2 || config.type == 4) ? function(){ + $('body').append(html[1]); + }() : function(){ + if(!content.parents('.'+doms[0])[0]){ + content.data('display', content.css('display')).show().addClass('layui-layer-wrap').wrap(html[1]); + $('#'+ doms[0] + times).find('.'+doms[5]).before(titleHTML); + } + }(); + }() : body.append(html[1]); + $('#'+ doms.MOVE)[0] || body.append(ready.moveElem = moveElem); + + that.layero = $('#'+ doms[0] + times); + that.shadeo = $('#'+ doms.SHADE + times); + + config.scrollbar || doms.html.css('overflow', 'hidden').attr('layer-full', times); + }).auto(times); + + //遮罩 + that.shadeo.css({ + 'background-color': config.shade[1] || '#000' + ,'opacity': config.shade[0] || config.shade + }); + + config.type == 2 && layer.ie == 6 && that.layero.find('iframe').attr('src', content[0]); + + //坐标自适应浏览器窗口尺寸 + config.type == 4 ? that.tips() : function(){ + that.offset() + //首次弹出时,若 css 尚未加载,则等待 css 加载完毕后,重新设定尺寸 + parseInt(ready.getStyle(document.getElementById(doms.MOVE), 'z-index')) || function(){ + that.layero.css('visibility', 'hidden'); + layer.ready(function(){ + that.offset(); + that.layero.css('visibility', 'visible'); + }); + }(); + }(); + + //如果是固定定位 + if(config.fixed){ + win.on('resize', function(){ + that.offset(); + (/^\d+%$/.test(config.area[0]) || /^\d+%$/.test(config.area[1])) && that.auto(times); + config.type == 4 && that.tips(); + }); + } + + config.time <= 0 || setTimeout(function(){ + layer.close(that.index); + }, config.time); + that.move().callback(); + + //为兼容jQuery3.0的css动画影响元素尺寸计算 + if(doms.anim[config.anim]){ + var animClass = 'layer-anim '+ doms.anim[config.anim]; + that.layero.addClass(animClass).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){ + $(this).removeClass(animClass); + }); + }; + + //记录关闭动画 + if(config.isOutAnim){ + that.layero.data('isOutAnim', true); + } +}; + +//自适应 +Class.pt.auto = function(index){ + var that = this, config = that.config, layero = $('#'+ doms[0] + index); + + if(config.area[0] === '' && config.maxWidth > 0){ + //为了修复IE7下一个让人难以理解的bug + if(layer.ie && layer.ie < 8 && config.btn){ + layero.width(layero.innerWidth()); + } + layero.outerWidth() > config.maxWidth && layero.width(config.maxWidth); + } + + var area = [layero.innerWidth(), layero.innerHeight()] + ,titHeight = layero.find(doms[1]).outerHeight() || 0 + ,btnHeight = layero.find('.'+doms[6]).outerHeight() || 0 + ,setHeight = function(elem){ + elem = layero.find(elem); + elem.height(area[1] - titHeight - btnHeight - 2*(parseFloat(elem.css('padding-top'))|0)); + }; + + switch(config.type){ + case 2: + setHeight('iframe'); + break; + default: + if(config.area[1] === ''){ + if(config.maxHeight > 0 && layero.outerHeight() > config.maxHeight){ + area[1] = config.maxHeight; + setHeight('.'+doms[5]); + } else if(config.fixed && area[1] >= win.height()){ + area[1] = win.height(); + setHeight('.'+doms[5]); + } + } else { + setHeight('.'+doms[5]); + } + break; + }; + + return that; +}; + +//计算坐标 +Class.pt.offset = function(){ + var that = this, config = that.config, layero = that.layero; + var area = [layero.outerWidth(), layero.outerHeight()]; + var type = typeof config.offset === 'object'; + that.offsetTop = (win.height() - area[1])/2; + that.offsetLeft = (win.width() - area[0])/2; + + if(type){ + that.offsetTop = config.offset[0]; + that.offsetLeft = config.offset[1]||that.offsetLeft; + } else if(config.offset !== 'auto'){ + + if(config.offset === 't'){ //上 + that.offsetTop = 0; + } else if(config.offset === 'r'){ //右 + that.offsetLeft = win.width() - area[0]; + } else if(config.offset === 'b'){ //下 + that.offsetTop = win.height() - area[1]; + } else if(config.offset === 'l'){ //左 + that.offsetLeft = 0; + } else if(config.offset === 'lt'){ //左上角 + that.offsetTop = 0; + that.offsetLeft = 0; + } else if(config.offset === 'lb'){ //左下角 + that.offsetTop = win.height() - area[1]; + that.offsetLeft = 0; + } else if(config.offset === 'rt'){ //右上角 + that.offsetTop = 0; + that.offsetLeft = win.width() - area[0]; + } else if(config.offset === 'rb'){ //右下角 + that.offsetTop = win.height() - area[1]; + that.offsetLeft = win.width() - area[0]; + } else { + that.offsetTop = config.offset; + } + + } + + if(!config.fixed){ + that.offsetTop = /%$/.test(that.offsetTop) ? + win.height()*parseFloat(that.offsetTop)/100 + : parseFloat(that.offsetTop); + that.offsetLeft = /%$/.test(that.offsetLeft) ? + win.width()*parseFloat(that.offsetLeft)/100 + : parseFloat(that.offsetLeft); + that.offsetTop += win.scrollTop(); + that.offsetLeft += win.scrollLeft(); + } + + if(layero.attr('minLeft')){ + that.offsetTop = win.height() - (layero.find(doms[1]).outerHeight() || 0); + that.offsetLeft = layero.css('left'); + } + + layero.css({top: that.offsetTop, left: that.offsetLeft}); +}; + +//Tips +Class.pt.tips = function(){ + var that = this, config = that.config, layero = that.layero; + var layArea = [layero.outerWidth(), layero.outerHeight()], follow = $(config.follow); + if(!follow[0]) follow = $('body'); + var goal = { + width: follow.outerWidth(), + height: follow.outerHeight(), + top: follow.offset().top, + left: follow.offset().left + }, tipsG = layero.find('.layui-layer-TipsG'); + + var guide = config.tips[0]; + config.tips[1] || tipsG.remove(); + + goal.autoLeft = function(){ + if(goal.left + layArea[0] - win.width() > 0){ + goal.tipLeft = goal.left + goal.width - layArea[0]; + tipsG.css({right: 12, left: 'auto'}); + } else { + goal.tipLeft = goal.left; + }; + }; + + //辨别tips的方位 + goal.where = [function(){ //上 + goal.autoLeft(); + goal.tipTop = goal.top - layArea[1] - 10; + tipsG.removeClass('layui-layer-TipsB').addClass('layui-layer-TipsT').css('border-right-color', config.tips[1]); + }, function(){ //右 + goal.tipLeft = goal.left + goal.width + 10; + goal.tipTop = goal.top; + tipsG.removeClass('layui-layer-TipsL').addClass('layui-layer-TipsR').css('border-bottom-color', config.tips[1]); + }, function(){ //下 + goal.autoLeft(); + goal.tipTop = goal.top + goal.height + 10; + tipsG.removeClass('layui-layer-TipsT').addClass('layui-layer-TipsB').css('border-right-color', config.tips[1]); + }, function(){ //左 + goal.tipLeft = goal.left - layArea[0] - 10; + goal.tipTop = goal.top; + tipsG.removeClass('layui-layer-TipsR').addClass('layui-layer-TipsL').css('border-bottom-color', config.tips[1]); + }]; + goal.where[guide-1](); + + /* 8*2为小三角形占据的空间 */ + if(guide === 1){ + goal.top - (win.scrollTop() + layArea[1] + 8*2) < 0 && goal.where[2](); + } else if(guide === 2){ + win.width() - (goal.left + goal.width + layArea[0] + 8*2) > 0 || goal.where[3]() + } else if(guide === 3){ + (goal.top - win.scrollTop() + goal.height + layArea[1] + 8*2) - win.height() > 0 && goal.where[0](); + } else if(guide === 4){ + layArea[0] + 8*2 - goal.left > 0 && goal.where[1]() + } + + layero.find('.'+doms[5]).css({ + 'background-color': config.tips[1], + 'padding-right': (config.closeBtn ? '30px' : '') + }); + layero.css({ + left: goal.tipLeft - (config.fixed ? win.scrollLeft() : 0), + top: goal.tipTop - (config.fixed ? win.scrollTop() : 0) + }); +} + +//拖拽层 +Class.pt.move = function(){ + var that = this + ,config = that.config + ,_DOC = $(document) + ,layero = that.layero + ,moveElem = layero.find(config.move) + ,resizeElem = layero.find('.layui-layer-resize') + ,dict = {}; + + if(config.move){ + moveElem.css('cursor', 'move'); + } + + moveElem.on('mousedown', function(e){ + e.preventDefault(); + if(config.move){ + dict.moveStart = true; + dict.offset = [ + e.clientX - parseFloat(layero.css('left')) + ,e.clientY - parseFloat(layero.css('top')) + ]; + ready.moveElem.css('cursor', 'move').show(); + } + }); + + resizeElem.on('mousedown', function(e){ + e.preventDefault(); + dict.resizeStart = true; + dict.offset = [e.clientX, e.clientY]; + dict.area = [ + layero.outerWidth() + ,layero.outerHeight() + ]; + ready.moveElem.css('cursor', 'se-resize').show(); + }); + + _DOC.on('mousemove', function(e){ + + //拖拽移动 + if(dict.moveStart){ + var X = e.clientX - dict.offset[0] + ,Y = e.clientY - dict.offset[1] + ,fixed = layero.css('position') === 'fixed'; + + e.preventDefault(); + + dict.stX = fixed ? 0 : win.scrollLeft(); + dict.stY = fixed ? 0 : win.scrollTop(); + + //控制元素不被拖出窗口外 + if(!config.moveOut){ + var setRig = win.width() - layero.outerWidth() + dict.stX + ,setBot = win.height() - layero.outerHeight() + dict.stY; + X < dict.stX && (X = dict.stX); + X > setRig && (X = setRig); + Y < dict.stY && (Y = dict.stY); + Y > setBot && (Y = setBot); + } + + layero.css({ + left: X + ,top: Y + }); + } + + //Resize + if(config.resize && dict.resizeStart){ + var X = e.clientX - dict.offset[0] + ,Y = e.clientY - dict.offset[1]; + + e.preventDefault(); + + layer.style(that.index, { + width: dict.area[0] + X + ,height: dict.area[1] + Y + }) + dict.isResize = true; + config.resizing && config.resizing(layero); + } + }).on('mouseup', function(e){ + if(dict.moveStart){ + delete dict.moveStart; + ready.moveElem.hide(); + config.moveEnd && config.moveEnd(layero); + } + if(dict.resizeStart){ + delete dict.resizeStart; + ready.moveElem.hide(); + } + }); + + return that; +}; + +Class.pt.callback = function(){ + var that = this, layero = that.layero, config = that.config; + that.openLayer(); + if(config.success){ + if(config.type == 2){ + layero.find('iframe').on('load', function(){ + config.success(layero, that.index, that); + }); + } else { + config.success(layero, that.index, that); + } + } + layer.ie == 6 && that.IE6(layero); + + //按钮 + layero.find('.'+ doms[6]).children('a').on('click', function(){ + var index = $(this).index(); + if(index === 0){ + if(config.yes){ + config.yes(that.index, layero) + } else if(config['btn1']){ + config['btn1'](that.index, layero) + } else { + layer.close(that.index); + } + } else { + var close = config['btn'+(index+1)] && config['btn'+(index+1)](that.index, layero); + close === false || layer.close(that.index); + } + }); + + //取消 + function cancel(){ + var close = config.cancel && config.cancel(that.index, layero); + close === false || layer.close(that.index); + } + + //右上角关闭回调 + layero.find('.'+ doms[7]).on('click', cancel); + + //点遮罩关闭 + if(config.shadeClose){ + that.shadeo.on('click', function(){ + layer.close(that.index); + }); + } + + //最小化 + layero.find('.layui-layer-min').on('click', function(){ + var min = config.min && config.min(layero, that.index); + min === false || layer.min(that.index, config); + }); + + //全屏/还原 + layero.find('.layui-layer-max').on('click', function(){ + if($(this).hasClass('layui-layer-maxmin')){ + layer.restore(that.index); + config.restore && config.restore(layero, that.index); + } else { + layer.full(that.index, config); + setTimeout(function(){ + config.full && config.full(layero, that.index); + }, 100); + } + }); + + config.end && (ready.end[that.index] = config.end); +}; + +//for ie6 恢复select +ready.reselect = function(){ + $.each($('select'), function(index , value){ + var sthis = $(this); + if(!sthis.parents('.'+doms[0])[0]){ + (sthis.attr('layer') == 1 && $('.'+doms[0]).length < 1) && sthis.removeAttr('layer').show(); + } + sthis = null; + }); +}; + +Class.pt.IE6 = function(layero){ + //隐藏select + $('select').each(function(index , value){ + var sthis = $(this); + if(!sthis.parents('.'+doms[0])[0]){ + sthis.css('display') === 'none' || sthis.attr({'layer' : '1'}).hide(); + } + sthis = null; + }); +}; + +//需依赖原型的对外方法 +Class.pt.openLayer = function(){ + var that = this; + + //置顶当前窗口 + layer.zIndex = that.config.zIndex; + layer.setTop = function(layero){ + var setZindex = function(){ + layer.zIndex++; + layero.css('z-index', layer.zIndex + 1); + }; + layer.zIndex = parseInt(layero[0].style.zIndex); + layero.on('mousedown', setZindex); + return layer.zIndex; + }; +}; + +//记录宽高坐标,用于还原 +ready.record = function(layero){ + var area = [ + layero.width(), + layero.height(), + layero.position().top, + layero.position().left + parseFloat(layero.css('margin-left')) + ]; + layero.find('.layui-layer-max').addClass('layui-layer-maxmin'); + layero.attr({area: area}); +}; + +ready.rescollbar = function(index){ + if(doms.html.attr('layer-full') == index){ + if(doms.html[0].style.removeProperty){ + doms.html[0].style.removeProperty('overflow'); + } else { + doms.html[0].style.removeAttribute('overflow'); + } + doms.html.removeAttr('layer-full'); + } +}; + +/** 内置成员 */ + +window.layer = layer; + +//获取子iframe的DOM +layer.getChildFrame = function(selector, index){ + index = index || $('.'+doms[4]).attr('times'); + return $('#'+ doms[0] + index).find('iframe').contents().find(selector); +}; + +//得到当前iframe层的索引,子iframe时使用 +layer.getFrameIndex = function(name){ + return $('#'+ name).parents('.'+doms[4]).attr('times'); +}; + +//iframe层自适应宽高 +layer.iframeAuto = function(index){ + if(!index) return; + var heg = layer.getChildFrame('html', index).outerHeight(); + var layero = $('#'+ doms[0] + index); + var titHeight = layero.find(doms[1]).outerHeight() || 0; + var btnHeight = layero.find('.'+doms[6]).outerHeight() || 0; + layero.css({height: heg + titHeight + btnHeight}); + layero.find('iframe').css({height: heg}); +}; + +//重置iframe url +layer.iframeSrc = function(index, url){ + $('#'+ doms[0] + index).find('iframe').attr('src', url); +}; + +//设定层的样式 +layer.style = function(index, options, limit){ + var layero = $('#'+ doms[0] + index) + ,contElem = layero.find('.layui-layer-content') + ,type = layero.attr('type') + ,titHeight = layero.find(doms[1]).outerHeight() || 0 + ,btnHeight = layero.find('.'+doms[6]).outerHeight() || 0 + ,minLeft = layero.attr('minLeft'); + + if(type === ready.type[3] || type === ready.type[4]){ + return; + } + + if(!limit){ + if(parseFloat(options.width) <= 260){ + options.width = 260; + }; + + if(parseFloat(options.height) - titHeight - btnHeight <= 64){ + options.height = 64 + titHeight + btnHeight; + }; + } + + layero.css(options); + btnHeight = layero.find('.'+doms[6]).outerHeight(); + + if(type === ready.type[2]){ + layero.find('iframe').css({ + height: parseFloat(options.height) - titHeight - btnHeight + }); + } else { + contElem.css({ + height: parseFloat(options.height) - titHeight - btnHeight + - parseFloat(contElem.css('padding-top')) + - parseFloat(contElem.css('padding-bottom')) + }) + } +}; + +//最小化 +layer.min = function(index, options){ + options = options || {}; + var layero = $('#'+ doms[0] + index) + ,shadeo = $('#'+ doms.SHADE + index) + ,titHeight = layero.find(doms[1]).outerHeight() || 0 + ,left = layero.attr('minLeft') || (181*ready.minIndex)+'px' + ,position = layero.css('position') + ,settings = { + width: 180 + ,height: titHeight + ,position: 'fixed' + ,overflow: 'hidden' + }; + + //记录宽高坐标,用于还原 + ready.record(layero); + + if(ready.minLeft[0]){ + left = ready.minLeft[0]; + ready.minLeft.shift(); + } + + //是否堆叠在左下角 + if(options.minStack){ + settings.left = left; + settings.top = win.height() - titHeight; + layero.attr('minLeft') || ready.minIndex++; //初次执行,最小化操作索引自增 + layero.attr('minLeft', left); + } + + layero.attr('position', position); + layer.style(index, settings, true); + + layero.find('.layui-layer-min').hide(); + layero.attr('type') === 'page' && layero.find(doms[4]).hide(); + ready.rescollbar(index); + + //隐藏遮罩 + shadeo.hide(); +}; + +//还原 +layer.restore = function(index){ + var layero = $('#'+ doms[0] + index) + ,shadeo = $('#'+ doms.SHADE + index) + ,area = layero.attr('area').split(',') + ,type = layero.attr('type'); + + //恢复原来尺寸 + layer.style(index, { + width: parseFloat(area[0]), + height: parseFloat(area[1]), + top: parseFloat(area[2]), + left: parseFloat(area[3]), + position: layero.attr('position'), + overflow: 'visible' + }, true); + + layero.find('.layui-layer-max').removeClass('layui-layer-maxmin'); + layero.find('.layui-layer-min').show(); + layero.attr('type') === 'page' && layero.find(doms[4]).show(); + ready.rescollbar(index); + + //恢复遮罩 + shadeo.show(); +}; + +//全屏 +layer.full = function(index){ + var layero = $('#'+ doms[0] + index), timer; + ready.record(layero); + if(!doms.html.attr('layer-full')){ + doms.html.css('overflow','hidden').attr('layer-full', index); + } + clearTimeout(timer); + timer = setTimeout(function(){ + var isfix = layero.css('position') === 'fixed'; + layer.style(index, { + top: isfix ? 0 : win.scrollTop(), + left: isfix ? 0 : win.scrollLeft(), + width: win.width(), + height: win.height() + }, true); + layero.find('.layui-layer-min').hide(); + }, 100); +}; + +//改变title +layer.title = function(name, index){ + var title = $('#'+ doms[0] + (index||layer.index)).find(doms[1]); + title.html(name); +}; + +//关闭layer总方法 +layer.close = function(index, callback){ + var layero = $('#'+ doms[0] + index), type = layero.attr('type'), closeAnim = 'layer-anim-close'; + if(!layero[0]) return; + var WRAP = 'layui-layer-wrap', remove = function(){ + if(type === ready.type[1] && layero.attr('conType') === 'object'){ + layero.children(':not(.'+ doms[5] +')').remove(); + var wrap = layero.find('.'+WRAP); + for(var i = 0; i < 2; i++){ + wrap.unwrap(); + } + wrap.css('display', wrap.data('display')).removeClass(WRAP); + } else { + //低版本IE 回收 iframe + if(type === ready.type[2]){ + try { + var iframe = $('#'+doms[4]+index)[0]; + iframe.contentWindow.document.write(''); + iframe.contentWindow.close(); + layero.find('.'+doms[5])[0].removeChild(iframe); + } catch(e){} + } + layero[0].innerHTML = ''; + layero.remove(); + } + typeof ready.end[index] === 'function' && ready.end[index](); + delete ready.end[index]; + typeof callback === 'function' && callback(); + }; + + if(layero.data('isOutAnim')){ + layero.addClass('layer-anim '+ closeAnim); + } + + $('#layui-layer-moves, #'+ doms.SHADE + index).remove(); + layer.ie == 6 && ready.reselect(); + ready.rescollbar(index); + if(layero.attr('minLeft')){ + ready.minIndex--; + ready.minLeft.push(layero.attr('minLeft')); + } + + if((layer.ie && layer.ie < 10) || !layero.data('isOutAnim')){ + remove() + } else { + setTimeout(function(){ + remove(); + }, 200); + } +}; + +//关闭所有层 +layer.closeAll = function(type, callback){ + if(typeof type === 'function'){ + callback = type; + type = null; + }; + var domsElem = $('.'+doms[0]); + $.each(domsElem, function(_index){ + var othis = $(this); + var is = type ? (othis.attr('type') === type) : 1; + is && layer.close(othis.attr('times'), _index === domsElem.length - 1 ? callback : null); + is = null; + }); + if(domsElem.length === 0) typeof callback === 'function' && callback(); +}; + +/** + + 拓展模块,layui 开始合并在一起 + + */ + +var cache = layer.cache||{}, skin = function(type){ + return (cache.skin ? (' ' + cache.skin + ' ' + cache.skin + '-'+type) : ''); +}; + +//仿系统prompt +layer.prompt = function(options, yes){ + var style = ''; + options = options || {}; + + if(typeof options === 'function') yes = options; + + if(options.area){ + var area = options.area; + style = 'style="width: '+ area[0] +'; height: '+ area[1] + ';"'; + delete options.area; + } + var prompt, content = options.formType == 2 ? '' : function(){ + return ''; + }(); + + var success = options.success; + delete options.success; + + return layer.open($.extend({ + type: 1 + ,btn: ['确定','取消'] + ,content: content + ,skin: 'layui-layer-prompt' + skin('prompt') + ,maxWidth: win.width() + ,success: function(layero){ + prompt = layero.find('.layui-layer-input'); + prompt.val(options.value || '').focus(); + typeof success === 'function' && success(layero); + } + ,resize: false + ,yes: function(index){ + var value = prompt.val(); + if(value === ''){ + prompt.focus(); + } else if(value.length > (options.maxlength||500)) { + layer.tips('最多输入'+ (options.maxlength || 500) +'个字数', prompt, {tips: 1}); + } else { + yes && yes(value, index, prompt); + } + } + }, options)); +}; + +//tab层 +layer.tab = function(options){ + options = options || {}; + + var tab = options.tab || {} + ,THIS = 'layui-this' + ,success = options.success; + + delete options.success; + + return layer.open($.extend({ + type: 1, + skin: 'layui-layer-tab' + skin('tab'), + resize: false, + title: function(){ + var len = tab.length, ii = 1, str = ''; + if(len > 0){ + str = ''+ tab[0].title +''; + for(; ii < len; ii++){ + str += ''+ tab[ii].title +''; + } + } + return str; + }(), + content: '
        '+ function(){ + var len = tab.length, ii = 1, str = ''; + if(len > 0){ + str = '
      • '+ (tab[0].content || 'no content') +'
      • '; + for(; ii < len; ii++){ + str += '
      • '+ (tab[ii].content || 'no content') +'
      • '; + } + } + return str; + }() +'
      ', + success: function(layero){ + var btn = layero.find('.layui-layer-title').children(); + var main = layero.find('.layui-layer-tabmain').children(); + btn.on('mousedown', function(e){ + e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; + var othis = $(this), index = othis.index(); + othis.addClass(THIS).siblings().removeClass(THIS); + main.eq(index).show().siblings().hide(); + typeof options.change === 'function' && options.change(index); + }); + typeof success === 'function' && success(layero); + } + }, options)); +}; + +//相册层 +layer.photos = function(options, loop, key){ + var dict = {}; + options = options || {}; + if(!options.photos) return; + + //若 photos 并非选择器或 jQuery 对象,则为普通 object + var isObject = !(typeof options.photos === 'string' || options.photos instanceof $) + ,photos = isObject ? options.photos : {} + ,data = photos.data || [] + ,start = photos.start || 0; + + dict.imgIndex = (start|0) + 1; + options.img = options.img || 'img'; + + var success = options.success; + delete options.success; + + //如果 options.photos 不是一个对象 + if(!isObject){ //页面直接获取 + var parent = $(options.photos), pushData = function(){ + data = []; + parent.find(options.img).each(function(index){ + var othis = $(this); + othis.attr('layer-index', index); + data.push({ + alt: othis.attr('alt'), + pid: othis.attr('layer-pid'), + src: othis.attr('layer-src') || othis.attr('src'), + thumb: othis.attr('src') + }); + }); + }; + + pushData(); + + if (data.length === 0) return; + + loop || parent.on('click', options.img, function(){ + pushData(); + var othis = $(this), index = othis.attr('layer-index'); + layer.photos($.extend(options, { + photos: { + start: index, + data: data, + tab: options.tab + }, + full: options.full + }), true); + }); + + //不直接弹出 + if(!loop) return; + + } else if (data.length === 0){ + return layer.msg('没有图片'); + } + + //上一张 + dict.imgprev = function(key){ + dict.imgIndex--; + if(dict.imgIndex < 1){ + dict.imgIndex = data.length; + } + dict.tabimg(key); + }; + + //下一张 + dict.imgnext = function(key,errorMsg){ + dict.imgIndex++; + if(dict.imgIndex > data.length){ + dict.imgIndex = 1; + if (errorMsg) {return}; + } + dict.tabimg(key) + }; + + //方向键 + dict.keyup = function(event){ + if(!dict.end){ + var code = event.keyCode; + event.preventDefault(); + if(code === 37){ + dict.imgprev(true); + } else if(code === 39) { + dict.imgnext(true); + } else if(code === 27) { + layer.close(dict.index); + } + } + } + + //切换 + dict.tabimg = function(key){ + if(data.length <= 1) return; + photos.start = dict.imgIndex - 1; + layer.close(dict.index); + return layer.photos(options, true, key); + setTimeout(function(){ + layer.photos(options, true, key); + }, 200); + } + + //一些动作 + dict.event = function(){ + /* + dict.bigimg.hover(function(){ + dict.imgsee.show(); + }, function(){ + dict.imgsee.hide(); + }); + */ + + dict.bigimg.find('.layui-layer-imgprev').on('click', function(event){ + event.preventDefault(); + dict.imgprev(true); + }); + + dict.bigimg.find('.layui-layer-imgnext').on('click', function(event){ + event.preventDefault(); + dict.imgnext(true); + }); + + $(document).on('keyup', dict.keyup); + }; + + //图片预加载 + function loadImage(url, callback, error) { + var img = new Image(); + img.src = url; + if(img.complete){ + return callback(img); + } + img.onload = function(){ + img.onload = null; + callback(img); + }; + img.onerror = function(e){ + img.onerror = null; + error(e); + }; + }; + + dict.loadi = layer.load(1, { + shade: 'shade' in options ? false : 0.9, + scrollbar: false + }); + + loadImage(data[start].src, function(img){ + layer.close(dict.loadi); + + //切换图片时不出现动画 + if(key) options.anim = -1; + + //弹出图片层 + dict.index = layer.open($.extend({ + type: 1, + id: 'layui-layer-photos', + area: function(){ + var imgarea = [img.width, img.height]; + var winarea = [$(window).width() - 100, $(window).height() - 100]; + + //如果 实际图片的宽或者高比 屏幕大(那么进行缩放) + if(!options.full && (imgarea[0]>winarea[0]||imgarea[1]>winarea[1])){ + var wh = [imgarea[0]/winarea[0],imgarea[1]/winarea[1]];//取宽度缩放比例、高度缩放比例 + if(wh[0] > wh[1]){//取缩放比例最大的进行缩放 + imgarea[0] = imgarea[0]/wh[0]; + imgarea[1] = imgarea[1]/wh[0]; + } else if(wh[0] < wh[1]){ + imgarea[0] = imgarea[0]/wh[1]; + imgarea[1] = imgarea[1]/wh[1]; + } + } + + return [imgarea[0]+'px', imgarea[1]+'px']; + }(), + title: false, + shade: 0.9, + shadeClose: true, + closeBtn: false, + move: '.layui-layer-phimg img', + moveType: 1, + scrollbar: false, + moveOut: true, + anim: 5, + isOutAnim: false, + skin: 'layui-layer-photos' + skin('photos'), + content: '
      ' + +''+ (data[start].alt||'') +'' + +function(){ + if(data.length > 1){ + return '
      ' + +'' + +'
      '+ (data[start].alt || '') +''+ dict.imgIndex +' / '+ data.length +'
      ' + +'
      ' + } + return ''; + }() + +'
      ', + success: function(layero, index){ + dict.bigimg = layero.find('.layui-layer-phimg'); + dict.imgsee = layero.find('.layui-layer-imgbar'); + dict.event(layero); + options.tab && options.tab(data[start], layero); + typeof success === 'function' && success(layero); + }, end: function(){ + dict.end = true; + $(document).off('keyup', dict.keyup); + } + }, options)); + }, function(){ + layer.close(dict.loadi); + layer.msg('当前图片地址异常
      是否继续查看下一张?', { + time: 30000, + btn: ['下一张', '不看了'], + yes: function(){ + data.length > 1 && dict.imgnext(true,true); + } + }); + }); +}; + +//主入口 +ready.run = function(_$){ + $ = _$; + win = $(window); + doms.html = $('html'); + layer.open = function(deliver){ + var o = new Class(deliver); + return o.index; + }; +}; + +//加载方式 +window.layui && layui.define ? ( + layer.ready() + ,layui.define('jquery', function(exports){ //layui 加载 + layer.path = layui.cache.dir; + ready.run(layui.$); + + //暴露模块 + window.layer = layer; + exports('layer', layer); + }) +) : ( + (typeof define === 'function' && define.amd) ? define(['jquery'], function(){ //requirejs 加载 + ready.run(window.jQuery); + return layer; + }) : function(){ //普通 script 标签加载 + layer.ready(); + ready.run(window.jQuery); + }() +); + +}(window); + + + diff --git a/static/layui/modules/laypage.js b/static/layui/modules/laypage.js new file mode 100644 index 0000000..2df27fd --- /dev/null +++ b/static/layui/modules/laypage.js @@ -0,0 +1,309 @@ +/** + + @Name : laypage 分页组件 + @License:MIT + + */ + +layui.define(function(exports){ + "use strict"; + + var doc = document + ,id = 'getElementById' + ,tag = 'getElementsByTagName' + + //字符常量 + ,MOD_NAME = 'laypage', DISABLED = 'layui-disabled' + + //构造器 + ,Class = function(options){ + var that = this; + that.config = options || {}; + that.config.index = ++laypage.index; + that.render(true); + }; + + //判断传入的容器类型 + Class.prototype.type = function(){ + var config = this.config; + if(typeof config.elem === 'object'){ + return config.elem.length === undefined ? 2 : 3; + } + }; + + //分页视图 + Class.prototype.view = function(){ + var that = this + ,config = that.config + ,groups = config.groups = 'groups' in config ? (config.groups|0) : 5; //连续页码个数 + + //排版 + config.layout = typeof config.layout === 'object' + ? config.layout + : ['prev', 'page', 'next']; + + config.count = config.count|0; //数据总数 + config.curr = (config.curr|0) || 1; //当前页 + + //每页条数的选择项 + config.limits = typeof config.limits === 'object' + ? config.limits + : [10, 20, 30, 40, 50]; + config.limit = (config.limit|0) || 10; //默认条数 + + //总页数 + config.pages = Math.ceil(config.count/config.limit) || 1; + + //当前页不能超过总页数 + if(config.curr > config.pages){ + config.curr = config.pages; + } + + //连续分页个数不能低于0且不能大于总页数 + if(groups < 0){ + groups = 1; + } else if (groups > config.pages){ + groups = config.pages; + } + + config.prev = 'prev' in config ? config.prev : '上一页'; //上一页文本 + config.next = 'next' in config ? config.next : '下一页'; //下一页文本 + + //计算当前组 + var index = config.pages > groups + ? Math.ceil( (config.curr + (groups > 1 ? 1 : 0)) / (groups > 0 ? groups : 1) ) + : 1 + + //视图片段 + ,views = { + //上一页 + prev: function(){ + return config.prev + ? ''+ config.prev +'' + : ''; + }() + + //页码 + ,page: function(){ + var pager = []; + + //数据量为0时,不输出页码 + if(config.count < 1){ + return ''; + } + + //首页 + if(index > 1 && config.first !== false && groups !== 0){ + pager.push(''+ (config.first || 1) +''); + } + + //计算当前页码组的起始页 + var halve = Math.floor((groups-1)/2) //页码数等分 + ,start = index > 1 ? config.curr - halve : 1 + ,end = index > 1 ? (function(){ + var max = config.curr + (groups - halve - 1); + return max > config.pages ? config.pages : max; + }()) : groups; + + //防止最后一组出现“不规定”的连续页码数 + if(end - start < groups - 1){ + start = end - groups + 1; + } + + //输出左分割符 + if(config.first !== false && start > 2){ + pager.push('') + } + + //输出连续页码 + for(; start <= end; start++){ + if(start === config.curr){ + //当前页 + pager.push(''+ start +''); + } else { + pager.push(''+ start +''); + } + } + + //输出输出右分隔符 & 末页 + if(config.pages > groups && config.pages > end && config.last !== false){ + if(end + 1 < config.pages){ + pager.push(''); + } + if(groups !== 0){ + pager.push(''+ (config.last || config.pages) +''); + } + } + + return pager.join(''); + }() + + //下一页 + ,next: function(){ + return config.next + ? ''+ config.next +'' + : ''; + }() + + //数据总数 + ,count: '共 '+ config.count +' 条' + + //每页条数 + ,limit: function(){ + var options = [''; + }() + + //刷新当前页 + ,refresh: ['' + ,'' + ,''].join('') + + //跳页区域 + ,skip: function(){ + return ['到第' + ,'' + ,'页' + ,''].join(''); + }() + }; + + return ['
      ' + ,function(){ + var plate = []; + layui.each(config.layout, function(index, item){ + if(views[item]){ + plate.push(views[item]) + } + }); + return plate.join(''); + }() + ,'
      '].join(''); + }; + + //跳页的回调 + Class.prototype.jump = function(elem, isskip){ + if(!elem) return; + var that = this + ,config = that.config + ,childs = elem.children + ,btn = elem[tag]('button')[0] + ,input = elem[tag]('input')[0] + ,select = elem[tag]('select')[0] + ,skip = function(){ + var curr = input.value.replace(/\s|\D/g, '')|0; + if(curr){ + config.curr = curr; + that.render(); + } + }; + + if(isskip) return skip(); + + //页码 + for(var i = 0, len = childs.length; i < len; i++){ + if(childs[i].nodeName.toLowerCase() === 'a'){ + laypage.on(childs[i], 'click', function(){ + var curr = this.getAttribute('data-page')|0; + if(curr < 1 || curr > config.pages) return; + config.curr = curr; + that.render(); + }); + } + } + + //条数 + if(select){ + laypage.on(select, 'change', function(){ + var value = this.value; + if(config.curr*value > config.count){ + config.curr = Math.ceil(config.count/value); + } + config.limit = value; + that.render(); + }); + } + + //确定 + if(btn){ + laypage.on(btn, 'click', function(){ + skip(); + }); + } + }; + + //输入页数字控制 + Class.prototype.skip = function(elem){ + if(!elem) return; + var that = this, input = elem[tag]('input')[0]; + if(!input) return; + laypage.on(input, 'keyup', function(e){ + var value = this.value + ,keyCode = e.keyCode; + if(/^(37|38|39|40)$/.test(keyCode)) return; + if(/\D/.test(value)){ + this.value = value.replace(/\D/, ''); + } + if(keyCode === 13){ + that.jump(elem, true) + } + }); + }; + + //渲染分页 + Class.prototype.render = function(load){ + var that = this + ,config = that.config + ,type = that.type() + ,view = that.view(); + + if(type === 2){ + config.elem && (config.elem.innerHTML = view); + } else if(type === 3){ + config.elem.html(view); + } else { + if(doc[id](config.elem)){ + doc[id](config.elem).innerHTML = view; + } + } + + config.jump && config.jump(config, load); + + var elem = doc[id]('layui-laypage-' + config.index); + that.jump(elem); + + if(config.hash && !load){ + location.hash = '!'+ config.hash +'='+ config.curr; + } + + that.skip(elem); + }; + + //外部接口 + var laypage = { + //分页渲染 + render: function(options){ + var o = new Class(options); + return o.index; + } + ,index: layui.laypage ? (layui.laypage.index + 10000) : 0 + ,on: function(elem, even, fn){ + elem.attachEvent ? elem.attachEvent('on'+ even, function(e){ //for ie + e.target = e.srcElement; + fn.call(elem, e); + }) : elem.addEventListener(even, fn, false); + return this; + } + } + + exports(MOD_NAME, laypage); +}); \ No newline at end of file diff --git a/static/layui/modules/laytpl.js b/static/layui/modules/laytpl.js new file mode 100644 index 0000000..498d73f --- /dev/null +++ b/static/layui/modules/laytpl.js @@ -0,0 +1,122 @@ +/** + + @Name : laytpl 模板引擎 + @License:MIT + + */ + +layui.define(function(exports){ + + "use strict"; + + var config = { + open: '{{', + close: '}}' + }; + + var tool = { + exp: function(str){ + return new RegExp(str, 'g'); + }, + //匹配满足规则内容 + query: function(type, _, __){ + var types = [ + '#([\\s\\S])+?', //js语句 + '([^{#}])*?' //普通字段 + ][type || 0]; + return exp((_||'') + config.open + types + config.close + (__||'')); + }, + escape: function(html){ + return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"'); + }, + error: function(e, tplog){ + var error = 'Laytpl Error: '; + typeof console === 'object' && console.error(error + e + '\n'+ (tplog || '')); + return error + e; + } + }; + + var exp = tool.exp, Tpl = function(tpl){ + this.tpl = tpl; + }; + + Tpl.pt = Tpl.prototype; + + window.errors = 0; + + //编译模版 + Tpl.pt.parse = function(tpl, data){ + var that = this, tplog = tpl; + var jss = exp('^'+config.open+'#', ''), jsse = exp(config.close+'$', ''); + + tpl = tpl.replace(/\s+|\r|\t|\n/g, ' ') + .replace(exp(config.open+'#'), config.open+'# ') + .replace(exp(config.close+'}'), '} '+config.close).replace(/\\/g, '\\\\') + + //不匹配指定区域的内容 + .replace(exp(config.open + '!(.+?)!' + config.close), function(str){ + str = str.replace(exp('^'+ config.open + '!'), '') + .replace(exp('!'+ config.close), '') + .replace(exp(config.open + '|' + config.close), function(tag){ + return tag.replace(/(.)/g, '\\$1') + }); + return str + }) + + //匹配JS规则内容 + .replace(/(?="|')/g, '\\').replace(tool.query(), function(str){ + str = str.replace(jss, '').replace(jsse, ''); + return '";' + str.replace(/\\(.)/g, '$1') + ';view+="'; + }) + + //匹配普通字段 + .replace(tool.query(1), function(str){ + var start = '"+('; + if(str.replace(/\s/g, '') === config.open+config.close){ + return ''; + } + str = str.replace(exp(config.open+'|'+config.close), ''); + if(/^=/.test(str)){ + str = str.replace(/^=/, ''); + start = '"+_escape_('; + } + return start + str.replace(/\\(.)/g, '$1') + ')+"'; + }); + + tpl = '"use strict";var view = "' + tpl + '";return view;'; + + try{ + that.cache = tpl = new Function('d, _escape_', tpl); + return tpl(data, tool.escape); + } catch(e){ + delete that.cache; + return tool.error(e, tplog); + } + }; + + Tpl.pt.render = function(data, callback){ + var that = this, tpl; + if(!data) return tool.error('no data'); + tpl = that.cache ? that.cache(data, tool.escape) : that.parse(that.tpl, data); + if(!callback) return tpl; + callback(tpl); + }; + + var laytpl = function(tpl){ + if(typeof tpl !== 'string') return tool.error('Template not found'); + return new Tpl(tpl); + }; + + laytpl.config = function(options){ + options = options || {}; + for(var i in options){ + config[i] = options[i]; + } + }; + + laytpl.v = '1.2.0'; + + exports('laytpl', laytpl); + +}); \ No newline at end of file diff --git a/static/layui/modules/layui.all.js b/static/layui/modules/layui.all.js new file mode 100644 index 0000000..4a7799b --- /dev/null +++ b/static/layui/modules/layui.all.js @@ -0,0 +1,12 @@ + +/*! + * 用于打包聚合版,该文件不会存在于构建后的目录 + */ + +layui.define(function(exports){ + var cache = layui.cache; + layui.config({ + dir: cache.dir.replace(/lay\/dest\/$/, '') + }); + exports('layui.all', layui.v); +}); \ No newline at end of file diff --git a/static/layui/modules/mobile.js b/static/layui/modules/mobile.js new file mode 100644 index 0000000..7306fb6 --- /dev/null +++ b/static/layui/modules/mobile.js @@ -0,0 +1,29 @@ +/** + + @Name:layui 移动模块入口 | 构建后则为移动模块集合 + @License:MIT + + */ + + +if(!layui['layui.mobile']){ + layui.config({ + base: layui.cache.dir + 'lay/modules/mobile/' + }).extend({ + 'layer-mobile': 'layer-mobile' + ,'zepto': 'zepto' + ,'upload-mobile': 'upload-mobile' + ,'layim-mobile': 'layim-mobile' + }); +} + +layui.define([ + 'layer-mobile' + ,'zepto' + ,'layim-mobile' +], function(exports){ + exports('mobile', { + layer: layui['layer-mobile'] //弹层 + ,layim: layui['layim-mobile'] //WebIM + }); +}); \ No newline at end of file diff --git a/static/layui/modules/rate.js b/static/layui/modules/rate.js new file mode 100644 index 0000000..550d79c --- /dev/null +++ b/static/layui/modules/rate.js @@ -0,0 +1,218 @@ +/** + + @Title: rate 评分评星组件 + @License:MIT + + */ + +layui.define('jquery',function(exports){ + "use strict"; + var $ = layui.jquery + + //外部接口 + ,rate = { + config: {} + ,index: layui.rate ? (layui.rate.index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisRate = function(){ + var that = this + ,options = that.config; + + return { + setvalue: function(value){ + that.setvalue.call(that, value); + } + ,config: options + } + } + + //字符常量 + ,MOD_NAME = 'rate',ELEM_VIEW = 'layui-rate', ICON_RATE = 'layui-icon-rate', ICON_RATE_SOLID = 'layui-icon-rate-solid', ICON_RATE_HALF = 'layui-icon-rate-half' + + ,ICON_SOLID_HALF = 'layui-icon-rate-solid layui-icon-rate-half', ICON_SOLID_RATE = 'layui-icon-rate-solid layui-icon-rate', ICON_HALF_RATE = 'layui-icon-rate layui-icon-rate-half' + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++rate.index; + that.config = $.extend({}, that.config, rate.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + length: 5 //初始长度 + ,text: false //是否显示评分等级 + ,readonly: false //是否只读 + ,half: false //是否可以半星 + ,value: 0 //星星选中个数 + ,theme: '' + }; + + //评分渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config + ,style = options.theme ? ('style="color: '+ options.theme + ';"') : ''; + + options.elem = $(options.elem); + + //最大值不能大于总长度 + if(options.value > options.length){ + options.value = options.length; + } + + //如果没有选择半星的属性,却给了小数的数值,统一向上或向下取整 + if(parseInt(options.value) !== options.value){ + if(!options.half){ + options.value = (Math.ceil(options.value) - options.value) < 0.5 ? Math.ceil(options.value): Math.floor(options.value) + } + } + + //组件模板 + var temp = '
        '; + for(var i = 1;i <= options.length;i++){ + var item = '
      • '; + + if(options.half){ + if(parseInt(options.value) !== options.value){ + if(i == Math.ceil(options.value)){ + temp = temp + '
      • '; + }else{ + temp = temp + item + } + }else{ + temp = temp + item + } + }else{ + temp = temp +item; + } + } + temp += '
      ' + (options.text ? (''+ options.value + '星') : '') + ''; + + //开始插入替代元素 + var othis = options.elem + ,hasRender = othis.next('.' + ELEM_VIEW); + + //生成替代元素 + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + + that.elemTemp = $(temp); + + options.span = that.elemTemp.next('span'); + + options.setText && options.setText(options.value); + + othis.html(that.elemTemp); + + othis.addClass("layui-inline"); + + //如果不是只读,那么进行触控事件 + if(!options.readonly) that.action(); + + }; + + //评分重置 + Class.prototype.setvalue = function(value){ + var that = this + ,options = that.config ; + + options.value = value ; + that.render(); + }; + + //li触控事件 + Class.prototype.action = function(){ + var that = this + ,options = that.config + ,_ul = that.elemTemp + ,wide = _ul.find("i").width(); + + _ul.children("li").each(function(index){ + var ind = index + 1 + ,othis = $(this); + + //点击 + othis.on('click', function(e){ + //将当前点击li的索引值赋给value + options.value = ind; + if(options.half){ + //获取鼠标在li上的位置 + var x = e.pageX - $(this).offset().left; + if(x <= wide / 2){ + options.value = options.value - 0.5; + } + } + + if(options.text) _ul.next("span").text(options.value + "星"); + + options.choose && options.choose(options.value); + options.setText && options.setText(options.value); + }); + + //移入 + othis.on('mousemove', function(e){ + _ul.find("i").each(function(){ + $(this).addClass(ICON_RATE).removeClass(ICON_SOLID_HALF) + }); + _ul.find("i:lt(" + ind + ")").each(function(){ + $(this).addClass(ICON_RATE_SOLID).removeClass(ICON_HALF_RATE) + }); + // 如果设置可选半星,那么判断鼠标相对li的位置 + if(options.half){ + var x = e.pageX - $(this).offset().left; + if(x <= wide / 2){ + othis.children("i").addClass(ICON_RATE_HALF).removeClass(ICON_RATE_SOLID) + } + } + }) + + //移出 + othis.on('mouseleave', function(){ + _ul.find("i").each(function(){ + $(this).addClass(ICON_RATE).removeClass(ICON_SOLID_HALF) + }); + _ul.find("i:lt(" + Math.floor(options.value) + ")").each(function(){ + $(this).addClass(ICON_RATE_SOLID).removeClass(ICON_HALF_RATE) + }); + //如果设置可选半星,根据分数判断是否有半星 + if(options.half){ + if(parseInt(options.value) !== options.value){ + _ul.children("li:eq(" + Math.floor(options.value) + ")").children("i").addClass(ICON_RATE_HALF).removeClass(ICON_SOLID_RATE) + } + } + }) + + }) + }; + + //事件处理 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + }; + + //核心入口 + rate.render = function(options){ + var inst = new Class(options); + return thisRate.call(inst); + }; + + exports(MOD_NAME, rate); +}) \ No newline at end of file diff --git a/static/layui/modules/slider.js b/static/layui/modules/slider.js new file mode 100644 index 0000000..e449632 --- /dev/null +++ b/static/layui/modules/slider.js @@ -0,0 +1,383 @@ +/** + + @Title: slider 滑块组件 + @License:MIT + + */ + +layui.define('jquery', function(exports){ + "use strict"; + var $ = layui.jquery + + //外部接口 + ,slider = { + config: {} + ,index: layui.slider ? (layui.slider.index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisSlider = function(){ + var that = this + ,options = that.config; + + return { + setValue: function(value, index){ //设置值 + options.value = value; + return that.slide('set', value, index || 0); + } + ,config: options + } + } + + //字符常量 + ,MOD_NAME = 'slider', DISABLED = 'layui-disabled', ELEM_VIEW = 'layui-slider', SLIDER_BAR = 'layui-slider-bar', SLIDER_WRAP = 'layui-slider-wrap', SLIDER_WRAP_BTN = 'layui-slider-wrap-btn', SLIDER_TIPS = 'layui-slider-tips', SLIDER_INPUT = 'layui-slider-input', SLIDER_INPUT_TXT = 'layui-slider-input-txt', SLIDER_INPUT_BTN = 'layui-slider-input-btn', ELEM_HOVER = 'layui-slider-hover' + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++slider.index; + that.config = $.extend({}, that.config, slider.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + type: 'default' //滑块类型,垂直:vertical + ,min: 0 //最小值 + ,max: 100 //最大值,默认100 + ,value: 0 //初始值,默认为0 + ,step: 1 //间隔值 + ,showstep: false //间隔点开启 + ,tips: true //文字提示,开启 + ,input: false //输入框,关闭 + ,range: false //范围选择,与输入框不能同时开启,默认关闭 + ,height: 200 //配合 type:"vertical" 使用,默认200px + ,disabled: false //滑块禁用,默认关闭 + ,theme: '#009688' //主题颜色 + }; + + //滑块渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + //间隔值不能小于 1 + if(options.step < 1) options.step = 1; + + //最大值不能小于最小值 + if(options.max < options.min) options.max = options.min + options.step; + + + + //判断是否开启双滑块 + if(options.range){ + options.value = typeof(options.value) == 'object' ? options.value : [options.min, options.value]; + var minValue = Math.min(options.value[0], options.value[1]) + ,maxValue = Math.max(options.value[0], options.value[1]); + options.value[0] = minValue > options.min ? minValue : options.min; + options.value[1] = maxValue > options.min ? maxValue : options.min; + options.value[0] = options.value[0] > options.max ? options.max : options.value[0]; + options.value[1] = options.value[1] > options.max ? options.max : options.value[1]; + + var scaleFir = Math.floor((options.value[0] - options.min) / (options.max - options.min) * 100) + ,scaleSec = Math.floor((options.value[1] - options.min) / (options.max - options.min) * 100) + ,scale = scaleSec - scaleFir + '%'; + scaleFir = scaleFir + '%'; + scaleSec = scaleSec + '%'; + } else { + //如果初始值是一个数组,则获取数组的最小值 + if(typeof options.value == 'object'){ + options.value = Math.min.apply(null, options.value); + } + + //初始值不能小于最小值且不能大于最大值 + if(options.value < options.min) options.value = options.min; + if(options.value > options.max) options.value = options.max; + + var scale = Math.floor((options.value - options.min) / (options.max - options.min) * 100) + '%'; + }; + + + //如果禁用,颜色为统一的灰色 + var theme = options.disabled ? '#c2c2c2' : options.theme; + + //滑块 + var temp = '
      '+ (options.tips ? '
      ' : '') + + '
      ' + + '
      '+ (options.range ? '
      ' : '') +'
      '; + + var othis = $(options.elem) + ,hasRender = othis.next('.' + ELEM_VIEW); + //生成替代元素 + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + that.elemTemp = $(temp); + + //把数据缓存到滑块上 + if(options.range){ + that.elemTemp.find('.' + SLIDER_WRAP).eq(0).data('value', options.value[0]); + that.elemTemp.find('.' + SLIDER_WRAP).eq(1).data('value', options.value[1]); + }else{ + that.elemTemp.find('.' + SLIDER_WRAP).data('value', options.value); + }; + + //插入替代元素 + othis.html(that.elemTemp); + + //垂直滑块 + if(options.type === 'vertical'){ + that.elemTemp.height(options.height + 'px'); + }; + + //显示间断点 + if(options.showstep){ + var number = (options.max - options.min) / options.step, item = ''; + for(var i = 1; i < number + 1; i++) { + var step = i * 100 / number; + if(step < 100){ + item += '
      ' + } + }; + that.elemTemp.append(item); + }; + + //插入输入框 + if(options.input && !options.range){ + var elemInput = $('
      '); + othis.css("position","relative"); + othis.append(elemInput); + othis.find('.' + SLIDER_INPUT_TXT).children('input').val(options.value); + if(options.type === 'vertical'){ + elemInput.css({ + left: 0 + ,top: -48 + }); + } else { + that.elemTemp.css("margin-right", elemInput.outerWidth() + 15); + } + }; + + //给未禁止的滑块滑动事件 + if(!options.disabled){ + that.slide(); + }else{ + that.elemTemp.addClass(DISABLED); + that.elemTemp.find('.' + SLIDER_WRAP_BTN).addClass(DISABLED); + }; + + //划过滑块显示数值 + that.elemTemp.find('.' + SLIDER_WRAP_BTN).on('mouseover', function(){ + var sliderWidth = options.type === 'vertical' ? options.height : that.elemTemp[0].offsetWidth + ,sliderWrap = that.elemTemp.find('.' + SLIDER_WRAP) + ,tipsLeft = options.type === 'vertical' ? (sliderWidth - $(this).parent()[0].offsetTop - sliderWrap.height()) : $(this).parent()[0].offsetLeft + ,left = tipsLeft / sliderWidth * 100 + ,value = $(this).parent().data('value') + ,tipsTxt = options.setTips ? options.setTips(value) : value; + that.elemTemp.find('.' + SLIDER_TIPS).html(tipsTxt); + if(options.type === 'vertical'){ + that.elemTemp.find('.' + SLIDER_TIPS).css({"bottom":left + '%', "margin-bottom":"20px", "display":"inline-block"}); + }else{ + that.elemTemp.find('.' + SLIDER_TIPS).css({"left":left + '%', "display":"inline-block"}); + }; + }).on('mouseout', function(){ + that.elemTemp.find('.' + SLIDER_TIPS).css("display", "none"); + }); + }; + + //滑块滑动 + Class.prototype.slide = function(setValue, value, i){ + var that = this + ,options = that.config + ,sliderAct = that.elemTemp + ,sliderWidth = function(){ + return options.type === 'vertical' ? options.height : sliderAct[0].offsetWidth + } + ,sliderWrap = sliderAct.find('.' + SLIDER_WRAP) + ,sliderTxt = sliderAct.next('.' + SLIDER_INPUT) + ,inputValue = sliderTxt.children('.' + SLIDER_INPUT_TXT).children('input').val() + ,step = 100 / ((options.max - options.min) / Math.ceil(options.step)) + ,change = function(offsetValue, index){ + if(Math.ceil(offsetValue) * step > 100){ + offsetValue = Math.ceil(offsetValue) * step + }else{ + offsetValue = Math.round(offsetValue) * step + }; + offsetValue = offsetValue > 100 ? 100: offsetValue; + sliderWrap.eq(index).css((options.type === 'vertical' ?'bottom':'left'), offsetValue + '%'); + var firLeft = valueTo(sliderWrap[0].offsetLeft) + ,secLeft = options.range ? valueTo(sliderWrap[1].offsetLeft) : 0; + if(options.type === 'vertical'){ + sliderAct.find('.' + SLIDER_TIPS).css({"bottom":offsetValue + '%', "margin-bottom":"20px"}); + firLeft = valueTo(sliderWidth() - sliderWrap[0].offsetTop - sliderWrap.height()); + secLeft = options.range ? valueTo(sliderWidth() - sliderWrap[1].offsetTop - sliderWrap.height()) : 0; + }else{ + sliderAct.find('.' + SLIDER_TIPS).css("left",offsetValue + '%'); + }; + firLeft = firLeft > 100 ? 100: firLeft; + secLeft = secLeft > 100 ? 100: secLeft; + var minLeft = Math.min(firLeft, secLeft) + ,wrapWidth = Math.abs(firLeft - secLeft); + if(options.type === 'vertical'){ + sliderAct.find('.' + SLIDER_BAR).css({"height":wrapWidth + '%', "bottom":minLeft + '%'}); + }else{ + sliderAct.find('.' + SLIDER_BAR).css({"width":wrapWidth + '%', "left":minLeft + '%'}); + }; + var selfValue = options.min + Math.round((options.max - options.min) * offsetValue / 100); + inputValue = selfValue; + sliderTxt.children('.' + SLIDER_INPUT_TXT).children('input').val(inputValue); + sliderWrap.eq(index).data('value', selfValue); + sliderAct.find('.' + SLIDER_TIPS).html(options.setTips ? options.setTips(selfValue) : selfValue); + + //如果开启范围选择,则返回数组值 + if(options.range){ + var arrValue = [ + sliderWrap.eq(0).data('value') + ,sliderWrap.eq(1).data('value') + ]; + if(arrValue[0] > arrValue[1]) arrValue.reverse(); //如果前面的圆点超过了后面的圆点值,则调换顺序 + } + + //回调 + options.change && options.change(options.range ? arrValue : selfValue); + } + ,valueTo = function(value){ + var oldLeft = value / sliderWidth() * 100 / step + ,left = Math.round(oldLeft) * step; + if(value == sliderWidth()){ + left = Math.ceil(oldLeft) * step; + }; + return left; + } + + //拖拽元素 + ,elemMove = $(['
      sliderWidth())left = sliderWidth(); + var reaLeft = left / sliderWidth() * 100 / step; + change(reaLeft, index); + othis.addClass(ELEM_HOVER); + sliderAct.find('.' + SLIDER_TIPS).show(); + e.preventDefault(); + }; + + var up = function(){ + othis.removeClass(ELEM_HOVER); + sliderAct.find('.' + SLIDER_TIPS).hide(); + }; + + createMoveElem(move, up) + }); + }); + + //点击滑块 + sliderAct.on('click', function(e){ + var main = $('.' + SLIDER_WRAP_BTN); + if(!main.is(event.target) && main.has(event.target).length === 0 && main.length){ + var left = options.type === 'vertical' ? (sliderWidth() - e.clientY + $(this).offset().top):(e.clientX - $(this).offset().left), index; + if(left < 0)left = 0; + if(left > sliderWidth())left = sliderWidth(); + var reaLeft = left / sliderWidth() * 100 / step; + if(options.range){ + if(options.type === 'vertical'){ + index = Math.abs(left - parseInt($(sliderWrap[0]).css('bottom'))) > Math.abs(left - parseInt($(sliderWrap[1]).css('bottom'))) ? 1 : 0; + }else{ + index = Math.abs(left - sliderWrap[0].offsetLeft) > Math.abs(left - sliderWrap[1].offsetLeft) ? 1 : 0; + } + }else{ + index = 0; + }; + change(reaLeft, index); + e.preventDefault(); + } + }); + + //点击加减输入框 + sliderTxt.children('.' + SLIDER_INPUT_BTN).children('i').each(function(index){ + $(this).on('click', function(){ + inputValue = sliderTxt.children('.' + SLIDER_INPUT_TXT).children('input').val(); + if(index == 1){ //减 + inputValue = inputValue - options.step < options.min + ? options.min + : Number(inputValue) - options.step; + }else{ + inputValue = Number(inputValue) + options.step > options.max + ? options.max + : Number(inputValue) + options.step; + }; + var inputScale = (inputValue - options.min) / (options.max - options.min) * 100 / step; + change(inputScale, 0); + }); + }); + + //获取输入框值 + var getInputValue = function(){ + var realValue = this.value; + realValue = isNaN(realValue) ? 0 : realValue; + realValue = realValue < options.min ? options.min : realValue; + realValue = realValue > options.max ? options.max : realValue; + this.value = realValue; + var inputScale = (realValue - options.min) / (options.max - options.min) * 100 / step; + change(inputScale, 0); + }; + sliderTxt.children('.' + SLIDER_INPUT_TXT).children('input').on('keydown', function(e){ + if(e.keyCode === 13){ + e.preventDefault(); + getInputValue.call(this); + } + }).on('change', getInputValue); + }; + + //事件处理 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + }; + + //核心入口 + slider.render = function(options){ + var inst = new Class(options); + return thisSlider.call(inst); + }; + + exports(MOD_NAME, slider); +}) \ No newline at end of file diff --git a/static/layui/modules/table.js b/static/layui/modules/table.js new file mode 100644 index 0000000..5ccd2e3 --- /dev/null +++ b/static/layui/modules/table.js @@ -0,0 +1,2042 @@ + +/*! + * layui.table + * 数据表格组件 + */ + +layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ + "use strict"; + + var $ = layui.$ + ,laytpl = layui.laytpl + ,laypage = layui.laypage + ,layer = layui.layer + ,form = layui.form + ,util = layui.util + ,hint = layui.hint() + ,device = layui.device() + + //外部接口 + ,table = { + config: { + checkName: 'LAY_CHECKED' //是否选中状态的字段名 + ,indexName: 'LAY_TABLE_INDEX' //初始下标索引名,用于恢复排序 + } //全局配置项 + ,cache: {} //数据缓存 + ,index: layui.table ? (layui.table.index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisTable = function(){ + var that = this + ,options = that.config + ,id = options.id || options.index; + + if(id){ + thisTable.that[id] = that; //记录当前实例对象 + thisTable.config[id] = options; //记录当前实例配置项 + } + + return { + config: options + ,reload: function(options, deep){ + that.reload.call(that, options, deep); + } + ,setColsWidth: function(){ + that.setColsWidth.call(that); + } + ,resize: function(){ //重置表格尺寸/结构 + that.resize.call(that); + } + } + } + + //获取当前实例配置项 + ,getThisTableConfig = function(id){ + var config = thisTable.config[id]; + if(!config) hint.error(id ? ('The table instance with ID \''+ id +'\' not found') : 'ID argument required'); + return config || null; + } + + //解析自定义模板数据 + ,parseTempData = function(item3, content, tplData, text){ //表头数据、原始内容、表体数据、是否只返回文本 + var options = this.config || {}; + + //是否防 xss + if(options.escape) content = util.escape(content); + + //获取内容 + var str = item3.templet ? function(){ + return typeof item3.templet === 'function' + ? item3.templet(tplData) + : laytpl($(item3.templet).html() || String(content)).render(tplData) + }() : content; + return text ? $('
      '+ str +'
      ').text() : str; + } + + //字符常量 + ,MOD_NAME = 'table', ELEM = '.layui-table', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled', NONE = 'layui-none' + + ,ELEM_VIEW = 'layui-table-view', ELEM_TOOL = '.layui-table-tool', ELEM_BOX = '.layui-table-box', ELEM_INIT = '.layui-table-init', ELEM_HEADER = '.layui-table-header', ELEM_BODY = '.layui-table-body', ELEM_MAIN = '.layui-table-main', ELEM_FIXED = '.layui-table-fixed', ELEM_FIXL = '.layui-table-fixed-l', ELEM_FIXR = '.layui-table-fixed-r', ELEM_TOTAL = '.layui-table-total', ELEM_PAGE = '.layui-table-page', ELEM_SORT = '.layui-table-sort', ELEM_EDIT = 'layui-table-edit', ELEM_HOVER = 'layui-table-hover' + + //thead区域模板 + ,TPL_HEADER = function(options){ + var rowCols = '{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}'; + + options = options || {}; + return ['
      ' + ,'' + ,'{{# layui.each(d.data.cols, function(i1, item1){ }}' + ,'' + ,'{{# layui.each(item1, function(i2, item2){ }}' + ,'{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}' + ,'{{# if(item2.fixed === "right"){ right = true; } }}' + ,function(){ + if(options.fixed && options.fixed !== 'right'){ + return '{{# if(item2.fixed && item2.fixed !== "right"){ }}'; + } + if(options.fixed === 'right'){ + return '{{# if(item2.fixed === "right"){ }}'; + } + return ''; + }() + ,'{{# var isSort = !(item2.colGroup) && item2.sort; }}' + ,'' + ,(options.fixed ? '{{# }; }}' : '') + ,'{{# }); }}' + ,'' + ,'{{# }); }}' + ,'' + ,'
      ' + ,'
      ' + ,'{{# if(item2.type === "checkbox"){ }}' //复选框 + ,'' + ,'{{# } else { }}' + ,'{{item2.title||""}}' + ,'{{# if(isSort){ }}' + ,'' + ,'{{# } }}' + ,'{{# } }}' + ,'
      ' + ,'
      '].join(''); + } + + //tbody区域模板 + ,TPL_BODY = ['' + ,'' + ,'
      '].join('') + + //主模板 + ,TPL_MAIN = ['
      ' + + ,'{{# if(d.data.toolbar){ }}' + ,'
      ' + ,'
      ' + ,'
      ' + ,'
      ' + ,'{{# } }}' + + ,'
      ' + ,'{{# if(d.data.loading){ }}' + ,'
      ' + ,'' + ,'
      ' + ,'{{# } }}' + + ,'{{# var left, right; }}' + ,'
      ' + ,TPL_HEADER() + ,'
      ' + ,'
      ' + ,TPL_BODY + ,'
      ' + + ,'{{# if(left){ }}' + ,'
      ' + ,'
      ' + ,TPL_HEADER({fixed: true}) + ,'
      ' + ,'
      ' + ,TPL_BODY + ,'
      ' + ,'
      ' + ,'{{# }; }}' + + ,'{{# if(right){ }}' + ,'
      ' + ,'
      ' + ,TPL_HEADER({fixed: 'right'}) + ,'
      ' + ,'
      ' + ,'
      ' + ,TPL_BODY + ,'
      ' + ,'
      ' + ,'{{# }; }}' + ,'
      ' + + ,'{{# if(d.data.totalRow){ }}' + ,'
      ' + ,'' + ,'' + , '
      ' + ,'
      ' + ,'{{# } }}' + + ,'{{# if(d.data.page){ }}' + ,'
      ' + ,'
      ' + ,'
      ' + ,'{{# } }}' + + ,'' + ,'
      '].join('') + + ,_WIN = $(window) + ,_DOC = $(document) + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++table.index; + that.config = $.extend({}, that.config, table.config, options); + that.render(); + }; + + //初始默认配置 + Class.prototype.config = { + limit: 10 //每页显示的数量 + ,loading: true //请求数据时,是否显示 loading + ,cellMinWidth: 60 //所有单元格默认最小宽度 + ,defaultToolbar: ['filter', 'exports', 'print'] //工具栏右侧图标 + ,autoSort: true //是否前端自动排序。如果否,则需自主排序(通常为服务端处理好排序) + ,text: { + none: '无数据' + } + }; + + //表格渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + options.elem = $(options.elem); + options.where = options.where || {}; + options.id = options.id || options.elem.attr('id') || that.index; + + //请求参数的自定义格式 + options.request = $.extend({ + pageName: 'page' + ,limitName: 'limit' + }, options.request) + + //响应数据的自定义格式 + options.response = $.extend({ + statusName: 'code' //规定数据状态的字段名称 + ,statusCode: 0 //规定成功的状态码 + ,msgName: 'msg' //规定状态信息的字段名称 + ,dataName: 'data' //规定数据总数的字段名称 + ,totalRowName: 'totalRow' //规定数据统计的字段名称 + ,countName: 'count' + }, options.response); + + //如果 page 传入 laypage 对象 + if(typeof options.page === 'object'){ + options.limit = options.page.limit || options.limit; + options.limits = options.page.limits || options.limits; + that.page = options.page.curr = options.page.curr || 1; + delete options.page.elem; + delete options.page.jump; + } + + if(!options.elem[0]) return that; + + //高度铺满:full-差距值 + if(options.height && /^full-\d+$/.test(options.height)){ + that.fullHeightGap = options.height.split('-')[1]; + options.height = _WIN.height() - that.fullHeightGap; + } + + //初始化一些参数 + that.setInit(); + + //开始插入替代元素 + var othis = options.elem + ,hasRender = othis.next('.' + ELEM_VIEW) + + //主容器 + ,reElem = that.elem = $(laytpl(TPL_MAIN).render({ + VIEW_CLASS: ELEM_VIEW + ,data: options + ,index: that.index //索引 + })); + + options.index = that.index; + that.key = options.id || options.index; + + //生成替代元素 + hasRender[0] && hasRender.remove(); //如果已经渲染,则Rerender + othis.after(reElem); + + //各级容器 + that.layTool = reElem.find(ELEM_TOOL); + that.layBox = reElem.find(ELEM_BOX); + that.layHeader = reElem.find(ELEM_HEADER); + that.layMain = reElem.find(ELEM_MAIN); + that.layBody = reElem.find(ELEM_BODY); + that.layFixed = reElem.find(ELEM_FIXED); + that.layFixLeft = reElem.find(ELEM_FIXL); + that.layFixRight = reElem.find(ELEM_FIXR); + that.layTotal = reElem.find(ELEM_TOTAL); + that.layPage = reElem.find(ELEM_PAGE); + + //初始化工具栏 + that.renderToolbar(); + + //让表格平铺 + that.fullSize(); + + //如果多级表头,则填补表头高度 + if(options.cols.length > 1){ + //补全高度 + var th = that.layFixed.find(ELEM_HEADER).find('th'); + th.height(that.layHeader.height() - 1 - parseFloat(th.css('padding-top')) - parseFloat(th.css('padding-bottom'))); + } + + that.pullData(that.page); //请求数据 + that.events(); //事件 + }; + + //根据列类型,定制化参数 + Class.prototype.initOpts = function(item){ + var that = this + ,options = that.config + ,initWidth = { + checkbox: 48 + ,radio: 48 + ,space: 15 + ,numbers: 40 + }; + + //让 type 参数兼容旧版本 + if(item.checkbox) item.type = "checkbox"; + if(item.space) item.type = "space"; + if(!item.type) item.type = "normal"; + + if(item.type !== "normal"){ + item.unresize = true; + item.width = item.width || initWidth[item.type]; + } + }; + + //初始化一些参数 + Class.prototype.setInit = function(type){ + var that = this + ,options = that.config; + + options.clientWidth = options.width || function(){ //获取容器宽度 + //如果父元素宽度为0(一般为隐藏元素),则继续查找上层元素,直到找到真实宽度为止 + var getWidth = function(parent){ + var width, isNone; + parent = parent || options.elem.parent() + width = parent.width(); + try { + isNone = parent.css('display') === 'none'; + } catch(e){} + if(parent[0] && (!width || isNone)) return getWidth(parent.parent()); + return width; + }; + return getWidth(); + }(); + + if(type === 'width') return options.clientWidth; + + //初始化列参数 + layui.each(options.cols, function(i1, item1){ + layui.each(item1, function(i2, item2){ + + //如果列参数为空,则移除 + if(!item2){ + item1.splice(i2, 1); + return; + } + + item2.key = i1 + '-' + i2; + item2.hide = item2.hide || false; + + //设置列的父列索引 + //如果是组合列,则捕获对应的子列 + if(item2.colGroup || item2.colspan > 1){ + var childIndex = 0; + layui.each(options.cols[i1 + 1], function(i22, item22){ + //如果子列已经被标注为{HAS_PARENT},或者子列累计 colspan 数等于父列定义的 colspan,则跳出当前子列循环 + if(item22.HAS_PARENT || (childIndex > 1 && childIndex == item2.colspan)) return; + + item22.HAS_PARENT = true; + item22.parentKey = i1 + '-' + i2; + + childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1); + }); + item2.colGroup = true; //标注是组合列 + } + + //根据列类型,定制化参数 + that.initOpts(item2); + }); + }); + + }; + + //初始工具栏 + Class.prototype.renderToolbar = function(){ + var that = this + ,options = that.config + + //添加工具栏左侧模板 + var leftDefaultTemp = [ + '
      ' + ,'
      ' + ,'
      ' + ].join('') + ,elemToolTemp = that.layTool.find('.layui-table-tool-temp'); + + if(options.toolbar === 'default'){ + elemToolTemp.html(leftDefaultTemp); + } else if(typeof options.toolbar === 'string'){ + var toolbarHtml = $(options.toolbar).html() || ''; + toolbarHtml && elemToolTemp.html( + laytpl(toolbarHtml).render(options) + ); + } + + //添加工具栏右侧面板 + var layout = { + filter: { + title: '筛选列' + ,layEvent: 'LAYTABLE_COLS' + ,icon: 'layui-icon-cols' + } + ,exports: { + title: '导出' + ,layEvent: 'LAYTABLE_EXPORT' + ,icon: 'layui-icon-export' + } + ,print: { + title: '打印' + ,layEvent: 'LAYTABLE_PRINT' + ,icon: 'layui-icon-print' + } + }, iconElem = []; + + if(typeof options.defaultToolbar === 'object'){ + layui.each(options.defaultToolbar, function(i, item){ + var thisItem = typeof item === 'string' ? layout[item] : item; + if(thisItem){ + iconElem.push('
      ' + +'' + +'
      '); + } + }); + } + that.layTool.find('.layui-table-tool-self').html(iconElem.join('')); + } + + //同步表头父列的相关值 + Class.prototype.setParentCol = function(hide, parentKey){ + var that = this + ,options = that.config + + ,parentTh = that.layHeader.find('th[data-key="'+ options.index +'-'+ parentKey +'"]') //获取父列元素 + ,parentColspan = parseInt(parentTh.attr('colspan')) || 0; + + if(parentTh[0]){ + var arrParentKey = parentKey.split('-') + ,getThisCol = options.cols[arrParentKey[0]][arrParentKey[1]]; + + hide ? parentColspan-- : parentColspan++; + + parentTh.attr('colspan', parentColspan); + parentTh[parentColspan < 1 ? 'addClass' : 'removeClass'](HIDE); + + getThisCol.colspan = parentColspan; //同步 colspan 参数 + getThisCol.hide = parentColspan < 1; //同步 hide 参数 + + //递归,继续往上查询是否有父列 + var nextParentKey = parentTh.data('parentkey'); + nextParentKey && that.setParentCol(hide, nextParentKey); + } + }; + + //多级表头补丁 + Class.prototype.setColsPatch = function(){ + var that = this + ,options = that.config + + //同步表头父列的相关值 + layui.each(options.cols, function(i1, item1){ + layui.each(item1, function(i2, item2){ + if(item2.hide){ + that.setParentCol(item2.hide, item2.parentKey); + } + }); + }); + }; + + //动态分配列宽 + Class.prototype.setColsWidth = function(){ + var that = this + ,options = that.config + ,colNums = 0 //列个数 + ,autoColNums = 0 //自动列宽的列个数 + ,autoWidth = 0 //自动列分配的宽度 + ,countWidth = 0 //所有列总宽度和 + ,cntrWidth = that.setInit('width'); + + //统计列个数 + that.eachCols(function(i, item){ + item.hide || colNums++; + }); + + //减去边框差和滚动条宽 + cntrWidth = cntrWidth - function(){ + return (options.skin === 'line' || options.skin === 'nob') ? 2 : colNums + 1; + }() - that.getScrollWidth(that.layMain[0]) - 1; + + //计算自动分配的宽度 + var getAutoWidth = function(back){ + //遍历所有列 + layui.each(options.cols, function(i1, item1){ + layui.each(item1, function(i2, item2){ + var width = 0 + ,minWidth = item2.minWidth || options.cellMinWidth; //最小宽度 + + if(!item2){ + item1.splice(i2, 1); + return; + } + + if(item2.colGroup || item2.hide) return; + + if(!back){ + width = item2.width || 0; + if(/\d+%$/.test(width)){ //列宽为百分比 + width = Math.floor((parseFloat(width) / 100) * cntrWidth); + width < minWidth && (width = minWidth); + } else if(!width){ //列宽未填写 + item2.width = width = 0; + autoColNums++; + } + } else if(autoWidth && autoWidth < minWidth){ + autoColNums--; + width = minWidth; + } + + if(item2.hide) width = 0; + countWidth = countWidth + width; + }); + }); + + //如果未填充满,则将剩余宽度平分 + (cntrWidth > countWidth && autoColNums) && ( + autoWidth = (cntrWidth - countWidth) / autoColNums + ); + } + + getAutoWidth(); + getAutoWidth(true); //重新检测分配的宽度是否低于最小列宽 + + //记录自动列数 + that.autoColNums = autoColNums; + + //设置列宽 + that.eachCols(function(i3, item3){ + var minWidth = item3.minWidth || options.cellMinWidth; + if(item3.colGroup || item3.hide) return; + + //给位分配宽的列平均分配宽 + if(item3.width === 0){ + that.getCssRule(options.index +'-'+ item3.key, function(item){ + item.style.width = Math.floor(autoWidth >= minWidth ? autoWidth : minWidth) + 'px'; + }); + } + + //给设定百分比的列分配列宽 + else if(/\d+%$/.test(item3.width)){ + that.getCssRule(options.index +'-'+ item3.key, function(item){ + item.style.width = Math.floor((parseFloat(item3.width) / 100) * cntrWidth) + 'px'; + }); + } + }); + + //填补 Math.floor 造成的数差 + var patchNums = that.layMain.width() - that.getScrollWidth(that.layMain[0]) + - that.layMain.children('table').outerWidth(); + + if(that.autoColNums && patchNums >= -colNums && patchNums <= colNums){ + var getEndTh = function(th){ + var field; + th = th || that.layHeader.eq(0).find('thead th:last-child') + field = th.data('field'); + if(!field && th.prev()[0]){ + return getEndTh(th.prev()) + } + return th + } + ,th = getEndTh() + ,key = th.data('key'); + + that.getCssRule(key, function(item){ + var width = item.style.width || th.outerWidth(); + item.style.width = (parseFloat(width) + patchNums) + 'px'; + + //二次校验,如果仍然出现横向滚动条(通常是 1px 的误差导致) + if(that.layMain.height() - that.layMain.prop('clientHeight') > 0){ + item.style.width = (parseFloat(item.style.width) - 1) + 'px'; + } + }); + } + + that.loading(!0); + }; + + //重置表格尺寸/结构 + Class.prototype.resize = function(){ + var that = this; + that.fullSize(); //让表格铺满 + that.setColsWidth(); //自适应列宽 + that.scrollPatch(); //滚动条补丁 + }; + + //表格重载 + Class.prototype.reload = function(options, deep){ + var that = this; + + options = options || {}; + delete that.haveInit; + + //防止数组深度合并 + layui.each(options, function(key, item){ + if(layui._typeof(item) === 'array') delete that.config[key]; + }); + + //对参数进行深度或浅扩展 + that.config = $.extend(deep, {}, that.config, options); + + //执行渲染 + that.render(); + }; + + //异常提示 + Class.prototype.errorView = function(html){ + var that = this + ,elemNone = that.layMain.find('.'+ NONE) + ,layNone = $('
      '+ (html || 'Error') +'
      '); + + if(elemNone[0]){ + that.layNone.remove(); + elemNone.remove(); + } + + that.layFixed.addClass(HIDE); + that.layMain.find('tbody').html(''); + + that.layMain.append(that.layNone = layNone); + + table.cache[that.key] = []; //格式化缓存数据 + }; + + //页码 + Class.prototype.page = 1; + + //获得数据 + Class.prototype.pullData = function(curr){ + var that = this + ,options = that.config + ,request = options.request + ,response = options.response + ,sort = function(){ + if(typeof options.initSort === 'object'){ + that.sort(options.initSort.field, options.initSort.type); + } + }; + + that.startTime = new Date().getTime(); //渲染开始时间 + + if(options.url){ //Ajax请求 + var params = {}; + params[request.pageName] = curr; + params[request.limitName] = options.limit; + + //参数 + var data = $.extend(params, options.where); + if(options.contentType && options.contentType.indexOf("application/json") == 0){ //提交 json 格式 + data = JSON.stringify(data); + } + + that.loading(); + + $.ajax({ + type: options.method || 'get' + ,url: options.url + ,contentType: options.contentType + ,data: data + ,dataType: 'json' + ,headers: options.headers || {} + ,success: function(res){ + //如果有数据解析的回调,则获得其返回的数据 + if(typeof options.parseData === 'function'){ + res = options.parseData(res) || res; + } + //检查数据格式是否符合规范 + if(res[response.statusName] != response.statusCode){ + that.renderForm(); + that.errorView( + res[response.msgName] || + ('返回的数据不符合规范,正确的成功状态码应为:"'+ response.statusName +'": '+ response.statusCode) + ); + } else { + that.renderData(res, curr, res[response.countName]), sort(); + options.time = (new Date().getTime() - that.startTime) + ' ms'; //耗时(接口请求+视图渲染) + } + that.setColsWidth(); + typeof options.done === 'function' && options.done(res, curr, res[response.countName]); + } + ,error: function(e, msg){ + that.errorView('请求异常,错误提示:'+ msg); + + that.renderForm(); + that.setColsWidth(); + + typeof options.error === 'function' && options.error(e, msg); + } + }); + } else if(layui._typeof(options.data) === 'array'){ //已知数据 + var res = {} + ,startLimit = curr*options.limit - options.limit + + res[response.dataName] = options.data.concat().splice(startLimit, options.limit); + res[response.countName] = options.data.length; + + //记录合计行数据 + if(typeof options.totalRow === 'object'){ + res[response.totalRowName] = $.extend({}, options.totalRow); + } + + that.renderData(res, curr, res[response.countName]), sort(); + that.setColsWidth(); + typeof options.done === 'function' && options.done(res, curr, res[response.countName]); + } + }; + + //遍历表头 + Class.prototype.eachCols = function(callback){ + var that = this; + table.eachCols(null, callback, that.config.cols); + return that; + }; + + //数据渲染 + Class.prototype.renderData = function(res, curr, count, sort){ + var that = this + ,options = that.config + ,data = res[options.response.dataName] || [] //列表数据 + ,totalRowData = res[options.response.totalRowName] //合计行数据 + ,trs = [] + ,trs_fixed = [] + ,trs_fixed_r = [] + + //渲染视图 + ,render = function(){ //后续性能提升的重点 + var thisCheckedRowIndex; + if(!sort && that.sortKey){ + return that.sort(that.sortKey.field, that.sortKey.sort, true); + } + layui.each(data, function(i1, item1){ + var tds = [], tds_fixed = [], tds_fixed_r = [] + ,numbers = i1 + options.limit*(curr - 1) + 1; //序号 + + //若数据项为空数组,则不往下执行(因为删除数据时,会将原有数据设置为 []) + if(layui._typeof(item1) === 'array' && item1.length === 0) return; + + //记录下标索引,用于恢复排序 + if(!sort){ + item1[table.config.indexName] = i1; + } + + //遍历表头 + that.eachCols(function(i3, item3){ + var field = item3.field || i3 + ,key = options.index + '-' + item3.key + ,content = item1[field]; + + if(content === undefined || content === null) content = ''; + if(item3.colGroup) return; + + //td内容 + var td = ['' + ,'
      ' + function(){ + var tplData = $.extend(true, { + LAY_INDEX: numbers + ,LAY_COL: item3 + }, item1) + ,checkName = table.config.checkName; + + //渲染不同风格的列 + switch(item3.type){ + case 'checkbox': + return ''; + break; + case 'radio': + if(tplData[checkName]){ + thisCheckedRowIndex = i1; + } + return ''; + break; + case 'numbers': + return numbers; + break; + }; + + //解析工具列模板 + if(item3.toolbar){ + return laytpl($(item3.toolbar).html()||'').render(tplData); + } + return parseTempData.call(that, item3, content, tplData); + }() + ,'
      '].join(''); + + tds.push(td); + if(item3.fixed && item3.fixed !== 'right') tds_fixed.push(td); + if(item3.fixed === 'right') tds_fixed_r.push(td); + }); + + trs.push(''+ tds.join('') + ''); + trs_fixed.push(''+ tds_fixed.join('') + ''); + trs_fixed_r.push(''+ tds_fixed_r.join('') + ''); + }); + + that.layBody.scrollTop(0); + that.layMain.find('.'+ NONE).remove(); + that.layMain.find('tbody').html(trs.join('')); + that.layFixLeft.find('tbody').html(trs_fixed.join('')); + that.layFixRight.find('tbody').html(trs_fixed_r.join('')); + + that.renderForm(); + typeof thisCheckedRowIndex === 'number' && that.setThisRowChecked(thisCheckedRowIndex); + that.syncCheckAll(); + + //滚动条补丁 + that.haveInit ? that.scrollPatch() : setTimeout(function(){ + that.scrollPatch(); + }, 50); + that.haveInit = true; + + layer.close(that.tipsIndex); + + //同步表头父列的相关值 + options.HAS_SET_COLS_PATCH || that.setColsPatch(); + options.HAS_SET_COLS_PATCH = true; + }; + + table.cache[that.key] = data; //记录数据 + + //显示隐藏分页栏 + that.layPage[(count == 0 || (data.length === 0 && curr == 1)) ? 'addClass' : 'removeClass'](HIDE); + + //如果无数据 + if(data.length === 0){ + that.renderForm(); + return that.errorView(options.text.none); + } else { + that.layFixed.removeClass(HIDE); + } + + //如果执行初始排序 + if(sort){ + return render(); + } + + //正常初始化数据渲染 + render(); //渲染数据 + that.renderTotal(data, totalRowData); //数据合计 + + //同步分页状态 + if(options.page){ + options.page = $.extend({ + elem: 'layui-table-page' + options.index + ,count: count + ,limit: options.limit + ,limits: options.limits || [10,20,30,40,50,60,70,80,90] + ,groups: 3 + ,layout: ['prev', 'page', 'next', 'skip', 'count', 'limit'] + ,prev: '' + ,next: '' + ,jump: function(obj, first){ + if(!first){ + //分页本身并非需要做以下更新,下面参数的同步,主要是因为其它处理统一用到了它们 + //而并非用的是 options.page 中的参数(以确保分页未开启的情况仍能正常使用) + that.page = obj.curr; //更新页码 + options.limit = obj.limit; //更新每页条数 + + that.pullData(obj.curr); + } + } + }, options.page); + options.page.count = count; //更新总条数 + laypage.render(options.page); + } + }; + + //数据合计行 + Class.prototype.renderTotal = function(data, totalRowData){ + var that = this + ,options = that.config + ,totalNums = {}; + + if(!options.totalRow) return; + + layui.each(data, function(i1, item1){ + //若数据项为空数组,则不往下执行(因为删除数据时,会将原有数据设置为 []) + if(layui._typeof(item1) === 'array' && item1.length === 0) return; + + that.eachCols(function(i3, item3){ + var field = item3.field || i3 + ,content = item1[field]; + + if(item3.totalRow){ + totalNums[field] = (totalNums[field] || 0) + (parseFloat(content) || 0); + } + }); + }); + + that.dataTotal = {}; + + var tds = []; + that.eachCols(function(i3, item3){ + var field = item3.field || i3; + + //td 内容 + var content = function(){ + var text = item3.totalRowText || '' + ,thisTotalNum = parseFloat(totalNums[field]).toFixed(2) + ,tplData = {} + ,getContent; + + tplData[field] = thisTotalNum; + + //获取自动计算的合并内容 + getContent = item3.totalRow ? (parseTempData.call(that, item3, thisTotalNum, tplData) || text) : text; + + //如果直接传入了合计行数据,则不输出自动计算的结果 + return totalRowData ? (totalRowData[item3.field] || getContent) : getContent; + }() + ,td = ['' + ,'
      ' + function(){ + var totalRow = item3.totalRow || options.totalRow; + //如果 totalRow 参数为字符类型,则解析为自定义模版 + if(typeof totalRow === 'string'){ + return laytpl(totalRow).render($.extend({ + TOTAL_NUMS: content + }, item3)) + } + return content; + }() + ,'
      '].join(''); + + item3.field && (that.dataTotal[field] = content); + tds.push(td); + }); + + that.layTotal.find('tbody').html('' + tds.join('') + ''); + }; + + //找到对应的列元素 + Class.prototype.getColElem = function(parent, key){ + var that = this + ,options = that.config; + return parent.eq(0).find('.laytable-cell-'+ (options.index + '-' + key) + ':eq(0)'); + }; + + //渲染表单 + Class.prototype.renderForm = function(type){ + form.render(type, 'LAY-table-'+ this.index); + }; + + //标记当前行选中状态 + Class.prototype.setThisRowChecked = function(index){ + var that = this + ,options = that.config + ,ELEM_CLICK = 'layui-table-click' + ,tr = that.layBody.find('tr[data-index="'+ index +'"]'); + + tr.addClass(ELEM_CLICK).siblings('tr').removeClass(ELEM_CLICK); + }; + + //数据排序 + Class.prototype.sort = function(th, type, pull, formEvent){ + var that = this + ,field + ,res = {} + ,options = that.config + ,filter = options.elem.attr('lay-filter') + ,data = table.cache[that.key], thisData; + + //字段匹配 + if(typeof th === 'string'){ + field = th; + that.layHeader.find('th').each(function(i, item){ + var othis = $(this) + ,_field = othis.data('field'); + if(_field === th){ + th = othis; + field = _field; + return false; + } + }); + } + + try { + var field = field || th.data('field') + ,key = th.data('key'); + + //如果欲执行的排序已在状态中,则不执行渲染 + if(that.sortKey && !pull){ + if(field === that.sortKey.field && type === that.sortKey.sort){ + return; + } + } + + var elemSort = that.layHeader.find('th .laytable-cell-'+ key).find(ELEM_SORT); + that.layHeader.find('th').find(ELEM_SORT).removeAttr('lay-sort'); //清除其它标题排序状态 + elemSort.attr('lay-sort', type || null); + that.layFixed.find('th') + } catch(e){ + hint.error('Table modules: sort field \''+ field +'\' not matched'); + } + + //记录排序索引和类型 + that.sortKey = { + field: field + ,sort: type + }; + + //默认为前端自动排序。如果否,则需自主排序(通常为服务端处理好排序) + if(options.autoSort){ + if(type === 'asc'){ //升序 + thisData = layui.sort(data, field); + } else if(type === 'desc'){ //降序 + thisData = layui.sort(data, field, true); + } else { //清除排序 + thisData = layui.sort(data, table.config.indexName); + delete that.sortKey; + } + } + + res[options.response.dataName] = thisData || data; + that.renderData(res, that.page, that.count, true); + + if(formEvent){ + layui.event.call(th, MOD_NAME, 'sort('+ filter +')', { + field: field + ,type: type + }); + } + }; + + //请求loading + Class.prototype.loading = function(hide){ + var that = this + ,options = that.config; + if(options.loading){ + if(hide){ + that.layInit && that.layInit.remove(); + delete that.layInit; + that.layBox.find(ELEM_INIT).remove(); + } else { + that.layInit = $(['
      ' + ,'' + ,'
      '].join('')); + that.layBox.append(that.layInit); + } + } + }; + + //同步选中值状态 + Class.prototype.setCheckData = function(index, checked){ + var that = this + ,options = that.config + ,thisData = table.cache[that.key]; + if(!thisData[index]) return; + if(layui._typeof(thisData[index]) === 'array') return; + thisData[index][options.checkName] = checked; + }; + + //同步全选按钮状态 + Class.prototype.syncCheckAll = function(){ + var that = this + ,options = that.config + ,checkAllElem = that.layHeader.find('input[name="layTableCheckbox"]') + ,syncColsCheck = function(checked){ + that.eachCols(function(i, item){ + if(item.type === 'checkbox'){ + item[options.checkName] = checked; + } + }); + return checked; + }; + + if(!checkAllElem[0]) return; + + if(table.checkStatus(that.key).isAll){ + if(!checkAllElem[0].checked){ + checkAllElem.prop('checked', true); + that.renderForm('checkbox'); + } + syncColsCheck(true); + } else { + if(checkAllElem[0].checked){ + checkAllElem.prop('checked', false); + that.renderForm('checkbox'); + } + syncColsCheck(false); + } + }; + + //获取cssRule + Class.prototype.getCssRule = function(key, callback){ + var that = this + ,style = that.elem.find('style')[0] + ,sheet = style.sheet || style.styleSheet || {} + ,rules = sheet.cssRules || sheet.rules; + layui.each(rules, function(i, item){ + if(item.selectorText === ('.laytable-cell-'+ key)){ + return callback(item), true; + } + }); + }; + + //让表格铺满 + Class.prototype.fullSize = function(){ + var that = this + ,options = that.config + ,height = options.height, bodyHeight; + + if(that.fullHeightGap){ + height = _WIN.height() - that.fullHeightGap; + if(height < 135) height = 135; + that.elem.css('height', height); + } + + if(!height) return; + + //减去列头区域的高度 + bodyHeight = parseFloat(height) - (that.layHeader.outerHeight() || 38); //此处的数字常量是为了防止容器处在隐藏区域无法获得高度的问题,暂时只对默认尺寸的表格做支持。 + + //减去工具栏的高度 + if(options.toolbar){ + bodyHeight = bodyHeight - (that.layTool.outerHeight() || 50); + } + + //减去统计朗的高度 + if(options.totalRow){ + bodyHeight = bodyHeight - (that.layTotal.outerHeight() || 40); + } + + //减去分页栏的高度 + if(options.page){ + bodyHeight = bodyHeight - (that.layPage.outerHeight() || 41); + } + + that.layMain.css('height', bodyHeight - 2); + }; + + //获取滚动条宽度 + Class.prototype.getScrollWidth = function(elem){ + var width = 0; + if(elem){ + width = elem.offsetWidth - elem.clientWidth; + } else { + elem = document.createElement('div'); + elem.style.width = '100px'; + elem.style.height = '100px'; + elem.style.overflowY = 'scroll'; + + document.body.appendChild(elem); + width = elem.offsetWidth - elem.clientWidth; + document.body.removeChild(elem); + } + return width; + }; + + //滚动条补丁 + Class.prototype.scrollPatch = function(){ + var that = this + ,layMainTable = that.layMain.children('table') + ,scollWidth = that.layMain.width() - that.layMain.prop('clientWidth') //纵向滚动条宽度 + ,scollHeight = that.layMain.height() - that.layMain.prop('clientHeight') //横向滚动条高度 + ,getScrollWidth = that.getScrollWidth(that.layMain[0]) //获取主容器滚动条宽度,如果有的话 + ,outWidth = layMainTable.outerWidth() - that.layMain.width() //表格内容器的超出宽度 + + //添加补丁 + ,addPatch = function(elem){ + if(scollWidth && scollHeight){ + elem = elem.eq(0); + if(!elem.find('.layui-table-patch')[0]){ + var patchElem = $('
      '); //补丁元素 + patchElem.find('div').css({ + width: scollWidth + }); + elem.find('tr').append(patchElem); + } + } else { + elem.find('.layui-table-patch').remove(); + } + } + + addPatch(that.layHeader); + addPatch(that.layTotal); + + //固定列区域高度 + var mainHeight = that.layMain.height() + ,fixHeight = mainHeight - scollHeight; + that.layFixed.find(ELEM_BODY).css('height', layMainTable.height() >= fixHeight ? fixHeight : 'auto'); + + //表格宽度小于容器宽度时,隐藏固定列 + that.layFixRight[outWidth > 0 ? 'removeClass' : 'addClass'](HIDE); + + //操作栏 + that.layFixRight.css('right', scollWidth - 1); + }; + + //事件处理 + Class.prototype.events = function(){ + var that = this + ,options = that.config + ,_BODY = $('body') + ,dict = {} + ,th = that.layHeader.find('th') + ,resizing + ,ELEM_CELL = '.layui-table-cell' + ,filter = options.elem.attr('lay-filter'); + + //工具栏操作事件 + that.layTool.on('click', '*[lay-event]', function(e){ + var othis = $(this) + ,events = othis.attr('lay-event') + ,openPanel = function(sets){ + var list = $(sets.list) + ,panel = $('
        '); + + panel.html(list); + + //限制最大高度 + if(options.height){ + panel.css('max-height', options.height - (that.layTool.outerHeight() || 50)); + } + + //插入元素 + othis.find('.layui-table-tool-panel')[0] || othis.append(panel); + that.renderForm(); + + panel.on('click', function(e){ + layui.stope(e); + }); + + sets.done && sets.done(panel, list) + }; + + layui.stope(e); + _DOC.trigger('table.tool.panel.remove'); + layer.close(that.tipsIndex); + + switch(events){ + case 'LAYTABLE_COLS': //筛选列 + openPanel({ + list: function(){ + var lis = []; + that.eachCols(function(i, item){ + if(item.field && item.type == 'normal'){ + lis.push('
      • '); + } + }); + return lis.join(''); + }() + ,done: function(){ + form.on('checkbox(LAY_TABLE_TOOL_COLS)', function(obj){ + var othis = $(obj.elem) + ,checked = this.checked + ,key = othis.data('key') + ,parentKey = othis.data('parentkey'); + + layui.each(options.cols, function(i1, item1){ + layui.each(item1, function(i2, item2){ + if(i1+ '-'+ i2 === key){ + var hide = item2.hide; + + //同步勾选列的 hide 值和隐藏样式 + item2.hide = !checked; + that.elem.find('*[data-key="'+ options.index +'-'+ key +'"]') + [checked ? 'removeClass' : 'addClass'](HIDE); + + //根据列的显示隐藏,同步多级表头的父级相关属性值 + if(hide != item2.hide){ + that.setParentCol(!checked, parentKey); + } + + //重新适配尺寸 + that.resize(); + } + }); + }); + }); + } + }); + break; + case 'LAYTABLE_EXPORT': //导出 + if(device.ie){ + layer.tips('导出功能不支持 IE,请用 Chrome 等高级浏览器导出', this, { + tips: 3 + }) + } else { + openPanel({ + list: function(){ + return [ + '
      • 导出到 Csv 文件
      • ' + ,'
      • 导出到 Excel 文件
      • ' + ].join('') + }() + ,done: function(panel, list){ + list.on('click', function(){ + var type = $(this).data('type') + table.exportFile.call(that, options.id, null, type); + }); + } + }); + } + break; + case 'LAYTABLE_PRINT': //打印 + var printWin = window.open('打印窗口', '_blank') + ,style = [''].join('') + ,html = $(that.layHeader.html()); //输出表头 + + html.append(that.layMain.find('table').html()); //输出表体 + html.append(that.layTotal.find('table').html()) //输出合计行 + + html.find('th.layui-table-patch').remove(); //移除补丁 + html.find('.layui-table-col-special').remove(); //移除特殊列 + + printWin.document.write(style + html.prop('outerHTML')); + printWin.document.close(); + printWin.print(); + printWin.close(); + break; + } + + layui.event.call(this, MOD_NAME, 'toolbar('+ filter +')', $.extend({ + event: events + ,config: options + },{})); + }); + + //拖拽调整宽度 + th.on('mousemove', function(e){ + var othis = $(this) + ,oLeft = othis.offset().left + ,pLeft = e.clientX - oLeft; + if(othis.data('unresize') || dict.resizeStart){ + return; + } + dict.allowResize = othis.width() - pLeft <= 10; //是否处于拖拽允许区域 + _BODY.css('cursor', (dict.allowResize ? 'col-resize' : '')); + }).on('mouseleave', function(){ + var othis = $(this); + if(dict.resizeStart) return; + _BODY.css('cursor', ''); + }).on('mousedown', function(e){ + var othis = $(this); + if(dict.allowResize){ + var key = othis.data('key'); + e.preventDefault(); + dict.resizeStart = true; //开始拖拽 + dict.offset = [e.clientX, e.clientY]; //记录初始坐标 + + that.getCssRule(key, function(item){ + var width = item.style.width || othis.outerWidth(); + dict.rule = item; + dict.ruleWidth = parseFloat(width); + dict.minWidth = othis.data('minwidth') || options.cellMinWidth; + }); + } + }); + + //拖拽中 + _DOC.on('mousemove', function(e){ + if(dict.resizeStart){ + e.preventDefault(); + if(dict.rule){ + var setWidth = dict.ruleWidth + e.clientX - dict.offset[0]; + if(setWidth < dict.minWidth) setWidth = dict.minWidth; + dict.rule.style.width = setWidth + 'px'; + layer.close(that.tipsIndex); + } + resizing = 1 + } + }).on('mouseup', function(e){ + if(dict.resizeStart){ + dict = {}; + _BODY.css('cursor', ''); + that.scrollPatch(); + } + if(resizing === 2){ + resizing = null; + } + }); + + //排序 + th.on('click', function(e){ + var othis = $(this) + ,elemSort = othis.find(ELEM_SORT) + ,nowType = elemSort.attr('lay-sort') + ,type; + + if(!elemSort[0] || resizing === 1) return resizing = 2; + + if(nowType === 'asc'){ + type = 'desc'; + } else if(nowType === 'desc'){ + type = null; + } else { + type = 'asc'; + } + that.sort(othis, type, null, true); + }).find(ELEM_SORT+' .layui-edge ').on('click', function(e){ + var othis = $(this) + ,index = othis.index() + ,field = othis.parents('th').eq(0).data('field') + layui.stope(e); + if(index === 0){ + that.sort(field, 'asc', null, true); + } else { + that.sort(field, 'desc', null, true); + } + }); + + //数据行中的事件返回的公共对象成员 + var commonMember = function(sets){ + var othis = $(this) + ,index = othis.parents('tr').eq(0).data('index') + ,tr = that.layBody.find('tr[data-index="'+ index +'"]') + ,data = table.cache[that.key] || []; + + + data = data[index] || {}; + + return $.extend({ + tr: tr //行元素 + ,data: table.clearCacheKey(data) //当前行数据 + ,del: function(){ //删除行数据 + table.cache[that.key][index] = []; + tr.remove(); + that.scrollPatch(); + } + ,update: function(fields){ //修改行数据 + fields = fields || {}; + layui.each(fields, function(key, value){ + if(key in data){ + var templet, td = tr.children('td[data-field="'+ key +'"]'); + data[key] = value; + that.eachCols(function(i, item2){ + if(item2.field == key && item2.templet){ + templet = item2.templet; + } + }); + td.children(ELEM_CELL).html(parseTempData.call(that, { + templet: templet + }, value, data)); + td.data('content', value); + } + }); + } + }, sets); + }; + + //复选框选择 + that.elem.on('click', 'input[name="layTableCheckbox"]+', function(){ //替代元素的 click 事件 + var checkbox = $(this).prev() + ,childs = that.layBody.find('input[name="layTableCheckbox"]') + ,index = checkbox.parents('tr').eq(0).data('index') + ,checked = checkbox[0].checked + ,isAll = checkbox.attr('lay-filter') === 'layTableAllChoose'; + + //全选 + if(isAll){ + childs.each(function(i, item){ + item.checked = checked; + that.setCheckData(i, checked); + }); + that.syncCheckAll(); + that.renderForm('checkbox'); + } else { + that.setCheckData(index, checked); + that.syncCheckAll(); + } + + layui.event.call(checkbox[0], MOD_NAME, 'checkbox('+ filter +')', commonMember.call(checkbox[0], { + checked: checked + ,type: isAll ? 'all' : 'one' + })); + }); + + //单选框选择 + that.elem.on('click', 'input[lay-type="layTableRadio"]+', function(){ + var radio = $(this).prev() + ,checked = radio[0].checked + ,thisData = table.cache[that.key] + ,index = radio.parents('tr').eq(0).data('index'); + + //重置数据单选属性 + layui.each(thisData, function(i, item){ + if(index === i){ + item[options.checkName] = true; + } else { + delete item[options.checkName]; + } + }); + that.setThisRowChecked(index); + + layui.event.call(this, MOD_NAME, 'radio('+ filter +')', commonMember.call(this, { + checked: checked + })); + }); + + //行事件 + that.layBody.on('mouseenter', 'tr', function(){ //鼠标移入行 + var othis = $(this) + ,index = othis.index(); + if(othis.data('off')) return; //不触发事件 + that.layBody.find('tr:eq('+ index +')').addClass(ELEM_HOVER) + }).on('mouseleave', 'tr', function(){ //鼠标移出行 + var othis = $(this) + ,index = othis.index(); + if(othis.data('off')) return; //不触发事件 + that.layBody.find('tr:eq('+ index +')').removeClass(ELEM_HOVER) + }).on('click', 'tr', function(){ //单击行 + setRowEvent.call(this, 'row'); + }).on('dblclick', 'tr', function(){ //双击行 + setRowEvent.call(this, 'rowDouble'); + }); + + //创建行单击、双击事件 + var setRowEvent = function(eventType){ + var othis = $(this); + if(othis.data('off')) return; //不触发事件 + layui.event.call(this, + MOD_NAME, eventType + '('+ filter +')' + ,commonMember.call(othis.children('td')[0]) + ); + }; + + //单元格编辑 + that.layBody.on('change', '.'+ELEM_EDIT, function(){ + var othis = $(this) + ,value = this.value + ,field = othis.parent().data('field') + ,index = othis.parents('tr').eq(0).data('index') + ,data = table.cache[that.key][index]; + + data[field] = value; //更新缓存中的值 + + layui.event.call(this, MOD_NAME, 'edit('+ filter +')', commonMember.call(this, { + value: value + ,field: field + })); + }).on('blur', '.'+ELEM_EDIT, function(){ + var templet + ,othis = $(this) + ,thisElem = this + ,field = othis.parent().data('field') + ,index = othis.parents('tr').eq(0).data('index') + ,data = table.cache[that.key][index]; + that.eachCols(function(i, item){ + if(item.field == field && item.templet){ + templet = item.templet; + } + }); + othis.siblings(ELEM_CELL).html(function(value){ + return parseTempData.call(that, { + templet: templet + }, value, data); + }(thisElem.value)); + othis.parent().data('content', thisElem.value); + othis.remove(); + }); + + //单元格单击事件 + that.layBody.on('click', 'td', function(e){ + var othis = $(this) + ,field = othis.data('field') + ,editType = othis.data('edit') + ,elemCell = othis.children(ELEM_CELL); + + if(othis.data('off')) return; //不触发事件 + + //显示编辑表单 + if(editType){ + var input = $(''); + input[0].value = othis.data('content') || elemCell.text(); + othis.find('.'+ELEM_EDIT)[0] || othis.append(input); + input.focus(); + layui.stope(e); + return; + } + }).on('mouseenter', 'td', function(){ + gridExpand.call(this) + }).on('mouseleave', 'td', function(){ + gridExpand.call(this, 'hide'); + }); + + //单元格展开图标 + var ELEM_GRID = 'layui-table-grid', ELEM_GRID_DOWN = 'layui-table-grid-down', ELEM_GRID_PANEL = 'layui-table-grid-panel' + ,gridExpand = function(hide){ + var othis = $(this) + ,elemCell = othis.children(ELEM_CELL); + + if(othis.data('off')) return; //不触发事件 + + if(hide){ + othis.find('.layui-table-grid-down').remove(); + } else if(elemCell.prop('scrollWidth') > elemCell.outerWidth()){ + if(elemCell.find('.'+ ELEM_GRID_DOWN)[0]) return; + othis.append('
        '); + } + }; + + //单元格展开事件 + that.layBody.on('click', '.'+ ELEM_GRID_DOWN, function(e){ + var othis = $(this) + ,td = othis.parent() + ,elemCell = td.children(ELEM_CELL); + + that.tipsIndex = layer.tips([ + '
        ' + ,elemCell.html() + ,'
        ' + ,'' + ].join(''), elemCell[0], { + tips: [3, ''] + ,time: -1 + ,anim: -1 + ,maxWidth: (device.ios || device.android) ? 300 : that.elem.width()/2 + ,isOutAnim: false + ,skin: 'layui-table-tips' + ,success: function(layero, index){ + layero.find('.layui-table-tips-c').on('click', function(){ + layer.close(index); + }); + } + }); + + layui.stope(e); + }); + + //行工具条操作事件 + that.layBody.on('click', '*[lay-event]', function(){ + var othis = $(this) + ,index = othis.parents('tr').eq(0).data('index'); + layui.event.call(this, MOD_NAME, 'tool('+ filter +')', commonMember.call(this, { + event: othis.attr('lay-event') + })); + that.setThisRowChecked(index); + }); + + //同步滚动条 + that.layMain.on('scroll', function(){ + var othis = $(this) + ,scrollLeft = othis.scrollLeft() + ,scrollTop = othis.scrollTop(); + + that.layHeader.scrollLeft(scrollLeft); + that.layTotal.scrollLeft(scrollLeft); + that.layFixed.find(ELEM_BODY).scrollTop(scrollTop); + + layer.close(that.tipsIndex); + }); + + //自适应 + _WIN.on('resize', function(){ + that.resize(); + }); + }; + + //一次性事件 + ;(function(){ + //全局点击 + _DOC.on('click', function(){ + _DOC.trigger('table.remove.tool.panel'); + }); + + //工具面板移除事件 + _DOC.on('table.remove.tool.panel', function(){ + $('.layui-table-tool-panel').remove(); + }); + })(); + + //初始化 + table.init = function(filter, settings){ + settings = settings || {}; + var that = this + ,inst = null + ,elemTable = filter ? $('table[lay-filter="'+ filter +'"]') : $(ELEM + '[lay-data]') + ,errorTips = 'Table element property lay-data configuration item has a syntax error: '; + + //遍历数据表格 + elemTable.each(function(){ + var othis = $(this), tableData = othis.attr('lay-data'); + + try { + tableData = new Function('return '+ tableData)(); + } catch(e) { + hint.error(errorTips + tableData, 'error') + } + + var cols = [], options = $.extend({ + elem: this + ,cols: [] + ,data: [] + ,skin: othis.attr('lay-skin') //风格 + ,size: othis.attr('lay-size') //尺寸 + ,even: typeof othis.attr('lay-even') === 'string' //偶数行背景 + }, table.config, settings, tableData); + + filter && othis.hide(); + + //获取表头数据 + othis.find('thead>tr').each(function(i){ + options.cols[i] = []; + $(this).children().each(function(ii){ + var th = $(this), itemData = th.attr('lay-data'); + + try{ + itemData = new Function('return '+ itemData)(); + } catch(e){ + return hint.error(errorTips + itemData) + } + + var row = $.extend({ + title: th.text() + ,colspan: th.attr('colspan') || 0 //列单元格 + ,rowspan: th.attr('rowspan') || 0 //行单元格 + }, itemData); + + if(row.colspan < 2) cols.push(row); + options.cols[i].push(row); + }); + }); + + //获取表体数据 + othis.find('tbody>tr').each(function(i1){ + var tr = $(this), row = {}; + //如果定义了字段名 + tr.children('td').each(function(i2, item2){ + var td = $(this) + ,field = td.data('field'); + if(field){ + return row[field] = td.html(); + } + }); + //如果未定义字段名 + layui.each(cols, function(i3, item3){ + var td = tr.children('td').eq(i3); + row[item3.field] = td.html(); + }); + options.data[i1] = row; + }); + + //执行渲染 + table.render(options); + }); + + return that; + }; + + //记录所有实例 + thisTable.that = {}; //记录所有实例对象 + thisTable.config = {}; //记录所有实例配置项 + + //遍历表头 + table.eachCols = function(id, callback, cols){ + var config = thisTable.config[id] || {} + ,arrs = [], index = 0; + + cols = $.extend(true, [], cols || config.cols); + + //重新整理表头结构 + layui.each(cols, function(i1, item1){ + layui.each(item1, function(i2, item2){ + + //如果是组合列,则捕获对应的子列 + if(item2.colGroup){ + var childIndex = 0; + index++ + item2.CHILD_COLS = []; + + layui.each(cols[i1 + 1], function(i22, item22){ + //如果子列已经被标注为{PARENT_COL_INDEX},或者子列累计 colspan 数等于父列定义的 colspan,则跳出当前子列循环 + if(item22.PARENT_COL_INDEX || (childIndex > 1 && childIndex == item2.colspan)) return; + + item22.PARENT_COL_INDEX = index; + + item2.CHILD_COLS.push(item22); + childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1); + }); + } + + if(item2.PARENT_COL_INDEX) return; //如果是子列,则不进行追加,因为已经存储在父列中 + arrs.push(item2) + }); + }); + + //重新遍历列,如果有子列,则进入递归 + var eachArrs = function(obj){ + layui.each(obj || arrs, function(i, item){ + if(item.CHILD_COLS) return eachArrs(item.CHILD_COLS); + typeof callback === 'function' && callback(i, item); + }); + }; + + eachArrs(); + }; + + //表格选中状态 + table.checkStatus = function(id){ + var nums = 0 + ,invalidNum = 0 + ,arr = [] + ,data = table.cache[id] || []; + //计算全选个数 + layui.each(data, function(i, item){ + if(layui._typeof(item) === 'array'){ + invalidNum++; //无效数据,或已删除的 + return; + } + if(item[table.config.checkName]){ + nums++; + arr.push(table.clearCacheKey(item)); + } + }); + return { + data: arr //选中的数据 + ,isAll: data.length ? (nums === (data.length - invalidNum)) : false //是否全选 + }; + }; + + //获取表格当前页的所有行数据 + table.getData = function(id){ + var arr = [] + ,data = table.cache[id] || []; + layui.each(data, function(i, item){ + if(layui._typeof(item) === 'array'){ + return; + }; + arr.push(table.clearCacheKey(item)); + }); + return arr; + }; + + //表格导出 + table.exportFile = function(id, data, type){ + var that = this; + + data = data || table.clearCacheKey(table.cache[id]); + type = type || 'csv'; + + var thatTable = thisTable.that[id] + ,config = thisTable.config[id] || {} + ,textType = ({ + csv: 'text/csv' + ,xls: 'application/vnd.ms-excel' + })[type] + ,alink = document.createElement("a"); + + if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS'); + + alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){ + var dataTitle = [], dataMain = [], dataTotal = []; + + //表头和表体 + layui.each(data, function(i1, item1){ + var vals = []; + if(typeof id === 'object'){ //如果 id 参数直接为表头数据 + layui.each(id, function(i, item){ + i1 == 0 && dataTitle.push(item || ''); + }); + layui.each(table.clearCacheKey(item1), function(i2, item2){ + vals.push('"'+ (item2 || '') +'"'); + }); + } else { + table.eachCols(id, function(i3, item3){ + if(item3.field && item3.type == 'normal' && !item3.hide){ + var content = item1[item3.field]; + if(content === undefined || content === null) content = ''; + + i1 == 0 && dataTitle.push(item3.title || ''); + vals.push('"'+ parseTempData.call(thatTable, item3, content, item1, 'text') + '"'); + } + }); + } + dataMain.push(vals.join(',')); + }); + + //表合计 + layui.each(that.dataTotal, function(key, value){ + dataTotal.push(value); + }); + + return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(','); + }()); + + alink.download = (config.title || 'table_'+ (config.index || '')) + '.' + type; + document.body.appendChild(alink); + alink.click(); + document.body.removeChild(alink); + }; + + //重置表格尺寸结构 + table.resize = function(id){ + //如果指定表格唯一 id,则只执行该 id 对应的表格实例 + if(id){ + var config = getThisTableConfig(id); //获取当前实例配置项 + if(!config) return; + + thisTable.that[id].resize(); + + } else { //否则重置所有表格实例尺寸 + layui.each(thisTable.that, function(){ + this.resize(); + }); + } + }; + + //表格重载 + table.reload = function(id, options, deep){ + var config = getThisTableConfig(id); //获取当前实例配置项 + if(!config) return; + + var that = thisTable.that[id]; + that.reload(options, deep); + + return thisTable.call(that); + }; + + //核心入口 + table.render = function(options){ + var inst = new Class(options); + return thisTable.call(inst); + }; + + //清除临时Key + table.clearCacheKey = function(data){ + data = $.extend({}, data); + delete data[table.config.checkName]; + delete data[table.config.indexName]; + return data; + }; + + //自动完成渲染 + $(function(){ + table.init(); + }); + + exports(MOD_NAME, table); +}); + + diff --git a/static/layui/modules/transfer.js b/static/layui/modules/transfer.js new file mode 100644 index 0000000..5ac2207 --- /dev/null +++ b/static/layui/modules/transfer.js @@ -0,0 +1,437 @@ +/** + + @Name:transfer 穿梭框组件 + @License:MIT + + */ + +layui.define(['laytpl', 'form'], function(exports){ + "use strict"; + + var $ = layui.$ + ,laytpl = layui.laytpl + ,form = layui.form + + //模块名 + ,MOD_NAME = 'transfer' + + //外部接口 + ,transfer = { + config: {} + ,index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisModule = function(){ + var that = this + ,options = that.config + ,id = options.id || that.index; + + thisModule.that[id] = that; //记录当前实例对象 + thisModule.config[id] = options; //记录当前实例配置项 + + return { + config: options + //重置实例 + ,reload: function(options){ + that.reload.call(that, options); + } + //获取右侧数据 + ,getData: function(){ + return that.getData.call(that); + } + } + } + + //获取当前实例配置项 + ,getThisModuleConfig = function(id){ + var config = thisModule.config[id]; + if(!config) hint.error('The ID option was not found in the '+ MOD_NAME +' instance'); + return config || null; + } + + //字符常量 + ,ELEM = 'layui-transfer', HIDE = 'layui-hide', DISABLED = 'layui-btn-disabled', NONE = 'layui-none' + ,ELEM_BOX = 'layui-transfer-box', ELEM_HEADER = 'layui-transfer-header', ELEM_SEARCH = 'layui-transfer-search', ELEM_ACTIVE = 'layui-transfer-active', ELEM_DATA = 'layui-transfer-data' + + //穿梭框模板 + ,TPL_BOX = function(obj){ + obj = obj || {}; + return ['
        ' + ,'
        ' + ,'' + ,'
        ' + ,'{{# if(d.data.showSearch){ }}' + ,'' + ,'{{# } }}' + ,'
          ' + ,'
          '].join(''); + } + + //主模板 + ,TPL_MAIN = ['
          ' + ,TPL_BOX({ + index: 0 + ,checkAllName: 'layTransferLeftCheckAll' + }) + ,'
          ' + ,'' + ,'' + ,'
          ' + ,TPL_BOX({ + index: 1 + ,checkAllName: 'layTransferRightCheckAll' + }) + ,'
          '].join('') + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++transfer.index; + that.config = $.extend({}, that.config, transfer.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + title: ['列表一', '列表二'] + ,width: 200 + ,height: 360 + ,data: [] //数据源 + ,value: [] //选中的数据 + ,showSearch: false //是否开启搜索 + ,id: '' //唯一索引,默认自增 index + ,text: { + none: '无数据' + ,searchNone: '无匹配数据' + } + }; + + //重载实例 + Class.prototype.reload = function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + that.render(); + }; + + //渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + //解析模板 + var thisElem = that.elem = $(laytpl(TPL_MAIN).render({ + data: options + ,index: that.index //索引 + })); + + var othis = options.elem = $(options.elem); + if(!othis[0]) return; + + //初始化属性 + options.data = options.data || []; + options.value = options.value || []; + + //索引 + that.key = options.id || that.index; + + //插入组件结构 + othis.html(that.elem); + + //各级容器 + that.layBox = that.elem.find('.'+ ELEM_BOX) + that.layHeader = that.elem.find('.'+ ELEM_HEADER) + that.laySearch = that.elem.find('.'+ ELEM_SEARCH) + that.layData = thisElem.find('.'+ ELEM_DATA); + that.layBtn = thisElem.find('.'+ ELEM_ACTIVE + ' .layui-btn'); + + //初始化尺寸 + that.layBox.css({ + width: options.width + ,height: options.height + }); + that.layData.css({ + height: function(){ + return options.height - that.layHeader.outerHeight() - that.laySearch.outerHeight() - 2 + }() + }); + + that.renderData(); //渲染数据 + that.events(); //事件 + }; + + //渲染数据 + Class.prototype.renderData = function(){ + var that = this + ,options = that.config; + + //左右穿梭框差异数据 + var arr = [{ + checkName: 'layTransferLeftCheck' + ,views: [] + }, { + checkName: 'layTransferRightCheck' + ,views: [] + }]; + + //解析格式 + that.parseData(function(item){ + //标注为 selected 的为右边的数据 + var _index = item.selected ? 1 : 0 + ,listElem = ['
        • ' + ,'' + ,'
        • '].join(''); + arr[_index].views.push(listElem); + delete item.selected; + }); + + that.layData.eq(0).html(arr[0].views.join('')); + that.layData.eq(1).html(arr[1].views.join('')); + + that.renderCheckBtn(); + } + + //渲染表单 + Class.prototype.renderForm = function(type){ + form.render(type, 'LAY-transfer-'+ this.index); + }; + + //同步复选框和按钮状态 + Class.prototype.renderCheckBtn = function(obj){ + var that = this + ,options = that.config; + + obj = obj || {}; + + that.layBox.each(function(_index){ + var othis = $(this) + ,thisDataElem = othis.find('.'+ ELEM_DATA) + ,allElemCheckbox = othis.find('.'+ ELEM_HEADER).find('input[type="checkbox"]') + ,listElemCheckbox = thisDataElem.find('input[type="checkbox"]'); + + //同步复选框和按钮状态 + var nums = 0 + ,haveChecked = false; + listElemCheckbox.each(function(){ + var isHide = $(this).data('hide'); + if(this.checked || this.disabled || isHide){ + nums++; + } + if(this.checked && !isHide){ + haveChecked = true; + } + }); + + allElemCheckbox.prop('checked', haveChecked && nums === listElemCheckbox.length); //全选复选框状态 + that.layBtn.eq(_index)[haveChecked ? 'removeClass' : 'addClass'](DISABLED); //对应的按钮状态 + + //无数据视图 + if(!obj.stopNone){ + var isNone = thisDataElem.children('li:not(.'+ HIDE +')').length + that.noneView(thisDataElem, isNone ? '' : options.text.none); + } + }); + + that.renderForm('checkbox'); + }; + + //无数据视图 + Class.prototype.noneView = function(thisDataElem, text){ + var createNoneElem = $('

          '+ (text || '') +'

          '); + if(thisDataElem.find('.'+ NONE)[0]){ + thisDataElem.find('.'+ NONE).remove(); + } + text.replace(/\s/g, '') && thisDataElem.append(createNoneElem); + }; + + //同步 value 属性值 + Class.prototype.setValue = function(){ + var that = this + ,options = that.config + ,arr = []; + that.layBox.eq(1).find('.'+ ELEM_DATA +' input[type="checkbox"]').each(function(){ + var isHide = $(this).data('hide'); + isHide || arr.push(this.value); + }); + options.value = arr; + + return that; + }; + + //解析数据 + Class.prototype.parseData = function(callback){ + var that = this + ,options = that.config + ,newData = []; + + layui.each(options.data, function(index, item){ + //解析格式 + item = (typeof options.parseData === 'function' + ? options.parseData(item) + : item) || item; + + newData.push(item = $.extend({}, item)) + + layui.each(options.value, function(index2, item2){ + if(item2 == item.value){ + item.selected = true; + } + }); + callback && callback(item); + }); + + options.data = newData; + return that; + }; + + //获得右侧面板数据 + Class.prototype.getData = function(value){ + var that = this + ,options = that.config + ,selectedData = []; + + that.setValue(); + + layui.each(value || options.value, function(index, item){ + layui.each(options.data, function(index2, item2){ + delete item2.selected; + if(item == item2.value){ + selectedData.push(item2); + }; + }); + }); + return selectedData; + }; + + //事件 + Class.prototype.events = function(){ + var that = this + ,options = that.config; + + //左右复选框 + that.elem.on('click', 'input[lay-filter="layTransferCheckbox"]+', function(){ + var thisElemCheckbox = $(this).prev() + ,checked = thisElemCheckbox[0].checked + ,thisDataElem = thisElemCheckbox.parents('.'+ ELEM_BOX).eq(0).find('.'+ ELEM_DATA); + + if(thisElemCheckbox[0].disabled) return; + + //判断是否全选 + if(thisElemCheckbox.attr('lay-type') === 'all'){ + thisDataElem.find('input[type="checkbox"]').each(function(){ + if(this.disabled) return; + this.checked = checked; + }); + } + + that.renderCheckBtn({stopNone: true}); + }); + + //按钮事件 + that.layBtn.on('click', function(){ + var othis = $(this) + ,_index = othis.data('index') + ,thisBoxElem = that.layBox.eq(_index) + ,arr = []; + if(othis.hasClass(DISABLED)) return; + + that.layBox.eq(_index).each(function(_index){ + var othis = $(this) + ,thisDataElem = othis.find('.'+ ELEM_DATA); + + thisDataElem.children('li').each(function(){ + var thisList = $(this) + ,thisElemCheckbox = thisList.find('input[type="checkbox"]') + ,isHide = thisElemCheckbox.data('hide'); + + if(thisElemCheckbox[0].checked && !isHide){ + thisElemCheckbox[0].checked = false; + thisBoxElem.siblings('.'+ ELEM_BOX).find('.'+ ELEM_DATA).append(thisList.clone()); + thisList.remove(); + + //记录当前穿梭的数据 + arr.push(thisElemCheckbox[0].value); + } + + that.setValue(); + }); + }); + + that.renderCheckBtn(); + + //穿梭时,如果另外一个框正在搜索,则触发匹配 + var siblingInput = thisBoxElem.siblings('.'+ ELEM_BOX).find('.'+ ELEM_SEARCH +' input') + siblingInput.val() === '' || siblingInput.trigger('keyup'); + + //穿梭时的回调 + options.onchange && options.onchange(that.getData(arr), _index); + }); + + //搜索 + that.laySearch.find('input').on('keyup', function(){ + var value = this.value + ,thisDataElem = $(this).parents('.'+ ELEM_SEARCH).eq(0).siblings('.'+ ELEM_DATA) + ,thisListElem = thisDataElem.children('li'); + + thisListElem.each(function(){ + var thisList = $(this) + ,thisElemCheckbox = thisList.find('input[type="checkbox"]') + ,isMatch = thisElemCheckbox[0].title.indexOf(value) !== -1; + + thisList[isMatch ? 'removeClass': 'addClass'](HIDE); + thisElemCheckbox.data('hide', isMatch ? false : true); + }); + + that.renderCheckBtn(); + + //无匹配数据视图 + var isNone = thisListElem.length === thisDataElem.children('li.'+ HIDE).length; + that.noneView(thisDataElem, isNone ? options.text.searchNone : ''); + }); + }; + + //记录所有实例 + thisModule.that = {}; //记录所有实例对象 + thisModule.config = {}; //记录所有实例配置项 + + //重载实例 + transfer.reload = function(id, options){ + var that = thisModule.that[id]; + that.reload(options); + + return thisModule.call(that); + }; + + //获得选中的数据(右侧面板) + transfer.getData = function(id){ + var that = thisModule.that[id]; + return that.getData(); + }; + + //核心入口 + transfer.render = function(options){ + var inst = new Class(options); + return thisModule.call(inst); + }; + + exports(MOD_NAME, transfer); +}); diff --git a/static/layui/modules/tree.js b/static/layui/modules/tree.js new file mode 100644 index 0000000..3f38abd --- /dev/null +++ b/static/layui/modules/tree.js @@ -0,0 +1,816 @@ +/** + + @Name:tree 树组件 + @License:MIT + + */ + +layui.define('form', function(exports){ + "use strict"; + + var $ = layui.$ + ,form = layui.form + ,layer = layui.layer + + //模块名 + ,MOD_NAME = 'tree' + + //外部接口 + ,tree = { + config: {} + ,index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisModule = function(){ + var that = this + ,options = that.config + ,id = options.id || that.index; + + thisModule.that[id] = that; //记录当前实例对象 + thisModule.config[id] = options; //记录当前实例配置项 + + return { + config: options + //重置实例 + ,reload: function(options){ + that.reload.call(that, options); + } + ,getChecked: function(){ + return that.getChecked.call(that); + } + ,setChecked: function(id){//设置值 + return that.setChecked.call(that, id); + } + } + } + + //获取当前实例配置项 + ,getThisModuleConfig = function(id){ + var config = thisModule.config[id]; + if(!config) hint.error('The ID option was not found in the '+ MOD_NAME +' instance'); + return config || null; + } + + //字符常量 + ,SHOW = 'layui-show', HIDE = 'layui-hide', NONE = 'layui-none', DISABLED = 'layui-disabled' + + ,ELEM_VIEW = 'layui-tree', ELEM_SET = 'layui-tree-set', ICON_CLICK = 'layui-tree-iconClick' + ,ICON_ADD = 'layui-icon-addition', ICON_SUB = 'layui-icon-subtraction', ELEM_ENTRY = 'layui-tree-entry', ELEM_MAIN = 'layui-tree-main', ELEM_TEXT = 'layui-tree-txt', ELEM_PACK = 'layui-tree-pack', ELEM_SPREAD = 'layui-tree-spread' + ,ELEM_LINE_SHORT = 'layui-tree-setLineShort', ELEM_SHOW = 'layui-tree-showLine', ELEM_EXTEND = 'layui-tree-lineExtend' + + //构造器 + ,Class = function(options){ + var that = this; + that.index = ++tree.index; + that.config = $.extend({}, that.config, tree.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + data: [] //数据 + + ,showCheckbox: false //是否显示复选框 + ,showLine: true //是否开启连接线 + ,accordion: false //是否开启手风琴模式 + ,onlyIconControl: false //是否仅允许节点左侧图标控制展开收缩 + ,isJump: false //是否允许点击节点时弹出新窗口跳转 + ,edit: false //是否开启节点的操作图标 + + ,text: { + defaultNodeName: '未命名' //节点默认名称 + ,none: '无数据' //数据为空时的文本提示 + } + }; + + //重载实例 + Class.prototype.reload = function(options){ + var that = this; + + layui.each(options, function(key, item){ + if(layui._typeof(item) === 'array') delete that.config[key]; + }); + + that.config = $.extend(true, {}, that.config, options); + that.render(); + }; + + //主体渲染 + Class.prototype.render = function(){ + var that = this + ,options = that.config; + + that.checkids = []; + + var temp = $('
          '); + that.tree(temp); + + var othis = options.elem = $(options.elem); + if(!othis[0]) return; + + //索引 + that.key = options.id || that.index; + + //插入组件结构 + that.elem = temp; + that.elemNone = $('
          '+ options.text.none +'
          '); + othis.html(that.elem); + + if(that.elem.find('.layui-tree-set').length == 0){ + return that.elem.append(that.elemNone); + }; + + //复选框渲染 + if(options.showCheckbox){ + that.renderForm('checkbox'); + }; + + that.elem.find('.layui-tree-set').each(function(){ + var othis = $(this); + //最外层 + if(!othis.parent('.layui-tree-pack')[0]){ + othis.addClass('layui-tree-setHide'); + }; + + //没有下一个节点 上一层父级有延伸线 + if(!othis.next()[0] && othis.parents('.layui-tree-pack').eq(1).hasClass('layui-tree-lineExtend')){ + othis.addClass(ELEM_LINE_SHORT); + }; + + //没有下一个节点 外层最后一个 + if(!othis.next()[0] && !othis.parents('.layui-tree-set').eq(0).next()[0]){ + othis.addClass(ELEM_LINE_SHORT); + }; + }); + + that.events(); + }; + + //渲染表单 + Class.prototype.renderForm = function(type){ + form.render(type, 'LAY-tree-'+ this.index); + }; + + //节点解析 + Class.prototype.tree = function(elem, children){ + var that = this + ,options = that.config + ,data = children || options.data; + + //遍历数据 + layui.each(data, function(index, item){ + var hasChild = item.children && item.children.length > 0 + ,packDiv = $('
          ') + ,entryDiv = $(['
          ' + ,'
          ' + ,'
          ' + //箭头 + ,function(){ + if(options.showLine){ + if(hasChild){ + return ''; + }else{ + return ''; + }; + }else{ + return ''; + }; + }() + + //复选框 + ,function(){ + return options.showCheckbox ? '' : ''; + }() + + //节点 + ,function(){ + if(options.isJump && item.href){ + return ''+ (item.title || item.label || options.text.defaultNodeName) +''; + }else{ + return ''+ (item.title || item.label || options.text.defaultNodeName) +''; + } + }() + ,'
          ' + + //节点操作图标 + ,function(){ + if(!options.edit) return ''; + + var editIcon = { + add: '' + ,update: '' + ,del: '' + }, arr = ['
          ']; + + if(options.edit === true){ + options.edit = ['update', 'del'] + } + + if(typeof options.edit === 'object'){ + layui.each(options.edit, function(i, val){ + arr.push(editIcon[val] || '') + }); + return arr.join('') + '
          '; + } + }() + ,'
          '].join('')); + + //如果有子节点,则递归继续生成树 + if(hasChild){ + entryDiv.append(packDiv); + that.tree(packDiv, item.children); + }; + + elem.append(entryDiv); + + //若有前置节点,前置节点加连接线 + if(entryDiv.prev('.'+ELEM_SET)[0]){ + entryDiv.prev().children('.layui-tree-pack').addClass('layui-tree-showLine'); + }; + + //若无子节点,则父节点加延伸线 + if(!hasChild){ + entryDiv.parent('.layui-tree-pack').addClass('layui-tree-lineExtend'); + }; + + //展开节点操作 + that.spread(entryDiv, item); + + //选择框 + if(options.showCheckbox){ + item.checked && that.checkids.push(item.id); + that.checkClick(entryDiv, item); + } + + //操作节点 + options.edit && that.operate(entryDiv, item); + + }); + }; + + //展开节点 + Class.prototype.spread = function(elem, item){ + var that = this + ,options = that.config + ,entry = elem.children('.'+ELEM_ENTRY) + ,elemMain = entry.children('.'+ ELEM_MAIN) + ,elemIcon = entry.find('.'+ ICON_CLICK) + ,elemText = entry.find('.'+ ELEM_TEXT) + ,touchOpen = options.onlyIconControl ? elemIcon : elemMain //判断展开通过节点还是箭头图标 + ,state = ''; + + //展开收缩 + touchOpen.on('click', function(e){ + var packCont = elem.children('.'+ELEM_PACK) + ,iconClick = touchOpen.children('.layui-icon')[0] ? touchOpen.children('.layui-icon') : touchOpen.find('.layui-tree-icon').children('.layui-icon'); + + //若没有子节点 + if(!packCont[0]){ + state = 'normal'; + }else{ + if(elem.hasClass(ELEM_SPREAD)){ + elem.removeClass(ELEM_SPREAD); + packCont.slideUp(200); + iconClick.removeClass(ICON_SUB).addClass(ICON_ADD); + }else{ + elem.addClass(ELEM_SPREAD); + packCont.slideDown(200); + iconClick.addClass(ICON_SUB).removeClass(ICON_ADD); + + //是否手风琴 + if(options.accordion){ + var sibls = elem.siblings('.'+ELEM_SET); + sibls.removeClass(ELEM_SPREAD); + sibls.children('.'+ELEM_PACK).slideUp(200); + sibls.find('.layui-tree-icon').children('.layui-icon').removeClass(ICON_SUB).addClass(ICON_ADD); + }; + }; + }; + }); + + //点击回调 + elemText.on('click', function(){ + var othis = $(this); + + //判断是否禁用状态 + if(othis.hasClass(DISABLED)) return; + + //判断展开收缩状态 + if(elem.hasClass(ELEM_SPREAD)){ + state = options.onlyIconControl ? 'open' : 'close'; + } else { + state = options.onlyIconControl ? 'close' : 'open'; + } + + //点击产生的回调 + options.click && options.click({ + elem: elem + ,state: state + ,data: item + }); + }); + }; + + //计算复选框选中状态 + Class.prototype.setCheckbox = function(elem, item, elemCheckbox){ + var that = this + ,options = that.config + ,checked = elemCheckbox.prop('checked'); + + if(elemCheckbox.prop('disabled')) return; + + //同步子节点选中状态 + if(typeof item.children === 'object' || elem.find('.'+ELEM_PACK)[0]){ + var childs = elem.find('.'+ ELEM_PACK).find('input[same="layuiTreeCheck"]'); + childs.each(function(){ + if(this.disabled) return; //不可点击则跳过 + this.checked = checked; + }); + }; + + //同步父节点选中状态 + var setParentsChecked = function(thisNodeElem){ + //若无父节点,则终止递归 + if(!thisNodeElem.parents('.'+ ELEM_SET)[0]) return; + + var state + ,parentPack = thisNodeElem.parent('.'+ ELEM_PACK) + ,parentNodeElem = parentPack.parent() + ,parentCheckbox = parentPack.prev().find('input[same="layuiTreeCheck"]'); + + //如果子节点有任意一条选中,则父节点为选中状态 + if(checked){ + parentCheckbox.prop('checked', checked); + } else { //如果当前节点取消选中,则根据计算“兄弟和子孙”节点选中状态,来同步父节点选中状态 + parentPack.find('input[same="layuiTreeCheck"]').each(function(){ + if(this.checked){ + state = true; + } + }); + + //如果兄弟子孙节点全部未选中,则父节点也应为非选中状态 + state || parentCheckbox.prop('checked', false); + } + + //向父节点递归 + setParentsChecked(parentNodeElem); + }; + + setParentsChecked(elem); + + that.renderForm('checkbox'); + }; + + //复选框选择 + Class.prototype.checkClick = function(elem, item){ + var that = this + ,options = that.config + ,entry = elem.children('.'+ ELEM_ENTRY) + ,elemMain = entry.children('.'+ ELEM_MAIN); + + + + //点击复选框 + elemMain.on('click', 'input[same="layuiTreeCheck"]+', function(e){ + layui.stope(e); //阻止点击节点事件 + + var elemCheckbox = $(this).prev() + ,checked = elemCheckbox.prop('checked'); + + if(elemCheckbox.prop('disabled')) return; + + that.setCheckbox(elem, item, elemCheckbox); + + //复选框点击产生的回调 + options.oncheck && options.oncheck({ + elem: elem + ,checked: checked + ,data: item + }); + }); + }; + + //节点操作 + Class.prototype.operate = function(elem, item){ + var that = this + ,options = that.config + ,entry = elem.children('.'+ ELEM_ENTRY) + ,elemMain = entry.children('.'+ ELEM_MAIN); + + entry.children('.layui-tree-btnGroup').on('click', '.layui-icon', function(e){ + layui.stope(e); //阻止节点操作 + + var type = $(this).data("type") + ,packCont = elem.children('.'+ELEM_PACK) + ,returnObj = { + data: item + ,type: type + ,elem:elem + }; + //增加 + if(type == 'add'){ + //若节点本身无子节点 + if(!packCont[0]){ + //若开启连接线,更改图标样式 + if(options.showLine){ + elemMain.find('.'+ICON_CLICK).addClass('layui-tree-icon'); + elemMain.find('.'+ICON_CLICK).children('.layui-icon').addClass(ICON_ADD).removeClass('layui-icon-file'); + //若未开启连接线,显示箭头 + }else{ + elemMain.find('.layui-tree-iconArrow').removeClass(HIDE); + }; + //节点添加子节点容器 + elem.append('
          '); + }; + + //新增节点 + var key = options.operate && options.operate(returnObj) + ,obj = {}; + obj.title = options.text.defaultNodeName; + obj.id = key; + that.tree(elem.children('.'+ELEM_PACK), [obj]); + + //放在新增后面,因为要对元素进行操作 + if(options.showLine){ + //节点本身无子节点 + if(!packCont[0]){ + //遍历兄弟节点,判断兄弟节点是否有子节点 + var siblings = elem.siblings('.'+ELEM_SET), num = 1 + ,parentPack = elem.parent('.'+ELEM_PACK); + layui.each(siblings, function(index, i){ + if(!$(i).children('.'+ELEM_PACK)[0]){ + num = 0; + }; + }); + + //若兄弟节点都有子节点 + if(num == 1){ + //兄弟节点添加连接线 + siblings.children('.'+ELEM_PACK).addClass(ELEM_SHOW); + siblings.children('.'+ELEM_PACK).children('.'+ELEM_SET).removeClass(ELEM_LINE_SHORT); + elem.children('.'+ELEM_PACK).addClass(ELEM_SHOW); + //父级移除延伸线 + parentPack.removeClass(ELEM_EXTEND); + //同层节点最后一个更改线的状态 + parentPack.children('.'+ELEM_SET).last().children('.'+ELEM_PACK).children('.'+ELEM_SET).last().addClass(ELEM_LINE_SHORT); + }else{ + elem.children('.'+ELEM_PACK).children('.'+ELEM_SET).addClass(ELEM_LINE_SHORT); + }; + }else{ + //添加延伸线 + if(!packCont.hasClass(ELEM_EXTEND)){ + packCont.addClass(ELEM_EXTEND); + }; + //子节点添加延伸线 + elem.find('.'+ELEM_PACK).each(function(){ + $(this).children('.'+ELEM_SET).last().addClass(ELEM_LINE_SHORT); + }); + //如果前一个节点有延伸线 + if(packCont.children('.'+ELEM_SET).last().prev().hasClass(ELEM_LINE_SHORT)){ + packCont.children('.'+ELEM_SET).last().prev().removeClass(ELEM_LINE_SHORT); + }else{ + //若之前的没有,说明处于连接状态 + packCont.children('.'+ELEM_SET).last().removeClass(ELEM_LINE_SHORT); + }; + //若是最外层,要始终保持相连的状态 + if(!elem.parent('.'+ELEM_PACK)[0] && elem.next()[0]){ + packCont.children('.'+ELEM_SET).last().removeClass(ELEM_LINE_SHORT); + }; + }; + }; + if(!options.showCheckbox) return; + //若开启复选框,同步新增节点状态 + if(elemMain.find('input[same="layuiTreeCheck"]')[0].checked){ + var packLast = elem.children('.'+ELEM_PACK).children('.'+ELEM_SET).last(); + packLast.find('input[same="layuiTreeCheck"]')[0].checked = true; + }; + that.renderForm('checkbox'); + + //修改 + }else if(type == 'update'){ + var text = elemMain.children('.'+ ELEM_TEXT).html(); + elemMain.children('.'+ ELEM_TEXT).html(''); + //添加输入框,覆盖在文字上方 + elemMain.append(''); + //获取焦点 + elemMain.children('.layui-tree-editInput').val(text).focus(); + //嵌入文字移除输入框 + var getVal = function(input){ + var textNew = input.val().trim(); + textNew = textNew ? textNew : options.text.defaultNodeName; + input.remove(); + elemMain.children('.'+ ELEM_TEXT).html(textNew); + + //同步数据 + returnObj.data.title = textNew; + + //节点修改的回调 + options.operate && options.operate(returnObj); + }; + //失去焦点 + elemMain.children('.layui-tree-editInput').blur(function(){ + getVal($(this)); + }); + //回车 + elemMain.children('.layui-tree-editInput').on('keydown', function(e){ + if(e.keyCode === 13){ + e.preventDefault(); + getVal($(this)); + }; + }); + + //删除 + } else { + layer.confirm('确认删除该节点 "'+ (item.title || '') +'" 吗?', function(index){ + options.operate && options.operate(returnObj); //节点删除的回调 + returnObj.status = 'remove'; //标注节点删除 + + layer.close(index); + + //若删除最后一个,显示空数据提示 + if(!elem.prev('.'+ELEM_SET)[0] && !elem.next('.'+ELEM_SET)[0] && !elem.parent('.'+ELEM_PACK)[0]){ + elem.remove(); + that.elem.append(that.elemNone); + return; + }; + //若有兄弟节点 + if(elem.siblings('.'+ELEM_SET).children('.'+ELEM_ENTRY)[0]){ + //若开启复选框 + if(options.showCheckbox){ + //若开启复选框,进行下步操作 + var elemDel = function(elem){ + //若无父结点,则不执行 + if(!elem.parents('.'+ELEM_SET)[0]) return; + var siblingTree = elem.siblings('.'+ELEM_SET).children('.'+ELEM_ENTRY) + ,parentTree = elem.parent('.'+ELEM_PACK).prev() + ,checkState = parentTree.find('input[same="layuiTreeCheck"]')[0] + ,state = 1, num = 0; + //若父节点未勾选 + if(checkState.checked == false){ + //遍历兄弟节点 + siblingTree.each(function(i, item1){ + var input = $(item1).find('input[same="layuiTreeCheck"]')[0] + if(input.checked == false && !input.disabled){ + state = 0; + }; + //判断是否全为不可勾选框 + if(!input.disabled){ + num = 1; + }; + }); + //若有可勾选选择框并且已勾选 + if(state == 1 && num == 1){ + //勾选父节点 + checkState.checked = true; + that.renderForm('checkbox'); + //向上遍历祖先节点 + elemDel(parentTree.parent('.'+ELEM_SET)); + }; + }; + }; + elemDel(elem); + }; + //若开启连接线 + if(options.showLine){ + //遍历兄弟节点,判断兄弟节点是否有子节点 + var siblings = elem.siblings('.'+ELEM_SET), num = 1 + ,parentPack = elem.parent('.'+ELEM_PACK); + layui.each(siblings, function(index, i){ + if(!$(i).children('.'+ELEM_PACK)[0]){ + num = 0; + }; + }); + //若兄弟节点都有子节点 + if(num == 1){ + //若节点本身无子节点 + if(!packCont[0]){ + //父级去除延伸线,因为此时子节点里没有空节点 + parentPack.removeClass(ELEM_EXTEND); + siblings.children('.'+ELEM_PACK).addClass(ELEM_SHOW); + siblings.children('.'+ELEM_PACK).children('.'+ELEM_SET).removeClass(ELEM_LINE_SHORT); + }; + //若为最后一个节点 + if(!elem.next()[0]){ + elem.prev().children('.'+ELEM_PACK).children('.'+ELEM_SET).last().addClass(ELEM_LINE_SHORT); + }else{ + parentPack.children('.'+ELEM_SET).last().children('.'+ELEM_PACK).children('.'+ELEM_SET).last().addClass(ELEM_LINE_SHORT); + }; + //若为最外层最后一个节点,去除前一个结点的连接线 + if(!elem.next()[0] && !elem.parents('.'+ELEM_SET)[1] && !elem.parents('.'+ELEM_SET).eq(0).next()[0]){ + elem.prev('.'+ELEM_SET).addClass(ELEM_LINE_SHORT); + }; + }else{ + //若为最后一个节点且有延伸线 + if(!elem.next()[0] && elem.hasClass(ELEM_LINE_SHORT)){ + elem.prev().addClass(ELEM_LINE_SHORT); + }; + }; + }; + + }else{ + //若无兄弟节点 + var prevDiv = elem.parent('.'+ELEM_PACK).prev(); + //若开启了连接线 + if(options.showLine){ + prevDiv.find('.'+ICON_CLICK).removeClass('layui-tree-icon'); + prevDiv.find('.'+ICON_CLICK).children('.layui-icon').removeClass(ICON_SUB).addClass('layui-icon-file'); + //父节点所在层添加延伸线 + var pare = prevDiv.parents('.'+ELEM_PACK).eq(0); + pare.addClass(ELEM_EXTEND); + + //兄弟节点最后子节点添加延伸线 + pare.children('.'+ELEM_SET).each(function(){ + $(this).children('.'+ELEM_PACK).children('.'+ELEM_SET).last().addClass(ELEM_LINE_SHORT); + }); + }else{ + //父节点隐藏箭头 + prevDiv.find('.layui-tree-iconArrow').addClass(HIDE); + }; + //移除展开属性 + elem.parents('.'+ELEM_SET).eq(0).removeClass(ELEM_SPREAD); + //移除节点容器 + elem.parent('.'+ELEM_PACK).remove(); + }; + + elem.remove(); + }); + + }; + }); + }; + + //部分事件 + Class.prototype.events = function(){ + var that = this + ,options = that.config + ,checkWarp = that.elem.find('.layui-tree-checkedFirst'); + + //初始选中 + that.setChecked(that.checkids); + + //搜索 + that.elem.find('.layui-tree-search').on('keyup', function(){ + var input = $(this) + ,val = input.val() + ,pack = input.nextAll() + ,arr = []; + + //遍历所有的值 + pack.find('.'+ ELEM_TEXT).each(function(){ + var entry = $(this).parents('.'+ELEM_ENTRY); + //若值匹配,加一个类以作标识 + if($(this).html().indexOf(val) != -1){ + arr.push($(this).parent()); + + var select = function(div){ + div.addClass('layui-tree-searchShow'); + //向上父节点渲染 + if(div.parent('.'+ELEM_PACK)[0]){ + select(div.parent('.'+ELEM_PACK).parent('.'+ELEM_SET)); + }; + }; + select(entry.parent('.'+ELEM_SET)); + }; + }); + + //根据标志剔除 + pack.find('.'+ELEM_ENTRY).each(function(){ + var parent = $(this).parent('.'+ELEM_SET); + if(!parent.hasClass('layui-tree-searchShow')){ + parent.addClass(HIDE); + }; + }); + if(pack.find('.layui-tree-searchShow').length == 0){ + that.elem.append(that.elemNone); + }; + + //节点过滤的回调 + options.onsearch && options.onsearch({ + elem: arr + }); + }); + + //还原搜索初始状态 + that.elem.find('.layui-tree-search').on('keydown', function(){ + $(this).nextAll().find('.'+ELEM_ENTRY).each(function(){ + var parent = $(this).parent('.'+ELEM_SET); + parent.removeClass('layui-tree-searchShow '+ HIDE); + }); + if($('.layui-tree-emptyText')[0]) $('.layui-tree-emptyText').remove(); + }); + }; + + //得到选中节点 + Class.prototype.getChecked = function(){ + var that = this + ,options = that.config + ,checkId = [] + ,checkData = []; + + //遍历节点找到选中索引 + that.elem.find('.layui-form-checked').each(function(){ + checkId.push($(this).prev()[0].value); + }); + + //遍历节点 + var eachNodes = function(data, checkNode){ + layui.each(data, function(index, item){ + layui.each(checkId, function(index2, item2){ + if(item.id == item2){ + var cloneItem = $.extend({}, item); + delete cloneItem.children; + + checkNode.push(cloneItem); + + if(item.children){ + cloneItem.children = []; + eachNodes(item.children, cloneItem.children); + } + return true + } + }); + }); + }; + + eachNodes($.extend({}, options.data), checkData); + + return checkData; + }; + + //设置选中节点 + Class.prototype.setChecked = function(checkedId){ + var that = this + ,options = that.config; + + //初始选中 + that.elem.find('.'+ELEM_SET).each(function(i, item){ + var thisId = $(this).data('id') + ,input = $(item).children('.'+ELEM_ENTRY).find('input[same="layuiTreeCheck"]') + ,reInput = input.next(); + + //若返回数字 + if(typeof checkedId === 'number'){ + if(thisId == checkedId){ + if(!input[0].checked){ + reInput.click(); + }; + return false; + }; + } + //若返回数组 + else if(typeof checkedId === 'object'){ + layui.each(checkedId, function(index, value){ + if(value == thisId && !input[0].checked){ + reInput.click(); + return true; + } + }); + }; + }); + }; + + //记录所有实例 + thisModule.that = {}; //记录所有实例对象 + thisModule.config = {}; //记录所有实例配置项 + + //重载实例 + tree.reload = function(id, options){ + var that = thisModule.that[id]; + that.reload(options); + + return thisModule.call(that); + }; + + //获得选中的节点数据 + tree.getChecked = function(id){ + var that = thisModule.that[id]; + return that.getChecked(); + }; + + //设置选中节点 + tree.setChecked = function(id, checkedId){ + var that = thisModule.that[id]; + return that.setChecked(checkedId); + }; + + //核心入口 + tree.render = function(options){ + var inst = new Class(options); + return thisModule.call(inst); + }; + + exports(MOD_NAME, tree); +}) \ No newline at end of file diff --git a/static/layui/modules/upload.js b/static/layui/modules/upload.js new file mode 100644 index 0000000..3338867 --- /dev/null +++ b/static/layui/modules/upload.js @@ -0,0 +1,565 @@ + +/*! + * upload 文件上传组件 + * MIT Licensed + */ + +layui.define('layer' , function(exports){ + "use strict"; + + var $ = layui.$ + ,layer = layui.layer + ,hint = layui.hint() + ,device = layui.device() + + //外部接口 + ,upload = { + config: {} //全局配置项 + + //设置全局项 + ,set: function(options){ + var that = this; + that.config = $.extend({}, that.config, options); + return that; + } + + //事件 + ,on: function(events, callback){ + return layui.onevent.call(this, MOD_NAME, events, callback); + } + } + + //操作当前实例 + ,thisUpload = function(){ + var that = this; + return { + upload: function(files){ + that.upload.call(that, files); + } + ,reload: function(options){ + that.reload.call(that, options); + } + ,config: that.config + } + } + + //字符常量 + ,MOD_NAME = 'upload', ELEM = 'layui-upload', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled' + + ,ELEM_FILE = 'layui-upload-file', ELEM_FORM = 'layui-upload-form', ELEM_IFRAME = 'layui-upload-iframe', ELEM_CHOOSE = 'layui-upload-choose', ELEM_DRAG = 'layui-upload-drag' + + + //构造器 + ,Class = function(options){ + var that = this; + that.config = $.extend({}, that.config, upload.config, options); + that.render(); + }; + + //默认配置 + Class.prototype.config = { + accept: 'images' //允许上传的文件类型:images/file/video/audio + ,exts: '' //允许上传的文件后缀名 + ,auto: true //是否选完文件后自动上传 + ,bindAction: '' //手动上传触发的元素 + ,url: '' //上传地址 + ,field: 'file' //文件字段名 + ,acceptMime: '' //筛选出的文件类型,默认为所有文件 + ,method: 'post' //请求上传的 http 类型 + ,data: {} //请求上传的额外参数 + ,drag: true //是否允许拖拽上传 + ,size: 0 //文件限制大小,默认不限制 + ,number: 0 //允许同时上传的文件数,默认不限制 + ,multiple: false //是否允许多文件上传,不支持ie8-9 + }; + + //初始渲染 + Class.prototype.render = function(options){ + var that = this + ,options = that.config; + + options.elem = $(options.elem); + options.bindAction = $(options.bindAction); + + that.file(); + that.events(); + }; + + //追加文件域 + Class.prototype.file = function(){ + var that = this + ,options = that.config + ,elemFile = that.elemFile = $([ + '' + ].join('')) + ,next = options.elem.next(); + + if(next.hasClass(ELEM_FILE) || next.hasClass(ELEM_FORM)){ + next.remove(); + } + + //包裹ie8/9容器 + if(device.ie && device.ie < 10){ + options.elem.wrap('
          '); + } + + that.isFile() ? ( + that.elemFile = options.elem + ,options.field = options.elem[0].name + ) : options.elem.after(elemFile); + + //初始化ie8/9的Form域 + if(device.ie && device.ie < 10){ + that.initIE(); + } + }; + + //ie8-9初始化 + Class.prototype.initIE = function(){ + var that = this + ,options = that.config + ,iframe = $('') + ,elemForm = $(['
          ' + ,'
          '].join('')); + + //插入iframe + $('#'+ ELEM_IFRAME)[0] || $('body').append(iframe); + + //包裹文件域 + if(!options.elem.next().hasClass(ELEM_FORM)){ + that.elemFile.wrap(elemForm); + + //追加额外的参数 + options.elem.next('.'+ ELEM_FORM).append(function(){ + var arr = []; + layui.each(options.data, function(key, value){ + value = typeof value === 'function' ? value() : value; + arr.push('') + }); + return arr.join(''); + }()); + } + }; + + //异常提示 + Class.prototype.msg = function(content){ + return layer.msg(content, { + icon: 2 + ,shift: 6 + }); + }; + + //判断绑定元素是否为文件域本身 + Class.prototype.isFile = function(){ + var elem = this.config.elem[0]; + if(!elem) return; + return elem.tagName.toLocaleLowerCase() === 'input' && elem.type === 'file' + } + + //预读图片信息 + Class.prototype.preview = function(callback){ + var that = this; + if(window.FileReader){ + layui.each(that.chooseFiles, function(index, file){ + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function(){ + callback && callback(index, file, this.result); + } + }); + } + }; + + //执行上传 + Class.prototype.upload = function(files, type){ + var that = this + ,options = that.config + ,elemFile = that.elemFile[0] + + //高级浏览器处理方式,支持跨域 + ,ajaxSend = function(){ + var successful = 0, aborted = 0 + ,items = files || that.files || that.chooseFiles || elemFile.files + ,allDone = function(){ //多文件全部上传完毕的回调 + if(options.multiple && successful + aborted === that.fileLength){ + typeof options.allDone === 'function' && options.allDone({ + total: that.fileLength + ,successful: successful + ,aborted: aborted + }); + } + }; + layui.each(items, function(index, file){ + var formData = new FormData(); + + formData.append(options.field, file); + + //追加额外的参数 + layui.each(options.data, function(key, value){ + value = typeof value === 'function' ? value() : value; + formData.append(key, value); + }); + + //提交文件 + var opts = { + url: options.url + ,type: 'post' //统一采用 post 上传 + ,data: formData + ,contentType: false + ,processData: false + ,dataType: 'json' + ,headers: options.headers || {} + //成功回调 + ,success: function(res){ + successful++; + done(index, res); + allDone(); + } + //异常回调 + ,error: function(){ + aborted++; + that.msg('请求上传接口出现异常'); + error(index); + allDone(); + } + }; + //进度条 + if(typeof options.progress === 'function'){ + opts.xhr = function(){ + var xhr = $.ajaxSettings.xhr(); + //上传进度 + xhr.upload.addEventListener("progress", function (obj) { + if(obj.lengthComputable){ + var percent = Math.floor((obj.loaded/obj.total)* 100); //百分比 + options.progress(percent, (options.item ? options.item[0] : options.elem[0]) , obj, index); + } + }); + return xhr; + } + } + $.ajax(opts); + }); + } + + //低版本IE处理方式,不支持跨域 + ,iframeSend = function(){ + var iframe = $('#'+ ELEM_IFRAME); + + that.elemFile.parent().submit(); + + //获取响应信息 + clearInterval(Class.timer); + Class.timer = setInterval(function() { + var res, iframeBody = iframe.contents().find('body'); + try { + res = iframeBody.text(); + } catch(e) { + that.msg('获取上传后的响应信息出现异常'); + clearInterval(Class.timer); + error(); + } + if(res){ + clearInterval(Class.timer); + iframeBody.html(''); + done(0, res); + } + }, 30); + } + + //统一回调 + ,done = function(index, res){ + that.elemFile.next('.'+ ELEM_CHOOSE).remove(); + elemFile.value = ''; + if(typeof res !== 'object'){ + try { + res = JSON.parse(res); + } catch(e){ + res = {}; + return that.msg('请对上传接口返回有效JSON'); + } + } + typeof options.done === 'function' && options.done(res, index || 0, function(files){ + that.upload(files); + }); + } + + //统一网络异常回调 + ,error = function(index){ + if(options.auto){ + elemFile.value = ''; + } + typeof options.error === 'function' && options.error(index || 0, function(files){ + that.upload(files); + }); + } + + ,exts = options.exts + ,check ,value = function(){ + var arr = []; + layui.each(files || that.chooseFiles, function(i, item){ + arr.push(item.name); + }); + return arr; + }() + + //回调返回的参数 + ,args = { + //预览 + preview: function(callback){ + that.preview(callback); + } + //上传 + ,upload: function(index, file){ + var thisFile = {}; + thisFile[index] = file; + that.upload(thisFile); + } + //追加文件到队列 + ,pushFile: function(){ + that.files = that.files || {}; + layui.each(that.chooseFiles, function(index, item){ + that.files[index] = item; + }); + return that.files; + } + //重置文件 + ,resetFile: function(index, file, filename){ + var newFile = new File([file], filename); + that.files = that.files || {}; + that.files[index] = newFile; + } + } + + //提交上传 + ,send = function(){ + //选择文件的回调 + if(type === 'choose' || options.auto){ + options.choose && options.choose(args); + if(type === 'choose'){ + return; + } + } + + //上传前的回调 - 如果回调函数明确返回false,则停止上传(#pulls55) + if(options.before && (options.before(args) === false)) return; + + //IE兼容处理 + if(device.ie){ + return device.ie > 9 ? ajaxSend() : iframeSend(); + } + + ajaxSend(); + } + + //校验文件格式 + value = value.length === 0 + ? ((elemFile.value.match(/[^\/\\]+\..+/g)||[]) || '') + : value; + + if(value.length === 0) return; + + switch(options.accept){ + case 'file': //一般文件 + if(exts && !RegExp('\\w\\.('+ exts +')$', 'i').test(escape(value))){ + that.msg('选择的文件中包含不支持的格式'); + return elemFile.value = ''; + } + break; + case 'video': //视频文件 + if(!RegExp('\\w\\.('+ (exts || 'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(value))){ + that.msg('选择的视频中包含不支持的格式'); + return elemFile.value = ''; + } + break; + case 'audio': //音频文件 + if(!RegExp('\\w\\.('+ (exts || 'mp3|wav|mid') +')$', 'i').test(escape(value))){ + that.msg('选择的音频中包含不支持的格式'); + return elemFile.value = ''; + } + break; + default: //图片文件 + layui.each(value, function(i, item){ + if(!RegExp('\\w\\.('+ (exts || 'jpg|png|gif|bmp|jpeg$') +')', 'i').test(escape(item))){ + check = true; + } + }); + if(check){ + that.msg('选择的图片中包含不支持的格式'); + return elemFile.value = ''; + } + break; + } + + //检验文件数量 + that.fileLength = function(){ + var length = 0 + ,items = files || that.files || that.chooseFiles || elemFile.files; + layui.each(items, function(){ + length++; + }); + return length; + }(); + if(options.number && that.fileLength > options.number){ + return that.msg('同时最多只能上传的数量为:'+ options.number); + } + + //检验文件大小 + if(options.size > 0 && !(device.ie && device.ie < 10)){ + var limitSize; + + layui.each(that.chooseFiles, function(index, file){ + if(file.size > 1024*options.size){ + var size = options.size/1024; + size = size >= 1 ? (size.toFixed(2) + 'MB') : options.size + 'KB' + elemFile.value = ''; + limitSize = size; + } + }); + if(limitSize) return that.msg('文件不能超过'+ limitSize); + } + send(); + }; + + //重置方法 + Class.prototype.reload = function(options){ + options = options || {}; + delete options.elem; + delete options.bindAction; + + var that = this + ,options = that.config = $.extend({}, that.config, upload.config, options) + ,next = options.elem.next(); + + //更新文件域相关属性 + next.attr({ + name: options.name + ,accept: options.acceptMime + ,multiple: options.multiple + }); + }; + + //事件处理 + Class.prototype.events = function(){ + var that = this + ,options = that.config + + //设置当前选择的文件队列 + ,setChooseFile = function(files){ + that.chooseFiles = {}; + layui.each(files, function(i, item){ + var time = new Date().getTime(); + that.chooseFiles[time + '-' + i] = item; + }); + } + + //设置选择的文本 + ,setChooseText = function(files, filename){ + var elemFile = that.elemFile + ,item = options.item ? options.item : options.elem + ,value = files.length > 1 + ? files.length + '个文件' + : ((files[0] || {}).name || (elemFile[0].value.match(/[^\/\\]+\..+/g)||[]) || ''); + + if(elemFile.next().hasClass(ELEM_CHOOSE)){ + elemFile.next().remove(); + } + that.upload(null, 'choose'); + if(that.isFile() || options.choose) return; + elemFile.after(''+ value +''); + }; + + //点击上传容器 + options.elem.off('upload.start').on('upload.start', function(){ + var othis = $(this), data = othis.attr('lay-data'); + + if(data){ + try{ + data = new Function('return '+ data)(); + that.config = $.extend({}, options, data); + } catch(e){ + hint.error('Upload element property lay-data configuration item has a syntax error: ' + data) + } + } + + that.config.item = othis; + that.elemFile[0].click(); + }); + + //拖拽上传 + if(!(device.ie && device.ie < 10)){ + options.elem.off('upload.over').on('upload.over', function(){ + var othis = $(this) + othis.attr('lay-over', ''); + }) + .off('upload.leave').on('upload.leave', function(){ + var othis = $(this) + othis.removeAttr('lay-over'); + }) + .off('upload.drop').on('upload.drop', function(e, param){ + var othis = $(this), files = param.originalEvent.dataTransfer.files || []; + + othis.removeAttr('lay-over'); + setChooseFile(files); + + if(options.auto){ + that.upload(files); + } else { + setChooseText(files); + } + }); + } + + //文件选择 + that.elemFile.off('upload.change').on('upload.change', function(){ + var files = this.files || []; + setChooseFile(files); + options.auto ? that.upload() : setChooseText(files); //是否自动触发上传 + }); + + //手动触发上传 + options.bindAction.off('upload.action').on('upload.action', function(){ + that.upload(); + }); + + //防止事件重复绑定 + if(options.elem.data('haveEvents')) return; + + that.elemFile.on('change', function(){ + $(this).trigger('upload.change'); + }); + + options.elem.on('click', function(){ + if(that.isFile()) return; + $(this).trigger('upload.start'); + }); + + if(options.drag){ + options.elem.on('dragover', function(e){ + e.preventDefault(); + $(this).trigger('upload.over'); + }).on('dragleave', function(e){ + $(this).trigger('upload.leave'); + }).on('drop', function(e){ + e.preventDefault(); + $(this).trigger('upload.drop', e); + }); + } + + options.bindAction.on('click', function(){ + $(this).trigger('upload.action'); + }); + + options.elem.data('haveEvents', true); + }; + + //核心入口 + upload.render = function(options){ + var inst = new Class(options); + return thisUpload.call(inst); + }; + + exports(MOD_NAME, upload); +}); + diff --git a/static/layui/modules/util.js b/static/layui/modules/util.js new file mode 100644 index 0000000..bb8b870 --- /dev/null +++ b/static/layui/modules/util.js @@ -0,0 +1,248 @@ + +/*! + * util 工具组件 +*/ + +layui.define('jquery', function(exports){ + "use strict"; + + var $ = layui.$ + ,hint = layui.hint() + + //外部接口 + ,util = { + //固定块 + fixbar: function(options){ + var ELEM = 'layui-fixbar', TOP_BAR = 'layui-fixbar-top' + ,dom = $(document), body = $('body') + ,is, timer; + + options = $.extend({ + showHeight: 200 //出现TOP的滚动条高度临界值 + }, options); + + options.bar1 = options.bar1 === true ? '' : options.bar1; + options.bar2 = options.bar2 === true ? '' : options.bar2; + options.bgcolor = options.bgcolor ? ('background-color:' + options.bgcolor) : ''; + + var icon = [options.bar1, options.bar2, ''] //图标:信息、问号、TOP + ,elem = $(['
            ' + ,options.bar1 ? '
          • '+ icon[0] +'
          • ' : '' + ,options.bar2 ? '
          • '+ icon[1] +'
          • ' : '' + ,'
          • '+ icon[2] +'
          • ' + ,'
          '].join('')) + ,topBar = elem.find('.'+TOP_BAR) + ,scroll = function(){ + var stop = dom.scrollTop(); + if(stop >= (options.showHeight)){ + is || (topBar.show(), is = 1); + } else { + is && (topBar.hide(), is = 0); + } + }; + if($('.'+ ELEM)[0]) return; + + typeof options.css === 'object' && elem.css(options.css); + body.append(elem), scroll(); + + //bar点击事件 + elem.find('li').on('click', function(){ + var othis = $(this), type = othis.attr('lay-type'); + if(type === 'top'){ + $('html,body').animate({ + scrollTop : 0 + }, 200); + } + options.click && options.click.call(this, type); + }); + + //Top显示控制 + dom.on('scroll', function(){ + clearTimeout(timer); + timer = setTimeout(function(){ + scroll(); + }, 100); + }); + } + + //倒计时 + ,countdown: function(endTime, serverTime, callback){ + var that = this + ,type = typeof serverTime === 'function' + ,end = new Date(endTime).getTime() + ,now = new Date((!serverTime || type) ? new Date().getTime() : serverTime).getTime() + ,count = end - now + ,time = [ + Math.floor(count/(1000*60*60*24)) //天 + ,Math.floor(count/(1000*60*60)) % 24 //时 + ,Math.floor(count/(1000*60)) % 60 //分 + ,Math.floor(count/1000) % 60 //秒 + ]; + + if(type) callback = serverTime; + + var timer = setTimeout(function(){ + that.countdown(endTime, now + 1000, callback); + }, 1000); + + callback && callback(count > 0 ? time : [0,0,0,0], serverTime, timer); + + if(count <= 0) clearTimeout(timer); + return timer; + } + + //某个时间在当前时间的多久前 + ,timeAgo: function(time, onlyDate){ + var that = this + ,arr = [[], []] + ,stamp = new Date().getTime() - new Date(time).getTime(); + + //返回具体日期 + if(stamp > 1000*60*60*24*31){ + stamp = new Date(time); + arr[0][0] = that.digit(stamp.getFullYear(), 4); + arr[0][1] = that.digit(stamp.getMonth() + 1); + arr[0][2] = that.digit(stamp.getDate()); + + //是否输出时间 + if(!onlyDate){ + arr[1][0] = that.digit(stamp.getHours()); + arr[1][1] = that.digit(stamp.getMinutes()); + arr[1][2] = that.digit(stamp.getSeconds()); + } + return arr[0].join('-') + ' ' + arr[1].join(':'); + } + + //30天以内,返回“多久前” + if(stamp >= 1000*60*60*24){ + return ((stamp/1000/60/60/24)|0) + '天前'; + } else if(stamp >= 1000*60*60){ + return ((stamp/1000/60/60)|0) + '小时前'; + } else if(stamp >= 1000*60*3){ //3分钟以内为:刚刚 + return ((stamp/1000/60)|0) + '分钟前'; + } else if(stamp < 0){ + return '未来'; + } else { + return '刚刚'; + } + } + + //数字前置补零 + ,digit: function(num, length){ + var str = ''; + num = String(num); + length = length || 2; + for(var i = num.length; i < length; i++){ + str += '0'; + } + return num < Math.pow(10, length) ? str + (num|0) : num; + } + + //转化为日期格式字符 + ,toDateString: function(time, format){ + //若 null 或空字符,则返回空字符 + if(time === null || time === '') return ''; + + var that = this + ,date = new Date(function(){ + if(!time) return; + return isNaN(time) ? time : (typeof time === 'string' ? parseInt(time) : time) + }() || new Date()) + ,ymd = [ + that.digit(date.getFullYear(), 4) + ,that.digit(date.getMonth() + 1) + ,that.digit(date.getDate()) + ] + ,hms = [ + that.digit(date.getHours()) + ,that.digit(date.getMinutes()) + ,that.digit(date.getSeconds()) + ]; + + if(!date.getDate()) return hint.error('Invalid Msec for "util.toDateString(Msec)"'), ''; + + format = format || 'yyyy-MM-dd HH:mm:ss'; + return format.replace(/yyyy/g, ymd[0]) + .replace(/MM/g, ymd[1]) + .replace(/dd/g, ymd[2]) + .replace(/HH/g, hms[0]) + .replace(/mm/g, hms[1]) + .replace(/ss/g, hms[2]); + } + + //转义 html,防 xss 攻击 + ,escape: function(html){ + return String(html || '').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') + .replace(//g, '>') + .replace(/'/g, ''').replace(/"/g, '"'); + } + + //还原转义的 html + ,unescape: function(str){ + return String(str || '').replace(/\&/g, '&') + .replace(/\</g, '<').replace(/\>/g, '>') + .replace(/\'/, '\'').replace(/\"/, '"'); + } + + //让指定的元素保持在可视区域 + ,toVisibleArea: function(options){ + options = $.extend({ + margin: 160 //触发动作的边界值 + ,duration: 200 //动画持续毫秒数 + ,type: 'y' //触发方向,x 水平、y 垂直 + }, options); + + if(!options.scrollElem[0] || !options.thisElem[0]) return; + + var scrollElem = options.scrollElem //滚动元素 + ,thisElem = options.thisElem //目标元素 + ,vertical = options.type === 'y' //是否垂直方向 + ,SCROLL_NAME = vertical ? 'scrollTop' : 'scrollLeft' //滚动方法 + ,OFFSET_NAME = vertical ? 'top' : 'left' //坐标方式 + ,scrollValue = scrollElem[SCROLL_NAME]() //当前滚动距离 + ,size = scrollElem[vertical ? 'height' : 'width']() //滚动元素的尺寸 + ,scrollOffet = scrollElem.offset()[OFFSET_NAME] //滚动元素所处位置 + ,thisOffset = thisElem.offset()[OFFSET_NAME] - scrollOffet //目标元素当前的所在位置 + ,obj = {}; + + //边界满足条件 + if(thisOffset > size - options.margin || thisOffset < options.margin){ + obj[SCROLL_NAME] = thisOffset - size/2 + scrollValue + scrollElem.animate(obj, options.duration); + } + } + + //批量事件 + ,event: function(attr, obj, eventType){ + var _body = $('body'); + eventType = eventType || 'click'; + + //记录事件回调集合 + obj = util.event[attr] = $.extend(true, util.event[attr], obj) || {}; + + //清除委托事件 + util.event.UTIL_EVENT_CALLBACK = util.event.UTIL_EVENT_CALLBACK || {}; + _body.off(eventType, '*['+ attr +']', util.event.UTIL_EVENT_CALLBACK[attr]) + + //绑定委托事件 + util.event.UTIL_EVENT_CALLBACK[attr] = function(){ + var othis = $(this) + ,key = othis.attr(attr); + (typeof obj[key] === 'function') && obj[key].call(this, othis); + }; + + //清除旧事件,绑定新事件 + _body.on(eventType, '*['+ attr +']', util.event.UTIL_EVENT_CALLBACK[attr]); + + return obj; + } + }; + + // DOM 尺寸变化,该创意来自:http://benalman.com/projects/jquery-resize-plugin/ + /* + !function(a,b,c){"$:nomunge";function l(){f=b[g](function(){d.each(function(){var b=a(this),c=b.width(),d=b.height(),e=a.data(this,i);(c!==e.w||d!==e.h)&&b.trigger(h,[e.w=c,e.h=d])}),l()},e[j])}var f,d=a([]),e=a.resize=a.extend(a.resize,{}),g="setTimeout",h="resize",i=h+"-special-event",j="delay",k="throttleWindow";e[j]=250,e[k]=!0,a.event.special[h]={setup:function(){if(!e[k]&&this[g])return!1;var b=a(this);d=d.add(b),a.data(this,i,{w:b.width(),h:b.height()}),1===d.length&&l()},teardown:function(){if(!e[k]&&this[g])return!1;var b=a(this);d=d.not(b),b.removeData(i),d.length||clearTimeout(f)},add:function(b){function f(b,e,f){var g=a(this),h=a.data(this,i)||{};h.w=e!==c?e:g.width(),h.h=f!==c?f:g.height(),d.apply(this,arguments)}if(!e[k]&&this[g])return!1;var d;return a.isFunction(b)?(d=b,f):(d=b.handler,b.handler=f,void 0)}}}($,window); + */ + + //暴露接口 + exports('util', util); +}); \ No newline at end of file