├── .travis.yml ├── less ├── forms.less ├── msgs.less ├── icons.less ├── scharts.less ├── component-animations.less ├── utilities.less ├── grid.less ├── hero-unit.less ├── scaffolding.less ├── wells.less ├── breadcrumbs.less ├── close.less ├── accordion.less ├── layouts.less ├── checkbox.less ├── label.less ├── loading.less ├── tag.less ├── code.less ├── responsive-utilities.less ├── responsive.less ├── sui.less ├── tests │ ├── forms-responsive.html │ └── forms.html ├── icon-pc.less ├── modals.less ├── carousel.less ├── popovers.less ├── progress-bars.less └── timepicker.less ├── fonts ├── icon-pc.eot ├── icon-pc.ttf ├── icon-pc.woff ├── icon-moon.eot ├── icon-moon.ttf ├── icon-moon.woff ├── icon-touch.eot ├── icon-touch.ttf └── icon-touch.woff ├── docs ├── pictures │ ├── logo.png │ ├── docs │ │ ├── btn.png │ │ ├── forms.png │ │ ├── input.png │ │ ├── msgs.png │ │ ├── steps.png │ │ ├── tab.png │ │ ├── table.png │ │ ├── text.png │ │ ├── loading.png │ │ ├── popover.png │ │ ├── popover.psb │ │ ├── search.png │ │ ├── tooltip.png │ │ ├── breadcrumb.png │ │ ├── checkbox.png │ │ ├── datepicker.png │ │ ├── dropdown.png │ │ ├── pagination.png │ │ ├── progress.png │ │ └── timepicker.png │ ├── example-form.png │ ├── title-arrow.png │ ├── bootstrap-logo.png │ ├── example-table.png │ ├── index-demo-browsers.png │ └── index-demo-components.png ├── assets │ ├── imgs │ │ └── pagination1.png │ ├── zeroclipboard │ │ └── ZeroClipboard.swf │ ├── js │ │ ├── index.js │ │ ├── google-code-prettify │ │ │ └── prettify.css │ │ ├── application.js │ │ ├── html5shiv.js │ │ └── README.md │ ├── css │ │ ├── my-animate.css │ │ └── index.css │ └── less │ │ ├── my-animate.less │ │ └── index.less ├── templates │ ├── foot.jade │ ├── ga.jade │ ├── base_index.jade │ ├── head.jade │ ├── base.jade │ ├── discuss.jade │ ├── about.jade │ ├── text.jade │ ├── header.jade │ ├── examples.jade │ ├── download.jade │ ├── progress.jade │ ├── layout.jade │ ├── global.jade │ ├── label.jade │ ├── button-groups.jade │ ├── index.jade │ ├── breadcrumb.jade │ ├── loading.jade │ ├── tag.jade │ ├── dropdown-js.jade │ ├── pagination.jade │ ├── sidenav.jade │ ├── grid.jade │ ├── buttons.jade │ ├── pagination-js.jade │ ├── msgs.jade │ ├── tab-js.jade │ ├── tab.jade │ ├── checkbox.jade │ └── tree-js.jade ├── demos │ ├── templates │ │ └── icons.jade │ └── icons.html └── examples │ └── todo-create.html ├── js ├── .jshintrc ├── tests │ ├── unit │ │ ├── transition.js │ │ ├── affix.js │ │ ├── scrollspy.js │ │ ├── alert.js │ │ ├── phantom.js │ │ ├── tab.js │ │ ├── collapse.js │ │ └── button.js │ └── index.html ├── sui.js ├── transition.js ├── alert.js ├── button.js ├── checkbox.js ├── popover.js ├── affix.js ├── tab.js └── validate-rules.js ├── .gitignore ├── index.html ├── package.json ├── scripts └── mod_his.sh ├── developer.md ├── README.md ├── gulpfile.js ├── CONTRIBUTING.md └── Gruntfile.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.6 -------------------------------------------------------------------------------- /less/forms.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/less/forms.less -------------------------------------------------------------------------------- /less/msgs.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/less/msgs.less -------------------------------------------------------------------------------- /fonts/icon-pc.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-pc.eot -------------------------------------------------------------------------------- /fonts/icon-pc.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-pc.ttf -------------------------------------------------------------------------------- /fonts/icon-pc.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-pc.woff -------------------------------------------------------------------------------- /fonts/icon-moon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-moon.eot -------------------------------------------------------------------------------- /fonts/icon-moon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-moon.ttf -------------------------------------------------------------------------------- /fonts/icon-moon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-moon.woff -------------------------------------------------------------------------------- /fonts/icon-touch.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-touch.eot -------------------------------------------------------------------------------- /fonts/icon-touch.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-touch.ttf -------------------------------------------------------------------------------- /docs/pictures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/logo.png -------------------------------------------------------------------------------- /fonts/icon-touch.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/fonts/icon-touch.woff -------------------------------------------------------------------------------- /docs/pictures/docs/btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/btn.png -------------------------------------------------------------------------------- /docs/pictures/docs/forms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/forms.png -------------------------------------------------------------------------------- /docs/pictures/docs/input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/input.png -------------------------------------------------------------------------------- /docs/pictures/docs/msgs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/msgs.png -------------------------------------------------------------------------------- /docs/pictures/docs/steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/steps.png -------------------------------------------------------------------------------- /docs/pictures/docs/tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/tab.png -------------------------------------------------------------------------------- /docs/pictures/docs/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/table.png -------------------------------------------------------------------------------- /docs/pictures/docs/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/text.png -------------------------------------------------------------------------------- /less/icons.less: -------------------------------------------------------------------------------- 1 | @import 'icon-pc.less'; 2 | @import 'icon-touch.less'; 3 | @import 'icon-moon.less'; 4 | -------------------------------------------------------------------------------- /docs/pictures/docs/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/loading.png -------------------------------------------------------------------------------- /docs/pictures/docs/popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/popover.png -------------------------------------------------------------------------------- /docs/pictures/docs/popover.psb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/popover.psb -------------------------------------------------------------------------------- /docs/pictures/docs/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/search.png -------------------------------------------------------------------------------- /docs/pictures/docs/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/tooltip.png -------------------------------------------------------------------------------- /docs/pictures/example-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/example-form.png -------------------------------------------------------------------------------- /docs/pictures/title-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/title-arrow.png -------------------------------------------------------------------------------- /docs/assets/imgs/pagination1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/assets/imgs/pagination1.png -------------------------------------------------------------------------------- /docs/pictures/bootstrap-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/bootstrap-logo.png -------------------------------------------------------------------------------- /docs/pictures/docs/breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/breadcrumb.png -------------------------------------------------------------------------------- /docs/pictures/docs/checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/checkbox.png -------------------------------------------------------------------------------- /docs/pictures/docs/datepicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/datepicker.png -------------------------------------------------------------------------------- /docs/pictures/docs/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/dropdown.png -------------------------------------------------------------------------------- /docs/pictures/docs/pagination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/pagination.png -------------------------------------------------------------------------------- /docs/pictures/docs/progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/progress.png -------------------------------------------------------------------------------- /docs/pictures/docs/timepicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/docs/timepicker.png -------------------------------------------------------------------------------- /docs/pictures/example-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/example-table.png -------------------------------------------------------------------------------- /docs/pictures/index-demo-browsers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/index-demo-browsers.png -------------------------------------------------------------------------------- /docs/pictures/index-demo-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/pictures/index-demo-components.png -------------------------------------------------------------------------------- /docs/assets/zeroclipboard/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdc-alibaba/wqui/HEAD/docs/assets/zeroclipboard/ZeroClipboard.swf -------------------------------------------------------------------------------- /docs/templates/foot.jade: -------------------------------------------------------------------------------- 1 | script(src="assets/js/google-code-prettify/prettify.js") 2 | script(src='assets/zeroclipboard/ZeroClipboard.js') 3 | script(src="assets/js/application.js") 4 | script(src="http://localhost:3456/livereload.js") 5 | -------------------------------------------------------------------------------- /js/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "validthis": true, 3 | "laxcomma" : true, 4 | "laxbreak" : true, 5 | "browser" : true, 6 | "eqnull" : true, 7 | "debug" : true, 8 | "devel" : true, 9 | "boss" : true, 10 | "expr" : true, 11 | "asi" : true 12 | } 13 | -------------------------------------------------------------------------------- /less/scharts.less: -------------------------------------------------------------------------------- 1 | .chart-tooltip { 2 | position: absolute; 3 | z-index:10000000; 4 | color: #fff; 5 | padding: 6px; 6 | box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.1); 7 | border-radius: 3px; 8 | h4 { 9 | margin: 0 0 6px 0; 10 | font-size: 16px; 11 | } 12 | p { 13 | margin: 0; 14 | } 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /less/component-animations.less: -------------------------------------------------------------------------------- 1 | // 2 | // Component animations 3 | // -------------------------------------------------- 4 | 5 | 6 | .fade { 7 | opacity: 0; 8 | .transition(opacity .15s linear); 9 | &.in { 10 | opacity: 1; 11 | } 12 | } 13 | 14 | .collapse { 15 | position: relative; 16 | height: 0; 17 | overflow: hidden; 18 | .transition(height .35s ease); 19 | &.in { 20 | height: auto; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/templates/ga.jade: -------------------------------------------------------------------------------- 1 | script. 2 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 3 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 4 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 5 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 6 | 7 | ga('create', 'UA-50817062-1', 'taobao.org'); 8 | ga('send', 'pageview'); 9 | -------------------------------------------------------------------------------- /js/tests/unit/transition.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("transition") 4 | 5 | test("should be defined on jquery support object", function () { 6 | ok($.support.transition !== undefined, 'transition object is defined') 7 | }) 8 | 9 | test("should provide an end object", function () { 10 | ok($.support.transition ? $.support.transition.end : true, 'end string is defined') 11 | }) 12 | 13 | }) 14 | -------------------------------------------------------------------------------- /docs/templates/base_index.jade: -------------------------------------------------------------------------------- 1 | html(lang="en") 2 | head 3 | include head 4 | 5 | block head 6 | 7 | body 8 | include header 9 | block header 10 | +header('demos') 11 | mixin sidebar(highlight) 12 | include sidenav 13 | block content_wrap 14 | block footer 15 | .footer 16 | ul.unstyled 17 | li @time 2014.03.07 18 | li @author 商家业务事业部-电商服务支撑平台-UED团队 19 | 20 | include foot 21 | block js_block 22 | -------------------------------------------------------------------------------- /less/utilities.less: -------------------------------------------------------------------------------- 1 | // 2 | // Utility classes 3 | // -------------------------------------------------- 4 | 5 | 6 | // Quick floats 7 | .pull-right { 8 | float: right; 9 | } 10 | .pull-left { 11 | float: left; 12 | } 13 | 14 | // Toggling content 15 | .hide { 16 | display: none; 17 | } 18 | .show { 19 | display: block; 20 | } 21 | 22 | // Visibility 23 | .invisible { 24 | visibility: hidden; 25 | } 26 | 27 | // For Affix plugin 28 | .affix { 29 | position: fixed; 30 | } 31 | -------------------------------------------------------------------------------- /js/sui.js: -------------------------------------------------------------------------------- 1 | //核心组件 2 | require('./transition') 3 | require('./alert') 4 | require('./button') 5 | require('./carousel') 6 | require('./collapse') 7 | require('./dropdown') 8 | require('./modal') 9 | require('./tooltip') 10 | require('./popover') 11 | require('./scrollspy') 12 | require('./tab') 13 | require('./affix') 14 | require('./pagination') 15 | require('./validate') 16 | require('./validate-rules') 17 | require('./tree') 18 | require('./datepicker') 19 | require('./timepicker') 20 | require('./checkbox') 21 | -------------------------------------------------------------------------------- /less/grid.less: -------------------------------------------------------------------------------- 1 | // 2 | // Grid system 3 | // -------------------------------------------------- 4 | 5 | 6 | // Fixed default 7 | #grid > .core(@gridColumnWidth, @gridGutterWidth); 8 | 9 | // Fluid default 10 | #grid > .fluid(@fluidGridColumnWidth, @fluidGridGutterWidth); 11 | 12 | // Reset utility classes due to specificity 13 | [class*="span"].hide, 14 | .sui-row-fluid [class*="span"].hide { 15 | display: none; 16 | } 17 | 18 | [class*="span"].pull-right, 19 | .sui-row-fluid [class*="span"].pull-right { 20 | float: right; 21 | } 22 | -------------------------------------------------------------------------------- /docs/assets/js/index.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 'use strict'; 3 | var windowHeight = $(window).height() 4 | 5 | var onScroll = function() { 6 | $('.jumbotron').each(function() { 7 | var scrollTop = $(document).scrollTop() 8 | var $this = $(this) 9 | var offsetBottom = windowHeight - ($this.offset()['top'] - scrollTop) 10 | if(offsetBottom > Math.min(windowHeight / 2, 300)) { 11 | $this.addClass('inview') 12 | } 13 | }) 14 | } 15 | $(document).scroll(onScroll) 16 | setTimeout(onScroll, 1000) 17 | }) 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.zip 10 | *.vi 11 | *~ 12 | *.sass-cache 13 | 14 | # OS or Editor folders 15 | .DS_Store 16 | ._* 17 | Thumbs.db 18 | .cache 19 | .project 20 | .settings 21 | .tmproj 22 | *.esproj 23 | nbproject 24 | *.sublime-project 25 | *.sublime-workspace 26 | 27 | # Komodo 28 | *.komodoproject 29 | .komodotools 30 | 31 | # Folders to ignore 32 | .hg 33 | .svn 34 | .CVS 35 | .idea 36 | node_modules 37 | #bootstrap 38 | docs/assets/fonts 39 | 40 | pid.txt 41 | 42 | #build files 43 | build/ 44 | docs/*.html 45 | .package/ 46 | -------------------------------------------------------------------------------- /less/hero-unit.less: -------------------------------------------------------------------------------- 1 | // 2 | // Hero unit 3 | // -------------------------------------------------- 4 | 5 | 6 | .sui-hero-unit { 7 | padding: 60px; 8 | margin-bottom: 30px; 9 | font-size: 18px; 10 | font-weight: 200; 11 | line-height: @baseLineHeight * 1.5; 12 | color: @heroUnitLeadColor; 13 | background-color: @heroUnitBackground; 14 | .border-radius(6px); 15 | h1 { 16 | margin-bottom: 0; 17 | font-size: 60px; 18 | line-height: 1; 19 | color: @heroUnitHeadingColor; 20 | letter-spacing: -1px; 21 | } 22 | li { 23 | line-height: @baseLineHeight * 1.5; // Reset since we specify in type.less 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/templates/head.jade: -------------------------------------------------------------------------------- 1 | meta(charset="utf-8") 2 | block title 3 | meta(http-equiv="X-UA-Compatible",content="IE=edge") 4 | meta(name="viewport",content="width=device-width, initial-scale=1") 5 | link(href="assets/css/animate.css",rel="stylesheet") 6 | link(href="../.package/css/sui.css",rel="stylesheet") 7 | link(href="assets/css/docs.css" rel="stylesheet") 8 | link(href="assets/js/google-code-prettify/prettify.css" rel="stylesheet") 9 | link(rel="shortcut icon" href="pictures/logo.png") 10 | script(src="../js/lib/jquery.js") 11 | script(src="../.package/js/sui.js") 12 | include ga 13 | 14 | //[if lt IE 9]> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 16 | 17 | 18 |
19 |
20 | SUI v1.0 21 |
22 |

23 | 访问 SUI 官方网站 24 |

25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /less/breadcrumbs.less: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumbs 3 | // -------------------------------------------------- 4 | 5 | .sui-breadcrumb { 6 | padding: 0; 7 | margin: 0 0 @baseMargin; 8 | list-style: none; 9 | font-size: @baseFontSize; 10 | font-weight: normal; 11 | .border-radius(@borderRadiusSmall); 12 | > li { 13 | display: inline-block; 14 | .ie7-inline-block(); 15 | // text-shadow: 0 1px 0 @white; 16 | + li:before { 17 | content: ">"; 18 | padding: 0 5px; 19 | color: #ccc; 20 | } 21 | } 22 | > .active { 23 | color: @grayLight; 24 | } 25 | &.breadcrumb-large { 26 | font-size: @fontSizeLarge; 27 | } 28 | 29 | &.breadcrumb-bold { 30 | font-weight: bold; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/templates/discuss.jade: -------------------------------------------------------------------------------- 1 | div#disqus_thread 2 | 3 | script(type="text/javascript"). 4 | /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ 5 | var disqus_shortname = 'sui-alibaba'; // required: replace example with your forum shortname 6 | 7 | /* * * DON'T EDIT BELOW THIS LINE * * */ 8 | (function() { 9 | var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; 10 | dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; 11 | (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); 12 | })(); 13 | a(href="http://disqus.com" class="dsq-brlink") comments powered by 14 | span.logo-disqus Disqus 15 | -------------------------------------------------------------------------------- /less/close.less: -------------------------------------------------------------------------------- 1 | // 2 | // Close icons 3 | // -------------------------------------------------- 4 | 5 | 6 | .sui-close { 7 | float: right; 8 | font-size: 24px; 9 | line-height: @baseLineHeight; 10 | color: #666; 11 | text-shadow: 0 1px 0 rgba(255,255,255,1); 12 | outline: none; 13 | &:hover, 14 | &:focus { 15 | color: #ff5050; 16 | text-decoration: none; 17 | cursor: pointer; 18 | } 19 | &:focus { 20 | color: #dd5050; 21 | } 22 | } 23 | 24 | // Additional properties for button version 25 | // iOS requires the button element instead of an anchor tag. 26 | // If you want the anchor version, it requires `href="#"`. 27 | button.sui-close { 28 | padding: 0; 29 | cursor: pointer; 30 | background: transparent; 31 | border: 0; 32 | -webkit-appearance: none; 33 | } 34 | -------------------------------------------------------------------------------- /less/accordion.less: -------------------------------------------------------------------------------- 1 | // 2 | // Accordion 3 | // -------------------------------------------------- 4 | 5 | 6 | // Parent container 7 | .sui-accordion { 8 | margin-bottom: @baseLineHeight; 9 | 10 | // Group == heading + body 11 | .accordion-group { 12 | margin-bottom: 2px; 13 | border: 1px solid #e5e5e5; 14 | .border-radius(@baseBorderRadius); 15 | } 16 | .accordion-heading { 17 | border-bottom: 0; 18 | } 19 | .accordion-heading .accordion-toggle { 20 | display: block; 21 | padding: 8px 15px; 22 | } 23 | 24 | // General toggle styles 25 | .accordion-toggle { 26 | cursor: pointer; 27 | } 28 | 29 | // Inner needs the styles because you can't animate properly with any styles on the element 30 | .accordion-inner { 31 | padding: 9px 15px; 32 | border-top: 1px solid #e5e5e5; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/assets/css/my-animate.css: -------------------------------------------------------------------------------- 1 | .animated { 2 | -webkit-animation-duration: 1s; 3 | animation-duration: 1s; 4 | -webkit-animation-fill-mode: both; 5 | animation-fill-mode: both; 6 | } 7 | @-webkit-keyframes myBounceInUp { 8 | 0% { 9 | opacity: 0; 10 | -webkit-transform: translateY(200px); 11 | transform: translateY(200px); 12 | } 13 | 100% { 14 | opacity: 1; 15 | -webkit-transform: translateY(0); 16 | transform: translateY(0); 17 | } 18 | } 19 | @keyframes myBounceInUp { 20 | 0% { 21 | opacity: 0; 22 | -webkit-transform: translateY(200px); 23 | transform: translateY(200px); 24 | } 25 | 100% { 26 | opacity: 1; 27 | -webkit-transform: translateY(0); 28 | transform: translateY(0); 29 | } 30 | } 31 | .myBounceInUp { 32 | -webkit-animation-name: myBounceInUp; 33 | animation-name: myBounceInUp; 34 | } 35 | -------------------------------------------------------------------------------- /docs/assets/less/my-animate.less: -------------------------------------------------------------------------------- 1 | .animated { 2 | -webkit-animation-duration: 1s; 3 | animation-duration: 1s; 4 | -webkit-animation-fill-mode: both; 5 | animation-fill-mode: both; 6 | } 7 | @-webkit-keyframes myBounceInUp { 8 | 0% { 9 | opacity: 0; 10 | -webkit-transform: translateY(200px); 11 | transform: translateY(200px); 12 | } 13 | 14 | 100% { 15 | opacity: 1; 16 | -webkit-transform: translateY(0); 17 | transform: translateY(0); 18 | } 19 | } 20 | 21 | @keyframes myBounceInUp { 22 | 0% { 23 | opacity: 0; 24 | -webkit-transform: translateY(200px); 25 | transform: translateY(200px); 26 | } 27 | 28 | 100% { 29 | opacity: 1; 30 | -webkit-transform: translateY(0); 31 | transform: translateY(0); 32 | } 33 | } 34 | 35 | .myBounceInUp { 36 | -webkit-animation-name: myBounceInUp; 37 | animation-name: myBounceInUp; 38 | } 39 | -------------------------------------------------------------------------------- /js/tests/unit/affix.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("affix") 4 | 5 | test("should provide no conflict", function () { 6 | var affix = $.fn.affix.noConflict() 7 | ok(!$.fn.affix, 'affix was set back to undefined (org value)') 8 | $.fn.affix = affix 9 | }) 10 | 11 | test("should be defined on jquery object", function () { 12 | ok($(document.body).affix, 'affix method is defined') 13 | }) 14 | 15 | test("should return element", function () { 16 | ok($(document.body).affix()[0] == document.body, 'document.body returned') 17 | }) 18 | 19 | test("should exit early if element is not visible", function () { 20 | var $affix = $('
').affix() 21 | $affix.data('affix').checkPosition() 22 | ok(!$affix.hasClass('affix'), 'affix class was not added') 23 | }) 24 | 25 | }) 26 | -------------------------------------------------------------------------------- /less/layouts.less: -------------------------------------------------------------------------------- 1 | // 2 | // Layouts 3 | // -------------------------------------------------- 4 | 5 | 6 | // Container (centered, fixed-width layouts) 7 | .sui-container { 8 | .container-fixed(); 9 | } 10 | 11 | // Fluid layouts (left aligned, with sidebar, min- & max-width content) 12 | .sui-container-fluid { 13 | padding-right: @gridGutterWidth; 14 | padding-left: @gridGutterWidth; 15 | .clearfix(); 16 | } 17 | 18 | // 2 & 3 column layout 19 | 20 | .sui-layout > { 21 | position: relative; 22 | .sidebar { 23 | width: @layoutSidebarWidth; 24 | float: left; 25 | } 26 | .sidebar + .sidebar { 27 | float: right; 28 | } 29 | .content + .sidebar { 30 | position: absolute; 31 | right: 0; 32 | top: 0; 33 | } 34 | .content { 35 | margin-left: @layoutSidebarWidth; 36 | } 37 | 38 | &.layout3 { 39 | > .content { 40 | margin-right: @layoutSidebarWidth; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sui", 3 | "description": "sui.", 4 | "version": "1.0.0", 5 | "keywords": [ 6 | "sui", 7 | "css" 8 | ], 9 | "homepage": "", 10 | "author": "", 11 | "scripts": { 12 | "test": "grunt test" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "http://gitlab.alibaba-inc.com/sj/dpl" 17 | }, 18 | "licenses": [ 19 | { 20 | "type": "Apache-2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0" 22 | } 23 | ], 24 | "dependencies": { 25 | "grunt": "~0.4.4", 26 | "grunt-contrib-connect": "~0.7.1", 27 | "grunt-contrib-copy": "~0.5.0", 28 | "grunt-contrib-jade": "~0.11.0", 29 | "grunt-contrib-jshint": "~0.9.2", 30 | "grunt-contrib-watch": "~0.6.1", 31 | "grunt-browserify": "~2.0.1", 32 | "grunt-contrib-less": "~0.11.0", 33 | "grunt-contrib-uglify": "~0.4.0", 34 | "grunt-newer": "~0.7.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/assets/js/google-code-prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .com { color: #93a1a1; } 2 | .lit { color: #195f91; } 3 | .pun, .opn, .clo { color: #93a1a1; } 4 | .fun { color: #dc322f; } 5 | .str, .atv { color: #D14; } 6 | .kwd, .prettyprint .tag { color: #1e347b; } 7 | .typ, .atn, .dec, .var { color: teal; } 8 | .pln { color: #48484c; } 9 | 10 | .prettyprint { 11 | padding: 8px; 12 | background-color: #f7f7f9; 13 | border: 1px solid #e1e1e8; 14 | } 15 | .prettyprint.linenums { 16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 19 | } 20 | 21 | /* Specify class=linenums on a pre to get line numbering */ 22 | ol.linenums { 23 | margin: 0 0 0 33px; /* IE indents via margin-left */ 24 | } 25 | ol.linenums li { 26 | padding-left: 12px; 27 | color: #bebec5; 28 | line-height: 20px; 29 | text-shadow: 0 1px 0 #fff; 30 | } -------------------------------------------------------------------------------- /docs/templates/about.jade: -------------------------------------------------------------------------------- 1 | extends base_index 2 | 3 | block title 4 | title 关于 5 | 6 | block header 7 | +header('about') 8 | 9 | block content_wrap 10 | .sui-container 11 | h1.sui-page-header 关于 12 | 13 | p.sui-lead 14 | | SUI 是商家后台系统的设计规范和前端组件库。 15 | 16 | h3 设计师 17 | 18 | p.sui-lead 19 | a(href='#') 致轩 20 | |, 21 | a(href='#') 裴芸 22 | |, 23 | a(href='#') 泉源 24 | | 以及 25 | strong 商家业务事业部设计师团队。 26 | 27 | h3 前端 28 | 29 | p.sui-lead 30 | a(href='#') 银鹏 31 | |, 32 | a(href='#') 半边 33 | |, 34 | a(href='#') 酥心 35 | |, 36 | a(href='#') 阿凯 37 | |, 38 | a(href='#') 墨焰 39 | |, 40 | a(href='#') 任行 41 | | 以及 42 | strong 商家业务事业部前端团队。 43 | 44 | h3 联系我们 45 | p.sui-lead 46 | |如果有任何问题和建议可以直接联系我们。
47 | |设计和交互请联系 48 | a(href='mailto:yun.peiy@alibaba-inc.com') 裴芸 49 | a(href='mailto:jingzhu.caijzh@taobao.com') 泉源 50 | |。 51 | br 52 | |技术以及其他任何问题都可以联系 53 | a(href='mailto:hongxun.lhx@alibaba-inc.com') 任行 54 | |。 55 | -------------------------------------------------------------------------------- /scripts/mod_his.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | git filter-branch -f --env-filter ' 4 | 5 | an="$GIT_AUTHOR_NAME" 6 | am="$GIT_AUTHOR_EMAIL" 7 | cn="$GIT_COMMITTER_NAME" 8 | cm="$GIT_COMMITTER_EMAIL" 9 | 10 | if [ "$GIT_COMMITTER_EMAIL" = "lihongxun945@163.com" ] 11 | then 12 | cn="hongxun.lhx" 13 | cm="hongxun.lhx@alibaba-inc.com" 14 | fi 15 | if [ "$GIT_AUTHOR_EMAIL" = "lihongxun945@163.com" ] 16 | then 17 | an="hongxun.lhx" 18 | am="hongxun.lhx@alibaba-inc.com" 19 | fi 20 | 21 | if [ "$GIT_COMMITTER_EMAIL" = "itaofe@gmail.com" ] 22 | then 23 | cn="半边" 24 | cm="zangtao.zt@alibaba-inc.com" 25 | fi 26 | if [ "$GIT_AUTHOR_EMAIL" = "itaofe@gmail.com" ] 27 | then 28 | an="半边" 29 | am="zangtao.zt@alibaba-inc.com" 30 | fi 31 | if [ "$GIT_COMMITTER_EMAIL" = "yiye.js@gmail.com" ] 32 | then 33 | cn="何道" 34 | cm="shuangling.ysl@alibaba-inc.com" 35 | fi 36 | if [ "$GIT_AUTHOR_EMAIL" = "yiye.js@gmail.com" ] 37 | then 38 | an="何道" 39 | am="shuangling.ysl@alibaba-inc.com" 40 | fi 41 | 42 | export GIT_AUTHOR_NAME="$an" 43 | export GIT_AUTHOR_EMAIL="$am" 44 | export GIT_COMMITTER_NAME="$cn" 45 | export GIT_COMMITTER_EMAIL="$cm" 46 | ' 47 | -------------------------------------------------------------------------------- /docs/demos/templates/icons.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 图标 5 | 6 | block content 7 | div.container 8 | - var ROLES = [{ roles: ["arrow-down", "arrow-left", "arrow-right", "arrow-up", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "circle-arrow-down", "circle-arrow-left", "circle-arrow-right", "circle-arrow-up"], name: "方向图标" }] 9 | - ROLES.push({ roles: ["ban-circle", "bell", "exclamation-sign", "ok", "ok-circle", "ok-sign", "remove", "remove-circle", "remove-sign", "warning-sign"], name: "提示反馈"}) 10 | - ROLES.push({ roles: ["calendar", "pencil", "search"], name: "表单"}) 11 | - ROLES.push({ roles: ["backward"," forward"," fast-backward","fast-forward","play","play-circle","step-backward","step-forward","stop"], name: "多媒体"}) 12 | - ROLES.push({ roles: ["book","bookmark","comment","download","file","flag","fullscreen","lock","move","plus","plus-sign","star","star-empty","user","zoom-in","zoom-out", "cog"], name: "其他"}) 13 | each v in ROLES 14 | h2 #{v.name} 15 | each r in v.roles 16 | - var classname = 'glyphicon glyphicon-' 17 | - classname += r 18 | i(class='#{classname}') 19 | |   20 | -------------------------------------------------------------------------------- /less/checkbox.less: -------------------------------------------------------------------------------- 1 | .checkbox-pretty, 2 | .radio-pretty 3 | { 4 | display: block; 5 | input { 6 | //这里不能用display:none,或者visibility:hidden;否则在ie下input会直接被忽略 7 | opacity: 0; 8 | position: absolute; 9 | left: -9999px; 10 | } 11 | span { 12 | .sui-icon; 13 | font-family: 'icon-pc'; 14 | } 15 | span:before { 16 | content: "\e605"; 17 | margin-right: 2px; 18 | vertical-align: middle; 19 | font-size: 150%; 20 | color: @checkboxColor; 21 | margin-left: -3px; 22 | } 23 | 24 | 25 | &.checked > span:before { 26 | content: "\e607"; 27 | color: @checkboxCheckedColor; 28 | } 29 | &.halfchecked > span:before { 30 | content: "\e606"; 31 | color: @checkboxCheckedColor; 32 | } 33 | &:hover { 34 | span:before { 35 | color: @checkboxHighlightColor; 36 | } 37 | } 38 | &.inline { 39 | display: inline; 40 | } 41 | &.inline + &.inline { 42 | margin-left: 6px; 43 | } 44 | 45 | &.disabled { 46 | color: lighten(@checkboxDisableColor, 10%); 47 | span:before { 48 | color: @checkboxDisableColor; 49 | } 50 | } 51 | } 52 | 53 | .radio-pretty { 54 | span:before { 55 | content: "\e603"; 56 | } 57 | &.checked > span:before { 58 | content: "\e604"; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /docs/templates/text.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 文本 5 | 6 | block sidebar 7 | +sidebar('text') 8 | 9 | block content 10 | div.sui-page-header 11 | h1 文本 12 | p.sui-lead 13 | | 不同功能和颜色的文本 14 | 15 | h2 不同类型 16 | ul.sui-nav.nav-tabs.nav-large 17 | li.active 18 | a(href='#demo1', data-toggle='tab') 示例 19 | li 20 | a(href='#code1', data-toggle='tab') 代码 21 | 22 | style. 23 | .bs-docs-example ul { 24 | margin-bottom: 20px; 25 | } 26 | .bs-docs-example li { 27 | display: inline-block; 28 | margin: 0 10px 10px 0; 29 | } 30 | div.tab-content 31 | div.tab-pane.active#demo1 32 | div.bs-docs-example 33 | - var cls = ['nav', 'description', 'less-important', 'disabled', 'help', 'success', 'warning', 'error'] 34 | - var txt = ['导航文本', '辅助说明', '次级文本', '禁用文本', '说明提示', '强调', '警告', '错误', '公告'] 35 | ul 36 | li 37 | span 默认文本 38 | each clsi, i in cls 39 | li 40 | span(class='sui-text-#{clsi}') #{txt[i]} 41 | div.tab-pane#code1 42 | pre.prettyprint.linenums(data-target='#demo1>div') 43 | ul.demo-operations.clearfix 44 | li 45 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 46 | -------------------------------------------------------------------------------- /less/label.less: -------------------------------------------------------------------------------- 1 | // 2 | // Labels and badges 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base classes 7 | .sui-label { 8 | display: inline-block; 9 | padding: 2px 10px; 10 | font-size: @baseFontSize * .846; 11 | line-height: @fontSizeLarge; // ensure proper line-height if floated 12 | color: @white; 13 | vertical-align: baseline; 14 | white-space: nowrap; 15 | text-shadow: 0 -1px 0 rgba(0,0,0,.25); 16 | background-color: @grayLight; 17 | .border-radius(1px); 18 | cursor: default; 19 | } 20 | 21 | // Empty labels/badges collapse 22 | .sui-label:empty { 23 | display: none; 24 | } 25 | 26 | 27 | // Colors 28 | .sui-label { 29 | // danger (red) 30 | &.label-danger { background-color: @errorText; } 31 | // Warnings (orange) 32 | &.label-warning { background-color: @orange; } 33 | // Success (green) 34 | &.label-success { background-color: @successText; } 35 | // Info (turquoise) 36 | &.label-info { background-color: @infoText; } 37 | // Inverse (black) 38 | &.label-inverse { background-color: @grayDark; } 39 | } 40 | 41 | // Quick fix for labels in buttons 42 | .sui-btn { 43 | .sui-label { 44 | position: relative; 45 | top: -1px; 46 | } 47 | } 48 | .btn-mini { 49 | .sui-label { 50 | top: 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/templates/header.jade: -------------------------------------------------------------------------------- 1 | mixin header(highlight) 2 | - var classIndex = '' 3 | - var classDemos = '' 4 | - var classExamples = '' 5 | - var classTutorial = '' 6 | - var classDownload = '' 7 | - var classAbout = '' 8 | 9 | if highlight == 'demos' 10 | - classDemos = 'active' 11 | else if highlight == 'examples' 12 | - classExamples = 'active' 13 | else if highlight == 'tutorial' 14 | - classTutorial = 'active' 15 | else if highlight == 'download' 16 | - classDownload = 'active' 17 | else if highlight == 'about' 18 | - classAbout = 'active' 19 | else 20 | - classIndex = 'active' 21 | div.sui-navbar.navbar-inverse.navbar-fixed-top 22 | div.navbar-inner 23 | .sui-container 24 | a.sui-brand(href="./index.html") 25 | i.sui-icon.icon-github-alt   26 | | WQUI 27 | ul.sui-nav 28 | li(class=classIndex) 29 | a(href="./index.html") 首页 30 | li(class=classDemos) 31 | a(href="./global.html") 组件库 32 | li(class=classExamples) 33 | a(href="./examples.html") 案例 34 | li(class=classTutorial) 35 | a(href="./tutorial.html") 教程 36 | li(class=classDownload) 37 | a(href="./download.html") 下载 38 | li(class=classAbout) 39 | a(href="./about.html") 关于 40 | -------------------------------------------------------------------------------- /docs/templates/examples.jade: -------------------------------------------------------------------------------- 1 | extends base_index 2 | 3 | block title 4 | title 案例 5 | 6 | block head 7 | style(type='text/css'). 8 | .jumbotron { 9 | background-color: #6f5499; 10 | color: #fff; 11 | padding: 40px 0; 12 | } 13 | 14 | .sui-row { 15 | margin-top: 20px; 16 | border-radius: 6px; 17 | background: #DEE8F3; 18 | } 19 | 20 | .sui-row [class^='span'] { 21 | padding: 20px; 22 | box-sizing: border-box; 23 | } 24 | 25 | block header 26 | +header('examples') 27 | 28 | block content_wrap 29 | .jumbotron 30 | .sui-container 31 | h1 经典案例 32 | p.sui-lead 33 | | 使用SUI可以轻松搭建一个漂亮的页面,她有丰富的组件库可以像搭积木一样轻松搭建一个页面。 34 | p.sui-lead 35 | | 你现在正在浏览的官网就是用SUI组件搭建的,想要更多的案例,看看下面这些精美的页面吧。 36 | 37 | 38 | .sui-container 39 | .sui-row 40 | .span8 41 | a.picture(href='examples/serving-custom.html', target='_blank') 42 | img(src='pictures/example-form.png') 43 | .span4 44 | h2 订购服务 45 | p.lead 46 | 经典的表单应用页面。包括输入框,按钮,图片,提示等。 47 | .sui-row 48 | .span4 49 | h2 我的采购单 50 | p.lead 51 | 典型的搜索页面,由一个多条件的搜索框和一个由复杂table组成的搜索结果。 52 | .span8 53 | a.picture(href='examples/my-purchase.html', target="_blank") 54 | img(src='pictures/example-table.png') 55 | 56 | -------------------------------------------------------------------------------- /docs/templates/download.jade: -------------------------------------------------------------------------------- 1 | extends base_index 2 | 3 | block title 4 | title 下载 5 | 6 | block head 7 | style(type='text/css'). 8 | .btn-huge { 9 | padding: 15px 40px; 10 | font-size: 20px; 11 | } 12 | block header 13 | +header('download') 14 | 15 | block content_wrap 16 | .sui-container 17 | h1.sui-page-header 下载 WQUI 18 | 19 | h2 直接引用CDN文件 20 | p 21 | | 最简单使用方式是直接引用我们的CDN,不需要下载任何文件: 22 | ul.unstyled 23 | li 24 | a(href='http://g.tbcdn.cn/sj/wqui/1.0.0/css/sui.min.css', target='_blank') g.tbcdn.cn/sj/wqui/1.0.0/css/sui.min.css 25 | li 26 | a(href='http://g.tbcdn.cn/sj/wqui/1.0.0/js/sui.min.js', target='_blank') g.tbcdn.cn/sj/wqui/1.0.0/js/sui.min.js 27 | 28 | p 29 | | 注意在引用sui.min.js之前必须先引用 jquery。 30 | 31 | h2 下载zip文件 32 | 33 | p.sui-lead 34 | | 包括所有的源代码和文档。 35 | 36 | p 37 | a.sui-btn.btn-primary.btn-xlarge.btn-huge(href='https://github.com/sdc-alibaba/wqui/archive/build.zip', target="_blank") 38 | i.sui-icon.icon-download 39 | | download WQUI-1.0.source.zip 40 | 41 | h2 获取最新源码 42 | 43 | p.sui-lead 44 | |可以从 github 上直接获取最新的代码,项目地址: 45 | a.sui-btn.btn-success.btn-huge(href='https://github.com/sdc-alibaba/wqui', target="_blank") 46 | i.sui-icon.icon-github-alt 47 | | view WQUI on github 48 | -------------------------------------------------------------------------------- /docs/templates/progress.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 进度条 5 | 6 | block head 7 | style(type='text/css'). 8 | .sui-progress { 9 | max-width: 400px; 10 | } 11 | 12 | block sidebar 13 | +sidebar('progress') 14 | 15 | block content 16 | 17 | h1 进度条 18 | 19 | h2.sui-page-header 设计规范 20 | 21 | div.docs-description 22 | img(src='pictures/docs/progress.png') 23 | 24 | ul.demo-operations.clearfix 25 | li 26 | a(href='#') 下载psd文件 27 | 28 | h2.sui-page-header 开发者文档 29 | p.sui-lead 30 | | 不同功能和样式的进度条。 31 | 32 | ul.sui-nav.nav-tabs.nav-large 33 | li.active 34 | a(href='#demo1', data-toggle='tab') 示例 35 | li 36 | a(href='#code1', data-toggle='tab') 代码 37 | div.tab-content 38 | div.tab-pane.active#demo1 39 | div.bs-docs-example 40 | div.sui-progress 41 | div.bar(style="width: 20%;") 42 | .bar-text 20% 43 | 44 | div.sui-progress.progress-small 45 | div.bar(style="width: 30%;") 46 | .bar-text 30% 47 | 48 | div.sui-progress.progress-small 49 | div.bar(style="width: 40%;") 50 | 51 | div.tab-pane#code12 52 | pre.prettyprint.linenums(data-target='#demo12>div') 53 | 54 | ul.demo-operations.clearfix 55 | li 56 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 57 | -------------------------------------------------------------------------------- /js/tests/unit/scrollspy.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("scrollspy") 4 | 5 | test("should provide no conflict", function () { 6 | var scrollspy = $.fn.scrollspy.noConflict() 7 | ok(!$.fn.scrollspy, 'scrollspy was set back to undefined (org value)') 8 | $.fn.scrollspy = scrollspy 9 | }) 10 | 11 | test("should be defined on jquery object", function () { 12 | ok($(document.body).scrollspy, 'scrollspy method is defined') 13 | }) 14 | 15 | test("should return element", function () { 16 | ok($(document.body).scrollspy()[0] == document.body, 'document.body returned') 17 | }) 18 | 19 | test("should switch active class on scroll", function () { 20 | var sectionHTML = '
' 21 | , $section = $(sectionHTML).append('#qunit-fixture') 22 | , topbarHTML ='
' 23 | + '
' 24 | + '
' 25 | + '

Bootstrap

' 26 | + '' 29 | + '
' 30 | + '
' 31 | + '
' 32 | , $topbar = $(topbarHTML).scrollspy() 33 | 34 | ok($topbar.find('.active', true)) 35 | }) 36 | 37 | }) 38 | -------------------------------------------------------------------------------- /docs/templates/layout.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 左右定宽三栏布局 5 | 6 | block head 7 | style(type='text/css'). 8 | .bs-docs-example .sui-layout div { background-color: #f5faff; min-height: 100px; } 9 | .bs-docs-example .sui-layout .sidebar { background: #3096de; } 10 | 11 | block sidebar 12 | +sidebar('layout') 13 | 14 | block content 15 | h1 左右定宽三栏布局 16 | 17 | h2.sui-page-header 开发者文档 18 | 19 | p.sui-lead 20 | | 不同与栅格系统的响应式布局,layout 是一个简单的两边固定宽度中间自适应的布局。 21 | 22 | ul.sui-nav.nav-tabs.nav-large 23 | li.active 24 | a(href='#demo1', data-toggle='tab') 示例 25 | li 26 | a(href='#code1', data-toggle='tab') 代码 27 | li 28 | a(href='#doc1', data-toggle='tab') 文档 29 | div.tab-content 30 | div.tab-pane.active#demo1 31 | div.bs-docs-example 32 | h2 2 col layout 33 | div.sui-layout 34 | div.sidebar sidebar 35 | div.content content 36 | h2 3 col layout 37 | div.sui-layout.layout3 38 | div.sidebar sidebar 39 | div.content content 40 | div.sidebar sidebar 41 | div.tab-pane#code1 42 | pre.prettyprint.linenums(data-target='#demo1>div') 43 | div.tab-pane#doc1 44 | |左右宽度固定中间自适应的布局,默认宽度会铺满整个屏幕。非常适合用在有侧边栏的全屏页面布局。默认的两边宽度是150px,可以根据需要自己重载。 45 | ul.demo-operations.clearfix 46 | li 47 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 48 | -------------------------------------------------------------------------------- /less/loading.less: -------------------------------------------------------------------------------- 1 | .icon-pc-loading { 2 | .sui-loading.loading-large & { 3 | font-size: 60px; 4 | } 5 | .sui-loading.loading-xlarge & { 6 | font-size: 80px; 7 | } 8 | .sui-loading.loading-xxlarge & { 9 | font-size: 100px; 10 | } 11 | .sui-loading.loading-small & { 12 | font-size: 40px; 13 | } 14 | .sui-loading.loading-xsmall & { 15 | font-size: 30px; 16 | } 17 | .sui-loading.loading-xxsmall & { 18 | font-size: 20px; 19 | } 20 | .sui-loading.loading-dark & { 21 | color: @black; 22 | opacity: 0.9; 23 | } 24 | .sui-loading.loading-light & { 25 | color: @gray; 26 | opacity: 0.2; 27 | } 28 | } 29 | 30 | .sui-loading { 31 | text-align: center; 32 | display: block; 33 | &.loading-inline { 34 | display: inline-block; 35 | } 36 | .icon-pc-loading { 37 | -webkit-animation: rotation 2s infinite linear; 38 | -moz-animation: rotation 2s infinite linear; 39 | animation: rotation 2s infinite linear; 40 | display: inline-block; 41 | font-size: 50px; 42 | color: @btnPrimaryBackground; 43 | } 44 | 45 | @-webkit-keyframes rotation { 46 | from {-webkit-transform: rotate(0deg);} 47 | to {-webkit-transform: rotate(359deg);} 48 | } 49 | @-moz-keyframes rotation { 50 | from {-moz-transform: rotate(0deg);} 51 | to {-moz-transform: rotate(359deg);} 52 | } 53 | @keyframes rotation { 54 | from {transform: rotate(0deg);} 55 | to {transform: rotate(359deg);} 56 | } 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/assets/less/index.less: -------------------------------------------------------------------------------- 1 | @import 'my-animate.less'; 2 | 3 | .intro { 4 | background-color: #6f5499; 5 | color: #fff; 6 | padding: 80px 0; 7 | } 8 | 9 | .jumbotron { 10 | padding: 60px 0; 11 | color: #fff; 12 | } 13 | .beautify(@bg) { 14 | background-color: lighten(@bg, 20%); 15 | -webkit-transition: background .5s, background ease-in-out .5s; 16 | transition: background .5s, background .5s; 17 | -webkit-transition: color 1s .5s, color ease-in-out 1s .5s; 18 | transition: color 1s .5s, color 1s .5s; 19 | img { 20 | opacity: 0; 21 | } 22 | color: #555; 23 | &.inview { 24 | background-color: @bg; 25 | color: #fff; 26 | 27 | img { 28 | .myBounceInUp; 29 | .animated; 30 | } 31 | } 32 | } 33 | .components { 34 | .beautify(#45b7ed); 35 | } 36 | .features { 37 | .beautify(#ac8); 38 | } 39 | .bootstrap { 40 | .beautify(#0b9); 41 | } 42 | .intro> .sui-container { 43 | text-align: center; 44 | } 45 | 46 | h1 { 47 | font-size: 64px; 48 | line-height: 1.5; 49 | } 50 | h2 { 51 | font-size: 48px; 52 | line-height: 1.5; 53 | } 54 | .center { 55 | text-align: center; 56 | } 57 | .brand-intro .sui-lead { 58 | font-size: 24px; 59 | line-height: 2; 60 | } 61 | 62 | .btn-lead { 63 | padding: 20px 80px; 64 | font-size: 24px; 65 | } 66 | 67 | .btn-wrap { 68 | margin-top: 50px; 69 | } 70 | 71 | .details ul { 72 | margin-top: 50px; 73 | } 74 | 75 | .details li { 76 | font-size: 18px; 77 | line-height: 2; 78 | } 79 | 80 | .bootstrap-logo { 81 | height: 300px; 82 | } 83 | -------------------------------------------------------------------------------- /docs/templates/global.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 全局样式 5 | 6 | block sidebar 7 | +sidebar('global') 8 | 9 | block content 10 | - var SIZES = ['xlarge', 'large', '', 'small'] 11 | - var ROLES = ["", "primary", "success", "info", "warning", "danger", "inverse"] 12 | 13 | h1 全局样式 14 | 15 | h2.sui-page-header 设计规范 16 | 17 | div.docs-description 18 | img(src='pictures/docs/text.png') 19 | 20 | ul.demo-operations.clearfix 21 | li 22 | a(href='#') 下载psd文件 23 | 24 | h2.sui-page-header 开发者文档 25 | 26 | h2 1. 基础字体和颜色 27 | ul.sui-nav.nav-tabs.nav-large 28 | li.active 29 | a(href='#demo1', data-toggle='tab') 示例 30 | li 31 | a(href='#code1', data-toggle='tab') 代码 32 | li 33 | a(href='#doc1', data-toggle='tab') 文档 34 | 35 | div.tab-content 36 | div.tab-pane.active#demo1 37 | div.bs-docs-example 38 | p 39 | | 段落 40 | | 基础字体:12px, #333, 微软雅黑 41 | | 基础行高: 18px 42 | 43 | h1 粗体标题一 44 | h2 粗体标题二 45 | h3 粗体标题三 46 | h4 粗体标题四 47 | h5 粗体标题五 48 | 49 | h1.sui-normal 标题一 50 | h2.sui-normal 标题二 51 | h3.sui-normal 标题三 52 | h4.sui-normal 标题四 53 | h5.sui-normal 标题五 54 | 55 | p 56 | a(href='#') 链接颜色 57 | div.tab-pane#code1 58 | pre.prettyprint.linenums(data-target='#demo1>div') 59 | div.tab-pane#doc1 60 | 61 | ul.demo-operations.clearfix 62 | li 63 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 64 | -------------------------------------------------------------------------------- /docs/templates/label.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title Label 5 | 6 | block sidebar 7 | +sidebar('Label') 8 | 9 | block content 10 | 11 | h1 Label 12 | 13 | h2.sui-page-header 开发者文档 14 | 15 | ul.sui-nav.nav-tabs.nav-large 16 | li.active 17 | a(href='#demo1', data-toggle='tab') 示例 18 | li 19 | a(href='#code1', data-toggle='tab') 代码 20 | li 21 | a(href='#doc1', data-toggle='tab') 文档 22 | 23 | div.tab-content 24 | div.tab-pane.active#demo1 25 | style. 26 | .bs-docs-example ul { 27 | margin-bottom: 20px; 28 | } 29 | .bs-docs-example li { 30 | display: inline-block; 31 | margin: 0 10px 10px 0; 32 | } 33 | div.bs-docs-example 34 | - var cls = ['', 'success', 'warning', 'danger', 'info'] 35 | - var txt = ['默认', '上升', '持平', '下降', '公告'] 36 | ul 37 | each clsi, i in cls 38 | li 39 | span.sui-label(class='label-#{clsi}') #{txt[i]} 40 | ul 41 | li 42 | span 默认文本 43 | each clsi, i in cls 44 | li 45 | span(class='sui-text-#{clsi}') #{txt[i]} 46 | 47 | div.tab-pane#code1 48 | pre.prettyprint.linenums(data-target='#demo1>div') 49 | div.tab-pane#doc1 50 | p 删掉原bootstrap里的badget,商家业务场合用的不多,且可以很方便的由label扩展去。 51 | p sui-label类名确定一个元素以label样式显示,再加之label-***可以区分不同状态的标识label 52 | ul.demo-operations.clearfix 53 | li 54 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 55 | 56 | -------------------------------------------------------------------------------- /less/tag.less: -------------------------------------------------------------------------------- 1 | .sui-tag { 2 | list-style: none; 3 | font-size: 0; 4 | line-height: 0; 5 | padding: 5px 5px 0 5px; 6 | &>li, &>a { 7 | font-size: @baseFontSize; 8 | margin: 0 5px 5px 0; 9 | display: inline-block; 10 | overflow: hidden; 11 | color: @black; 12 | background: @btnBackgroundHighlight; 13 | padding: 0 7px; 14 | height: 20px; 15 | line-height: 20px; 16 | border: 1px solid #d1d1d1; 17 | white-space: nowrap; 18 | cursor: pointer; 19 | &:hover { 20 | color: @stepsCurrentColor; 21 | } 22 | &.tag-selected { 23 | color: @white; 24 | background: @stepsCurrentColor; 25 | border-color: #1c91d3; 26 | } 27 | .transition(color 0.2s ease-out); 28 | &.with-x { 29 | cursor: default; 30 | i { 31 | margin-left: 10px; 32 | cursor: pointer; 33 | font: normal 14px tahoma; 34 | display: inline-block; 35 | height: 100%; 36 | vertical-align: middle; 37 | } 38 | } 39 | 40 | } 41 | /* 42 | &.tag-hole { 43 | &>li, &>span { 44 | padding: 0 10px 0 15px; 45 | height: 28px; 46 | line-height: 28px; 47 | position: relative; 48 | &:before { 49 | content: ''; 50 | position: absolute; 51 | width: 12px; 52 | height: 12px; 53 | left: -7px; 54 | top: 50%; 55 | margin-top: -7px; 56 | background: @white; 57 | border: 1px solid #d1d1d1; 58 | //border-width: 1px 1px 0 0; 59 | .border-radius(6px); 60 | } 61 | } 62 | } 63 | */ 64 | } 65 | -------------------------------------------------------------------------------- /less/code.less: -------------------------------------------------------------------------------- 1 | // 2 | // Code (inline and blocK) 3 | // -------------------------------------------------- 4 | 5 | 6 | // Inline and block code styles 7 | code, 8 | .sui-code, 9 | pre, 10 | .sui-pre 11 | { 12 | padding: 0 3px 2px; 13 | #font > #family > .monospace; 14 | font-size: @baseFontSize - 2; 15 | color: @grayDark; 16 | .border-radius(3px); 17 | } 18 | 19 | // Inline code 20 | code, 21 | .sui-code 22 | { 23 | padding: 2px 4px; 24 | color: #d14; 25 | background-color: #f7f7f9; 26 | white-space: nowrap; 27 | } 28 | 29 | // Blocks of code 30 | pre, 31 | sui-pre 32 | { 33 | display: block; 34 | padding: (@baseLineHeight - 1) / 2; 35 | margin: 0 0 @baseLineHeight / 2; 36 | font-size: @baseFontSize - 1; // 14px to 13px 37 | line-height: @baseLineHeight; 38 | word-break: break-all; 39 | word-wrap: break-word; 40 | white-space: pre; 41 | white-space: pre-wrap; 42 | background-color: #f5f5f5; 43 | border: 1px solid #ccc; // fallback for IE7-8 44 | border: 1px solid rgba(0,0,0,.15); 45 | .border-radius(@baseBorderRadius); 46 | 47 | // Make prettyprint styles more spaced out for readability 48 | &.prettyprint { 49 | margin-bottom: @baseLineHeight; 50 | } 51 | 52 | // Account for some code outputs that place code tags in pre tags 53 | code, .sui-code { 54 | padding: 0; 55 | color: inherit; 56 | white-space: pre; 57 | white-space: pre-wrap; 58 | background-color: transparent; 59 | border: 0; 60 | } 61 | } 62 | 63 | // Enable scrollable blocks of code 64 | .pre-scrollable { 65 | max-height: 340px; 66 | overflow-y: scroll; 67 | } 68 | -------------------------------------------------------------------------------- /docs/assets/js/application.js: -------------------------------------------------------------------------------- 1 | // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT 2 | // IT'S ALL JUST JUNK FOR OUR DOCS! 3 | // ++++++++++++++++++++++++++++++++++++++++++ 4 | 5 | (function($) { 6 | "use strict"; 7 | var parseCode = function(code) { 8 | //格式化代码,删除多余缩进空格,删除多余空行 9 | if(!code) return; 10 | code = code.replace(/^ *\n/g, '').replace(/\s+$/g, '') 11 | var indentNum = (/^\s+/.exec(code) || ["", ""])[0] .length 12 | return code.replace(new RegExp(' {'+indentNum+'}', 'g'), '') 13 | } 14 | // 侧边栏 15 | var $sidenav = $(".docs-sidenav").on("click", '> li', function(e) { 16 | var $li = $(e.currentTarget) 17 | if($li.hasClass(".active")) { 18 | return 19 | } 20 | $sidenav.find(".active").removeClass("active") 21 | $li.addClass("active") 22 | }) 23 | 24 | //代码高亮 25 | $('.prettyprint').each(function() { 26 | var $this = $(this) 27 | var $target = $($this.data("target")) 28 | if(!$target[0]) return; 29 | $this.text(parseCode($target.html())) 30 | }) 31 | $(function() { 32 | // make code pretty 33 | window.prettyPrint && prettyPrint() 34 | }) 35 | 36 | //复制代码 37 | $(".copy-btn").each(function() { 38 | var $btn = $(this) 39 | var $target = $($btn.data("target")) 40 | var $li = $btn.parents("li") 41 | var $msg = $li.find(".sui-msg") 42 | if (!$msg[0]) { 43 | $msg = $('
代码已复制
').appendTo($li) 44 | } 45 | $btn.attr('data-clipboard-text', parseCode($target.html())) 46 | var cp = new ZeroClipboard(this, { 47 | moviePath: "assets/zeroclipboard/ZeroClipboard.swf" 48 | }) 49 | cp.on('load', function(cp) { 50 | cp.on( "complete", function(cp, args) { 51 | $msg.show().delay(2000).fadeOut() 52 | }) 53 | }) 54 | }) 55 | })(window.jQuery) 56 | -------------------------------------------------------------------------------- /less/responsive-utilities.less: -------------------------------------------------------------------------------- 1 | // 2 | // Responsive: Utility classes 3 | // -------------------------------------------------- 4 | 5 | 6 | // IE10 Metro responsive 7 | // Required for Windows 8 Metro split-screen snapping with IE10 8 | // Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ 9 | @-ms-viewport{ 10 | width: device-width; 11 | } 12 | 13 | // Hide from screenreaders and browsers 14 | // Credit: HTML5 Boilerplate 15 | .hidden { 16 | display: none; 17 | visibility: hidden; 18 | } 19 | 20 | // Visibility utilities 21 | 22 | // For desktops 23 | .visible-phone { display: none !important; } 24 | .visible-tablet { display: none !important; } 25 | .hidden-phone { } 26 | .hidden-tablet { } 27 | .hidden-desktop { display: none !important; } 28 | .visible-desktop { display: inherit !important; } 29 | 30 | // Tablets & small desktops only 31 | @media (min-width: 768px) and (max-width: 979px) { 32 | // Hide everything else 33 | .hidden-desktop { display: inherit !important; } 34 | .visible-desktop { display: none !important ; } 35 | // Show 36 | .visible-tablet { display: inherit !important; } 37 | // Hide 38 | .hidden-tablet { display: none !important; } 39 | } 40 | 41 | // Phones only 42 | @media (max-width: 767px) { 43 | // Hide everything else 44 | .hidden-desktop { display: inherit !important; } 45 | .visible-desktop { display: none !important; } 46 | // Show 47 | .visible-phone { display: inherit !important; } // Use inherit to restore previous behavior 48 | // Hide 49 | .hidden-phone { display: none !important; } 50 | } 51 | 52 | // Print utilities 53 | .visible-print { display: none !important; } 54 | .hidden-print { } 55 | 56 | @media print { 57 | .visible-print { display: inherit !important; } 58 | .hidden-print { display: none !important; } 59 | } 60 | -------------------------------------------------------------------------------- /less/responsive.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.3.2 3 | * 4 | * Copyright 2013 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world by @mdo and @fat. 9 | */ 10 | 11 | 12 | // Responsive.less 13 | // For phone and tablet devices 14 | // ------------------------------------------------------------- 15 | 16 | 17 | // REPEAT VARIABLES & MIXINS 18 | // ------------------------- 19 | // Required since we compile the responsive stuff separately 20 | 21 | @import "variables.less"; // Modify this for custom colors, font-sizes, etc 22 | @import "mixins.less"; 23 | 24 | 25 | // RESPONSIVE CLASSES 26 | // ------------------ 27 | 28 | @import "responsive-utilities.less"; 29 | 30 | 31 | // MEDIA QUERIES 32 | // ------------------ 33 | @media (min-width: 1440px) { 34 | 35 | // Fixed grid 36 | #grid > .core(@gridColumnWidthXLarge, @gridGutterWidthXLarge); 37 | 38 | // Fluid grid 39 | #grid > .fluid(@fluidGridColumnWidthXLarge, @fluidGridGutterWidthXLarge); 40 | 41 | // Input grid 42 | #grid > .input(@gridColumnWidthXLarge, @gridGutterWidthXLarge); 43 | 44 | // Thumbnails 45 | .thumbnails { 46 | margin-left: -@gridGutterWidthXLarge; 47 | } 48 | .thumbnails > li { 49 | margin-left: @gridGutterWidthXLarge; 50 | } 51 | .row-fluid .thumbnails { 52 | margin-left: 0; 53 | } 54 | 55 | } 56 | // Large desktops 57 | @media (min-width: 1280px) and (max-width: 1439px) { 58 | 59 | // Fixed grid 60 | #grid > .core(@gridColumnWidthLarge, @gridGutterWidthLarge); 61 | 62 | // Fluid grid 63 | #grid > .fluid(@fluidGridColumnWidthLarge, @fluidGridGutterWidthLarge); 64 | 65 | // Input grid 66 | #grid > .input(@gridColumnWidthLarge, @gridGutterWidthLarge); 67 | 68 | // No need to reset .thumbnails here since it's the same @gridGutterWidth 69 | 70 | } 71 | -------------------------------------------------------------------------------- /docs/templates/button-groups.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 按钮组 5 | 6 | block head 7 | style(type="text/css"). 8 | .btn-group-vertical .sui-btn { 9 | min-width: 100px; 10 | } 11 | 12 | block sidebar 13 | +sidebar('btn-group') 14 | 15 | block content 16 | h1 按钮组 17 | h2.sui-page-header 开发者文档 18 | 19 | p.sui-lead 20 | | 垂直和水平方向按钮组 21 | 22 | ul.sui-nav.nav-tabs.nav-large 23 | li.active 24 | a(href='#demo1', data-toggle='tab') 示例 25 | li 26 | a(href='#code1', data-toggle='tab') 代码 27 | li 28 | a(href='#doc1', data-toggle='tab') 文档 29 | 30 | div.tab-content 31 | div.tab-pane.active#demo1 32 | div.bs-docs-example 33 | div.sui-btn-group 34 | button.sui-btn 左边 35 | button.sui-btn 中间 36 | button.sui-btn 右边 37 | div.sui-btn-group 38 | button.sui-btn 按钮 39 | button.sui-btn.btn-primray 按钮 40 | button.sui-btn.btn-warning 按钮 41 | button.sui-btn.btn-success 按钮 42 | button.sui-btn.btn-danger 按钮 43 | 44 | h2 垂直方向 45 | div.sui-btn-group.btn-group-vertical 46 | button.sui-btn 左边 47 | button.sui-btn 中间 48 | button.sui-btn 右边 49 | 50 | h2 工具栏 51 | div.sui-btn-toolbar(style="margin: 0;") 52 | div.sui-btn-group 53 | button.sui-btn 复制 54 | button.sui-btn 粘贴 55 | button.sui-btn 缩进 56 | 57 | div.sui-btn-group 58 | button.sui-btn.btn-danger 删除 59 | button.sui-btn.btn-primary 插入 60 | div.tab-pane#code1 61 | pre.prettyprint.linenums(data-target='#demo1>div') 62 | div.tab-pane#doc1 63 | | 按钮组,默认是水平排列,通过class btn-group-vertical 控制按钮组垂直排列。 64 | 65 | ul.demo-operations.clearfix 66 | li 67 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/templates/index.jade: -------------------------------------------------------------------------------- 1 | extends base_index 2 | 3 | block title 4 | title WQUI 5 | 6 | block head 7 | link(rel="stylesheet",href="assets/css/index.css") 8 | script(src='assets/js/index.js') 9 | 10 | block header 11 | +header('index') 12 | 13 | block content_wrap 14 | .jumbotron.intro 15 | .sui-container.brand-intro 16 | h1 WQUI 17 | p.sui-lead 18 | | WQUI 是一套基于bootstrap开发的前端组件库,同时她也是一套设计规范。 19 | br 20 | | 通过WQUI,可以非常方便的设计和实现精美的页面。 21 | 22 | p.btn-wrap.bounceInDown.animated 23 | a.sui-btn.btn-success.btn-lead(href='download.html') 立即下载 WQUI V1.0 24 | 25 | .jumbotron.components 26 | .sui-container 27 | .sui-row 28 | .span4 29 | .details.center 30 | h2 丰富的组件库 31 | ul.unstyled 32 | li 响应式栅格 33 | li icon font 字体图标 34 | li 按钮,表单,表格,提示 35 | li 标签页,步骤条,面包屑 36 | li 对话框,Tooltip,分页器 37 | li 更多组件敬请期待... 38 | .span8.center 39 | a(href='global.html') 40 | img(src='pictures/index-demo-components.png') 41 | 42 | .jumbotron.features 43 | .sui-container 44 | .sui-row 45 | .span4 46 | .details.center 47 | h2 为现代浏览器设计 48 | ul.unstyled 49 | li 扁平化设计 50 | li 响应式布局 51 | li icon font 52 | li CSS 特效 53 | li 兼容chrome,firfox,safari,ie8+等主流浏览器 54 | .span8.center 55 | img(src='pictures/index-demo-browsers.png') 56 | 57 | .jumbotron.bootstrap 58 | .sui-container 59 | .sui-row 60 | .span4 61 | .details.center 62 | h2 基于 bootstrap 2.3 63 | 64 | ul.unstyled 65 | li 基于 boostrap 2.3 ,有良好的代码结构和丰富的文档及示例 66 | li 引入了 icon font, grunt, jade 等新技术 67 | 68 | .span8.center 69 | img.bootstrap-logo(src='pictures/bootstrap-logo.png') 70 | -------------------------------------------------------------------------------- /less/sui.less: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | /*! 4 | * Bootstrap v2.3.2 5 | * 6 | * Copyright 2013 Twitter, Inc 7 | * Licensed under the Apache License v2.0 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Designed and built with all the love in the world by @mdo and @fat. 11 | */ 12 | 13 | // Core variables and mixins 14 | @import "variables.less"; // Modify this for custom colors, font-sizes, etc 15 | @import "mixins.less"; 16 | 17 | // CSS Reset 18 | @import "reset.less"; 19 | 20 | // Grid system and page structure 21 | @import "scaffolding.less"; 22 | @import "grid.less"; 23 | @import "layouts.less"; 24 | 25 | // Base CSS 26 | @import "type.less"; 27 | @import "icons.less"; 28 | @import "code.less"; 29 | @import "forms.less"; 30 | @import "checkbox.less"; 31 | @import "msgs.less"; // 添加消息提示模块 @by kai 2014-01-20 32 | @import "tables.less"; 33 | 34 | // Components: common 35 | @import "dropdowns.less"; 36 | @import "wells.less"; 37 | @import "component-animations.less"; 38 | @import "close.less"; 39 | 40 | // Components: Buttons & Alerts 41 | @import "buttons.less"; 42 | @import "button-groups.less"; 43 | 44 | // Components: Nav 45 | @import "navs.less"; 46 | @import "navbar.less"; 47 | @import "breadcrumbs.less"; 48 | @import "pagination.less"; 49 | 50 | // Components: Popovers 51 | @import "modals.less"; 52 | @import "tooltip.less"; 53 | @import "popovers.less"; 54 | @import "datepicker.less"; 55 | @import "timepicker.less"; 56 | 57 | // Components: label,tag 58 | @import "label.less"; 59 | @import "tag.less"; 60 | 61 | // Components: Misc 62 | @import "progress-bars.less"; 63 | @import "accordion.less"; 64 | @import "carousel.less"; 65 | @import "hero-unit.less"; 66 | @import "loading.less"; 67 | 68 | // steps 69 | @import "steps.less"; 70 | 71 | //scharts 72 | @import "scharts.less"; 73 | 74 | // Utility classes 75 | @import "utilities.less"; // Has to be last to override when necessary 76 | 77 | // responsive 78 | @import "responsive.less"; 79 | -------------------------------------------------------------------------------- /js/transition.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * bootstrap-transition.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#transitions 4 | * =================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) 27 | * ======================================================= */ 28 | 29 | $(function () { 30 | 31 | $.support.transition = (function () { 32 | 33 | var transitionEnd = (function () { 34 | 35 | var el = document.createElement('bootstrap') 36 | , transEndEventNames = { 37 | 'WebkitTransition' : 'webkitTransitionEnd' 38 | , 'MozTransition' : 'transitionend' 39 | , 'OTransition' : 'oTransitionEnd otransitionend' 40 | , 'transition' : 'transitionend' 41 | } 42 | , name 43 | 44 | for (name in transEndEventNames){ 45 | if (el.style[name] !== undefined) { 46 | return transEndEventNames[name] 47 | } 48 | } 49 | 50 | }()) 51 | 52 | return transitionEnd && { 53 | end: transitionEnd 54 | } 55 | 56 | })() 57 | 58 | }) 59 | 60 | }(window.jQuery); 61 | -------------------------------------------------------------------------------- /js/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bootstrap Plugin Test Suite 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |

Bootstrap Plugin Test Suite

47 |

48 |

49 |
    50 |
    51 |
    52 | 53 | 54 | -------------------------------------------------------------------------------- /developer.md: -------------------------------------------------------------------------------- 1 | # 一,仓库和分支 2 | 3 | ## 仓库和分支说明 4 | 5 | 三个仓库分别是 **sui,wqui,qnui**。其中 **wqui** 和 **qnui** 都是从 **sui** 复制来的,可以理解为 **fork** ,因为在github上无法在同一个organization中fork,所以我们用复制。 6 | 7 | 每个仓库中的主分支都是dev。 8 | build分支包含所有编译出来的代码,用来在官网服务器上部署。 9 | 10 | ## 设置remote 11 | 假设把三个仓库都clone到本地之后分别是**~/sui**,**~/qnui**,和**~/wqui**。 12 | 下一步就是要设置remote,每个仓库中现在都有一个默认的remote叫 **origin** ,指向github上的同名仓库,这个不要修改。 13 | 14 | ### 设置sui的remote 15 | 16 | 进入sui仓库,执行 `git remote -v` 会发现已经存在一个 **origin**,那么我们还需要添加一个 **gitlab** 来发布代码。 17 | 执行命令 **git remote add gitlab git@gitlab.alibaba-inc.com:sj/sui.git** 即可 18 | 19 | ### 设置qnui的remote 20 | 21 | 进入qnui仓库,执行 `git remote -v` 会发现也已经存在一个origin,然后和sui中的一样 我们也需要添加gitlab用来发布代码。 22 | 23 | * 执行命令 `git remote add gitlab git@gitlab.alibaba-inc.com:sj/qnui.git`。 24 | * 为了能同步sui上的更新,我们还需要把sui也加入自己的remote: 25 | * 执行命令 `git remote add sui git@github.com:sdc-alibaba/sui.git`。 26 | 27 | 这样如果我们 `git fetch sui` 就可以把sui仓库的分支全部更新到qnui中。 28 | 29 | **全部的remote关系如下图所示** 30 | 31 | ![img](http://gtms03.alicdn.com/tps/i3/T17_q9FrFdXXX6cUbS-830-646.png) 32 | 33 | # 二,开发流程 34 | 35 | 假设A开发一个组件ac。 36 | 37 | 1. A从dev新建一个分支ac,并开发代码, `git checkout -b ac`。 38 | 2. A提交代码并push到github,然后在github上向dev发pull request,指定给另一个人B。 39 | 3. B review之后同意merge,此时ac分支上的代码就进入了sui的dev分支。 40 | 41 | 下一步是要把ac组件同步到qnui和wqui。 42 | 43 | 1. 切换到本地的qnui仓库,切换到dev分支,然后`git fetch sui`,此时会看到一个sui/dev的更新 44 | 2. 然后git merge sui/dev,如果有冲突可能要手动解决下 45 | 3. 解决完冲突并提交之后,执行 git push origin dev就可以了。 46 | 47 | wqui的操作和上面一样。 48 | 49 | 经过上面的操作,三个仓库中的dev分支中都包含了ac组件。 50 | 51 | # 三,发布流程 52 | 发布包含两部分,一是把代码发布到CDN上,二是更新官网。 53 | 54 | ## 发布代码到CDN 55 | 1. 以sui为例,切换到分支daily/1.0.0,如果没有就从dev上新建一个。 56 | 2. 然后merge dev分支 57 | 3. 删除上次发布的tag,`git push gitlab :publish/1.0.0` 58 | 4. `git push gitlab daily/1.0.0`,发布到daily环境 59 | 5. 本地重新打一个tag,并push 60 | - `git tag -d publish/1/0.0` 61 | - `git tag -d publish/1/0.0` 62 | - `git push gitlab publish/1.0.0` 63 | 64 | ## 更新官网 65 | 66 | 因为官网服务器没有安装node,所以需要我们本地构建好代码 67 | 68 | 1. 切换到build分支,`git checkout dev` 69 | 2. `git merge dev` 70 | 3. 执行 `grunt` 71 | 4. 提交并push。 72 | * `git commit -a` 73 | * `git push origin build` 74 | 75 | 最后在官网服务器上对应仓库执行git pull 即可。 76 | -------------------------------------------------------------------------------- /docs/templates/breadcrumb.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title Breadcrumb 面包屑 5 | 6 | block sidebar 7 | +sidebar('breadcrumb') 8 | 9 | block content 10 | 11 | h1 面包屑 12 | 13 | h2.sui-page-header 设计规范 14 | 15 | div.docs-description 16 | img(src='pictures/docs/breadcrumb.png') 17 | 18 | ul.demo-operations.clearfix 19 | li 20 | a(href='#') 下载psd文件 21 | 22 | h2.sui-page-header 开发者文档 23 | 24 | ul.sui-nav.nav-tabs.nav-large 25 | li.active 26 | a(href='#demo1', data-toggle='tab') 示例 27 | li 28 | a(href='#code1', data-toggle='tab') 代码 29 | li 30 | a(href='#doc1', data-toggle='tab') 文档 31 | div.tab-content 32 | div.tab-pane.active#demo1 33 | div.bs-docs-example 34 | h1 默认尺寸 35 | ul.sui-breadcrumb 36 | li 37 | a(href='#') 首页 38 | li 39 | a(href='#') 手机数码、电脑办公 40 | li.active 智能手机 41 | ul.sui-breadcrumb.breadcrumb-bold 42 | li 43 | a(href='#') 首页 44 | li 45 | a(href='#') 手机数码、电脑办公 46 | li.active 智能手机 47 | 48 | h1 大尺寸 49 | ul.sui-breadcrumb.breadcrumb-large 50 | li 51 | a(href='#') 首页 52 | li 53 | a(href='#') 手机数码、电脑办公 54 | li.active 智能手机 55 | ul.sui-breadcrumb.breadcrumb-large.breadcrumb-bold 56 | li 57 | a(href='#') 首页 58 | li 59 | a(href='#') 手机数码、电脑办公 60 | li.active 智能手机 61 | 62 | div.tab-pane#code1 63 | pre.prettyprint.linenums(data-target='#demo1>div') 64 | div.tab-pane#doc1 65 | | 由于从IE8+开始兼容,故无需加分割符,利用:before自动添加,面包屑有默认18px(一个行高)的下边距,宽度100%。 66 | ul.demo-operations.clearfix 67 | li 68 | a(href='#') 下载psd文件 69 | li 70 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 71 | -------------------------------------------------------------------------------- /js/tests/unit/alert.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("alerts") 4 | 5 | test("should provide no conflict", function () { 6 | var alert = $.fn.alert.noConflict() 7 | ok(!$.fn.alert, 'alert was set back to undefined (org value)') 8 | $.fn.alert = alert 9 | }) 10 | 11 | test("should be defined on jquery object", function () { 12 | ok($(document.body).alert, 'alert method is defined') 13 | }) 14 | 15 | test("should return element", function () { 16 | ok($(document.body).alert()[0] == document.body, 'document.body returned') 17 | }) 18 | 19 | test("should fade element out on clicking .close", function () { 20 | var alertHTML = '
    ' 21 | + '×' 22 | + '

    Holy guacamole! Best check yo self, you\'re not looking too good.

    ' 23 | + '
    ' 24 | , alert = $(alertHTML).alert() 25 | 26 | alert.find('.close').click() 27 | 28 | ok(!alert.hasClass('in'), 'remove .in class on .close click') 29 | }) 30 | 31 | test("should remove element when clicking .close", function () { 32 | $.support.transition = false 33 | 34 | var alertHTML = '
    ' 35 | + '×' 36 | + '

    Holy guacamole! Best check yo self, you\'re not looking too good.

    ' 37 | + '
    ' 38 | , alert = $(alertHTML).appendTo('#qunit-fixture').alert() 39 | 40 | ok($('#qunit-fixture').find('.alert-message').length, 'element added to dom') 41 | 42 | alert.find('.close').click() 43 | 44 | ok(!$('#qunit-fixture').find('.alert-message').length, 'element removed from dom') 45 | }) 46 | 47 | test("should not fire closed when close is prevented", function () { 48 | $.support.transition = false 49 | stop(); 50 | $('
    ') 51 | .bind('close', function (e) { 52 | e.preventDefault(); 53 | ok(true); 54 | start(); 55 | }) 56 | .bind('closed', function () { 57 | ok(false); 58 | }) 59 | .alert('close') 60 | }) 61 | 62 | }) 63 | -------------------------------------------------------------------------------- /docs/assets/js/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f); 8 | if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d.sui-tag。近亲label在 15 | a(href='./label.html') 这里 16 | 17 | h2 普通与选中的tag 18 | ul.sui-nav.nav-tabs.nav-large 19 | li.active 20 | a(href='#demo1', data-toggle='tab') 示例 21 | li 22 | a(href='#code1', data-toggle='tab') 代码 23 | li 24 | a(href='#doc1', data-toggle='tab') 文档 25 | 26 | div.tab-content 27 | div.tab-pane.active#demo1 28 | div.bs-docs-example 29 | - var txt = ['Normal', 'logo设计', '店铺装修达人', '艺术', '公sdf告', '注意afs'] 30 | h3 默认 31 | ul.sui-tag 32 | each text, i in txt 33 | li #{text} 34 | h3 选中的tag的状态:li.tag-selected 35 | ul.sui-tag.tag-selected 36 | each text, i in txt 37 | if i % 2 == 0 38 | li #{text} 39 | else 40 | li.tag-selected #{text} 41 | 42 | div.tab-pane#code1 43 | pre.prettyprint.linenums(data-target='#demo1>div') 44 | div.tab-pane#doc1 45 | p 使用方法很简单了,最好是用ul>li的结构,或者内部是a标签也可以。 46 | ul.demo-operations.clearfix 47 | li 48 | a(href='#') 下载psd文件 49 | li 50 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 51 | 52 | 53 | h2 右侧带叉(用以删除) 54 | ul.sui-nav.nav-tabs.nav-large 55 | li.active 56 | a(href='#demo2', data-toggle='tab') 示例 57 | li 58 | a(href='#code2', data-toggle='tab') 代码 59 | li 60 | a(href='#doc2', data-toggle='tab') 文档 61 | 62 | div.tab-content 63 | div.tab-pane.active#demo2 64 | div.bs-docs-example 65 | - var txt = ['Normal', 'logo设计', '店铺装修达人', '艺术', '公sdf告', '注意afs', '店铺装修达人', '艺术', '公sdf告'] 66 | h3 默认 .sui-tag 67 | ul.sui-tag(style="width:300px;border: 1px solid #999") 68 | each text, i in txt 69 | if i % 2 == 0 70 | li #{text} 71 | else 72 | li.tag-selected.with-x #{text} 73 | i × 74 | 75 | div.tab-pane#code2 76 | pre.prettyprint.linenums(data-target='#demo2>div') 77 | div.tab-pane#doc2 78 | p 带叉的tag则在每个tag元素附加class="with-x",同时内部添加html: 79 | code <i>&times;</i> 80 | p 因为是CSS组件,相关事件需要根据业务逻辑自己添加 81 | ul.demo-operations.clearfix 82 | li 83 | a(href='#') 下载psd文件 84 | li 85 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>div') 复制代码 86 | 87 | -------------------------------------------------------------------------------- /less/tests/forms-responsive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sui, from Twitter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
    36 | 37 | 40 | 41 |

    Vertical alignment

    42 | 43 | 44 | span1 45 | 46 |

    Width across elements

    47 |
    48 | 49 |
    50 |
    51 | 52 |
    53 |
    54 | span2 55 |
    56 | 57 | 58 | 61 | 62 |
    63 | 64 | 65 | span1 66 |
    67 | 68 |
    69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /less/icon-pc.less: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icon-pc'; 3 | src:url('@{iconFontPath}/icon-pc.eot?59lb71'); 4 | src:url('@{iconFontPath}/icon-pc.eot?#iefix59lb71') format('embedded-opentype'), 5 | url('@{iconFontPath}/icon-pc.woff?59lb71') format('woff'), 6 | url('@{iconFontPath}/icon-pc.ttf?59lb71') format('truetype'), 7 | url('@{iconFontPath}/icon-pc.svg?59lb71#icon-pc') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | .sui-icon { 13 | &[class^="icon-pc-"], 14 | &[class*=" icon-pc-"] { 15 | font-family: 'icon-pc'; 16 | speak: none; 17 | font-style: normal; 18 | font-weight: normal; 19 | font-variant: normal; 20 | text-transform: none; 21 | line-height: 1; 22 | 23 | /* Better Font Rendering =========== */ 24 | -webkit-font-smoothing: antialiased; 25 | -moz-osx-font-smoothing: grayscale; 26 | } 27 | } 28 | .icon-pc-loading:before { 29 | content: "\e600"; 30 | } 31 | .icon-pc-enter:before { 32 | content: "\e602"; 33 | } 34 | .icon-pc-ww:before { 35 | content: "\c600"; 36 | } 37 | .icon-pc-sound:before { 38 | content: "\c601"; 39 | } 40 | .icon-pc-settings:before { 41 | content: "\c602"; 42 | } 43 | .icon-pc-right:before { 44 | content: "\c603"; 45 | } 46 | .icon-pc-right-circle:before { 47 | content: "\e601"; 48 | } 49 | .icon-pc-refresh:before { 50 | content: "\c604"; 51 | } 52 | .icon-pc-question-circle:before { 53 | content: "\c605"; 54 | } 55 | .icon-pc-prev:before { 56 | content: "\c606"; 57 | } 58 | .icon-pc-next:before { 59 | content: "\c607"; 60 | } 61 | .icon-pc-list:before { 62 | content: "\c608"; 63 | } 64 | .icon-pc-light:before { 65 | content: "\c609"; 66 | } 67 | .icon-pc-info-circle:before { 68 | content: "\c60a"; 69 | } 70 | .icon-pc-forbidden:before { 71 | content: "\c60b"; 72 | } 73 | .icon-pc-error:before { 74 | content: "\c60c"; 75 | } 76 | .icon-pc-error-circle:before { 77 | content: "\c60d"; 78 | } 79 | .icon-pc-chevron-top:before { 80 | content: "\c60e"; 81 | } 82 | .icon-pc-chevron-right:before { 83 | content: "\c60f"; 84 | } 85 | .icon-pc-chevron-left:before { 86 | content: "\c610"; 87 | } 88 | .icon-pc-chevron-bottom:before { 89 | content: "\c611"; 90 | } 91 | .icon-pc-bell:before { 92 | content: "\c612"; 93 | } 94 | .icon-pc-checkbox-checked:before { 95 | content: "\e607"; 96 | } 97 | .icon-pc-checkbox-unchecked:before { 98 | content: "\e605"; 99 | } 100 | .icon-pc-checkbox-halfchecked:before { 101 | content: "\e606"; 102 | } 103 | .icon-pc-radio-checked:before { 104 | content: "\e604"; 105 | } 106 | .icon-pc-radio-unchecked:before { 107 | content: "\e603"; 108 | } 109 | -------------------------------------------------------------------------------- /docs/templates/dropdown-js.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 下拉菜单 5 | 6 | block sidebar 7 | +sidebar('dropdown-js') 8 | 9 | block content 10 | h1 对话框 11 | 12 | h2.sui-page-header 开发者文档 13 | 14 | p.sui-lead 15 | | JS 下拉菜单,比原生的select有更精美的样式并且有更好的可拓展性。 16 | 17 | h2 通过标记使用 18 | ul.sui-nav.nav-tabs.nav-large 19 | li.active 20 | a(href='#demo1', data-toggle='tab') 示例 21 | li 22 | a(href='#code1', data-toggle='tab') 代码 23 | li 24 | a(href='#doc1', data-toggle='tab') 文档 25 | 26 | div.tab-content 27 | div.tab-pane.active#demo1 28 | div.bs-docs-example(style='height: 140px;') 29 | span.sui-dropdown 30 | a.dropdown-toggle#drop1(role="button" data-toggle="dropdown" href="#") 杭州 31 | ul#menu1.sui-dropdown-menu(role="menu" aria-labelledby="drop1") 32 | li(role="presentation") 33 | a(role="menuitem" tabindex="-1" href="#") 北京 34 | li(role="presentation") 35 | a(role="menuitem" tabindex="-1" href="#") 圣彼得堡 36 | li(role="presentation") 37 | a(role="menuitem" tabindex="-1" href="#") 莫斯科 38 | 39 | div.tab-pane#code1 40 | pre.prettyprint.linenums(data-target='#demo1>div') 41 | div.tab-pane#doc1 42 | | 通过添加 data-toggle="dropdown" 可以启用下拉功能。 43 | ul.demo-operations.clearfix 44 | li 45 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 46 | 47 | 48 | h2 通过JS调用 49 | ul.sui-nav.nav-tabs.nav-large 50 | li.active 51 | a(href='#demo2', data-toggle='tab') 示例 52 | li 53 | a(href='#code2', data-toggle='tab') 代码 54 | li 55 | a(href='#doc2', data-toggle='tab') 文档 56 | 57 | div.tab-content 58 | div.tab-pane.active#demo2 59 | div.bs-docs-example(style='height: 140px;') 60 | span.sui-dropdown#dropdown-demo2 61 | a.dropdown-toggle#drop2(role='button' href="#") 杭州 62 | ul#menu2.sui-dropdown-menu(role='menu' aria-labelledby="drop2") 63 | li(role="presentation") 64 | a(role="menuitem" tabindex="-1" href="#") 北京 65 | li(role="presentation") 66 | a(role="menuitem" tabindex="-1" href="#") 上海 67 | li(role="presentation") 68 | a(role="menuitem" tabindex="-1" href="#") 深圳 69 | script. 70 | $('#dropdown-demo2 .dropdown-toggle').dropdown() 71 | div.tab-pane#code2 72 | pre.prettyprint.linenums(data-target='#demo2>div') 73 | div.tab-pane#doc2 74 | p 75 | js直接调用 $().dropdown() 76 | p 77 | | 还提供一个 $().dropdown('toggle') 方法可以控制菜单的显示。 78 | ul.demo-operations.clearfix 79 | li 80 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>div') 复制代码 81 | -------------------------------------------------------------------------------- /docs/templates/pagination.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 分页器 5 | 6 | block sidebar 7 | +sidebar('pagination') 8 | 9 | block content 10 | h1 分页器 11 | 12 | h2.sui-page-header 设计规范 13 | 14 | div.docs-description 15 | img(src='pictures/docs/pagination.png') 16 | 17 | ul.demo-operations.clearfix 18 | li 19 | a(href='#') 下载psd文件 20 | 21 | h2.sui-page-header 开发者文档 22 | 23 | p.sui-lead 24 | div 25 | a(href='pagination-js.html') 点击访问:pagination-JS组件 26 | 27 | ul.sui-nav.nav-tabs.nav-large 28 | li.active 29 | a(href='#demo1', data-toggle='tab') 示例 30 | li 31 | a(href='#code1', data-toggle='tab') 代码 32 | li 33 | a(href='#doc1', data-toggle='tab') 文档 34 | 35 | div.tab-content 36 | div.tab-pane.active#demo1 37 | div.bs-docs-example 38 | h2 小型分页器 39 | p.sui-lead 40 | | 当只有一页内容,且不超过5条时,可以只显示数字,把“上一页”和“下一页”拿掉。 41 | div.sui-pagination 42 | ul 43 | li.prev.disabled 44 | a(href='#') « 45 | li.active 46 | a(href='#') 1 47 | li 48 | a(href='#') 2 49 | li 50 | a(href='#') 3 51 | li 52 | a(href='#') 4 53 | li 54 | a(href='#') 5 55 | li.next 56 | a(href='#') » 57 | h2 常态分页器 58 | div.sui-pagination 59 | ul 60 | li.prev.disabled 61 | a(href='#') «上一页 62 | li.active 63 | a(href='#') 1 64 | li 65 | a(href='#') 2 66 | li 67 | a(href='#') 3 68 | li 69 | a(href='#') 4 70 | li 71 | a(href='#') 5 72 | li.dotted 73 | span ... 74 | li.next 75 | a(href='#') 下一页» 76 | div 77 | span 共10页  78 | span 79 | |到 80 | | 81 | |页 82 | h2 无页码分页器 83 | div.sui-pagination 84 | ul 85 | li.prev 86 | a(href='#') «上一页 87 | li.next 88 | a(href='#') 下一页» 89 | div.tab-pane#code1 90 | pre.prettyprint.linenums(data-target='#demo1>div') 91 | div.tab-pane#doc1 92 | | 所有形式的分页器都提供三种尺寸,除此之外,还有pagination-centered,,pagination-right 控制分页器的水平位置 93 | ul.demo-operations.clearfix 94 | li 95 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DPL 2 | 3 | ## 一,开发环境: 4 | 5 | ### Grunt 6 | 7 | 之前的make脚本已经被改成grunt,除了常规的[grunt安装](http://gruntjs.com/),还需要安装[hogan](http://twitter.github.io/hogan.js/)用来编译文档模板。grunt 中已经配置了如下几个任务: 8 | 9 | * dist:编辑css和js,包含两个任务dist-js和dist-css 10 | * docs:编译文档, 因为依赖关系,所以编译文档实际上也会执行dist 11 | * test:代码检查和单元测试 12 | * default:默认任务,等价于 test + dist 13 | * watch:监控文件改动实时编译 14 | 15 | ** 因为我们的代码构建放在了服务器端,而服务器端使用的npm源是 [http://registry.npm.taobao.net](http://registry.npm.taobao.net),所以建议把在自己的电脑上也设置这个源。** 16 | 17 | ### Gulp 18 | 19 | **gulp 暂时无人维护,不要用** 20 | 21 | ### iconfont 22 | 图标全部用iconfont实现。 23 | 24 | ### git协作: 25 | 26 | 分支说明 27 | * master分支用来发布代码,不要在master上做任何改动。 28 | * dev分支用来预发布,所有测试通过准备发布的代码都先merge进dev。 29 | * build分支包含了所有打包编译出的代码,用在不方便安装node的环境。 30 | 31 | 每个人新建一个自己的分支,比如开发btn的分支就叫btn,开发完成后向dev发送一个merge request,另一个同学review完代码之后点击merge即可提交到dev。 32 | 33 | 开发时候只需要执行 **grunt watch** 就可以,会自动编译代码并刷新页面。最后提交的时候要执行 **grunt test** 保证没有错误再提交。 34 | 35 | 36 | ## 二,文件结构: 37 | - .package: 编译后的js和css文件,这个被gitignore,执行grunt会自动生成。 38 | - docs:文档,文档是用mustache模板写的,mustache是一个无逻辑模板语言(官网:[mustache](http://mustache.github.io/)),用twitter自己写的一个编译器hogan来编译([hogan](http://twitter.github.io/hogan.js/))。 每个组件都有自己的demo,开发一个组件就在这里新建一个demo,这里用的是jade模板生成的,执行grunt docs会自动把docs/template下的jade模板编译到docs目录下的同名文件。其中base.jade是公用模板,其他模板都应该继承base。如果模板名字以com-开头或者以-com.jade结尾,则不会被编译为html,适合中间组件. 39 | docs中注意如下几个文件: 40 | - assets:只在docs中使用的静态文件放这里,和bootstrap代码相关的比如bootstrap.css和fonts是从外面cp进来的。 41 | - example:示例,这个是没有用模板来写的,后面如果有必要我会用mustache改造一下。每完成一个组件都应该在这里面写一个详细的例子(或者在less下面建一个demo文件夹更好点?)。 42 | - template:官网页面,这个是用mustache来写的,里面有一个base和若干pages。 43 | 44 | - fonts: 字体描述文件,icon font字体是支持包括ie6在内的所有主流浏览器,只是每个浏览器支持的字体描述文件格式不同,这里提供了全部四种格式。但是因为icon用了:before和content来实现,所以ie8以下的浏览器还是不支持的。 45 | - less:css源码(注意这里面的test没有测试框架的支持,人肉检查组件而已) 46 | 模块结构可以在bootstrap.less中看的非常清楚,直接看bootstrap.less的代码。 47 | 48 | - js:重点注意单元测试,需要先学习qunit的用法。每一个js模块都对应一个单元测试。js代码的提交一定要通过单元测试。grunt test或者直接访问index.html都可以。(目前grunt qunit会有一个超时bug,暂时去掉了) 49 | 50 | 51 | ## css组件规范: 52 | 53 | 1. 尺寸规范: 54 | 元素的尺寸由line-height,padding,border,margin组成,还有不影响元素本身大小的是font-size 55 | 所以广义的元素尺寸包括了上述五个因素。 56 | 我们把组件都分成四种大小:mini,small,default,large。这四种大小分别对应四种不同的font-size,line-height,padding,border和margin,这些是在variables中已经定义好的。 57 | 一些基础css组件可能包含全部的四种尺寸,比如btn和input,大部分组件都是其中一种尺寸。 58 | 当然很多时候一个组件无法对应这四种尺寸之一,那就直接写死常量。 59 | 这方面bootstrap做的不好,大部分都是写死在代码中的常量。 60 | 61 | 2. 颜色规范: 62 | 常用的颜色可能就十几种,定义在variables中,其他颜色最好能根据常用颜色算出来。这样换皮肤的话只需要把颜色配置换掉就好了。 63 | 比如btn-primary的颜色是这么定义的: 64 | @btnPrimaryBackground: @linkColor; 65 | @btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 20%); 66 | 67 | 3. 浏览器分级 68 | 对浏览器分ABC级: 69 | A: 最优体验,视觉和功能完全保证 70 | B: 功能保证,无法保证视觉美观 71 | C: 不兼容 72 | 73 | 74 | 4. 命名规范: 75 | 76 | - css中除了变量用驼峰法,其他都是’-‘分割(3.0全部改成减号分割) 77 | - 一个组件有不同的样式,应该把每一种样式都作为一个追加的classname,而不是修改原有的class。即 .btn.btn-primary,而不是直接用.btn-primary替换.btn 78 | 最重要的是语义化命名,参见后文。 79 | 80 | ## js 插件开发规范: 81 | 82 | ## js:单元测试规范: 83 | TODO 84 | -------------------------------------------------------------------------------- /docs/demos/icons.html: -------------------------------------------------------------------------------- 1 | 图标

    方向图标

                

    提示反馈

              

    表单

       

    多媒体

             

    其他

                     
    -------------------------------------------------------------------------------- /js/alert.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-alert.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#alerts 4 | * ========================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* ALERT CLASS DEFINITION 27 | * ====================== */ 28 | 29 | var dismiss = '[data-dismiss="alert"]' 30 | , Alert = function (el) { 31 | $(el).on('click', dismiss, this.close) 32 | } 33 | 34 | Alert.prototype.close = function (e) { 35 | var $this = $(this) 36 | , selector = $this.attr('data-target') 37 | , $parent 38 | 39 | if (!selector) { 40 | selector = $this.attr('href') 41 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 42 | } 43 | 44 | $parent = $(selector) 45 | 46 | e && e.preventDefault() 47 | 48 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) 49 | 50 | $parent.trigger(e = $.Event('close')) 51 | 52 | if (e.isDefaultPrevented()) return 53 | 54 | $parent.removeClass('in') 55 | 56 | function removeElement() { 57 | $parent 58 | .trigger('closed') 59 | .remove() 60 | } 61 | 62 | $.support.transition && $parent.hasClass('fade') ? 63 | $parent.on($.support.transition.end, removeElement) : 64 | removeElement() 65 | } 66 | 67 | 68 | /* ALERT PLUGIN DEFINITION 69 | * ======================= */ 70 | 71 | var old = $.fn.alert 72 | 73 | $.fn.alert = function (option) { 74 | return this.each(function () { 75 | var $this = $(this) 76 | , data = $this.data('alert') 77 | if (!data) $this.data('alert', (data = new Alert(this))) 78 | if (typeof option == 'string') data[option].call($this) 79 | }) 80 | } 81 | 82 | $.fn.alert.Constructor = Alert 83 | 84 | 85 | /* ALERT NO CONFLICT 86 | * ================= */ 87 | 88 | $.fn.alert.noConflict = function () { 89 | $.fn.alert = old 90 | return this 91 | } 92 | 93 | 94 | /* ALERT DATA-API 95 | * ============== */ 96 | 97 | $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) 98 | 99 | }(window.jQuery); 100 | -------------------------------------------------------------------------------- /less/modals.less: -------------------------------------------------------------------------------- 1 | // 2 | // Modals 3 | // -------------------------------------------------- 4 | .popdiv-footer { 5 | padding: 7px 10px 5px; 6 | margin-bottom: 0; 7 | text-align: right; // right align buttons 8 | .border-radius(0 0 3px 3px); 9 | .clearfix(); // clear it in case folks use .pull-* classes on buttons 10 | 11 | // Properly space out buttons 12 | .sui-btn + .sui-btn { 13 | margin-left: 7px; 14 | margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs 15 | } 16 | // but override that for button groups 17 | .sui-btn-group .sui-btn + .sui-btn { 18 | margin-left: -1px; 19 | } 20 | // and override it for block buttons as well 21 | .btn-block + .btn-block { 22 | margin-left: 0; 23 | } 24 | } 25 | 26 | .overspread { 27 | top: 0; 28 | right: 0; 29 | bottom: 0; 30 | left: 0; 31 | } 32 | // Background 33 | .sui-modal-backdrop { 34 | position: fixed; 35 | .overspread; 36 | z-index: @zindexModalBackdrop; 37 | // Fade for backdrop 38 | &.fade { opacity: 0; } 39 | } 40 | 41 | .sui-modal-backdrop, 42 | .sui-modal-backdrop.fade.in { 43 | .opacity(40); 44 | } 45 | // modal shade 46 | .sui-modal .shade { 47 | position: absolute; 48 | .overspread; 49 | &.in {.opacity(40);} 50 | } 51 | 52 | // Base modal 53 | .sui-modal { 54 | position: fixed; 55 | top: 50%; 56 | left: 50%; 57 | margin-left: -220px; 58 | z-index: @zindexModal; 59 | width: 440px; 60 | background-color: @white; 61 | .border-radius(3px); 62 | .box-shadow(0 0 8px 2px #999); 63 | .background-clip(padding-box); 64 | // Remove focus outline from opened modal 65 | outline: none; 66 | 67 | &.fade { 68 | .transition(e('opacity .3s linear, top .3s ease-out')); 69 | top: -25%; 70 | } 71 | &.fade.in { 72 | top: 50%; 73 | } 74 | 75 | .modal-header { 76 | padding: 0 10px; 77 | background: #4a4a4a; 78 | color: #fff; 79 | .border-radius(3px 3px 0 0); 80 | // Heading 81 | h4 { 82 | margin: 0; 83 | line-height: 30px; 84 | font-weight: normal; 85 | } 86 | .modal-title{ 87 | margin: 0; 88 | } 89 | .sui-close { 90 | color: #bebebe; 91 | text-shadow: none; 92 | font-size: 20px; 93 | line-height: 30px; 94 | &:hover { 95 | color: #ff5050; 96 | } 97 | } 98 | } 99 | 100 | // Body (where all modal content resides) 101 | .modal-body { 102 | position: relative; 103 | overflow-y: auto; 104 | min-height: 100px; 105 | max-height: 500px; 106 | margin: 0; 107 | padding: 10px 20px; 108 | &.no-foot{ 109 | min-height: 190px; 110 | } 111 | } 112 | // Remove bottom margin if need be 113 | .modal-form { 114 | margin-bottom: 0; 115 | } 116 | 117 | // Footer (for actions) 118 | .modal-footer { 119 | .popdiv-footer() 120 | } 121 | 122 | } 123 | .tooltip-footer { 124 | .popdiv-footer() 125 | } 126 | 127 | -------------------------------------------------------------------------------- /docs/templates/sidenav.jade: -------------------------------------------------------------------------------- 1 | ul.sui-nav.nav-tabs.nav-stacked.nav-xlarge.docs-sidenav 2 | - var items = [] 3 | - items.push({name: 'global', title:'全局样式', url: 'global.html', icon: 'sui-icon icon-globe'}) 4 | - items.push({name: 'base-css', title: '基础css', children:[], icon: 'sui-icon icon-magic' }) 5 | - items.push({name: 'css-components', title: 'css组件', children:[], icon: 'sui-icon icon-picture'}) 6 | - items.push({name: 'js-components', title: 'js组件', children:[], icon: 'sui-icon icon-shopping-cart'}) 7 | 8 | - items[1].children.push({name: 'btn', title:'按钮', url:'buttons.html'}) 9 | - items[1].children.push({name: 'form', title:'表单', url:'forms.html'}) 10 | - items[1].children.push({name: 'icons', title:'图标', url:'icons.html'}) 11 | - items[1].children.push({name: 'table', title:'表格', url:'tables.html'}) 12 | 13 | 14 | - items[2].children.push({name: 'msg', title:'提示消息', url:'msgs.html'}) 15 | - items[2].children.push({name: 'step', title:'步骤条', url:'steps.html'}) 16 | - items[2].children.push({name: 'tab', title:'标签页', url:'tab.html'}) 17 | - items[2].children.push({name: 'breadcrumb', title:'面包屑', url:'breadcrumb.html'}) 18 | - items[2].children.push({name: 'pagination', title:'分页器', url:'pagination.html'}) 19 | - items[2].children.push({name: 'dropdown', title:'下拉菜单', url:'dropdown.html'}) 20 | - items[2].children.push({name: 'checkbox', title:'选框', url:'checkbox.html'}) 21 | - items[2].children.push({name: 'progress', title:'进度条', url:'progress.html'}) 22 | - items[2].children.push({name: 'Loading', title:'Loading', url:'loading.html'}) 23 | 24 | - items[3].children.push({name: 'dialog', title:'对话框', url:'dialog.html'}) 25 | - items[3].children.push({name: 'tooltip', title:'tooltip', url:'tooltip.html'}) 26 | - items[3].children.push({name: 'tab-js', title:'标签页', url:'tab-js.html'}) 27 | - items[3].children.push({name: 'pagination-js', title:'分页器', url:'pagination-js.html'}) 28 | - items[3].children.push({name: 'dropdown-js', title:'下拉菜单', url:'dropdown-js.html'}) 29 | - items[3].children.push({name: 'tree-js', title:'级联选择', url:'tree-js.html'}) 30 | - items[3].children.push({name: 'datetimepicker', title:'datetimepicker', url:'datetimepicker.html'}) 31 | 32 | for cat, i in items 33 | - var classname = '' 34 | if highlight == cat.name 35 | - classname = "active" 36 | if cat.children 37 | for item,j in cat.children 38 | if highlight == item.name 39 | - classname = 'active' 40 | li(class=classname) 41 | if !cat.children 42 | a(href=cat.url) 43 | i(class='#{cat.icon}')   44 | |#{cat.title} 45 | else 46 | a(href=cat.url) 47 | i(class='#{cat.icon}')   48 | |#{cat.title} 49 | i.sui-icon.icon-angle-down.pull-right 50 | ul.sui-nav.nav-tabs.nav-stacked 51 | 52 | for item,j in cat.children 53 | - var classname = '' 54 | if highlight == item.name 55 | - classname = "active" 56 | li(class=classname) 57 | a(href=item.url) #{item.title} 58 | 59 | script(type="text/javascript"). 60 | var disqus_identifier = 'disqus-id-!{highlight}'; 61 | -------------------------------------------------------------------------------- /js/tests/unit/tab.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("tabs") 4 | 5 | test("should provide no conflict", function () { 6 | var tab = $.fn.tab.noConflict() 7 | ok(!$.fn.tab, 'tab was set back to undefined (org value)') 8 | $.fn.tab = tab 9 | }) 10 | 11 | test("should be defined on jquery object", function () { 12 | ok($(document.body).tab, 'tabs method is defined') 13 | }) 14 | 15 | test("should return element", function () { 16 | ok($(document.body).tab()[0] == document.body, 'document.body returned') 17 | }) 18 | 19 | test("should activate element by tab id", function () { 20 | var tabsHTML = 21 | '' 25 | 26 | $('').appendTo("#qunit-fixture") 27 | 28 | $(tabsHTML).find('li:last a').tab('show') 29 | equal($("#qunit-fixture").find('.active').attr('id'), "profile") 30 | 31 | $(tabsHTML).find('li:first a').tab('show') 32 | equal($("#qunit-fixture").find('.active').attr('id'), "home") 33 | }) 34 | 35 | test("should activate element by tab id", function () { 36 | var pillsHTML = 37 | '' 41 | 42 | $('').appendTo("#qunit-fixture") 43 | 44 | $(pillsHTML).find('li:last a').tab('show') 45 | equal($("#qunit-fixture").find('.active').attr('id'), "profile") 46 | 47 | $(pillsHTML).find('li:first a').tab('show') 48 | equal($("#qunit-fixture").find('.active').attr('id'), "home") 49 | }) 50 | 51 | 52 | test("should not fire closed when close is prevented", function () { 53 | $.support.transition = false 54 | stop(); 55 | $('
    ') 56 | .bind('show', function (e) { 57 | e.preventDefault(); 58 | ok(true); 59 | start(); 60 | }) 61 | .bind('shown', function () { 62 | ok(false); 63 | }) 64 | .tab('show') 65 | }) 66 | 67 | test("show and shown events should reference correct relatedTarget", function () { 68 | var dropHTML = 69 | '
      ' 70 | + '' 76 | + '
    ' 77 | 78 | $(dropHTML).find('ul>li:first a').tab('show').end() 79 | .find('ul>li:last a').on('show', function(event){ 80 | equal(event.relatedTarget.hash, "#1-1") 81 | }).on('shown', function(event){ 82 | equal(event.relatedTarget.hash, "#1-1") 83 | }).tab('show') 84 | }) 85 | 86 | }) 87 | -------------------------------------------------------------------------------- /docs/templates/grid.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 12 栏栅格 5 | 6 | block head 7 | style(type="text/css"). 8 | .grid-demo .sui-row div, 9 | .grid-demo .sui-row-fluid div { 10 | background: #dfedfc; 11 | min-height: 50px; 12 | } 13 | .grid-demo .sui-row + .sui-row, 14 | .grid-demo .sui-row-fluid + .sui-row-fluid { 15 | margin-top: 10px; 16 | } 17 | block sidebar 18 | +sidebar('grid') 19 | 20 | block content 21 | h1 响应式栅格系统 22 | 23 | h2.sui-page-header 开发者文档 24 | 25 | p.sui-lead 26 | | 响应式的12栏栅格系统,兼容三种主流屏幕尺寸 1024,1280/1366以及1440。实际上用户屏幕宽度在1024px以上的情况下会自动选择一个最佳的栅格宽度。
    27 | | 如果想关闭响应式布局,只需要删除 sui-responsive.less文件即可。 28 | 29 | h2 1. 默认栅格系统 30 | ul.sui-nav.nav-tabs.nav-large 31 | li.active 32 | a(href='#demo1', data-toggle='tab') 示例 33 | li 34 | a(href='#code1', data-toggle='tab') 代码 35 | li 36 | a(href='#doc1', data-toggle='tab') 文档 37 | 38 | div.tab-content 39 | div.tab-pane.active#demo1 40 | div.bs-docs-example 41 | div.grid-demo 42 | div.sui-row 43 | - for (var x = 1; x <= 8; x++) 44 | div(class="span#{1}")=1 45 | div.sui-row 46 | - each x in [1, 2, 2, 3, ] 47 | div(class="span#{x}")=x 48 | div.sui-row 49 | - each x in [4, 4] 50 | div(class="span#{x}")=x 51 | div.sui-row 52 | - each x in [2, 6] 53 | div(class="span#{x}")=x 54 | div.tab-pane#code1 55 | pre.prettyprint.linenums(data-target='#demo1>div') 56 | div.tab-pane#doc1 57 | p 58 | | 默认栅格系统每一栏是定宽的,并且宽度可以根据屏幕宽度在几个固定值之间变化,区别于流式栅格系统的百分比宽度。 59 | 60 | ul.demo-operations.clearfix 61 | li 62 | a(href='#') 下载psd文件 63 | li 64 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 65 | 66 | 67 | h2 2. 流式栅格系统 68 | ul.sui-nav.nav-tabs.nav-large 69 | li.active 70 | a(href='#demo2', data-toggle='tab') 示例 71 | li 72 | a(href='#code2', data-toggle='tab') 代码 73 | li 74 | a(href='#doc2', data-toggle='tab') 文档 75 | 76 | div.tab-content 77 | div.tab-pane.active#demo2 78 | div.bs-docs-example 79 | div.grid-demo 80 | div.sui-row-fluid 81 | - for (var x = 1; x <= 8; x++) 82 | div(class="span#{1}")=1 83 | div.sui-row-fluid 84 | - each x in [1, 2, 2, 3, ] 85 | div(class="span#{x}")=x 86 | div.sui-row-fluid 87 | - each x in [4, 4] 88 | div(class="span#{x}")=x 89 | div.sui-row-fluid 90 | - each x in [2, 6] 91 | div(class="span#{x}")=x 92 | div.tab-pane#code2 93 | pre.prettyprint.linenums(data-target='#demo2>div') 94 | div.tab-pane#doc2 95 | p 96 | | 流式栅格系统每一栏的宽度都是其容器的百分比,因此会随着屏幕宽度的变化而不断变化,没有一个固定的宽度像素值。 97 | 98 | ul.demo-operations.clearfix 99 | li 100 | a(href='#') 下载psd文件 101 | li 102 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>div') 复制代码 103 | -------------------------------------------------------------------------------- /docs/templates/buttons.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 按钮 5 | 6 | block sidebar 7 | +sidebar('btn') 8 | 9 | block content 10 | - var SIZES = ['xlarge', 'large', '', 'small'] 11 | - var ROLES = [["", "默认"], ["primary", "首要"], ["success", "成功"], ["info", "信息"], ["warning", "警告"], ["danger", "危险"], ["link", "链接"]] 12 | 13 | h1 按钮 14 | 15 | h2.sui-page-header 设计规范 16 | 17 | div.docs-description 18 | img(src='pictures/docs/btn.png') 19 | 20 | ul.demo-operations.clearfix 21 | li 22 | a(href='#') 下载psd文件 23 | 24 | h2.sui-page-header 开发者文档 25 | 26 | p.sui-lead 27 | ul.unstyled 28 | li 按钮统一使用下面提供的高度和样式,最好不要自己添加新的尺寸和样式(但是可以把其中某些样式进行重载)。 29 | li 一般情况下推荐使用灰白色按钮,根据具体的页面和使用环境来选择。 30 | li 比较重要的操作或者需要用户明显注意到的地方使用蓝色按钮。 31 | li 黄色按钮请谨慎使用,在非常重要和特殊的情况下需要用户迅速发现并立即处理的时候使用,一个页面不能超过一个黄色按钮。 32 | 33 | ul.demo-operations.clearfix 34 | li 35 | a(href='#') 下载psd文件 36 | 37 | h2 1. 不同大小和功能的按钮 38 | ul.sui-nav.nav-tabs.nav-large 39 | li.active 40 | a(href='#demo1', data-toggle='tab') 示例 41 | li 42 | a(href='#code1', data-toggle='tab') 代码 43 | 44 | div.tab-content 45 | div.tab-pane.active#demo1 46 | div.bs-docs-example 47 | 48 | each s in SIZES 49 | - var classname = 'sui-btn' 50 | - var size = '' 51 | if s 52 | - size = 'btn-' + s 53 | each r in ROLES 54 | - var role = '' 55 | if r[0] 56 | - role = 'btn-' + r[0] 57 | | #{r[1]} 58 | | 59 | a(disabled class='sui-btn #{size}' href='javascript:void(0);') 禁用 60 | a(disabled class='sui-btn btn-text #{size}' href='javascript:void(0);') 禁用 61 | a(disabled class='sui-btn btn-link #{size}' href='javascript:void(0);') 禁用 62 | br 63 | br 64 | div.tab-pane#code1 65 | pre.prettyprint.linenums(data-target='#demo1>div') 66 | 67 | ul.demo-operations.clearfix 68 | li 69 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 70 | 71 | 72 | h2 2.带图标的按钮 73 | ul.sui-nav.nav-tabs.nav-large 74 | li.active 75 | a(href='#demo2', data-toggle='tab') 示例 76 | li 77 | a(href='#code2', data-toggle='tab') 代码 78 | 79 | div.tab-content 80 | div.tab-pane.active#demo2 81 | div.bs-docs-example 82 | each v in ROLES 83 | - var classname = 'sui-btn' 84 | if v[0] 85 | - classname += ' btn-' + v[0] 86 | if v[0] != 'link' 87 | |#{v[1]} 88 | | 89 | 90 | a.sui-btn.btn-text(href='javascript:void(0);') 91 | i.sui-icon.icon-pc-refresh 92 | a.sui-btn.btn-text.btn-default(href='javascript:void(0);') 93 | i.sui-icon.icon-pc-refresh 94 | | 刷新 95 | div.tab-pane#code2 96 | pre.prettyprint.linenums(data-target='#demo2>div') 97 | 98 | ul.demo-operations.clearfix 99 | li 100 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>div') 复制代码 101 | -------------------------------------------------------------------------------- /docs/examples/todo-create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 新建待办事项 5 | 6 | 7 | 8 | 9 | ; 10 | ; 11 | 12 | 13 |
    14 | 18 |
    19 |
    20 | 新的待办事项”晚上9点拿夜宵”创建成功! 21 |
    22 | 23 |
    24 |
    25 |
    26 | 27 |
    28 | 29 |
    30 |
    31 |
    32 | 33 |
    34 | 49 | 月 50 | 65 | 日 66 |
    67 |
    68 |
    69 | 70 |
    71 | 72 |
    73 |
    74 |
    75 |
    76 | 77 |
    78 |
    79 |
    80 |
    81 | 82 |
    ').collapse('show') 21 | ok(el.hasClass('in'), 'has class in') 22 | ok(/height/.test(el.attr('style')), 'has height set') 23 | }) 24 | 25 | test("should hide a collapsed element", function () { 26 | var el = $('
    ').collapse('hide') 27 | ok(!el.hasClass('in'), 'does not have class in') 28 | ok(/height/.test(el.attr('style')), 'has height set') 29 | }) 30 | 31 | test("should not fire shown when show is prevented", function () { 32 | $.support.transition = false 33 | stop() 34 | stop() //这里有一个bug, 下面的start方法会触发两次 35 | $('
    ') 36 | .bind('show', function (e) { 37 | e.preventDefault(); 38 | ok(true); 39 | start(); 40 | }) 41 | .bind('shown', function () { 42 | ok(false); 43 | }) 44 | .collapse('show') 45 | }) 46 | 47 | test("should reset style to auto after finishing opening collapse", function () { 48 | $.support.transition = false 49 | stop() 50 | $('
    ') 51 | .bind('show', function () { 52 | ok(this.style.height == '0px') 53 | }) 54 | .bind('shown', function () { 55 | ok(this.style.height == 'auto') 56 | start() 57 | }) 58 | .collapse('show') 59 | }) 60 | 61 | test("should add active class to target when collapse shown", function () { 62 | $.support.transition = false 63 | stop() 64 | 65 | var target = $('') 66 | .appendTo($('#qunit-fixture')) 67 | 68 | var collapsible = $('
    ') 69 | .appendTo($('#qunit-fixture')) 70 | .on('show', function () { 71 | ok(!target.hasClass('collapsed')) 72 | start() 73 | }) 74 | 75 | target.click() 76 | }) 77 | 78 | test("should remove active class to target when collapse hidden", function () { 79 | $.support.transition = false 80 | stop() 81 | 82 | var target = $('') 83 | .appendTo($('#qunit-fixture')) 84 | 85 | var collapsible = $('
    ') 86 | .appendTo($('#qunit-fixture')) 87 | .on('hide', function () { 88 | ok(target.hasClass('collapsed')) 89 | start() 90 | }) 91 | 92 | target.click() 93 | }) 94 | 95 | }) 96 | -------------------------------------------------------------------------------- /js/button.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-button.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#buttons 4 | * ============================================================ 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* BUTTON PUBLIC CLASS DEFINITION 27 | * ============================== */ 28 | 29 | var Button = function (element, options) { 30 | this.$element = $(element) 31 | this.options = $.extend({}, $.fn.button.defaults, options) 32 | } 33 | 34 | Button.prototype.setState = function (state) { 35 | var d = 'disabled' 36 | , $el = this.$element 37 | , data = $el.data() 38 | , val = $el.is('input') ? 'val' : 'html' 39 | 40 | state = state + 'Text' 41 | data.resetText || $el.data('resetText', $el[val]()) 42 | 43 | $el[val](data[state] || this.options[state]) 44 | 45 | // push to event loop to allow forms to submit 46 | setTimeout(function () { 47 | state == 'loadingText' ? 48 | $el.addClass(d).attr(d, d) : 49 | $el.removeClass(d).removeAttr(d) 50 | }, 0) 51 | } 52 | 53 | Button.prototype.toggle = function () { 54 | var $parent = this.$element.closest('[data-toggle="buttons-radio"]') 55 | 56 | $parent && $parent 57 | .find('.active') 58 | .removeClass('active') 59 | 60 | this.$element.toggleClass('active') 61 | } 62 | 63 | 64 | /* BUTTON PLUGIN DEFINITION 65 | * ======================== */ 66 | 67 | var old = $.fn.button 68 | 69 | $.fn.button = function (option) { 70 | return this.each(function () { 71 | var $this = $(this) 72 | , data = $this.data('button') 73 | , options = typeof option == 'object' && option 74 | if (!data) $this.data('button', (data = new Button(this, options))) 75 | if (option == 'toggle') data.toggle() 76 | else if (option) data.setState(option) 77 | }) 78 | } 79 | 80 | $.fn.button.defaults = { 81 | loadingText: 'loading...' 82 | } 83 | 84 | $.fn.button.Constructor = Button 85 | 86 | 87 | /* BUTTON NO CONFLICT 88 | * ================== */ 89 | 90 | $.fn.button.noConflict = function () { 91 | $.fn.button = old 92 | return this 93 | } 94 | 95 | 96 | /* BUTTON DATA-API 97 | * =============== */ 98 | 99 | $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { 100 | var $btn = $(e.target) 101 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 102 | $btn.button('toggle') 103 | }) 104 | 105 | }(window.jQuery); 106 | -------------------------------------------------------------------------------- /js/checkbox.js: -------------------------------------------------------------------------------- 1 | !function ($) { 2 | 3 | "use strict"; 4 | 5 | var CHECKED_CLASS = 'checked'; 6 | var HALF_CHECKED_CLASS = 'halfchecked'; 7 | var DISABLED_CLASS= 'disabled'; 8 | 9 | var Checkbox = function (element, options) { 10 | this.$element = $(element) 11 | //this.options = $.extend({}, $.fn.checkbox.defaults, options) 12 | this.$checkbox = this.$element.find("input").change($.proxy(this.update, this)) 13 | //同步状态 14 | this.update() 15 | var name = this.$checkbox.prop("name") 16 | var self = this; 17 | if (name && this.$checkbox.attr("type").toUpperCase() == 'RADIO') { 18 | //radio 会因为其他相同name 的radio的改变而受到影响 19 | $("input[name='"+name+"']").each(function(){ 20 | $(this).change($.proxy(self.update, self)) 21 | }) 22 | } 23 | } 24 | 25 | var old = $.fn.checkbox 26 | 27 | $.fn.checkbox = function (option) { 28 | return this.each(function () { 29 | var $this = $(this) 30 | , data = $this.data('checkbox') 31 | , options = typeof option == 'object' && option 32 | if (!data) $this.data('checkbox', (data = new Checkbox(this, options))) 33 | else if (option) data[option]() 34 | }) 35 | } 36 | //同步状态 37 | Checkbox.prototype.update = function () { 38 | if(this.$checkbox.prop("checked")) this.$element.removeClass(HALF_CHECKED_CLASS).addClass(CHECKED_CLASS) 39 | else this.$element.removeClass(CHECKED_CLASS) 40 | if(this.$checkbox.prop('disabled')) this.$element.addClass(DISABLED_CLASS) 41 | else this.$element.removeClass(DISABLED_CLASS) 42 | } 43 | Checkbox.prototype.toggle = function () { 44 | if(this.$checkbox.prop("checked")) this.uncheck() 45 | else this.check() 46 | } 47 | 48 | Checkbox.prototype.check = function () { 49 | if(this.$checkbox.prop("disabled")) return 50 | this.$element.removeClass(HALF_CHECKED_CLASS).addClass(CHECKED_CLASS) 51 | this.$checkbox.prop('checked', 'checked') 52 | } 53 | Checkbox.prototype.uncheck = function () { 54 | if(this.$checkbox.prop("disabled")) return 55 | this.$element.removeClass(HALF_CHECKED_CLASS).removeClass(CHECKED_CLASS) 56 | this.$checkbox.removeAttr('checked') 57 | } 58 | Checkbox.prototype.halfcheck = function () { 59 | if(this.$checkbox.prop("disabled")) return 60 | this.$element.removeClass(CHECKED_CLASS).addClass(HALF_CHECKED_CLASS) 61 | this.$checkbox.removeAttr('checked') 62 | } 63 | 64 | Checkbox.prototype.disable = function () { 65 | this.$element.addClass(DISABLED_CLASS) 66 | this.$checkbox.prop('disabled', 'disabled') 67 | } 68 | Checkbox.prototype.enable = function () { 69 | this.$element.removeClass(DISABLED_CLASS) 70 | this.$checkbox.removeAttr('disabled') 71 | } 72 | 73 | $.fn.checkbox.defaults = { 74 | loadingText: 'loading...' 75 | } 76 | 77 | $.fn.checkbox.Constructor = Checkbox 78 | 79 | 80 | /* NO CONFLICT 81 | * ================== */ 82 | 83 | $.fn.checkbox.noConflict = function () { 84 | $.fn.checkbox = old 85 | return this 86 | } 87 | 88 | $.fn.radio = $.fn.checkbox; 89 | 90 | 91 | /* DATA-API 92 | * =============== */ 93 | 94 | //必须一开始就初始化,不然对于radio,由于其他相同name的radio改动的时候由于没有初始化就无法更新状态 95 | $(function() { 96 | $('[data-toggle^=checkbox],[data-toggle^=radio] ').each(function () { 97 | $(this).checkbox() 98 | }) 99 | }) 100 | 101 | }(window.jQuery); 102 | -------------------------------------------------------------------------------- /less/carousel.less: -------------------------------------------------------------------------------- 1 | // 2 | // Carousel 3 | // -------------------------------------------------- 4 | 5 | 6 | .sui-carousel { 7 | position: relative; 8 | margin-bottom: @baseLineHeight; 9 | line-height: 1; 10 | 11 | .carousel-inner { 12 | overflow: hidden; 13 | width: 100%; 14 | position: relative; 15 | } 16 | 17 | .carousel-inner { 18 | 19 | > .item { 20 | display: none; 21 | position: relative; 22 | .transition(.6s ease-in-out left); 23 | 24 | // Account for jankitude on images 25 | > img, 26 | > a > img { 27 | display: block; 28 | line-height: 1; 29 | } 30 | } 31 | 32 | > .active, 33 | > .next, 34 | > .prev { display: block; } 35 | 36 | > .active { 37 | left: 0; 38 | } 39 | 40 | > .next, 41 | > .prev { 42 | position: absolute; 43 | top: 0; 44 | width: 100%; 45 | } 46 | 47 | > .next { 48 | left: 100%; 49 | } 50 | > .prev { 51 | left: -100%; 52 | } 53 | > .next.left, 54 | > .prev.right { 55 | left: 0; 56 | } 57 | 58 | > .active.left { 59 | left: -100%; 60 | } 61 | > .active.right { 62 | left: 100%; 63 | } 64 | 65 | } 66 | 67 | // Left/right controls for nav 68 | // --------------------------- 69 | 70 | .carousel-control { 71 | position: absolute; 72 | top: 40%; 73 | left: 15px; 74 | width: 40px; 75 | height: 40px; 76 | margin-top: -20px; 77 | font-size: 60px; 78 | font-weight: 100; 79 | line-height: 30px; 80 | color: @white; 81 | text-align: center; 82 | background: @grayDarker; 83 | border: 3px solid @white; 84 | .border-radius(23px); 85 | .opacity(50); 86 | 87 | // we can't have this transition here 88 | // because webkit cancels the carousel 89 | // animation if you trip this while 90 | // in the middle of another animation 91 | // ;_; 92 | // .transition(opacity .2s linear); 93 | 94 | // Reposition the right one 95 | &.right { 96 | left: auto; 97 | right: 15px; 98 | } 99 | 100 | // Hover/focus state 101 | &:hover, 102 | &:focus { 103 | color: @white; 104 | text-decoration: none; 105 | .opacity(90); 106 | } 107 | } 108 | 109 | // Carousel indicator pips 110 | // ----------------------------- 111 | .carousel-indicators { 112 | position: absolute; 113 | top: 15px; 114 | right: 15px; 115 | z-index: 5; 116 | margin: 0; 117 | list-style: none; 118 | 119 | li { 120 | display: block; 121 | float: left; 122 | width: 10px; 123 | height: 10px; 124 | margin-left: 5px; 125 | text-indent: -999px; 126 | background-color: #ccc; 127 | background-color: rgba(255,255,255,.25); 128 | border-radius: 5px; 129 | } 130 | .active { 131 | background-color: #fff; 132 | } 133 | } 134 | 135 | // Caption for text below images 136 | // ----------------------------- 137 | 138 | .carousel-caption { 139 | position: absolute; 140 | left: 0; 141 | right: 0; 142 | bottom: 0; 143 | padding: 15px; 144 | background: @grayDark; 145 | background: rgba(0,0,0,.75); 146 | } 147 | .carousel-caption h4, 148 | .carousel-caption p { 149 | color: @white; 150 | line-height: @baseLineHeight; 151 | } 152 | .carousel-caption h4 { 153 | margin: 0 0 5px; 154 | } 155 | .carousel-caption p { 156 | margin-bottom: 0; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /js/popover.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * bootstrap-popover.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#popovers 4 | * =========================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * =========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* POPOVER PUBLIC CLASS DEFINITION 27 | * =============================== */ 28 | 29 | var Popover = function (element, options) { 30 | this.init('popover', element, options) 31 | } 32 | 33 | 34 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js 35 | ========================================== */ 36 | 37 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { 38 | 39 | constructor: Popover 40 | 41 | , setContent: function () { 42 | var $tip = this.tip() 43 | , title = this.getTitle() 44 | , content = this.getContent() 45 | 46 | $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 47 | $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content) 48 | 49 | $tip.removeClass('fade top bottom left right in') 50 | } 51 | 52 | , hasContent: function () { 53 | return this.getTitle() || this.getContent() 54 | } 55 | 56 | , getContent: function () { 57 | var content 58 | , $e = this.$element 59 | , o = this.options 60 | 61 | content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) 62 | || $e.attr('data-content') 63 | 64 | return content 65 | } 66 | 67 | , tip: function () { 68 | if (!this.$tip) { 69 | this.$tip = $(this.options.template) 70 | } 71 | return this.$tip 72 | } 73 | 74 | , destroy: function () { 75 | this.hide().$element.off('.' + this.type).removeData(this.type) 76 | } 77 | 78 | }) 79 | 80 | 81 | /* POPOVER PLUGIN DEFINITION 82 | * ======================= */ 83 | 84 | var old = $.fn.popover 85 | 86 | $.fn.popover = function (option) { 87 | return this.each(function () { 88 | var $this = $(this) 89 | , data = $this.data('popover') 90 | , options = typeof option == 'object' && option 91 | if (!data) $this.data('popover', (data = new Popover(this, options))) 92 | if (typeof option == 'string') data[option]() 93 | }) 94 | } 95 | 96 | $.fn.popover.Constructor = Popover 97 | 98 | $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { 99 | placement: 'right' 100 | , trigger: 'click' 101 | , content: '' 102 | , template: '

    ' 103 | }) 104 | 105 | 106 | /* POPOVER NO CONFLICT 107 | * =================== */ 108 | 109 | $.fn.popover.noConflict = function () { 110 | $.fn.popover = old 111 | return this 112 | } 113 | 114 | }(window.jQuery); 115 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 3 | var join = require("path").join 4 | 5 | var gulp = require('gulp'), 6 | gutil = require('gulp-util'), 7 | requirejs = require('gulp-requirejs'), 8 | uglify = require('gulp-uglify'), 9 | rename = require("gulp-rename"), 10 | jshint = require('gulp-jshint'), 11 | less = require('gulp-less'), 12 | jade = require('gulp-jade'), 13 | qunit = require('gulp-qunit'), 14 | watch = require('gulp-watch'), 15 | livereload = require('gulp-livereload'), 16 | tinnylr = require('tiny-lr') 17 | 18 | var server = tinnylr() 19 | 20 | var exec = require("child_process").exec 21 | 22 | var paths = { 23 | distRoot: './build', 24 | docsRoot: './docs', 25 | demosRoot: './docs/demos' 26 | } 27 | 28 | var pkg = { 29 | name: "bootstrap" 30 | } 31 | 32 | gulp.task('requirejs', function() { 33 | //目前requirejs还不支持gulp.src 34 | var jsDist = join(paths.distRoot, 'js') 35 | var requirejsConfig= { 36 | baseUrl: "js", 37 | name: "almond", 38 | optimize: "none", 39 | include: pkg.name, 40 | insertRequire: [pkg.name], 41 | mainConfigFile: "js/requirejs-config.js", 42 | out: pkg.name + '.js', 43 | wrap: true 44 | } 45 | requirejs(requirejsConfig) 46 | //uncompressed 47 | .pipe(gulp.dest(jsDist)) 48 | //uglify 49 | .pipe(uglify({preserveComments: 'some'})) 50 | .pipe(rename(pkg.name + '.min.js')) 51 | .pipe(gulp.dest(jsDist)) 52 | .pipe(livereload(server)) 53 | }) 54 | 55 | gulp.task('less', function() { 56 | var cssDist = join(paths.distRoot, 'css') 57 | 58 | var recess = function(input, output) { 59 | output = output || input 60 | gulp.src(join('less', input + '.less')) 61 | .pipe(less()) 62 | .pipe(rename(output + '.css')) 63 | .pipe(gulp.dest(cssDist)) 64 | .pipe(less({compress: true})) 65 | .pipe(rename(output + '.min.css')) 66 | .pipe(gulp.dest(cssDist)) 67 | .pipe(livereload(server)) 68 | } 69 | 70 | recess('bootstrap') 71 | recess('responsive', pkg.name + '-responsive') 72 | }) 73 | 74 | // compile jade template 75 | gulp.task('jade', function() { 76 | gulp.src(['**/*.jade', '!base.jade', '!com-*', '!*-com.jade'], {cwd: join(paths.demosRoot, 'templates')}) 77 | .pipe(jade({pretty: true})) 78 | .pipe(gulp.dest(paths.demosRoot)) 79 | .pipe(livereload(server)) 80 | }) 81 | 82 | //compile mastache template 83 | gulp.task('hogan', function(callback) { 84 | var child = exec('node docs/build', function(e) { 85 | callback() 86 | }) 87 | }) 88 | 89 | gulp.task('jshint', function() { 90 | var jsfiles = [ 91 | 'gulpfile.js', 92 | 'js/*.js', 93 | 'js/tests/unit/*.js' 94 | ] 95 | gulp.src(jsfiles) 96 | .pipe(jshint('js/.jshintrc')) 97 | .pipe(jshint.reporter('default')) 98 | }) 99 | 100 | gulp.task('qunit', function(callback) { 101 | gulp.src('js/tests/*.html') 102 | .pipe(qunit()); 103 | }) 104 | 105 | // copy fonts to build 106 | gulp.task('fonts', function() { 107 | gulp.src('./fonts/*') 108 | .pipe(gulp.dest(join(paths.distRoot, 'fonts'))) 109 | }) 110 | 111 | gulp.task('watch', function() { 112 | server.listen(3456) 113 | gulp.watch('js/**/*.js', ['requirejs']) 114 | gulp.watch('less/**/*.less', ['less']) 115 | gulp.watch(join(paths.docsRoot, 'templates/**/*.mustache'), ['hogan']) 116 | gulp.watch(join(paths.demosRoot, 'templates/**/*.jade'), ['jade']) 117 | gulp.watch('./fonts/*', ['jade']) 118 | }) 119 | 120 | gulp.task('test', ['jshint', 'qunit']) 121 | 122 | gulp.task('docs', ['fonts', 'jade', 'hogan']) 123 | 124 | gulp.task('default', ['less', 'test', 'requirejs', 'docs']) 125 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Bootstrap 2 | 3 | Looking to contribute something to Bootstrap? **Here's how you can help.** 4 | 5 | 6 | 7 | ## Reporting issues 8 | 9 | We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Bootstrap core. Please read the following guidelines before opening any issue. 10 | 11 | 1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. 12 | 2. **Create an isolated and reproducible test case.** Be sure the problem exists in Bootstrap's code with a [reduced test case](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report. 13 | 3. **Include a live example.** Make use of jsFiddle or jsBin to share your isolated test cases. 14 | 4. **Share as much information as possible.** Include operating system and version, browser and version, version of Bootstrap, customized or vanilla build, etc. where appropriate. Also include steps to reproduce the bug. 15 | 16 | 17 | 18 | ## Key branches 19 | 20 | - `master` is the latest, deployed version. 21 | - `gh-pages` is the hosted docs (not to be used for pull requests). 22 | - `*-wip` is the official work in progress branch for the next release. 23 | 24 | 25 | 26 | ## Notes on the repo 27 | 28 | As of v2.0.0, Bootstrap's documentation is powered by Mustache templates and built via `make` before each commit and release. This was done to enable internationalization (translation) in a future release by uploading our strings to the [Twitter Translation Center](http://translate.twttr.com/). Any edits to the docs should be first done in the Mustache files and then recompiled into the HTML. 29 | 30 | 31 | 32 | ## Pull requests 33 | 34 | - Try to submit pull requests against the latest `*-wip` branch for easier merging 35 | - Any changes to the docs must be made to the Mustache templates, not just the compiled HTML pages 36 | - CSS changes must be done in .less files first, never just the compiled files 37 | - If modifying the .less files, always recompile and commit the compiled files bootstrap.css and bootstrap.min.css 38 | - Try not to pollute your pull request with unintended changes--keep them simple and small 39 | - Try to share which browsers your code has been tested in before submitting a pull request 40 | 41 | 42 | 43 | ## Coding standards: HTML 44 | 45 | - Two spaces for indentation, never tabs 46 | - Double quotes only, never single quotes 47 | - Always use proper indentation 48 | - Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags) 49 | 50 | 51 | 52 | ## Coding standards: CSS 53 | 54 | - Adhere to the [Recess CSS property order](http://markdotto.com/2011/11/29/css-property-order/) 55 | - Multiple-line approach (one property and value per line) 56 | - Always a space after a property's colon (.e.g, `display: block;` and not `display:block;`) 57 | - End all lines with a semi-colon 58 | - For multiple, comma-separated selectors, place each selector on it's own line 59 | - Attribute selectors, like `input[type="text"]` should always wrap the attribute's value in double quotes, for consistency and safety (see this [blog post on unquoted attribute values](http://mathiasbynens.be/notes/unquoted-attribute-values) that can lead to XSS attacks). 60 | 61 | 62 | 63 | ## Coding standards: JS 64 | 65 | - No semicolons 66 | - Comma first 67 | - 2 spaces (no tabs) 68 | - strict mode 69 | - "Attractive" 70 | 71 | 72 | 73 | ## License 74 | 75 | By contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/twbs/bootstrap/blob/master/LICENSE 76 | -------------------------------------------------------------------------------- /docs/assets/js/README.md: -------------------------------------------------------------------------------- 1 | ## 2.0 BOOTSTRAP JS PHILOSOPHY 2 | These are the high-level design rules which guide the development of Bootstrap's plugin apis. 3 | 4 | --- 5 | 6 | ### DATA-ATTRIBUTE API 7 | 8 | We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of javascript. 9 | 10 | We acknowledge that this isn't always the most performant and sometimes it may be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this: 11 | 12 | $('body').off('.data-api') 13 | 14 | To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this: 15 | 16 | $('body').off('.alert.data-api') 17 | 18 | --- 19 | 20 | ### PROGRAMMATIC API 21 | 22 | We also believe you should be able to use all plugins provided by Bootstrap purely through the JS API. 23 | 24 | All public APIs should be single, chainable methods, and return the collection acted upon. 25 | 26 | $(".btn.danger").button("toggle").addClass("fat") 27 | 28 | All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior: 29 | 30 | $("#myModal").modal() // initialized with defaults 31 | $("#myModal").modal({ keyboard: false }) // initialized with now keyboard 32 | $("#myModal").modal('show') // initializes and invokes show immediately afterqwe2 33 | 34 | --- 35 | 36 | ### OPTIONS 37 | 38 | Options should be sparse and add universal value. We should pick the right defaults. 39 | 40 | All plugins should have a default object which can be modified to effect all instance's default options. The defaults object should be available via `$.fn.plugin.defaults`. 41 | 42 | $.fn.modal.defaults = { … } 43 | 44 | An options definition should take the following form: 45 | 46 | *noun*: *adjective* - describes or modifies a quality of an instance 47 | 48 | examples: 49 | 50 | backdrop: true 51 | keyboard: false 52 | placement: 'top' 53 | 54 | --- 55 | 56 | ### EVENTS 57 | 58 | All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action. 59 | 60 | show | shown 61 | hide | hidden 62 | 63 | --- 64 | 65 | ### CONSTRUCTORS 66 | 67 | Each plugin should expose it's raw constructor on a `Constructor` property -- accessed in the following way: 68 | 69 | 70 | $.fn.popover.Constructor 71 | 72 | --- 73 | 74 | ### DATA ACCESSOR 75 | 76 | Each plugin stores a copy of the invoked class on an object. This class instance can be accessed directly through jQuery's data API like this: 77 | 78 | $('[rel=popover]').data('popover') instanceof $.fn.popover.Constructor 79 | 80 | --- 81 | 82 | ### DATA ATTRIBUTES 83 | 84 | Data attributes should take the following form: 85 | 86 | - data-{{verb}}={{plugin}} - defines main interaction 87 | - data-target || href^=# - defined on "control" element (if element controls an element other than self) 88 | - data-{{noun}} - defines class instance options 89 | 90 | examples: 91 | 92 | // control other targets 93 | data-toggle="modal" data-target="#foo" 94 | data-toggle="collapse" data-target="#foo" data-parent="#bar" 95 | 96 | // defined on element they control 97 | data-spy="scroll" 98 | 99 | data-dismiss="modal" 100 | data-dismiss="alert" 101 | 102 | data-toggle="dropdown" 103 | 104 | data-toggle="button" 105 | data-toggle="buttons-checkbox" 106 | data-toggle="buttons-radio" -------------------------------------------------------------------------------- /less/popovers.less: -------------------------------------------------------------------------------- 1 | // 2 | // Popovers 3 | // -------------------------------------------------- 4 | 5 | 6 | .sui-popover { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | z-index: @zindexPopover; 11 | display: none; 12 | max-width: 276px; 13 | padding: 1px; 14 | text-align: left; // Reset given new insertion method 15 | background-color: @popoverBackground; 16 | -webkit-background-clip: padding-box; 17 | -moz-background-clip: padding; 18 | background-clip: padding-box; 19 | border: 1px solid #ccc; 20 | border: 1px solid rgba(0,0,0,.2); 21 | .border-radius(6px); 22 | .box-shadow(0 5px 10px rgba(0,0,0,.2)); 23 | 24 | // Overrides for proper insertion 25 | white-space: normal; 26 | 27 | // Offset the popover to account for the popover arrow 28 | &.top { margin-top: -10px; } 29 | &.right { margin-left: 10px; } 30 | &.bottom { margin-top: 10px; } 31 | &.left { margin-left: -10px; } 32 | } 33 | 34 | .popover-title { 35 | margin: 0; // reset heading margin 36 | padding: 8px 14px; 37 | font-size: 14px; 38 | font-weight: normal; 39 | line-height: 18px; 40 | background-color: @popoverTitleBackground; 41 | border-bottom: 1px solid darken(@popoverTitleBackground, 5%); 42 | .border-radius(5px 5px 0 0); 43 | 44 | &:empty { 45 | display: none; 46 | } 47 | } 48 | 49 | .popover-content { 50 | padding: 9px 14px; 51 | } 52 | 53 | // Arrows 54 | // 55 | // .arrow is outer, .arrow:after is inner 56 | 57 | .sui-popover .arrow { 58 | &, &:after { 59 | position: absolute; 60 | display: block; 61 | width: 0; 62 | height: 0; 63 | border-color: transparent; 64 | border-style: solid; 65 | } 66 | .arrow { 67 | border-width: @popoverArrowOuterWidth; 68 | } 69 | .arrow:after { 70 | border-width: @popoverArrowWidth; 71 | content: ""; 72 | } 73 | } 74 | 75 | .sui-popover { 76 | &.top .arrow { 77 | left: 50%; 78 | margin-left: -@popoverArrowOuterWidth; 79 | border-bottom-width: 0; 80 | border-top-color: #999; // IE8 fallback 81 | border-top-color: @popoverArrowOuterColor; 82 | bottom: -@popoverArrowOuterWidth; 83 | &:after { 84 | bottom: 1px; 85 | margin-left: -@popoverArrowWidth; 86 | border-bottom-width: 0; 87 | border-top-color: @popoverArrowColor; 88 | } 89 | } 90 | &.right .arrow { 91 | top: 50%; 92 | left: -@popoverArrowOuterWidth; 93 | margin-top: -@popoverArrowOuterWidth; 94 | border-left-width: 0; 95 | border-right-color: #999; // IE8 fallback 96 | border-right-color: @popoverArrowOuterColor; 97 | &:after { 98 | left: 1px; 99 | bottom: -@popoverArrowWidth; 100 | border-left-width: 0; 101 | border-right-color: @popoverArrowColor; 102 | } 103 | } 104 | &.bottom .arrow { 105 | left: 50%; 106 | margin-left: -@popoverArrowOuterWidth; 107 | border-top-width: 0; 108 | border-bottom-color: #999; // IE8 fallback 109 | border-bottom-color: @popoverArrowOuterColor; 110 | top: -@popoverArrowOuterWidth; 111 | &:after { 112 | top: 1px; 113 | margin-left: -@popoverArrowWidth; 114 | border-top-width: 0; 115 | border-bottom-color: @popoverArrowColor; 116 | } 117 | } 118 | 119 | &.left .arrow { 120 | top: 50%; 121 | right: -@popoverArrowOuterWidth; 122 | margin-top: -@popoverArrowOuterWidth; 123 | border-right-width: 0; 124 | border-left-color: #999; // IE8 fallback 125 | border-left-color: @popoverArrowOuterColor; 126 | &:after { 127 | right: 1px; 128 | border-right-width: 0; 129 | border-left-color: @popoverArrowColor; 130 | bottom: -@popoverArrowWidth; 131 | } 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /docs/templates/pagination-js.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 分页器 5 | 6 | block sidebar 7 | +sidebar('pagination-js') 8 | 9 | block content 10 | h1 分页器-JS 11 | 12 | h2.sui-page-header 开发者文档 13 | 14 | p.sui-lead 15 | | pagination-JS组件用于前端分页,无刷新等应用场景 16 | div 17 | a(href="pagination.html") 点击访问pagination-CSS组件 18 | 19 | ul.sui-nav.nav-tabs.nav-large 20 | li.active 21 | a(href='#demo1', data-toggle='tab') 示例 22 | li 23 | a(href='#doc1', data-toggle='tab') 文档 24 | 25 | div.tab-content 26 | div.tab-pane.active#demo1 27 | div.bs-docs-example 28 | h3 示例 29 | p.test 30 | pre.prettyprint.linenums. 31 | $('.test').pagination({ 32 | pages: 50, 33 | styleClass: ['pagination-large'], 34 | showCtrl: true, 35 | displayPage: 6, 36 | onSelect: function (num) { 37 | console.log(num) //打开控制台观察 38 | } 39 | }) 40 | h3 最小配置项 41 | p.test1 42 | pre.prettyprint.linenums. 43 | $('.test').pagination({ 44 | pages: 6 45 | }) 46 | 47 | div.tab-pane#doc1 48 | h3 配置项 49 | h4 pagination组件一共有8个配置项,较于其他分页插件,配置更为灵活简单,提供2种分页计算方式,且可控页码显示的数量。 50 | dl 51 | dt styleClass 52 | dd styleClass接收一个数组,包括结合SUI CSS部分的pagination-small,pagiantion-large和默认的pagination样式,以后提供皮肤样式和自定义样式的时候也可以在这里引入 53 | dd eg: styleClass: ['pagination-large', 'custom-red', 'custom-size'] 54 | dl 55 | dt displayPage 56 | dd displayPage指的是要显示多少个页码,如下图所示,展示了6个,默认显示5个 57 | dd 58 | img(src="assets/imgs/pagination1.png") 59 | dd 指定了displayPage以后,pagination组件会根据该配置项自动分页,出于用户体验的考虑,displayPage最小为5个,低于5个会自动被改写为5个 60 | dd 需要指出一种情况是,如果displayPage为n,但是总的页码为n+1时,pagination组件会展示全部的页码(也就是n+1),不出现省略号 61 | dl 62 | dt currentPage 63 | dd 当前页,默认为第1页,不解释 64 | dl 65 | dt itemsCount,pageSize和pages 66 | dd pagination组件提供两种计算分页的方式,一种是直接给出pages,另一种是给出数据的总条数和每页显示的条数,pagination会自动计算出页数。 67 | dd 当给出pages时,会忽略itemsCount和pageSize参数 68 | dd P.S:一般情况来讲,通过pages来配置分页,适用于分页数固定的情况。 69 | dl 70 | dt showCtrl 71 | dd 是否展示总页数和跳转控制器,默认为false,设置为true时会在pagination节点上注册一些事件,对跳转页码做合法性校验,并支持键盘操作。 72 | dl 73 | dt onSelect 74 | dd 点击页码时的回调函数,提供一个当前点击的页码的参数,可以在回调函数中使用自定义事件。 75 | dt remote 76 | dd 远程控制开关,如果设置为true的话,分页器不会自动跳转,需要人工调用goToPage方法,主要用于一些特殊条件下,比如点击了页码之后,需要等页面加载完之后再跳转 77 | h3 函数 78 | h4 pagination组件对外暴露2个函数 79 | dl 80 | dt $('selector').pagination('updateItemsCount',itemsCount[, pageToGo]) 81 | dd 当数据条目总数发生变化时,调用此方法,参数为新的数据条目总数 82 | dd pageToGo是要跳转到的某页 83 | dl 84 | dt $('selector').pagination('updatePages',pages[, pageToGo]) 85 | dd 当分页直接采用pages配置项时,pageSize不存在,因此只能通过该方法直接更新分页数 86 | dd P.S:一般情况来讲,通过pages来配置分页,适用于分页数固定的情况,不推荐使用此方法。 87 | dd pageToGo是要跳转到的某页 88 | dl 89 | dt $('selector').pagination('goToPage', pageNum) 90 | dd 跳转到指定页面 91 | 92 | block js_block 93 | script. 94 | $('.test').pagination({ 95 | pages: 50, 96 | styleClass: ['pagination-large'], 97 | showCtrl: true, 98 | displayPage: 6, 99 | onSelect: function (num) { 100 | console.log(num) 101 | } 102 | }) 103 | 104 | $('.test1').pagination({ 105 | pages: 6 106 | }) 107 | 108 | -------------------------------------------------------------------------------- /docs/assets/css/index.css: -------------------------------------------------------------------------------- 1 | .animated { 2 | -webkit-animation-duration: 1s; 3 | animation-duration: 1s; 4 | -webkit-animation-fill-mode: both; 5 | animation-fill-mode: both; 6 | } 7 | @-webkit-keyframes myBounceInUp { 8 | 0% { 9 | opacity: 0; 10 | -webkit-transform: translateY(200px); 11 | transform: translateY(200px); 12 | } 13 | 100% { 14 | opacity: 1; 15 | -webkit-transform: translateY(0); 16 | transform: translateY(0); 17 | } 18 | } 19 | @keyframes myBounceInUp { 20 | 0% { 21 | opacity: 0; 22 | -webkit-transform: translateY(200px); 23 | transform: translateY(200px); 24 | } 25 | 100% { 26 | opacity: 1; 27 | -webkit-transform: translateY(0); 28 | transform: translateY(0); 29 | } 30 | } 31 | .myBounceInUp { 32 | -webkit-animation-name: myBounceInUp; 33 | animation-name: myBounceInUp; 34 | } 35 | .intro { 36 | background-color: #6f5499; 37 | color: #fff; 38 | padding: 80px 0; 39 | } 40 | .jumbotron { 41 | padding: 60px 0; 42 | color: #fff; 43 | } 44 | .components { 45 | background-color: #a2dbf6; 46 | -webkit-transition: background 0.5s, background ease-in-out 0.5s; 47 | transition: background .5s, background .5s; 48 | -webkit-transition: color 1s 0.5s, color ease-in-out 1s 0.5s; 49 | transition: color 1s .5s, color 1s .5s; 50 | color: #555; 51 | } 52 | .components img { 53 | opacity: 0; 54 | } 55 | .components.inview { 56 | background-color: #45b7ed; 57 | color: #fff; 58 | } 59 | .components.inview img { 60 | -webkit-animation-name: myBounceInUp; 61 | animation-name: myBounceInUp; 62 | -webkit-animation-duration: 1s; 63 | animation-duration: 1s; 64 | -webkit-animation-fill-mode: both; 65 | animation-fill-mode: both; 66 | } 67 | .features { 68 | background-color: #ddebcf; 69 | -webkit-transition: background 0.5s, background ease-in-out 0.5s; 70 | transition: background .5s, background .5s; 71 | -webkit-transition: color 1s 0.5s, color ease-in-out 1s 0.5s; 72 | transition: color 1s .5s, color 1s .5s; 73 | color: #555; 74 | } 75 | .features img { 76 | opacity: 0; 77 | } 78 | .features.inview { 79 | background-color: #aacc88; 80 | color: #fff; 81 | } 82 | .features.inview img { 83 | -webkit-animation-name: myBounceInUp; 84 | animation-name: myBounceInUp; 85 | -webkit-animation-duration: 1s; 86 | animation-duration: 1s; 87 | -webkit-animation-fill-mode: both; 88 | animation-fill-mode: both; 89 | } 90 | .bootstrap { 91 | background-color: #22ffd7; 92 | -webkit-transition: background 0.5s, background ease-in-out 0.5s; 93 | transition: background .5s, background .5s; 94 | -webkit-transition: color 1s 0.5s, color ease-in-out 1s 0.5s; 95 | transition: color 1s .5s, color 1s .5s; 96 | color: #555; 97 | } 98 | .bootstrap img { 99 | opacity: 0; 100 | } 101 | .bootstrap.inview { 102 | background-color: #00bb99; 103 | color: #fff; 104 | } 105 | .bootstrap.inview img { 106 | -webkit-animation-name: myBounceInUp; 107 | animation-name: myBounceInUp; 108 | -webkit-animation-duration: 1s; 109 | animation-duration: 1s; 110 | -webkit-animation-fill-mode: both; 111 | animation-fill-mode: both; 112 | } 113 | .intro > .sui-container { 114 | text-align: center; 115 | } 116 | h1 { 117 | font-size: 64px; 118 | line-height: 1.5; 119 | } 120 | h2 { 121 | font-size: 48px; 122 | line-height: 1.5; 123 | } 124 | .center { 125 | text-align: center; 126 | } 127 | .brand-intro .sui-lead { 128 | font-size: 24px; 129 | line-height: 2; 130 | } 131 | .btn-lead { 132 | padding: 20px 80px; 133 | font-size: 24px; 134 | } 135 | .btn-wrap { 136 | margin-top: 50px; 137 | } 138 | .details ul { 139 | margin-top: 50px; 140 | } 141 | .details li { 142 | font-size: 18px; 143 | line-height: 2; 144 | } 145 | .bootstrap-logo { 146 | height: 300px; 147 | } 148 | -------------------------------------------------------------------------------- /js/affix.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-affix.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#affix 4 | * ========================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* AFFIX CLASS DEFINITION 27 | * ====================== */ 28 | 29 | var Affix = function (element, options) { 30 | this.options = $.extend({}, $.fn.affix.defaults, options) 31 | this.$window = $(window) 32 | .on('scroll.affix.data-api', $.proxy(this.checkPosition, this)) 33 | .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this)) 34 | this.$element = $(element) 35 | this.checkPosition() 36 | } 37 | 38 | Affix.prototype.checkPosition = function () { 39 | if (!this.$element.is(':visible')) return 40 | 41 | var scrollHeight = $(document).height() 42 | , scrollTop = this.$window.scrollTop() 43 | , position = this.$element.offset() 44 | , offset = this.options.offset 45 | , offsetBottom = offset.bottom 46 | , offsetTop = offset.top 47 | , reset = 'affix affix-top affix-bottom' 48 | , affix 49 | 50 | if (typeof offset != 'object') offsetBottom = offsetTop = offset 51 | if (typeof offsetTop == 'function') offsetTop = offset.top() 52 | if (typeof offsetBottom == 'function') offsetBottom = offset.bottom() 53 | 54 | affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? 55 | false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 56 | 'bottom' : offsetTop != null && scrollTop <= offsetTop ? 57 | 'top' : false 58 | 59 | if (this.affixed === affix) return 60 | 61 | this.affixed = affix 62 | this.unpin = affix == 'bottom' ? position.top - scrollTop : null 63 | 64 | this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : '')) 65 | } 66 | 67 | 68 | /* AFFIX PLUGIN DEFINITION 69 | * ======================= */ 70 | 71 | var old = $.fn.affix 72 | 73 | $.fn.affix = function (option) { 74 | return this.each(function () { 75 | var $this = $(this) 76 | , data = $this.data('affix') 77 | , options = typeof option == 'object' && option 78 | if (!data) $this.data('affix', (data = new Affix(this, options))) 79 | if (typeof option == 'string') data[option]() 80 | }) 81 | } 82 | 83 | $.fn.affix.Constructor = Affix 84 | 85 | $.fn.affix.defaults = { 86 | offset: 0 87 | } 88 | 89 | 90 | /* AFFIX NO CONFLICT 91 | * ================= */ 92 | 93 | $.fn.affix.noConflict = function () { 94 | $.fn.affix = old 95 | return this 96 | } 97 | 98 | 99 | /* AFFIX DATA-API 100 | * ============== */ 101 | 102 | $(window).on('load', function () { 103 | $('[data-spy="affix"]').each(function () { 104 | var $spy = $(this) 105 | , data = $spy.data() 106 | 107 | data.offset = data.offset || {} 108 | 109 | data.offsetBottom && (data.offset.bottom = data.offsetBottom) 110 | data.offsetTop && (data.offset.top = data.offsetTop) 111 | 112 | $spy.affix(data) 113 | }) 114 | }) 115 | 116 | 117 | }(window.jQuery); 118 | -------------------------------------------------------------------------------- /docs/templates/msgs.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 提示消息 5 | 6 | block head 7 | style(type="text/css"). 8 | code { 9 | display: inline-block; 10 | *display: inline; 11 | *zoom: 1; 12 | padding: 2px 4px; 13 | border: 1px solid #e1e1e8; 14 | font-size: 12px; 15 | } 16 | 17 | block sidebar 18 | +sidebar('msg') 19 | block content 20 | 21 | h1 提示消息 22 | 23 | h2.sui-page-header 设计规范 24 | 25 | div.docs-description 26 | img(src='pictures/docs/msgs.png') 27 | 28 | ul.demo-operations.clearfix 29 | li 30 | a(href='#') 下载psd文件 31 | 32 | h2.sui-page-header 开发者文档 33 | 34 | h2 不同种类 35 | 36 | ul.sui-nav.nav-tabs.nav-large 37 | li.active 38 | a(href='#demo1', data-toggle='tab') 示例 39 | li 40 | a(href='#code1', data-toggle='tab') 代码 41 | 42 | div.tab-content 43 | div.tab-pane.active#demo1 44 | div.bs-docs-example 45 | div.sui-msg.msg-error 46 | div.msg-con 47 | strong 错误 48 | | 辅助信息说明 49 | s.msg-icon 50 | 51 |

    52 | 53 | div.sui-msg.msg-stop 54 | div.msg-con 55 | strong 禁止 56 | | 辅助信息说明 57 | s.msg-icon 58 | 59 |

    60 | 61 | div.sui-msg.msg-success 62 | div.msg-con 63 | strong 成功 64 | | 辅助信息说明 65 | s.msg-icon 66 | 67 |

    68 | 69 | div.sui-msg.msg-warning 70 | div.msg-con 71 | strong 警告 72 | | 辅助信息说明 73 | s.msg-icon 74 | 75 |

    76 | 77 | div.sui-msg.msg-notice 78 | div.msg-con 79 | strong 系统 80 | | 辅助信息说明 81 | s.msg-icon 82 | 83 |

    84 | 85 | div.sui-msg.msg-tips 86 | div.msg-con 87 | strong 提示 88 | | 辅助信息说明 89 | s.msg-icon 90 | 91 |

    92 | 93 | div.sui-msg.msg-info 94 | div.msg-con 95 | strong 提醒 96 | | 辅助信息说明 97 | s.msg-icon 98 | 99 |

    100 | 101 | div.sui-msg.msg-question 102 | div.msg-con 103 | strong 疑问 104 | | 辅助信息说明 105 | s.msg-icon 106 | 107 |

    108 | 109 | div.tab-pane#code1 110 | pre.prettyprint.linenums(data-target='#demo1>div') 111 | 112 | ul.demo-operations.clearfix 113 | li 114 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 115 | 116 | h2 去边框和底色 117 | 118 | ul.sui-nav.nav-tabs.nav-large 119 | li.active 120 | a(href='#demo6', data-toggle='tab') 示例 121 | li 122 | a(href='#code6', data-toggle='tab') 代码 123 | 124 | div.tab-content 125 | div.tab-pane.active#demo6 126 | div.bs-docs-example 127 | div.sui-msg.msg-naked.msg-error 128 | div.msg-con 129 | strong 错误 130 | | 辅助说明 131 | s.msg-icon 132 | 133 | div.tab-pane#code6 134 | pre.prettyprint.linenums(data-target='#demo6>div') 135 | 136 | ul.demo-operations.clearfix 137 | li 138 | a.copy-btn(href='javascript:void(0)', data-target='#demo6>div') 复制代码 139 | 140 | 141 | h2 带删除按钮 142 | 143 | ul.sui-nav.nav-tabs.nav-large 144 | li.active 145 | a(href='#demo7', data-toggle='tab') 示例 146 | li 147 | a(href='#code7', data-toggle='tab') 代码 148 | 149 | div.tab-content 150 | div.tab-pane.active#demo7 151 | div.bs-docs-example 152 | div.sui-msg.msg-error.msg-block 153 | div.msg-con 154 | strong 错误 155 | | 辅助说明 156 | a.remove 157 | i.msg-icon 158 | 159 | div.tab-pane#code7 160 | pre.prettyprint.linenums(data-target='#demo7>div') 161 | 162 | ul.demo-operations.clearfix 163 | li 164 | a.copy-btn(href='javascript:void(0)', data-target='#demo7>div') 复制代码 165 | -------------------------------------------------------------------------------- /docs/templates/tab-js.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 标签页 5 | 6 | block sidebar 7 | +sidebar('tab-js') 8 | block content 9 | h1 标签页 10 | 11 | h2.sui-page-header 开发者文档 12 | p.sui-lead 13 | 通过此组件轻松添加动态的标签页切换功能。此文档的标签页切换效果正是通过这个组件实现的。 14 | 15 | h2 1. 通过标记使用 16 | 17 | ul.sui-nav.nav-tabs.nav-large 18 | li.active 19 | a(href='#demo1', data-toggle='tab') 示例 20 | li 21 | a(href='#code1', data-toggle='tab') 代码 22 | li 23 | a(href='#doc1', data-toggle='tab') 文档 24 | 25 | div.tab-content 26 | div.tab-pane.active#demo1 27 | div.bs-docs-example 28 | ul.sui-nav.nav-tabs 29 | li.active 30 | a(href='#index', data-toggle='tab') 首页 31 | li 32 | a(href='#profile', data-toggle='tab') 教程 33 | li 34 | a(href='#about', data-toggle='tab') 关于 35 | div.tab-content 36 | div.tab-pane.active#index 37 | p qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui. 38 | div.tab-pane#profile 39 | p Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park 40 | div.tab-pane#about 41 | p Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr. 42 | div.tab-pane#code1 43 | pre.prettyprint.linenums(data-target='#demo1>div') 44 | div.tab-pane#doc1 45 | | 通过在tab元素上添加 data-toggle="tab" 或者 data-toggle="pill" 来开启标签切换功能. 46 | | 每一个tab对应的内容区域由tab的 href 或者 data-target 属性来指定。 47 | 48 | ul.demo-operations.clearfix 49 | li 50 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 51 | 52 | 53 | h2 2. 通过js调用 54 | 55 | ul.sui-nav.nav-tabs.nav-large 56 | li.active 57 | a(href='#demo2', data-toggle='tab') 示例 58 | li 59 | a(href='#code2', data-toggle='tab') 代码 60 | li 61 | a(href='#doc2', data-toggle='tab') 文档 62 | li 63 | a(href='#event2', data-toggle='tab') 事件 64 | 65 | div.tab-content 66 | 67 | div.tab-pane.active#demo2 68 | div.bs-docs-example 69 | ul.sui-nav.nav-tabs#tab-demo2 70 | li.active 71 | a(href='#index2') 首页 72 | li 73 | a(href='#profile2') 教程 74 | li 75 | a(href='#about2') 关于 76 | div.tab-content 77 | div.tab-pane.active#index2 78 | p qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui. 79 | div.tab-pane#profile2 80 | p Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park 81 | div.tab-pane#about2 82 | p Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr. 83 | 84 | script. 85 | $('#tab-demo2 a').click(function (e) { 86 | e.preventDefault(); 87 | $(this).tab('show'); 88 | }) 89 | 90 | div.tab-pane#code2 91 | pre.prettyprint.linenums(data-target='#demo2>div') 92 | div.tab-pane#doc2 93 | | 通过在tab中的a标签上调用 tab("show") 方法来显示此tab对应的内容区域。 94 | | 每一个tab对应的内容区域由tab的 href 或者 data-target 属性来指定。 95 | 96 | div.tab-pane#event2 97 | table.sui-table.table-bordered 98 | tr 99 | th 事件 100 | th 说明 101 | 102 | tr 103 | td show 104 | td 在标签页显示之前触发,在shown事件之前。event.targetevent.relatedTarget 分别是当前标签和上一个标签。 105 | tr 106 | td shown 107 | td 在标签页显示之后触发,在show事件之后。event.targetevent.relatedTarget 分别是当前标签和上一个标签。 108 | 109 | ul.demo-operations.clearfix 110 | li 111 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 112 | -------------------------------------------------------------------------------- /js/tab.js: -------------------------------------------------------------------------------- 1 | /* ======================================================== 2 | * bootstrap-tab.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#tabs 4 | * ======================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ======================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; 24 | 25 | 26 | /* TAB CLASS DEFINITION 27 | * ==================== */ 28 | 29 | var Tab = function (element) { 30 | this.element = $(element) 31 | } 32 | 33 | Tab.prototype = { 34 | 35 | constructor: Tab 36 | 37 | , show: function () { 38 | var $this = this.element 39 | , $ul = $this.closest('ul:not(.dropdown-menu)') 40 | , selector = $this.attr('data-target') 41 | , previous 42 | , $target 43 | , e 44 | 45 | if (!selector) { 46 | selector = $this.attr('href') 47 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 48 | } 49 | 50 | if ( $this.parent('li').hasClass('active') ) return 51 | 52 | previous = $ul.find('.active:last a')[0] 53 | 54 | e = $.Event('show', { 55 | relatedTarget: previous 56 | }) 57 | 58 | $this.trigger(e) 59 | 60 | if (e.isDefaultPrevented()) return 61 | 62 | $target = $(selector) 63 | 64 | this.activate($this.parent('li'), $ul) 65 | this.activate($target, $target.parent(), function () { 66 | $this.trigger({ 67 | type: 'shown' 68 | , relatedTarget: previous 69 | }) 70 | }) 71 | } 72 | 73 | , activate: function ( element, container, callback) { 74 | var $active = container.find('> .active') 75 | , transition = callback 76 | && $.support.transition 77 | && $active.hasClass('fade') 78 | 79 | function next() { 80 | $active 81 | .removeClass('active') 82 | .find('> .dropdown-menu > .active') 83 | .removeClass('active') 84 | 85 | element.addClass('active') 86 | 87 | if (transition) { 88 | element[0].offsetWidth // reflow for transition 89 | element.addClass('in') 90 | } else { 91 | element.removeClass('fade') 92 | } 93 | 94 | if ( element.parent('.dropdown-menu') ) { 95 | element.closest('li.dropdown').addClass('active') 96 | } 97 | 98 | callback && callback() 99 | } 100 | 101 | transition ? 102 | $active.one($.support.transition.end, next) : 103 | next() 104 | 105 | $active.removeClass('in') 106 | } 107 | } 108 | 109 | 110 | /* TAB PLUGIN DEFINITION 111 | * ===================== */ 112 | 113 | var old = $.fn.tab 114 | 115 | $.fn.tab = function ( option ) { 116 | return this.each(function () { 117 | var $this = $(this) 118 | , data = $this.data('tab') 119 | if (!data) $this.data('tab', (data = new Tab(this))) 120 | if (typeof option == 'string') data[option]() 121 | }) 122 | } 123 | 124 | $.fn.tab.Constructor = Tab 125 | 126 | 127 | /* TAB NO CONFLICT 128 | * =============== */ 129 | 130 | $.fn.tab.noConflict = function () { 131 | $.fn.tab = old 132 | return this 133 | } 134 | 135 | 136 | /* TAB DATA-API 137 | * ============ */ 138 | 139 | $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 140 | e.preventDefault() 141 | $(this).tab('show') 142 | }) 143 | 144 | }(window.jQuery); 145 | -------------------------------------------------------------------------------- /js/tests/unit/button.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | 3 | module("buttons") 4 | 5 | test("should provide no conflict", function () { 6 | var button = $.fn.button.noConflict() 7 | ok(!$.fn.button, 'button was set back to undefined (org value)') 8 | $.fn.button = button 9 | }) 10 | 11 | test("should be defined on jquery object", function () { 12 | ok($(document.body).button, 'button method is defined') 13 | }) 14 | 15 | test("should return element", function () { 16 | ok($(document.body).button()[0] == document.body, 'document.body returned') 17 | }) 18 | 19 | test("should return set state to loading", function () { 20 | var btn = $('') 21 | equal(btn.html(), 'mdo', 'btn text equal mdo') 22 | btn.button('loading') 23 | equal(btn.html(), 'fat', 'btn text equal fat') 24 | stop() 25 | setTimeout(function () { 26 | ok(btn.attr('disabled'), 'btn is disabled') 27 | ok(btn.hasClass('disabled'), 'btn has disabled class') 28 | start() 29 | }, 0) 30 | }) 31 | 32 | test("should return reset state", function () { 33 | var btn = $('') 34 | equal(btn.html(), 'mdo', 'btn text equal mdo') 35 | btn.button('loading') 36 | equal(btn.html(), 'fat', 'btn text equal fat') 37 | stop() 38 | setTimeout(function () { 39 | ok(btn.attr('disabled'), 'btn is disabled') 40 | ok(btn.hasClass('disabled'), 'btn has disabled class') 41 | start() 42 | stop() 43 | }, 0) 44 | btn.button('reset') 45 | equal(btn.html(), 'mdo', 'btn text equal mdo') 46 | setTimeout(function () { 47 | ok(!btn.attr('disabled'), 'btn is not disabled') 48 | ok(!btn.hasClass('disabled'), 'btn does not have disabled class') 49 | start() 50 | }, 100) 51 | }) 52 | 53 | test("should toggle active", function () { 54 | var btn = $('') 55 | ok(!btn.hasClass('active'), 'btn does not have active class') 56 | btn.button('toggle') 57 | ok(btn.hasClass('active'), 'btn has class active') 58 | }) 59 | 60 | test("should toggle active when btn children are clicked", function () { 61 | var btn = $('') 62 | , inner = $('') 63 | btn 64 | .append(inner) 65 | .appendTo($('#qunit-fixture')) 66 | ok(!btn.hasClass('active'), 'btn does not have active class') 67 | inner.click() 68 | ok(btn.hasClass('active'), 'btn has class active') 69 | }) 70 | 71 | test("should toggle active when btn children are clicked within btn-group", function () { 72 | var btngroup = $('
    ') 73 | , btn = $('') 74 | , inner = $('') 75 | btngroup 76 | .append(btn.append(inner)) 77 | .appendTo($('#qunit-fixture')) 78 | ok(!btn.hasClass('active'), 'btn does not have active class') 79 | inner.click() 80 | ok(btn.hasClass('active'), 'btn has class active') 81 | }) 82 | 83 | test("should check for closest matching toggle", function () { 84 | var group = $("
    ") 85 | , btn1 = $("") 86 | , btn2 = $("") 87 | , wrap = $("
    ") 88 | 89 | wrap.append(btn1, btn2) 90 | 91 | group 92 | .append(wrap) 93 | .appendTo($('#qunit-fixture')) 94 | 95 | ok(btn1.hasClass('active'), 'btn1 has active class') 96 | ok(!btn2.hasClass('active'), 'btn2 does not have active class') 97 | btn2.click() 98 | ok(!btn1.hasClass('active'), 'btn1 does not have active class') 99 | ok(btn2.hasClass('active'), 'btn2 has active class') 100 | }) 101 | 102 | }) 103 | -------------------------------------------------------------------------------- /js/validate-rules.js: -------------------------------------------------------------------------------- 1 | // add rules 2 | !function($) { 3 | Validate = $.validate; 4 | trim = function(v) { 5 | if (!v) return v; 6 | return v.replace(/^\s+/g, '').replace(/\s+$/g, '') 7 | }; 8 | var required = function(value, element, param) { 9 | var $input = $(element) 10 | return !!trim(value); 11 | }; 12 | var requiredMsg = function ($input, param) { 13 | var getWord = function($input) { 14 | var tagName = $input[0].tagName.toUpperCase(); 15 | var type = $input[0].type.toUpperCase(); 16 | if ( type == 'CHECKBOX' || type == 'RADIO' || tagName == 'SELECT') { 17 | return '选择' 18 | } 19 | return '填写' 20 | } 21 | return "请" + getWord($input) 22 | } 23 | Validate.setRule("required", required, requiredMsg); 24 | 25 | var prefill = function(value, element, param) { 26 | var $input = $(element) 27 | if (param && typeof param === typeof 'a') { 28 | var $form = $input.parents("form") 29 | var $required = $form.find("[name='"+param+"']") 30 | return !!$required.val() 31 | } 32 | return true 33 | } 34 | Validate.setRule("prefill", prefill, function($input, param) { 35 | var getWord = function($input) { 36 | var tagName = $input[0].tagName.toUpperCase(); 37 | var type = $input[0].type.toUpperCase(); 38 | if ( type == 'CHECKBOX' || type == 'RADIO' || tagName == 'SELECT') { 39 | return '选择' 40 | } 41 | return '填写' 42 | } 43 | if (param && typeof param === typeof 'a') { 44 | var $form = $input.parents("form") 45 | var $required = $form.find("[name='"+param+"']") 46 | if (!$required.val()) { 47 | return "请先" + getWord($required) + ($required.attr("title") || $required.attr("name")) 48 | } 49 | } 50 | return '错误' 51 | }); 52 | var match = function(value, element, param) { 53 | value = trim(value); 54 | return value == $(element).parents('form').find("[name='"+param+"']").val() 55 | }; 56 | Validate.setRule("match", match, '必须与$0相同'); 57 | var number = function(value, element, param) { 58 | value = trim(value); 59 | return (/^\d+(.\d*)?$/).test(value) 60 | }; 61 | Validate.setRule("number", number, '请输入数字'); 62 | var digits = function(value, element, param) { 63 | value = trim(value); 64 | return (/^\d+$/).test(value) 65 | }; 66 | Validate.setRule("digits", digits, '请输入整数'); 67 | var mobile = function(value, element, param) { 68 | return (/^0?1[3|4|5|7|8][0-9]\d{8,9}$/).test(trim(value)); 69 | }; 70 | Validate.setRule("mobile", mobile, '请填写正确的手机号码'); 71 | var tel = function(value, element, param) { 72 | return (/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,11})+$/).test(trim(value)); 73 | }; 74 | Validate.setRule("tel", tel, '请填写正确的电话号码'); 75 | var email = function(value, element, param) { 76 | return (/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(trim(value)); //" 77 | }; 78 | Validate.setRule("email", email, '请填写正确的email地址'); 79 | var zip = function(value, element, param) { 80 | return (/^[1-9][0-9]{5}$/).test(trim(value)); 81 | }; 82 | Validate.setRule("zip", zip, '请填写正确的邮编'); 83 | var date = function(value, element, param) { 84 | return (/^[1|2]\d{3}-[0-2][0-9]-[0-3][0-9]$/).test(trim(value)); 85 | }; 86 | Validate.setRule("date", date, '请填写正确的日期'); 87 | var url = function(value, element, param) { 88 | var urlPattern; 89 | value = trim(value); 90 | urlPattern = /(http|ftp|https):\/\/([\w-]+\.)?[\w-]+\.(com|net|cn|org|me|io|info)/; 91 | if (!/^http/.test(value)) { 92 | value = 'http://' + value; 93 | } 94 | return urlPattern.test(value); 95 | }; 96 | Validate.setRule("url", url, '请填写正确的网址'); 97 | var minlength = function(value, element, param) { 98 | return trim(value).length >= param; 99 | }; 100 | Validate.setRule("minlength", minlength, '长度不能少于$0'); 101 | var maxlength = function(value, element, param) { 102 | return trim(value).length <= param; 103 | }; 104 | Validate.setRule("maxlength", maxlength, '长度不能超过$0'); 105 | }(window.jQuery) 106 | -------------------------------------------------------------------------------- /less/progress-bars.less: -------------------------------------------------------------------------------- 1 | // 2 | // Progress bars 3 | // -------------------------------------------------- 4 | 5 | 6 | // ANIMATIONS 7 | // ---------- 8 | 9 | // Webkit 10 | @-webkit-keyframes progress-bar-stripes { 11 | from { background-position: 40px 0; } 12 | to { background-position: 0 0; } 13 | } 14 | 15 | // Firefox 16 | @-moz-keyframes progress-bar-stripes { 17 | from { background-position: 40px 0; } 18 | to { background-position: 0 0; } 19 | } 20 | 21 | // IE9 22 | @-ms-keyframes progress-bar-stripes { 23 | from { background-position: 40px 0; } 24 | to { background-position: 0 0; } 25 | } 26 | 27 | // Opera 28 | @-o-keyframes progress-bar-stripes { 29 | from { background-position: 0 0; } 30 | to { background-position: 40px 0; } 31 | } 32 | 33 | // Spec 34 | @keyframes progress-bar-stripes { 35 | from { background-position: 40px 0; } 36 | to { background-position: 0 0; } 37 | } 38 | 39 | 40 | 41 | // THE BARS 42 | // -------- 43 | 44 | // Outer container 45 | .sui-progress { 46 | overflow: hidden; 47 | height: @baseLineHeight + 12px; 48 | margin-bottom: @baseMargin; 49 | background-color: #eee; 50 | .border-radius(@baseBorderRadius); 51 | border: none; 52 | position: relative; 53 | 54 | // Bar of progress 55 | .bar { 56 | width: 0%; 57 | height: 100%; 58 | padding: 6px 0; 59 | padding-left: 0; 60 | padding-right: 0; 61 | color: @white; 62 | float: left; 63 | font-size: 12px; 64 | text-align: center; 65 | text-shadow: 0 -1px 0 rgba(0,0,0,.25); 66 | background-color: @progressColor; 67 | .box-sizing(border-box); 68 | .transition(width .6s ease); 69 | } 70 | 71 | .bar-text { 72 | position: absolute; 73 | color: @textColor; 74 | text-align: center; 75 | width: 100%; 76 | padding: 2px 0; 77 | } 78 | 79 | //不同大小 80 | &.progress-small { 81 | height: @baseLineHeight; 82 | line-height: @baseLineHeight; 83 | font-size: @fontSizeSmall; 84 | 85 | .bar, 86 | .bar-text 87 | { 88 | padding: 0; 89 | } 90 | } 91 | &.progress-large { 92 | height: @lineHeightLarge + 14px; 93 | line-height: @lineHeightLarge; 94 | font-size: @fontSizeLarge; 95 | .bar { 96 | padding: 8px 0; 97 | } 98 | } 99 | &.progress-xlarge { 100 | height: @lineHeightXLarge + 14px; 101 | line-height: @lineHeightXLarge; 102 | font-size: @fontSizeXLarge; 103 | .bar { 104 | padding: 8px 0; 105 | } 106 | } 107 | } 108 | 109 | // Striped bars 110 | .progress-striped .bar { 111 | #gradient > .striped(@progressColor); 112 | .background-size(40px 40px); 113 | } 114 | 115 | // Call animation for the active one 116 | .sui-progress.active .bar { 117 | -webkit-animation: progress-bar-stripes 2s linear infinite; 118 | -moz-animation: progress-bar-stripes 2s linear infinite; 119 | -ms-animation: progress-bar-stripes 2s linear infinite; 120 | -o-animation: progress-bar-stripes 2s linear infinite; 121 | animation: progress-bar-stripes 2s linear infinite; 122 | } 123 | 124 | 125 | 126 | // COLORS 127 | // ------ 128 | 129 | // Danger (red) 130 | .progress-danger .bar, .sui-progress .bar-danger { 131 | background-color: @progressDangerColor; 132 | } 133 | .progress-danger.progress-striped .bar, .progress-striped .bar-danger { 134 | #gradient > .striped(@progressDangerColor); 135 | } 136 | 137 | // Success (green) 138 | .progress-success .bar, .sui-progress .bar-success { 139 | background-color: @progressSuccessColor; 140 | } 141 | .progress-success.progress-striped .bar, .progress-striped .bar-success { 142 | #gradient > .striped(@progressSuccessColor); 143 | } 144 | 145 | // Info (teal) 146 | .progress-info .bar, .sui-progress .bar-info { 147 | background-color: @progressInfoColor; 148 | } 149 | .progress-info.progress-striped .bar, .progress-striped .bar-info { 150 | #gradient > .striped(@progressInfoColor); 151 | } 152 | 153 | // Warning (orange) 154 | .progress-warning .bar, .sui-progress .bar-warning { 155 | background-color: @progressWarningColor; 156 | } 157 | .progress-warning.progress-striped .bar, .progress-striped .bar-warning { 158 | #gradient > .striped(@progressWarningColor); 159 | } 160 | -------------------------------------------------------------------------------- /docs/templates/tab.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 标签页 5 | 6 | block sidebar 7 | +sidebar('tab') 8 | 9 | block content 10 | 11 | h1 标签页 12 | 13 | h2.sui-page-header 设计规范 14 | 15 | div.docs-description 16 | img(src='pictures/docs/tab.png') 17 | 18 | ul.demo-operations.clearfix 19 | li 20 | a(href='#') 下载psd文件 21 | 22 | h2.sui-page-header 开发者文档 23 | 24 | p.sui-lead 25 | | 三种不同大小的标签页,可以当做静态组件使用,引入js之后可以做动态的切换。 26 | 27 | h2 默认标签页 28 | ul.sui-nav.nav-tabs.nav-large 29 | li.active 30 | a(href='#demo1', data-toggle='tab') 示例 31 | li 32 | a(href='#code1', data-toggle='tab') 代码 33 | li 34 | a(href='#doc1', data-toggle='tab') 文档 35 | div.tab-content 36 | div.tab-pane.active#demo1 37 | div.bs-docs-example 38 | ul.sui-nav.nav-tabs 39 | li.active 40 | a 标签一 41 | li 42 | a(href='#') 标签二 43 | li 44 | a(href='#') 标签二 45 | 46 | 47 | h3 垂直 48 | ul.sui-nav.nav-tabs.nav-large.tab-vertical 49 | li 50 | a 语文 51 | li.active 52 | a(href='#') 数学 53 | li 54 | a(href='#') 英语 55 | 56 | div.tab-pane#code1 57 | pre.prettyprint.linenums(data-target='#demo1>div') 58 | div.tab-pane#doc1 59 | | 有三种尺寸: default, .nav-large, .nav-tabs-xlarge。通过在 li 标签上添加 .active 可以指定当前高亮的tab。
    60 | | 默认标签页是静态的,如果需要动态的标签页可以参考这里 js 标签页 61 | 62 | ul.demo-operations.clearfix 63 | li 64 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>div') 复制代码 65 | 66 | 67 | 68 | h2 首要标签页 69 | ul.sui-nav.nav-tabs.nav-large 70 | li.active 71 | a(href='#demo2', data-toggle='tab') 示例 72 | li 73 | a(href='#code2', data-toggle='tab') 代码 74 | li 75 | a(href='#doc2', data-toggle='tab') 文档 76 | div.tab-content 77 | div.tab-pane.active#demo2 78 | div.bs-docs-example 79 | ul.sui-nav.nav-tabs.nav-primary 80 | li.active 81 | a 标签一 82 | li 83 | a(href='#') 标签二 84 | li 85 | a(href='#') 标签二 86 | 87 | h3 垂直 88 | ul.sui-nav.nav-tabs.nav-primary.nav-large.tab-vertical 89 | li 90 | a 标签一 91 | li.active 92 | a(href='#') 标签二 93 | li 94 | a(href='#') 标签二 95 | div.tab-pane#code2 96 | pre.prettyprint.linenums(data-target='#demo2>div') 97 | div.tab-pane#doc2 98 | | 首要标签页,添加 nav-primary 99 | 100 | ul.demo-operations.clearfix 101 | li 102 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>div') 复制代码 103 | 104 | h2 纯文字 105 | ul.sui-nav.nav-tabs.nav-large 106 | li.active 107 | a(href='#demo3', data-toggle='tab') 示例 108 | li 109 | a(href='#code3', data-toggle='tab') 代码 110 | div.tab-content 111 | div.tab-pane.active#demo3 112 | div.bs-docs-example 113 | ul.sui-nav.nav-tabs.tab-light 114 | li.active 115 | a 标签一 116 | li 117 | a(href='#') 标签二 118 | li 119 | a(href='#') 标签二 120 | 121 | h3 垂直 122 | ul.sui-nav.nav-tabs.tab-light.tab-vertical 123 | li 124 | a 前端 125 | li.active 126 | a(href='#') 后端 127 | li 128 | a(href='#') 运维 129 | 130 | div.tab-pane#code3 131 | pre.prettyprint.linenums(data-target='#demo3>div') 132 | 133 | ul.demo-operations.clearfix 134 | li 135 | a.copy-btn(href='javascript:void(0)', data-target='#demo3>div') 复制代码 136 | 137 | h2 带背景 138 | ul.sui-nav.nav-tabs.nav-large 139 | li.active 140 | a(href='#demo4', data-toggle='tab') 示例 141 | li 142 | a(href='#code4', data-toggle='tab') 代码 143 | div.tab-content 144 | div.tab-pane.active#demo4 145 | div.bs-docs-example 146 | ul.sui-nav.nav-tabs.tab-dark 147 | li.active 148 | a 标签一 149 | i.sui-icon 150 | li 151 | a(href='#') 标签二 152 | li 153 | a(href='#') 标签二 154 | 155 | h3 垂直 156 | ul.sui-nav.nav-tabs.tab-dark.tab-vertical 157 | li 158 | a 前端 159 | li 160 | a(href='#') 后端 161 | li.active 162 | a(href='#') 运维 163 | div.tab-pane#code4 164 | pre.prettyprint.linenums(data-target='#demo4>div') 165 | 166 | ul.demo-operations.clearfix 167 | li 168 | a.copy-btn(href='javascript:void(0)', data-target='#demo4>div') 复制代码 169 | -------------------------------------------------------------------------------- /docs/templates/checkbox.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title 选框 5 | 6 | block sidebar 7 | +sidebar('checkbox') 8 | 9 | block content 10 | 11 | h1 单选框和复选框 12 | 13 | h2.sui-page-header 开发者文档 14 | 15 | p.sui-lead 16 | | 这是js重写的选框组件,兼容ie8+。但是使用此组件必须引入sui.js。此组件内部依然通过原生的checkbox和radio来实现,所以不会影响原生的表单操作。 17 | br 18 | | 注意,在使用此组件的时候不要通过直接修改input的方式来操作,而是通过checkbox api来调用。 19 | 20 | h2 通过data-api使用 21 | 22 | ul.sui-nav.nav-tabs.nav-large 23 | li.active 24 | a(href='#demo1', data-toggle='tab') 示例 25 | li 26 | a(href='#code1', data-toggle='tab') 代码 27 | li 28 | a(href='#doc1', data-toggle='tab') 文档 29 | 30 | 31 | div.tab-content 32 | div.tab-pane.active#demo1 33 | form.sui-form 34 | h3 复选框 35 | label.checkbox-pretty.inline.checked(data-toggle='checkbox') 36 | input(type='checkbox' checked='checked') 37 | span 鸣人 38 | 39 | label.checkbox-pretty.inline(data-toggle='checkbox') 40 | input(type='checkbox') 41 | span 佐助 42 | 43 | h3 单选框 44 | label.radio-pretty.inline.checked(data-toggle='radio') 45 | input(type='radio' checked='checked' name='radio') 46 | span 服装 47 | 48 | label.radio-pretty.inline(data-toggle='radio') 49 | input(type='radio' name='radio') 50 | span 电器 51 | label.radio-pretty.inline(data-toggle='radio') 52 | input(type='radio' name='radio') 53 | span 美食 54 | 55 | h3 半选 56 | label.checkbox-pretty.inline.halfchecked(data-toggle='radio') 57 | input(type='checkbox') 58 | span 半选 59 | 60 | h3 禁用 61 | label.checkbox-pretty.inline.checked.disabled(data-toggle='radio') 62 | input(type='checkbox' checked='checked' disabled) 63 | span 不可选 64 | 65 | 66 | div.tab-pane#code1 67 | pre.prettyprint.linenums(data-target='#demo1') 68 | div.tab-pane#doc1 69 | p 70 | | 通过添加 data-toggle='checobox' 或者 data-toggle='radio' 来启用。 71 | p 72 | | 在初始化的时候同时设置好input的属性和label的class,否则在js加载之后可能会闪一下或者会出现状态不一致。 73 | 74 | 75 | ul.demo-operations.clearfix 76 | li 77 | a.copy-btn(href='javascript:void(0)', data-target='#demo1>form') 复制代码 78 | 79 | h2 通过JS调用 80 | 81 | ul.sui-nav.nav-tabs.nav-large 82 | li.active 83 | a(href='#demo2', data-toggle='tab') 示例 84 | li 85 | a(href='#code2', data-toggle='tab') 代码 86 | li 87 | a(href='#doc2', data-toggle='tab') 文档 88 | li 89 | a(href='#api2', data-toggle='tab') API 90 | 91 | 92 | div.tab-content 93 | div.tab-pane.active#demo2 94 | form.sui-form 95 | h3 复选框 96 | label.checkbox-pretty.inline.checked#checkbox2(data-toggle='checkbox') 97 | input(type='checkbox' checked='checked') 98 | span 选项一 99 | div.op.sui-btn-group(style='display:block;margin-top: 15px;') 100 | a.sui-btn.btn-primary(name='check' href='javascript:void(0);') 选中 101 | a.sui-btn.btn-primary(name='uncheck' href='javascript:void(0);') 取消 102 | a.sui-btn.btn-primary(name='halfcheck' href='javascript:void(0);') 半选 103 | a.sui-btn.btn-primary(name='toggle' href='javascript:void(0);') toggle 104 | a.sui-btn.btn-primary(name='disable' href='javascript:void(0);') disable 105 | a.sui-btn.btn-primary(name='enable' href='javascript:void(0);') enable 106 | script. 107 | var $checkbox = $("#checkbox2").checkbox() 108 | $(".op").on("click", "a", function(e){ 109 | var $a = $(e.currentTarget); 110 | $checkbox.checkbox($a.attr("name")) 111 | }) 112 | 113 | div.tab-pane#code2 114 | pre.prettyprint.linenums(data-target='#demo2') 115 | div.tab-pane#doc2 116 | ul.unstyled 117 | li 要把checkbox当做一个组件来用,不要通过js直接修改input的属性,要通过checkbox api来调用。 118 | li 禁用状态会禁止用户的操作,但是不会禁止通过api来修改状态。 119 | li 半选状态其实就是未选中,所以不会向后台提交。 120 | div.tab-pane#api2 121 | table.sui-table 122 | thead 123 | tr 124 | th 方法 125 | th 说明 126 | tbody 127 | tr 128 | td check 129 | td 选中 130 | tr 131 | td uncheck 132 | td 取消选中 133 | tr 134 | td halfcheck 135 | td 半选 136 | tr 137 | td disable 138 | td 禁用 139 | tr 140 | td enable 141 | td 启用 142 | 143 | ul.demo-operations.clearfix 144 | li 145 | a.copy-btn(href='javascript:void(0)', data-target='#demo2>form') 复制代码 146 | 147 | -------------------------------------------------------------------------------- /less/timepicker.less: -------------------------------------------------------------------------------- 1 | .timepicker { 2 | width: 100px; 3 | height: 228px; 4 | //border: 1px solid #ddd; 5 | position: relative; 6 | padding: 12px 20px; 7 | background: #fff; 8 | .clearfix(); 9 | .picker-wrap { 10 | width: 40px; 11 | overflow: hidden; 12 | float: left; 13 | position: relative; 14 | z-index: 1 15 | } 16 | .picker-wrap:first-child { 17 | margin-right: 20px 18 | } 19 | .picker-btn { 20 | display: block; 21 | width: 50%; 22 | height: 27px; 23 | line-height: 25px; 24 | margin: 0 auto; 25 | text-align: center; 26 | position: relative; 27 | @top: 0px; 28 | .arrow,.arrow-bg{ 29 | width: 0; 30 | height: 0; 31 | display: inline-block; 32 | position: absolute; 33 | left: 3px; 34 | } 35 | .arrow{ 36 | border: 7px solid #bbb; 37 | } 38 | .arrow-bg{ 39 | border: 7px solid #fff; 40 | } 41 | &.up{ 42 | @top:0px; 43 | .arrow,.arrow-bg{ 44 | border-left-color: transparent; 45 | border-top-color: transparent; 46 | border-right-color: transparent; 47 | } 48 | .arrow{ 49 | top: @top; 50 | } 51 | .arrow-bg{ 52 | top: @top + 1; 53 | } 54 | } 55 | &.down{ 56 | @bottom: 0px; 57 | .arrow,.arrow-bg{ 58 | border-left-color: transparent; 59 | border-right-color: transparent; 60 | border-bottom-color: transparent; 61 | } 62 | .arrow{ 63 | bottom: @bottom; 64 | } 65 | .arrow-bg{ 66 | bottom: @bottom + 1; 67 | } 68 | } 69 | } 70 | .picker-con { 71 | width: 100%; 72 | height: 174px; 73 | overflow: hidden; 74 | position: relative; 75 | // border: 1px solid red; 76 | .picker-innercon { 77 | position: absolute; 78 | top: 0; 79 | left: 0; 80 | width: 100%; 81 | -webkit-transition: .5s; 82 | transition: .5s; 83 | -webkit-touch-callout: none; 84 | -webkit-user-select: none; 85 | -khtml-user-select: none; 86 | -moz-user-select: none; 87 | -ms-user-select: none; 88 | user-select: none; 89 | } 90 | span { 91 | display: block; 92 | height: 35px; 93 | width: 100%; 94 | text-align: center; 95 | line-height: 35px; 96 | cursor: pointer; 97 | color: #bbb; 98 | &.current { 99 | color: #000; 100 | font-size: 16px 101 | } 102 | } 103 | } 104 | .timePicker-split { 105 | position: absolute; 106 | left: 20px; 107 | top: 50%; 108 | margin-top: -15px; 109 | height: 30px; 110 | width: 100px; 111 | z-index: 0; 112 | .hour-input, 113 | .minute-input{ 114 | width: 38px; 115 | height: 28px; 116 | border: 1px solid #ececec; 117 | float: left; 118 | background: #f9f9f9; 119 | } 120 | .split-icon { 121 | width: 20px; 122 | height: 30px; 123 | line-height: 30px; 124 | float: left; 125 | text-align: center; 126 | color: #000; 127 | } 128 | } 129 | &.dropdown-menu{ 130 | position: absolute; 131 | top: 0; 132 | left: 0; 133 | z-index: @zindexDropdown; 134 | float: left; 135 | display: none; // none by default, but block on "open" of the menu 136 | list-style: none; 137 | /* padding: 0;*/ 138 | background-color: @dropdownBackground; 139 | border: 1px solid #ccc; 140 | border: 1px solid rgba(0,0,0,.2); 141 | .border-radius(0px); 142 | .box-shadow(0 5px 10px rgba(0,0,0,.2)); 143 | -webkit-background-clip: padding-box; 144 | -moz-background-clip: padding; 145 | background-clip: padding-box; 146 | *border-right-width: 2px; 147 | *border-bottom-width: 2px; 148 | 149 | // Normally inherited from bootstrap's `body` 150 | color: #333333; 151 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; 152 | font-size:13px; 153 | line-height: @baseLineHeight; 154 | } 155 | } -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 3 | var exec = require("child_process").exec; 4 | 5 | module.exports = function(grunt) { 6 | 'use strict'; 7 | grunt.initConfig({ 8 | pkg: grunt.file.readJSON('package.json'), 9 | banner: '/*dpl started*/', 10 | distRoot: grunt.option('target') || '.package', 11 | docsRoot: 'docs', 12 | 13 | jshint: { 14 | options: { 15 | jshintrc: 'js/.jshintrc' 16 | }, 17 | gruntfile: { 18 | src: 'Gruntfile.js' 19 | }, 20 | src: { 21 | src: ['js/*.js'] 22 | }, 23 | test: { 24 | src: ['js/tests/unit/*.js'] 25 | } 26 | }, 27 | browserify: { 28 | build: { 29 | files: { 30 | '<%= distRoot %>/js/<%= pkg.name %>.js': ['js/<%= pkg.name %>.js'], 31 | } 32 | } 33 | }, 34 | 35 | uglify: { 36 | build: { 37 | options: { 38 | sourceMap: true 39 | }, 40 | files: [{ 41 | expand: true, 42 | cwd: '<%= distRoot %>/js/', 43 | src: ['**/*.js', '!*.min.js'], 44 | dest: '<%= distRoot %>/js/', 45 | ext: '.min.js' 46 | }] 47 | } 48 | }, 49 | 50 | less: { 51 | options: { 52 | compile: true 53 | }, 54 | sui: { 55 | src: ['less/<%= pkg.name %>.less'], 56 | dest: '<%= distRoot %>/css/<%= pkg.name %>.css' 57 | }, 58 | suiMin: { 59 | options: { 60 | compress: true 61 | }, 62 | src: ['less/<%= pkg.name %>.less'], 63 | dest: '<%= distRoot %>/css/<%= pkg.name %>.min.css' 64 | }, 65 | 66 | docs: { 67 | files: [{ 68 | expand: true, 69 | cwd: '<%= docsRoot %>/assets/less/', 70 | src: ['**/*.less'], 71 | dest: '<%= docsRoot %>/assets/css/', 72 | ext: '.css' 73 | }] 74 | } 75 | }, 76 | jade: { 77 | docs: { 78 | options: { 79 | pretty: true 80 | }, 81 | files: [ 82 | { 83 | expand: true, 84 | cwd: '<%= docsRoot %>/templates', 85 | src: ['**/*.jade', '!base.jade', '!sidenav.jade', '!header.jade', '!com-*', '!*-com.jade', '!discuss.jade', '!foot.jade', '!head.jade'], 86 | dest: '<%= docsRoot %>', 87 | ext: '.html' 88 | }, 89 | ], 90 | } 91 | }, 92 | copy: { 93 | fonts: { 94 | files: [ 95 | { expand: true, src: ['./fonts/*'], dest: '<%= distRoot %>/' }, 96 | ] 97 | } 98 | }, 99 | /* 100 | qunit: { 101 | options: { 102 | inject: 'js/tests/unit/phantom.js' 103 | }, 104 | files: ['js/tests/*.html'] 105 | }, 106 | */ 107 | 108 | connect: { 109 | server: { 110 | options: { 111 | port: 3000, 112 | base: '.' 113 | } 114 | } 115 | }, 116 | 117 | watch: { 118 | options: { 119 | livereload: 3456 120 | }, 121 | css: { 122 | files: 'less/*.less', 123 | tasks: ['less:sui', 'newer:copy'] 124 | }, 125 | js: { 126 | files: 'js/*.js', 127 | tasks: ['browserify', 'newer:copy'] 128 | }, 129 | docs: { 130 | files: '<%= docsRoot %>/templates/**/*.jade', 131 | tasks: ['newer:jade:docs'] 132 | }, 133 | docsCss: { 134 | files: '<%= docsRoot %>/assets/less/**/*.less', 135 | tasks: ['newer:less:docs'] 136 | } 137 | } 138 | }); 139 | 140 | 141 | // These plugins provide necessary tasks. 142 | grunt.loadNpmTasks('grunt-contrib-connect'); 143 | grunt.loadNpmTasks('grunt-contrib-copy'); 144 | grunt.loadNpmTasks('grunt-contrib-jade'); 145 | grunt.loadNpmTasks('grunt-contrib-jshint'); 146 | grunt.loadNpmTasks('grunt-contrib-watch'); 147 | grunt.loadNpmTasks('grunt-browserify'); 148 | grunt.loadNpmTasks('grunt-contrib-less'); 149 | grunt.loadNpmTasks('grunt-contrib-uglify'); 150 | grunt.loadNpmTasks('grunt-newer'); 151 | // Test task. 152 | grunt.registerTask('test', ['jshint']); 153 | 154 | // JS distribution task. 155 | grunt.registerTask('dist-js', ['browserify', 'uglify']); 156 | 157 | // CSS distribution task. 158 | grunt.registerTask('dist-css', ['less']); 159 | 160 | // CSS distribution task. 161 | grunt.registerTask('dist-fonts', ['copy:fonts']); 162 | 163 | // Full distribution task. 164 | grunt.registerTask('dist', ['dist-css', 'dist-js', 'dist-fonts']); 165 | grunt.registerTask('docs', ['jade']); //必须先执行dist才能执行此任务 166 | 167 | // Default task. 168 | grunt.registerTask('default', ['test', 'dist', 'docs']); 169 | //local server and watch 170 | grunt.registerTask('local',['connect','watch']); 171 | } 172 | -------------------------------------------------------------------------------- /less/tests/forms.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sui, from Twitter 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
    36 | 37 | 40 | 41 |
    42 |
    43 | 44 | 45 | 50 | 51 |
    52 | 53 | 54 | 55 | 56 |
    57 | 58 | 59 | 60 | 61 |
    62 | 63 | 64 | 65 | 66 |
    67 | 68 | 69 | 70 | 71 |
    72 | 73 | 74 | 75 | 76 |
    77 | 78 | 79 | 80 | 81 |
    82 | 83 | 84 | 85 | 86 |
    87 | 88 | 89 | 90 | 91 |
    92 |
    93 | 94 | 95 | 96 | 97 |
    98 | 99 | 100 | 101 | 102 |
    103 | 104 | 105 | 106 | 107 |
    108 | 109 | 110 | 111 | 112 |
    113 | 114 | 115 | 116 | 117 |
    118 | 119 | 120 | 121 | 122 |
    123 | 124 | 125 | 126 | 127 |
    128 | 129 | 130 | 131 | 132 |
    133 | 134 | 135 | 136 | 137 |
    138 |
    139 | 140 | 141 | 142 | 143 |
    144 | 145 | 146 | 147 | 148 |
    149 | 150 | 151 | 152 | 153 |
    154 | 155 | 156 | 157 | 158 |
    159 | 160 | 161 | 162 | 163 |
    164 | 165 | 166 | 167 | 168 |
    169 | 170 | 171 | 172 | 173 |
    174 |
    175 | 176 |
    177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /docs/templates/tree-js.jade: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block title 4 | title TREE 级联选择 5 | 6 | block head 7 | style. 8 | .bs-docs-example{font-size:12px;} 9 | .sui-tree-group > select + select{margin-left:5px;} 10 | 11 | block sidebar 12 | +sidebar('tree-js') 13 | 14 | block content 15 | h1 级联选择 16 | 17 | h2.sui-page-header 开发者文档 18 | 19 | p.docs 20 | | 根据给定的数据生成下拉框,并且能够级联选择,并取到相应的数据。
    21 | | 修改日志:由原来的一次性获取所有数据改为只获取第一级数据,后面的数据在选中某个节点后获取,并且移除了source参数 22 | 23 | h1 1. select,通过标记自动初始化 24 | 25 | ul.sui-nav.nav-tabs.nav-large 26 | li.active 27 | a(href='#demo1', data-toggle='tab') 示例 28 | li 29 | a(href='#code1', data-toggle='tab') 代码 30 | li 31 | a(href='#doc1', data-toggle='tab') 文档 32 | li 33 | a(href='#api1', data-toggle='tab') API 34 | 35 | div.tab-content 36 | .tab-pane.active#demo1 37 | .bs-docs-example 38 | form.sui-form 39 | .sui-tree-group(data-toggle='tree', data-src='http://10.68.111.150/php/demo/server/getCity.json', data-jsonp='true') 40 | .tab-pane#code1 41 | pre.prettyprint.linenums(data-target='#demo1>div') 42 | .tab-pane#doc1 43 | | data-toggle='tree'通过在元素上加此属性自动初始化,并生成第一个select,必须在初始化之前指定数据源
    44 | | data-src="url" 通过ajax或jsonp方式获取数据的url
    45 | | data-jsonp="true" 为true表示src的url为垮域请求,会以jsonp的形式发送
    46 | | data-val="[x,y,z]" 初始化的时候的初始值,注意xyz的值必须要能在srouce对象中找到
    47 | .tab-pane#api1 48 | | $(element).data('tree').datas,element为data-toggle='tree'的元素,获取当前的值对象,格式为{value : [], option : []},value代表select的value值,option表示显示的option的文字
    49 | | $(element).tree('setValue', [x,y,z]) 设置tree的值,参数同初始化的data-val相同 50 | h1 2. select,通过js调用初始化 51 | 52 | ul.sui-nav.nav-tabs.nav-large 53 | li.active 54 | a(href='#demo2', data-toggle='tab') 示例 55 | li 56 | a(href='#code2', data-toggle='tab') 代码 57 | li 58 | a(href='#doc2', data-toggle='tab') 文档 59 | li 60 | a(href='#api2', data-toggle='tab') API 61 | 62 | .tab-content 63 | .tab-pane.active#demo2 64 | .bs-docs-example 65 | .sui-tree-group.sui-form#treeGroup2 66 | script. 67 | $(function() { 68 | $('#treeGroup2').tree({ 69 | src : 'http://10.68.111.150/php/demo/server/getCategory.json', 70 | placeholder : '-- 请选择 --', 71 | val : [2, 148, 152], 72 | jsonp : true 73 | }); 74 | }) 75 | .tab-pane#code2 76 | pre.prettyprint.linenums(data-target='#demo2>div') 77 | .tab-pane#doc2 78 | | 手动调用tree方法,并传入参数
    79 | | 返回数据的格式:
    80 | pre.prettyprint. 81 | { 82 | "code" : 200, // 代表请求成功 83 | "data" : [ 84 | { 85 | "id" : "id", // id值,用于option的value 86 | "value" : "value", // 显示的内容,用于option的text 87 | "parent" : "parent", // 父节点的id,暂无用途 88 | "isleaf" : "false", // 是否是叶结点,如果为false,则选中此项的时候会根据id获取子节点的数据 89 | }, 90 | {...}, 91 | ... 92 | ] 93 | } 94 | .tab-pane#api2 95 | table.sui-table.table-bordered 96 | thead 97 | tr 98 | th(style="width:100px") 名称 99 | th(style="width:50px") 类型 100 | th(style="width:50px") 默认值 101 | th 描述 102 | tbody 103 | tr 104 | td src 105 | td string 106 | td null 107 | td 通过ajax获取数据的url 108 | tr 109 | td jsonp 110 | td boolean 111 | td false 112 | td 表示src请求是一个jsonp请求 113 | tr 114 | td key 115 | td string 116 | td "id" 117 | td 发送请求时获取数据的参数名,默认为id 118 | tr 119 | td placeholder 120 | td string 121 | td "请选择" 122 | td 默认的第一个option,可以传null或空串,则不会出现默认的option 123 | tr 124 | td val 125 | td Array 126 | td [] 127 | td 初始化的值,是一个数组,里面的值是option的value值 128 | --------------------------------------------------------------------------------