diff --git a/.csscomb.json b/.csscomb.json new file mode 100644 index 0000000000..1baf6bedd6 --- /dev/null +++ b/.csscomb.json @@ -0,0 +1,290 @@ +{ + "always-semicolon": true, + "block-indent": 2, + "colon-space": true, + "color-case": "lower", + "color-shorthand": true, + "combinator-space": true, + "element-case": "lower", + "eof-newline": true, + "leading-zero": false, + "remove-empty-rulesets": true, + "rule-indent": 2, + "stick-brace": true, + "strip-spaces": true, + "unitless-zero": true, + "vendor-prefix-align": true, + "sort-order": [ + [ + "position", + "top", + "right", + "bottom", + "left", + "z-index", + "display", + "float", + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "-webkit-box-sizing", + "-moz-box-sizing", + "box-sizing", + "padding", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + "margin", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "overflow", + "overflow-x", + "overflow-y", + "-ms-overflow-x", + "-ms-overflow-y", + "clip", + "clear", + "font", + "font-family", + "font-size", + "font-style", + "font-weight", + "font-variant", + "font-size-adjust", + "font-stretch", + "font-effect", + "font-emphasize", + "font-emphasize-position", + "font-emphasize-style", + "font-smooth", + "-webkit-hyphens", + "-moz-hyphens", + "hyphens", + "line-height", + "color", + "text-align", + "-webkit-text-align-last", + "-moz-text-align-last", + "-ms-text-align-last", + "text-align-last", + "text-emphasis", + "text-emphasis-color", + "text-emphasis-style", + "text-emphasis-position", + "text-decoration", + "text-indent", + "text-justify", + "text-outline", + "-ms-text-overflow", + "text-overflow", + "text-overflow-ellipsis", + "text-overflow-mode", + "text-shadow", + "text-transform", + "text-wrap", + "letter-spacing", + "-ms-word-break", + "word-break", + "word-spacing", + "-ms-word-wrap", + "word-wrap", + "-moz-tab-size", + "-o-tab-size", + "tab-size", + "white-space", + "vertical-align", + "list-style", + "list-style-position", + "list-style-type", + "list-style-image", + "pointer-events", + "cursor", + "visibility", + "zoom", + "flex-direction", + "flex-order", + "flex-pack", + "flex-align", + "table-layout", + "empty-cells", + "caption-side", + "border-spacing", + "border-collapse", + "content", + "quotes", + "counter-reset", + "counter-increment", + "resize", + "-webkit-user-select", + "-moz-user-select", + "-ms-user-select", + "user-select", + "nav-index", + "nav-up", + "nav-right", + "nav-down", + "nav-left", + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", + "background", + "background-color", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", + "filter:progid:DXImageTransform.Microsoft.gradient", + "background-image", + "background-repeat", + "background-attachment", + "background-position", + "background-position-x", + "background-position-y", + "-webkit-background-clip", + "-moz-background-clip", + "background-clip", + "background-origin", + "-webkit-background-size", + "-moz-background-size", + "-o-background-size", + "background-size", + "border", + "border-color", + "border-style", + "border-width", + "border-top", + "border-top-color", + "border-top-style", + "border-top-width", + "border-right", + "border-right-color", + "border-right-style", + "border-right-width", + "border-bottom", + "border-bottom-color", + "border-bottom-style", + "border-bottom-width", + "border-left", + "border-left-color", + "border-left-style", + "border-left-width", + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "-webkit-border-image", + "-moz-border-image", + "-o-border-image", + "border-image", + "-webkit-border-image-source", + "-moz-border-image-source", + "-o-border-image-source", + "border-image-source", + "-webkit-border-image-slice", + "-moz-border-image-slice", + "-o-border-image-slice", + "border-image-slice", + "-webkit-border-image-width", + "-moz-border-image-width", + "-o-border-image-width", + "border-image-width", + "-webkit-border-image-outset", + "-moz-border-image-outset", + "-o-border-image-outset", + "border-image-outset", + "-webkit-border-image-repeat", + "-moz-border-image-repeat", + "-o-border-image-repeat", + "border-image-repeat", + "outline", + "outline-width", + "outline-style", + "outline-color", + "outline-offset", + "-webkit-box-shadow", + "-moz-box-shadow", + "box-shadow", + "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", + "opacity", + "-ms-interpolation-mode", + "-webkit-transition", + "-moz-transition", + "-ms-transition", + "-o-transition", + "transition", + "-webkit-transition-delay", + "-moz-transition-delay", + "-ms-transition-delay", + "-o-transition-delay", + "transition-delay", + "-webkit-transition-timing-function", + "-moz-transition-timing-function", + "-ms-transition-timing-function", + "-o-transition-timing-function", + "transition-timing-function", + "-webkit-transition-duration", + "-moz-transition-duration", + "-ms-transition-duration", + "-o-transition-duration", + "transition-duration", + "-webkit-transition-property", + "-moz-transition-property", + "-ms-transition-property", + "-o-transition-property", + "transition-property", + "-webkit-transform", + "-moz-transform", + "-ms-transform", + "-o-transform", + "transform", + "-webkit-transform-origin", + "-moz-transform-origin", + "-ms-transform-origin", + "-o-transform-origin", + "transform-origin", + "-webkit-animation", + "-moz-animation", + "-ms-animation", + "-o-animation", + "animation", + "-webkit-animation-name", + "-moz-animation-name", + "-ms-animation-name", + "-o-animation-name", + "animation-name", + "-webkit-animation-duration", + "-moz-animation-duration", + "-ms-animation-duration", + "-o-animation-duration", + "animation-duration", + "-webkit-animation-play-state", + "-moz-animation-play-state", + "-ms-animation-play-state", + "-o-animation-play-state", + "animation-play-state", + "-webkit-animation-timing-function", + "-moz-animation-timing-function", + "-ms-animation-timing-function", + "-o-animation-timing-function", + "animation-timing-function", + "-webkit-animation-delay", + "-moz-animation-delay", + "-ms-animation-delay", + "-o-animation-delay", + "animation-delay", + "-webkit-animation-iteration-count", + "-moz-animation-iteration-count", + "-ms-animation-iteration-count", + "-o-animation-iteration-count", + "animation-iteration-count", + "-webkit-animation-direction", + "-moz-animation-direction", + "-ms-animation-direction", + "-o-animation-direction", + "animation-direction" + ] + ] +} diff --git a/.csslintrc b/.csslintrc new file mode 100644 index 0000000000..8cf2f846df --- /dev/null +++ b/.csslintrc @@ -0,0 +1,18 @@ +{ + "adjoining-classes": false, + "box-sizing": false, + "box-model": false, + "compatible-vendor-prefixes": false, + "floats": false, + "font-sizes": false, + "gradients": false, + "important": false, + "known-properties": false, + "outline-none": false, + "qualified-headings": false, + "regex-selectors": false, + "text-indent": false, + "unique-headings": false, + "universal-selector": false, + "unqualified-attributes": false +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..0c6b2fea5f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# Enforce Unix newlines +*.css text eol=lf +*.html text eol=lf +*.js text eol=lf +*.json text eol=lf +*.less text eol=lf +*.md text eol=lf +*.yml text eol=lf diff --git a/.gitignore b/.gitignore index 10c58cf685..465cdb4633 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ validation-report.json # Folders to ignore node_modules +bower_components diff --git a/.travis.yml b/.travis.yml index 9f2371887f..78a89aabf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,18 @@ language: node_js node_js: - - 0.8 -before_script: - - gem install jekyll - - npm install -g grunt-cli + - 0.10 +before_install: + - time sudo pip install --use-mirrors -r ./test-infra/requirements.txt +install: + - time gem install jekyll + - time npm install -g grunt-cli + - time ./test-infra/node_modules_cache.py download || time npm install +after_script: + - time ./test-infra/node_modules_cache.py upload env: global: - - secure: Besg41eyU+2mfxrywQ4ydOShMdc34ImaO0S0ENP+aCOBuyNBIgP59wy5tBMmyai2/8eInYeVps4Td96mWInMMxzTe3Bar7eTLG5tWVKRSr/wc4NBPZ/ppoPAmCEsz9Y+VptRH9/FO8n7hsL9EFZ+xBKbG+C0SccGoyBDpA5j7/w= - - secure: Ptiv7phCImFP3ALIz+sMQzrZg8k7C1gLZbFBhWxjnQr3g06wIfX3Ls5y9OHvxid+lOZZjISui3wzBVgpVHqwHUYf96+r0mo6/mJ+F4ffUmShZANVaIMD/JRTnXhUQJbvntGLvxn1EYWPdNM+2IHJrMipnjHxU9tkgAnlel4Zdew= - - TWBS_HAVE_OWN_BROWSERSTACK_KEY: "" + - SAUCE_USERNAME: bootstrap + - secure: "pJkBwnuae9dKU5tEcCqccfS1QQw7/meEcfz63fM7ba7QJNjoA6BaXj08L5Z3Vb5vBmVPwBawxo5Hp0jC0r/Z/O0hGnAmz/Cz09L+cy7dSAZ9x4hvZePSja/UAusaB5ogMoO8l2b773MzgQeSmrLbExr9BWLeqEfjC2hFgdgHLaQ=" + - secure: "gqjqISbxBJK6byFbsmr1AyP1qoWH+rap06A2gI7v72+Tn2PU2nYkIMUkCvhZw6K889jv+LhQ/ybcBxDOXHpNCExCnSgB4dcnmYp+9oeNZb37jSP0rQ+Ib4OTLjzc3/FawE/fUq5kukZTC7porzc/k0qJNLAZRx3YLALmK1GIdUY=" + - secure: "Gghh/e3Gsbj1+4RR9Lh2aR/xJl35HWiHqlPIeSUqE9D7uDCVTAwNce/dGL3Ew7uJPfJ6Pgr70wD3zgu3stw0Zmzayax0hiDtGwcQCxVIER08wqGANK9C2Q7PYJkNTNtiTo6ehKWbdV4Z+/U+TEYyQfpQTDbAFYk/vVpsdjp0Lmc=" + - secure: "RTbRdx4G/2OTLfrZtP1VbRljxEmd6A1F3GqXboeQTldsnAlwpsES65es5CE3ub/rmixLApOY9ot7OPmNixFgC2Y8xOsV7lNCC62QVpmqQEDyGFFQKb3yO6/dmwQxdsCqGfzf9Np6Wh5V22QFvr50ZLKLd7Uhd9oXMDIk/z1MJ3o=" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96b7732b0d..708ace7ec9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ We only accept issues that are bug reports or feature requests. Bugs must be iso ## Pull requests -- CSS changes must be done in `.less` files first, never just the compiled `.css` files +- CSS changes must be done in `.less` files first, never just in the compiled `.css` files - If modifying the `.less` files, always recompile and commit the compiled files `bootstrap.css` and `bootstrap.min.css` - Try not to pollute your pull request with unintended changes--keep them simple and small - Try to share which browsers your code has been tested in before submitting a pull request @@ -58,4 +58,22 @@ We only accept issues that are bug reports or feature requests. Bugs must be iso With v3.1, we're moving from the Apache 2 to the MIT license for the Bootstrap code (not the docs). We're in the process of collecting permissions from all Bootstrap contributors with code still part of the project to make this happen. For details, please see [#2054](https://github.com/twbs/bootstrap/issues/2054). -By contributing your code, you agree to dual-license your contribution under the [Apache 2](https://github.com/twbs/bootstrap/blob/master/LICENSE) and [MIT](https://github.com/twbs/bootstrap/blob/master/MIT) licenses. +By contributing your code, you agree to dual-license your contribution under the [Apache 2](https://github.com/twbs/bootstrap/blob/master/LICENSE) and [MIT](https://github.com/twbs/bootstrap/blob/master/LICENSE-MIT) licenses. + + + +## Release checklist + +1. Close ship list issue for the release. +2. Close the milestone for the release. +3. Open new release issue that includes this checklist. +4. Ping folks to coordinate release (mainly @jdorfman for BootstrapCDN). +5. Update version numbers using `grunt change-version-number --oldver=A.B.C --newver=X.Y.Z`. Review the changes and stage them manually. +6. Run `grunt` one last time. +7. Push to `master` branch. +8. Merge `master` into `gh-pages`. +9. Generate `bootstrap-X.Y.Z-dist.zip` file for release. +10. Create release on GitHub with `/dist/` folder and release notes. +11. Push `gh-pages`. +12. Publish blog post. +13. Tweet tweet. diff --git a/Gruntfile.js b/Gruntfile.js index 41f7ed3315..aae80dc3df 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,8 +1,12 @@ /* jshint node: true */ -module.exports = function(grunt) { - "use strict"; +module.exports = function (grunt) { + 'use strict'; + // Force use of Unix newlines + grunt.util.linefeed = '\n'; + + RegExp.quote = require('regexp-quote') var btoa = require('btoa') // Project configuration. grunt.initConfig({ @@ -10,12 +14,10 @@ module.exports = function(grunt) { // Metadata. pkg: grunt.file.readJSON('package.json'), banner: '/*!\n' + - ' * Bootstrap v<%= pkg.version %> by @fat and @mdo\n' + + ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + ' * Licensed under <%= _.pluck(pkg.licenses, "url").join(", ") %>\n' + - ' *\n' + - ' * Designed and built with all the love in the world by @mdo and @fat.\n' + - ' */\n', + ' */\n\n', jqueryCheck: 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") }\n\n', // Task configuration. @@ -35,9 +37,34 @@ module.exports = function(grunt) { }, test: { src: ['js/tests/unit/*.js'] + }, + assets: { + src: ['docs-assets/js/application.js', 'docs-assets/js/customizer.js'] } }, + jscs: { + options: { + config: 'js/.jscs.json', + }, + gruntfile: { + src: ['Gruntfile.js'] + }, + src: { + src: ['js/*.js'] + }, + test: { + src: ['js/tests/unit/*.js'] + } + }, + + csslint: { + options: { + csslintrc: '.csslintrc' + }, + src: ['dist/css/bootstrap.css', 'dist/css/bootstrap-theme.css'] + }, + concat: { options: { banner: '<%= banner %><%= jqueryCheck %>', @@ -70,42 +97,74 @@ module.exports = function(grunt) { bootstrap: { src: ['<%= concat.bootstrap.dest %>'], dest: 'dist/js/<%= pkg.name %>.min.js' + }, + customize: { + src: [ + 'docs-assets/js/less.js', + 'docs-assets/js/jszip.js', + 'docs-assets/js/uglify.js', + 'docs-assets/js/filesaver.js', + 'docs-assets/js/customizer.js' + ], + dest: 'docs-assets/js/customize.js' } }, - recess: { - options: { - compile: true, - banner: '<%= banner %>' - }, - bootstrap: { - src: ['less/bootstrap.less'], - dest: 'dist/css/<%= pkg.name %>.css' - }, - min: { + less: { + compile: { options: { - compress: true + strictMath: true }, - src: ['less/bootstrap.less'], - dest: 'dist/css/<%= pkg.name %>.min.css' + files: { + 'dist/css/<%= pkg.name %>.css': 'less/bootstrap.less', + 'dist/css/<%= pkg.name %>-theme.css': 'less/theme.less' + } }, - theme: { - src: ['less/theme.less'], - dest: 'dist/css/<%= pkg.name %>-theme.css' - }, - theme_min: { + minify: { options: { - compress: true + cleancss: true, + report: 'min' }, - src: ['less/theme.less'], - dest: 'dist/css/<%= pkg.name %>-theme.min.css' + files: { + 'dist/css/<%= pkg.name %>.min.css': 'dist/css/<%= pkg.name %>.css', + 'dist/css/<%= pkg.name %>-theme.min.css': 'dist/css/<%= pkg.name %>-theme.css' + } + } + }, + + usebanner: { + dist: { + options: { + position: 'top', + banner: '<%= banner %>' + }, + files: { + src: [ + 'dist/css/<%= pkg.name %>.css', + 'dist/css/<%= pkg.name %>.min.css', + 'dist/css/<%= pkg.name %>-theme.css', + 'dist/css/<%= pkg.name %>-theme.min.css', + ] + } + } + }, + + csscomb: { + sort: { + options: { + sortOrder: '.csscomb.json' + }, + files: { + 'dist/css/<%= pkg.name %>.css': ['dist/css/<%= pkg.name %>.css'], + 'dist/css/<%= pkg.name %>-theme.css': ['dist/css/<%= pkg.name %>-theme.css'], + } } }, copy: { fonts: { expand: true, - src: ["fonts/*"], + src: ['fonts/*'], dest: 'dist/' } }, @@ -132,10 +191,14 @@ module.exports = function(grunt) { validation: { options: { - reset: true + reset: true, + relaxerror: [ + 'Bad value X-UA-Compatible for attribute http-equiv on element meta.', + 'Element img is missing required attribute src.' + ] }, files: { - src: ["_gh_pages/**/*.html"] + src: ['_gh_pages/**/*.html'] } }, @@ -148,39 +211,131 @@ module.exports = function(grunt) { files: '<%= jshint.test.src %>', tasks: ['jshint:test', 'qunit'] }, - recess: { + less: { files: 'less/*.less', - tasks: ['recess'] + tasks: ['less'] + } + }, + + sed: { + versionNumber: { + pattern: (function () { + var old = grunt.option('oldver') + return old ? RegExp.quote(old) : old + })(), + replacement: grunt.option('newver'), + recursive: true + } + }, + + 'saucelabs-qunit': { + all: { + options: { + build: process.env.TRAVIS_JOB_ID, + concurrency: 3, + urls: ['http://127.0.0.1:3000/js/tests/index.html'], + browsers: [ + // See https://saucelabs.com/docs/platforms/webdriver + { + browserName: 'safari', + version: '7', + platform: 'OS X 10.9' + }, + { + browserName: 'chrome', + version: '31', + platform: 'OS X 10.9' + }, + /* FIXME: currently fails 1 tooltip test + { + browserName: 'firefox', + version: '25', + platform: 'OS X 10.6' + },*/ + // Mac Opera not currently supported by Sauce Labs + /* FIXME: currently fails 1 tooltip test + { + browserName: 'internet explorer', + version: '11', + platform: 'Windows 8.1' + },*/ + /* + { + browserName: 'internet explorer', + version: '10', + platform: 'Windows 8' + }, + { + browserName: 'internet explorer', + version: '9', + platform: 'Windows 7' + }, + { + browserName: 'internet explorer', + version: '8', + platform: 'Windows 7' + }, + {// unofficial + browserName: 'internet explorer', + version: '7', + platform: 'Windows XP' + }, + */ + { + browserName: 'chrome', + version: '31', + platform: 'Windows 8.1' + }, + { + browserName: 'firefox', + version: '25', + platform: 'Windows 8.1' + }, + // Win Opera 15+ not currently supported by Sauce Labs + { + browserName: 'iphone', + version: '6.1', + platform: 'OS X 10.8' + }, + // iOS Chrome not currently supported by Sauce Labs + // Linux (unofficial) + { + browserName: 'chrome', + version: '30', + platform: 'Linux' + }, + { + browserName: 'firefox', + version: '25', + platform: 'Linux' + } + // Android Chrome not currently supported by Sauce Labs + /* Android Browser (super-unofficial) + { + browserName: 'android', + version: '4.0', + platform: 'Linux' + } + */ + ], + } } } }); // These plugins provide necessary tasks. - grunt.loadNpmTasks('browserstack-runner'); - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-concat'); - grunt.loadNpmTasks('grunt-contrib-connect'); - grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-contrib-qunit'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-html-validation'); - grunt.loadNpmTasks('grunt-jekyll'); - grunt.loadNpmTasks('grunt-recess'); + require('load-grunt-tasks')(grunt, {scope: 'devDependencies'}); // Docs HTML validation task grunt.registerTask('validate-html', ['jekyll', 'validation']); // Test task. - var testSubtasks = ['dist-css', 'jshint', 'qunit', 'validate-html']; - // Only run BrowserStack tests under Travis - if (process.env.TRAVIS) { - // Only run BrowserStack tests if this is a mainline commit in twbs/bootstrap, or you have your own BrowserStack key - if ((process.env.TRAVIS_REPO_SLUG === 'twbs/bootstrap' && process.env.TRAVIS_PULL_REQUEST === 'false') || process.env.TWBS_HAVE_OWN_BROWSERSTACK_KEY) { - testSubtasks.push('browserstack_runner'); - } + var testSubtasks = ['dist-css', 'jshint', 'jscs', 'qunit', 'validate-html']; + // Only run Sauce Labs tests if there's a Sauce access key + if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined') { + testSubtasks.push('connect'); + testSubtasks.push('saucelabs-qunit'); } grunt.registerTask('test', testSubtasks); @@ -188,7 +343,7 @@ module.exports = function(grunt) { grunt.registerTask('dist-js', ['concat', 'uglify']); // CSS distribution task. - grunt.registerTask('dist-css', ['recess']); + grunt.registerTask('dist-css', ['less', 'csscomb', 'usebanner']); // Fonts distribution task. grunt.registerTask('dist-fonts', ['copy']); @@ -199,6 +354,11 @@ module.exports = function(grunt) { // Default task. grunt.registerTask('default', ['test', 'dist', 'build-customizer']); + // Version numbering task. + // grunt change-version-number --oldver=A.B.C --newver=X.Y.Z + // This can be overzealous, so its changes should always be manually reviewed! + grunt.registerTask('change-version-number', ['sed']); + // task for building customizer grunt.registerTask('build-customizer', 'Add scripts/less files to customizer.', function () { var fs = require('fs') diff --git a/README.md b/README.md index 2b768520cd..7d342d7a70 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # [Bootstrap](http://getbootstrap.com) [![Build Status](https://secure.travis-ci.org/twbs/bootstrap.png)](http://travis-ci.org/twbs/bootstrap) [![devDependency Status](https://david-dm.org/twbs/bootstrap/dev-status.png)](https://david-dm.org/twbs/bootstrap#info=devDependencies) +[![Selenium Test Status](https://saucelabs.com/browser-matrix/bootstrap.svg)](https://saucelabs.com/u/bootstrap) Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created and maintained by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat). -To get started, check out [http://getbootstrap.com](http://getbootstrap.com)! +To get started, check out ! @@ -10,7 +11,7 @@ To get started, check out [http://getbootstrap.com](http://getbootstrap.com)! Three quick start options are available: -* [Download the latest release](https://github.com/twbs/bootstrap/releases/tag/v3.0.0). +* [Download the latest release](https://github.com/twbs/bootstrap/archive/v3.0.3.zip). * Clone the repo: `git clone https://github.com/twbs/bootstrap.git`. * Install with [Bower](http://bower.io): `bower install bootstrap`. @@ -51,20 +52,21 @@ You may use [this JS Bin](http://jsbin.com/aKiCIDO/1/edit) as a template for you ## Documentation -Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at [http://getbootstrap.com](http://getbootstrap.com). The docs may also be run locally. +Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at . The docs may also be run locally. ### Running documentation locally 1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v1.x). + - **Windows users:** read [this unofficial guide](https://github.com/juthilo/run-jekyll-on-windows/) to get Jekyll up and running without problems. 2. From the root `/bootstrap` directory, run `jekyll serve` in the command line. - - **Windows users:** run `chcp 65001` first to change the command prompt's character encoding ([code page](http://en.wikipedia.org/wiki/Windows_code_page)) to UTF-8 so Jekyll runs without errors. -3. Open [http://localhost:9001](http://localhost:9001) in your browser, and voilà. + - **Windows users:** For Ruby 2.0.0 run `chcp 65001` first to change the command prompt's character encoding ([code page](http://en.wikipedia.org/wiki/Windows_code_page)) to UTF-8 so Jekyll runs without errors. For Ruby 1.9.3 you can alternatively do `SET LANG=en_EN.UTF-8`. In addition, ensure you have Python installed and added in your `PATH` or the build will fail due to our Pygments dependency. +3. Open in your browser, and voilà. Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). ### Documentation for previous releases -Documentation for v2.3.2 has been made available for the time being at [http://getbootstrap.com/2.3.2/](http://getbootstrap.com/2.3.2/) while folks transition to Bootstrap 3. +Documentation for v2.3.2 has been made available for the time being at while folks transition to Bootstrap 3. [Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download. @@ -111,7 +113,7 @@ Please read through our [contributing guidelines](https://github.com/twbs/bootst More over, if your pull request contains JavaScript patches or features, you must include relevant unit tests. All HTML and CSS should conform to the [Code Guide](http://github.com/mdo/code-guide), maintained by [Mark Otto](http://github.com/mdo). -Editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at [http://editorconfig.org](http://editorconfig.org). +Editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at . With v3.1, we're moving from the Apache 2 to the MIT license for the Bootstrap code (not the docs). Please see the [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) for more information. @@ -122,7 +124,6 @@ Keep track of development and community news. * Follow [@twbootstrap on Twitter](http://twitter.com/twbootstrap). * Read and subscribe to [The Official Bootstrap Blog](http://blog.getbootstrap.com). -* Have a question that's not a feature request or bug report? [Ask on the mailing list.](http://groups.google.com/group/twitter-bootstrap) * Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##twitter-bootstrap` channel. @@ -142,7 +143,7 @@ And constructed with the following guidelines: * New additions without breaking backward compatibility bumps the minor (and resets the patch) * Bug fixes and misc changes bumps the patch -For more information on SemVer, please visit [http://semver.org/](http://semver.org/). +For more information on SemVer, please visit . @@ -150,13 +151,13 @@ For more information on SemVer, please visit [http://semver.org/](http://semver. **Mark Otto** -+ [http://twitter.com/mdo](http://twitter.com/mdo) -+ [http://github.com/mdo](http://github.com/mdo) ++ ++ **Jacob Thornton** -+ [http://twitter.com/fat](http://twitter.com/fat) -+ [http://github.com/fat](http://github.com/fat) ++ ++ diff --git a/_config.yml b/_config.yml index 2024f4c407..02f2f4989b 100644 --- a/_config.yml +++ b/_config.yml @@ -11,15 +11,15 @@ exclude: [".editorconfig", ".gitignore", "bower.json", "composer.json", port: 9001 # Custom vars -current_version: 3.0.0 +current_version: 3.0.3 repo: https://github.com/twbs/bootstrap -download_source: https://github.com/twbs/bootstrap/archive/v3.0.0.zip -download_dist: https://github.com/twbs/bootstrap/releases/download/v3.0.0/bootstrap-3.0.0-dist.zip +download_source: https://github.com/twbs/bootstrap/archive/v3.0.3.zip +download_dist: https://github.com/twbs/bootstrap/releases/download/v3.0.3/bootstrap-3.0.3-dist.zip blog: http://blog.getbootstrap.com expo: http://expo.getbootstrap.com -cdn_css: //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css -cdn_theme_css: //netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css -cdn_js: //netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js +cdn_css: //netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css +cdn_theme_css: //netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css +cdn_js: //netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js diff --git a/_includes/footer.html b/_includes/footer.html index 7f9f8f103b..095e96eb59 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -1,23 +1,33 @@ - - + + - {% if page.slug == "customize" %} - - - - - + {% endif %} +{% comment %} + Inject Twitter widgets asynchronously. Snippet snipped from Twitter's + JS interface site: https://dev.twitter.com/docs/tfw-javascript + + * "js.async=1;" added to add async attribute to the generated script tag. +{% endcomment %} + + + + + + diff --git a/examples/dashboard/dashboard.css b/examples/dashboard/dashboard.css new file mode 100644 index 0000000000..750124bf84 --- /dev/null +++ b/examples/dashboard/dashboard.css @@ -0,0 +1,93 @@ +/* + * Base structure + */ + +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; +} + + +/* + * Global add-ons + */ + +.sub-header { + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + + +/* + * Sidebar + */ + +/* Hide for mobile, show later */ +.sidebar { + display: none; +} +@media (min-width: 768px) { + .sidebar { + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 1000; + display: block; + padding: 70px 20px 20px; + background-color: #f5f5f5; + border-right: 1px solid #eee; + } +} + +/* Sidebar navigation */ +.nav-sidebar { + margin-left: -20px; + margin-right: -21px; /* 20px padding + 1px border */ + margin-bottom: 20px; +} +.nav-sidebar > li > a { + padding-left: 20px; + padding-right: 20px; +} +.nav-sidebar > .active > a { + color: #fff; + background-color: #428bca; +} + + +/* + * Main content + */ + +.main { + padding: 20px; +} +@media (min-width: 768px) { + .main { + padding-left: 40px; + pading-right: 40px; + } +} +.main .page-header { + margin-top: 0; +} + + +/* + * Placeholder dashboard ideas + */ + +.placeholders { + margin-bottom: 30px; + text-align: center; +} +.placeholders h4 { + margin-bottom: 0; +} +.placeholder { + margin-bottom: 20px; +} +.placeholder img { + border-radius: 50%; +} diff --git a/examples/dashboard/index.html b/examples/dashboard/index.html new file mode 100644 index 0000000000..e721aa16a3 --- /dev/null +++ b/examples/dashboard/index.html @@ -0,0 +1,243 @@ + + + + + + + + + + + Dashboard Template for Bootstrap + + + + + + + + + + + + + + + + + + +
+
+ +
+

Dashboard

+ +
+
+ Generic placeholder thumbnail +

Label

+ Something else +
+
+ Generic placeholder thumbnail +

Label

+ Something else +
+
+ Generic placeholder thumbnail +

Label

+ Something else +
+
+ Generic placeholder thumbnail +

Label

+ Something else +
+
+ +

Section title

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#HeaderHeaderHeaderHeader
1,001Loremipsumdolorsit
1,002ametconsecteturadipiscingelit
1,003IntegernecodioPraesent
1,003liberoSedcursusante
1,004dapibusdiamSednisi
1,005Nullaquissemat
1,006nibhelementumimperdietDuis
1,007sagittisipsumPraesentmauris
1,008Fuscenectellussed
1,009auguesemperportaMauris
1,010massaVestibulumlaciniaarcu
1,011egetnullaClassaptent
1,012tacitisociosquadlitora
1,013torquentperconubianostra
1,014perinceptoshimenaeosCurabitur
1,015sodalesligulainlibero
+
+
+
+
+ + + + + + + + diff --git a/examples/grid/index.html b/examples/grid/index.html index d3159e6318..be1e39c1f3 100644 --- a/examples/grid/index.html +++ b/examples/grid/index.html @@ -17,7 +17,7 @@ - + - + - + - +
-

Heading

+

Safari bug warning!

+

Safari exhibits a bug in which resizing your browser horizontally causes rendering errors in the justified nav that are cleared upon refreshing.

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

View details »

diff --git a/examples/navbar-fixed-top/index.html b/examples/navbar-fixed-top/index.html index 6b38d7bff1..de04aa645c 100644 --- a/examples/navbar-fixed-top/index.html +++ b/examples/navbar-fixed-top/index.html @@ -17,7 +17,7 @@ - + - @@ -705,14 +763,6 @@ bootstrap/

Internet Explorer 8 and 9

Internet Explorer 8 and 9 are also supported, however, please be aware that some CSS3 properties and HTML5 elements are not fully supported by these browsers. In addition, Internet Explorer 8 requires the use of Respond.js to enable media query support.

-
-

Respond.js and cross-domain CSS

-

Using Respond.js with CSS hosted on a different (sub)domain (for example, on a CDN) requires some additional setup. See the Respond.js docs for details.

-
-
-

Respond.js and file://

-

Due to browser security rules, Respond.js doesn't work with pages viewed via the file:// protocol (like when opening a local HTML file). To test responsive features in IE8, view your pages over HTTP(S). See the Respond.js docs for details.

-
@@ -754,6 +804,15 @@ bootstrap/

Visit Can I use... for details on browser support of CSS3 and HTML5 features.

+

Internet Explorer 8 and Respond.js

+

Beware of the following caveats when using Respond.js in your development and production environments for Internet Explorer 8.

+

Respond.js and cross-domain CSS

+

Using Respond.js with CSS hosted on a different (sub)domain (for example, on a CDN) requires some additional setup. See the Respond.js docs for details.

+

Respond.js and file://

+

Due to browser security rules, Respond.js doesn't work with pages viewed via the file:// protocol (like when opening a local HTML file). To test responsive features in IE8, view your pages over HTTP(S). See the Respond.js docs for details.

+

Respond.js and @import

+

Respond.js doesn't work with CSS that's referenced via @import. In particular, some Drupal configurations are known to use @import. See the Respond.js docs for details.

+

Internet Explorer 8 and box-sizing

IE8 does not fully support box-sizing: border-box; when combined with min-width, max-width, min-height, or max-height. For that reason, as of v3.0.1, we no longer use max-width on .containers.

@@ -762,7 +821,8 @@ bootstrap/ {% highlight html %} {% endhighlight %} -

This tag is included in all docs pages and examples to ensure the best rendering possible in each supported version of Internet Explorer.

+

Confirm the document mode by opening the debugging tools: press F12 and check the "Document Mode".

+

This tag is included in all Bootstrap's documentation and examples to ensure the best rendering possible in each supported version of Internet Explorer.

See this StackOverflow question for more information.

Internet Explorer 10 in Windows 8 and Windows Phone 8

diff --git a/javascript.html b/javascript.html index eb051a87bf..39dbc6e8e9 100644 --- a/javascript.html +++ b/javascript.html @@ -30,7 +30,7 @@ base_url: "../"

Data attributes

You can use all Bootstrap plugins purely through the markup API without writing a single line of JavaScript. This is Bootstrap's first-class API and should be your first consideration when using a plugin.

-

That said, in some situations it may be desirable to turn this functionality off. Therefore, we also provide the ability to disable the data attribute API by unbinding all events on the document namespaced with data-api. This looks like this: +

That said, in some situations it may be desirable to turn this functionality off. Therefore, we also provide the ability to disable the data attribute API by unbinding all events on the document namespaced with data-api. This looks like this:

{% highlight js %} $(document).off('.data-api') {% endhighlight %} @@ -43,14 +43,14 @@ $(document).off('.alert.data-api')

Programmatic API

We also believe you should be able to use all Bootstrap plugins purely through the JavaScript API. All public APIs are single, chainable methods, and return the collection acted upon.

{% highlight js %} -$(".btn.danger").button("toggle").addClass("fat") +$('.btn.danger').button('toggle').addClass('fat') {% endhighlight %}

All methods should accept an optional options object, a string which targets a particular method, or nothing (which initiates a plugin with default behavior):

{% highlight js %} -$("#myModal").modal() // initialized with defaults -$("#myModal").modal({ keyboard: false }) // initialized with no keyboard -$("#myModal").modal('show') // initializes and invokes show immediately

+$('#myModal').modal() // initialized with defaults +$('#myModal').modal({ keyboard: false }) // initialized with no keyboard +$('#myModal').modal('show') // initializes and invokes show immediately {% endhighlight %}

Each plugin also exposes its raw constructor on a Constructor property: $.fn.popover.Constructor. If you'd like to get a particular plugin instance, retrieve it directly from an element: $('[rel=popover]').data('popover').

@@ -304,15 +304,15 @@ $('#myModal').modal({ {% endhighlight %}

.modal('toggle')

-

Manually toggles a modal.

+

Manually toggles a modal. Returns to the caller before the modal has actually been shown or hidden (i.e. before the shown.bs.modal or hidden.bs.modal event occurs).

{% highlight js %}$('#myModal').modal('toggle'){% endhighlight %}

.modal('show')

-

Manually opens a modal.

+

Manually opens a modal. Returns to the caller before the modal has actually been shown (i.e. before the shown.bs.modal event occurs).

{% highlight js %}$('#myModal').modal('show'){% endhighlight %}

.modal('hide')

-

Manually hides a modal.

+

Manually hides a modal. Returns to the caller before the modal has actually been hidden (i.e. before the hidden.bs.modal event occurs).

{% highlight js %}$('#myModal').modal('hide'){% endhighlight %}

Events

@@ -328,11 +328,11 @@ $('#myModal').modal({ - + - + @@ -346,8 +346,8 @@ $('#myModal').modal({
show.bs.modalThis event fires immediately when the show instance method is called.This event fires immediately when the show instance method is called. If caused by a click, the clicked element is available as the relatedTarget property of the event.
shown.bs.modalThis event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete).This event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete). If caused by a click, the clicked element is available as the relatedTarget property of the event.
hide.bs.modal
{% highlight js %} -$('#myModal').on('hidden.bs.modal', function () { - // do something… +$('#myModal').on('hidden.bs.modal', function (e) { + // do something... }) {% endhighlight %}
@@ -415,7 +415,7 @@ $('#myModal').on('hidden.bs.modal', function () { -

Within tabs

+

Within pills

- +
@@ -529,6 +529,7 @@ $('#myDropdown').on('show.bs.dropdown', function () { {% endhighlight %} +
@@ -588,7 +589,13 @@ $('#myDropdown').on('show.bs.dropdown', function () {

Via data attributes

To easily add scrollspy behavior to your topbar navigation, add data-spy="scroll" to the element you want to spy on (most typically this would be the <body>). Then add the data-target attribute with the ID or class of the parent element of any Bootstrap .nav component.

{% highlight html %} - + + ... + ... {% endhighlight %} @@ -596,7 +603,7 @@ $('#myDropdown').on('show.bs.dropdown', function () {

Via JavaScript

Call the scrollspy via JavaScript:

{% highlight js %} -$('body').scrollspy({ target: '#navbar-example' }) +$('body').scrollspy({ target: '.navbar-example' }) {% endhighlight %}
@@ -1116,7 +1123,7 @@ $('#myTooltip').on('hidden.bs.tooltip', function () { animation boolean true - apply a CSS fade transition to the tooltip + apply a CSS fade transition to the popover html @@ -1134,7 +1141,7 @@ $('#myTooltip').on('hidden.bs.tooltip', function () { selector string false - if a selector is provided, tooltip objects will be delegated to the specified targets. in practice, this is used to enable dynamic HTML content to have popovers added. See this and an informative example. + if a selector is provided, tooltip objects will be delegated to the specified targets. In practice, this is used to enable dynamic HTML content to have popovers added. See this and an informative example. trigger @@ -1327,14 +1334,23 @@ $('#my-alert').bind('closed.bs.alert', function () {

Stateful

Add data-loading-text="Loading..." to use a loading state on a button.

-
{% highlight html %} - + {% endhighlight %}

Single toggle

@@ -1408,7 +1424,7 @@ $('#my-alert').bind('closed.bs.alert', function () {

Usage

Enable buttons via JavaScript:

{% highlight js %} -$('.btn-group').button() +$('.btn').button() {% endhighlight %}

Markup

@@ -1426,14 +1442,23 @@ $('.btn-group').button()

You can enable auto toggling of a button by using the data-toggle attribute.

{% highlight html %} - + {% endhighlight %}

$().button('loading')

Sets button state to loading - disables button and swaps text to loading text. Loading text should be defined on the button element using the data attribute data-loading-text.

{% highlight html %} - + + {% endhighlight %}
@@ -1447,7 +1472,7 @@ $('.btn-group').button()

$().button(string)

Resets button state - swaps text to any data defined text state.

{% highlight html %} - + @@ -1593,7 +1618,7 @@ $('.btn-group').button()

Via JavaScript

Enable manually with:

{% highlight js %} -$(".collapse").collapse() +$('.collapse').collapse() {% endhighlight %}

Options

@@ -1703,13 +1728,13 @@ $('#myCollapsible').on('hidden.bs.collapse', function () { @@ -1765,21 +1790,21 @@ $('#myCollapsible').on('hidden.bs.collapse', function () {