diff --git a/sharding-jdbc-doc/public/.gitignore b/sharding-jdbc-doc/public/.gitignore new file mode 100644 index 0000000000000..f79a22e5b1f11 --- /dev/null +++ b/sharding-jdbc-doc/public/.gitignore @@ -0,0 +1,32 @@ +# maven ignore +target/ +*.jar +*.war +*.zip +*.tar +*.tar.gz + +# eclipse ignore +.settings/ +.project +.classpath + +# idea ignore +.idea/ +*.ipr +*.iml +*.iws + +# temp ignore +logs/ +*.doc +*.log +*.cache +*.diff +*.patch +*.tmp + +# system ignore +.DS_Store +Thumbs.db + diff --git a/sharding-jdbc-doc/public/404.html b/sharding-jdbc-doc/public/404.html new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/sharding-jdbc-doc/public/css/bootstrap.css b/sharding-jdbc-doc/public/css/bootstrap.css new file mode 100644 index 0000000000000..037dd0561510d --- /dev/null +++ b/sharding-jdbc-doc/public/css/bootstrap.css @@ -0,0 +1,6203 @@ +/*! + * Bootstrap v3.2.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + width: 100% \9; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + width: 100% \9; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #428bca; +} +a.text-primary:hover { + color: #3071a9; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #428bca; +} +a.bg-primary:hover { + background-color: #3071a9; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #777; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #777; +} +.form-control::-webkit-input-placeholder { + color: #777; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + line-height: 34px; + line-height: 1.42857143 \0; +} +input[type="date"].input-sm, +input[type="time"].input-sm, +input[type="datetime-local"].input-sm, +input[type="month"].input-sm { + line-height: 30px; +} +input[type="date"].input-lg, +input[type="time"].input-lg, +input[type="datetime-local"].input-lg, +input[type="month"].input-lg { + line-height: 46px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm, +.form-horizontal .form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg, +.form-horizontal .form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 25px; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.3px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #3071a9; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary .badge { + color: #428bca; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + -o-transition: height .35s ease; + transition: height .35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #428bca; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: 0; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + position: absolute; + z-index: -1; + filter: alpha(opacity=0); + opacity: 0; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #428bca; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #428bca; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + -webkit-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #777; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #777; +} +.navbar-inverse .navbar-nav > li > a { + color: #777; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #777; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #777; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #428bca; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #2a6496; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #428bca; + border-color: #428bca; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #428bca; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #3071a9; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #428bca; + background-color: #fff; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #428bca; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar[aria-valuenow="1"], +.progress-bar[aria-valuenow="2"] { + min-width: 30px; +} +.progress-bar[aria-valuenow="0"] { + min-width: 30px; + color: #777; + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + box-shadow: none; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media, +.media .media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-object { + display: block; +} +.media-heading { + margin: 0 0 5px; +} +.media > .pull-left { + margin-right: 10px; +} +.media > .pull-right { + margin-left: 10px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #428bca; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #428bca; +} +.panel-primary > .panel-heading .badge { + color: #428bca; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #428bca; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate3d(0, -25%, 0); + -o-transform: translate3d(0, -25%, 0); + transform: translate3d(0, -25%, 0); +} +.modal.in .modal-dialog { + -webkit-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-size: 12px; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + right: 5px; + bottom: 0; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; + -webkit-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/sharding-jdbc-doc/public/css/bootstrap.min.css b/sharding-jdbc-doc/public/css/bootstrap.min.css new file mode 100644 index 0000000000000..a9f35ceedfac7 --- /dev/null +++ b/sharding-jdbc-doc/public/css/bootstrap.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.2.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;width:100% \9;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;width:100% \9;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#777;opacity:1}.form-control:-ms-input-placeholder{color:#777}.form-control::-webkit-input-placeholder{color:#777}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;min-height:20px;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm,.form-horizontal .form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg,.form-horizontal .form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:25px;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#3071a9;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{position:absolute;z-index:-1;filter:alpha(opacity=0);opacity:0}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#777}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#777}.navbar-inverse .navbar-nav>li>a{color:#777}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#777}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#777}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#428bca;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar[aria-valuenow="1"],.progress-bar[aria-valuenow="2"]{min-width:30px}.progress-bar[aria-valuenow="0"]{min-width:30px;color:#777;background-color:transparent;background-image:none;-webkit-box-shadow:none;box-shadow:none}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#428bca}.panel-primary>.panel-heading .badge{color:#428bca;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate3d(0,-25%,0);-o-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0)}.modal.in .modal-dialog{-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed;-webkit-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/sharding-jdbc-doc/public/css/landing-page.css b/sharding-jdbc-doc/public/css/landing-page.css new file mode 100644 index 0000000000000..325c267d88651 --- /dev/null +++ b/sharding-jdbc-doc/public/css/landing-page.css @@ -0,0 +1,209 @@ +/*! + * Start Bootstrap - Landing Page Bootstrap Theme (http://startbootstrap.com) + * Code licensed under the Apache License v2.0. + * For details, see http://www.apache.org/licenses/LICENSE-2.0. + */ + + body, + html { + width: 100%; + height: 100%; + font-size: 16px; +} + +body, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: -apple-system-headline, 'Helvetica Neue', Helvetica, sans-serif; +} + +.lead { + font-size: 18px; + font-weight: 400; +} + +.intro-header { + padding-top: 40px; + text-align: center; + color: #f8f8f8; +} + +.intro-message { + margin-top: 100px; + color: rgb(51, 51, 51); + text-align: left; +} + +.intro-message > h3 { + font-family: -apple-system-headline, 'HelveticaNeue-Light', 'Helvetica Neue', Helvetica, sans-serif; +} + +.intro-message > h1 { + font-family: -apple-system-subheadline, 'HelveticaNeue-UltraLight', 'Helvetica Neue', Helvetica, sans-serif; + font-size: 5em; +} + +.intro-divider { + width: 400px; + border-top: 1px solid #f8f8f8; + border-bottom: 1px solid rgba(0,0,0,0.2); +} + +.network-name { + text-transform: uppercase; + font-size: 14px; + font-weight: 400; + letter-spacing: 2px; +} + +.container { + width: 1024px; + line-height: 1.2em; +} + +.header-container { + width: 100%; +} + +.container ul { + line-height: 1.6em; +} + +.container pre { + margin-top: 20px; + margin-bottom: 20px; + line-height: 1.6em; +} + +.container h3 { + margin-top: 20px; + margin-bottom: 10px; +} + +.content-section-a { + padding: 50px 0; + background-color: #f8f8f8; +} + +.content-section-b { + padding: 50px 0; + border-top: 1px solid #e7e7e7; + border-bottom: 1px solid #e7e7e7; +} + +.section-heading { + margin-bottom: 30px; +} + +.section-heading-spacer { + float: left; + width: 200px; + border-top: 3px solid #e7e7e7; +} + +.contact { + padding: 100px 0; + color: #f8f8f8; + background: url(../img/contact-bg.jpg) no-repeat center center; + background-size: cover; +} + +.contact h2 { + margin: 0; + text-shadow: 2px 2px 3px rgba(0,0,0,0.6); + font-size: 3em; +} + +.contact ul { + margin-bottom: 0; +} + +.contact-social-buttons { + float: right; + margin-top: 0; +} + +@media(max-width:1199px) { + ul.contact-social-buttons { + float: left; + margin-top: 15px; + } +} + +@media(max-width:767px) { + .contact h2 { + margin: 0; + text-shadow: 2px 2px 3px rgba(0,0,0,0.6); + font-size: 3em; + } + + ul.contact-social-buttons > li { + display: block; + margin-bottom: 20px; + padding: 0; + } + + ul.contact-social-buttons > li:last-child { + margin-bottom: 0; + } +} + +footer { + padding: 50px 0; + background-color: #f8f8f8; +} + +p.copyright { + margin: 15px 0 0; +} + + +@media(max-width:1000px) { + .intro-message { + padding-bottom: 10%; + margin-top: -30px; + } + + .intro-message > h1 { + font-size: 3em; + } + + ul.intro-social-buttons > li { + display: block; + margin-bottom: 20px; + padding: 0; + } + + ul.intro-social-buttons > li:last-child { + margin-bottom: 0; + } + + .intro-divider { + width: 100%; + } + + .container { + width: 80%; + } + + .intro-message { + text-align: center; + } +} + +.intro-image { + height: 100%; + min-height: 380px; + margin-top: 20px; + /*background: url(../img/intro-bg.svg) no-repeat center center; + background-size: 280px; + */ +} + +.github-btn { + margin-top: 10px; +} diff --git a/sharding-jdbc-doc/public/css/prism.css b/sharding-jdbc-doc/public/css/prism.css new file mode 100644 index 0000000000000..847f556b38771 --- /dev/null +++ b/sharding-jdbc-doc/public/css/prism.css @@ -0,0 +1,140 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+bash+groovy+java+json+sql */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + diff --git a/sharding-jdbc-doc/public/css/table.css b/sharding-jdbc-doc/public/css/table.css new file mode 100644 index 0000000000000..3d3812b180971 --- /dev/null +++ b/sharding-jdbc-doc/public/css/table.css @@ -0,0 +1,11 @@ +table { + display: block; + width: 100%; + overflow: auto; + word-break: normal; + word-break: keep-all; } +table th { + font-weight: bold; } +table th, table td { + padding: 0.5rem 1rem; + border: 1px solid #e9ebec; } diff --git a/sharding-jdbc-doc/public/data/chart.js b/sharding-jdbc-doc/public/data/chart.js new file mode 100644 index 0000000000000..9c9378530edbd --- /dev/null +++ b/sharding-jdbc-doc/public/data/chart.js @@ -0,0 +1,108 @@ +var chartData = { + "compareQuery": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "JDBC", + data: [1812, 3828, 5217, 7239, 7169] + }, { + label: "Sharding-JDBC", + data: [1591, 2547, 5062, 7284, 7151] + } + + ] + },"compareInsert": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "JDBC", + data: [2520, 5860, 6420, 6200, 6250] + },{ + label: "Sharding-JDBC", + data: [2410, 4230, 5445, 5603, 5642] + } + + ] + },"compareUpdate": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "JDBC", + data: [2430, 5712, 6557, 7773, 7561] + },{ + label: "Sharding-JDBC", + data: [2059, 2715, 4770, 7280, 7210] + } + + ] + }, "singleAndDubbleQuery": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "双库", + data: [3724, 6246, 11480, 13107, 13960] + },{ + label: "单库", + data: [1591, 2547, 5062, 7284, 7151] + } + + ] + },"singleAndDubbleInsert": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "双库", + data: [4021, 6807, 7911, 8109, 7619] + },{ + label: "单库", + data: [2410, 4230, 5445, 5603, 5642] + } + + ] + },"singleAndDubbleUpdate": { + labels: ["50", "100", "200", "300", "600"], + datasets: [ + { + label: "双库", + data: [2190, 4464, 9039, 10144, 11970] + },{ + label: "单库", + data: [2059, 2715, 4770, 7280, 7210] + } + ] + },"fatigueTest": { + labels: ["0", "1小时", "2小时", "3小时", "4小时", "5小时", "6小时", "7小时", "8小时"], + datasets: [ + { + label: "jvm堆大小", + data: [0, 567, 533, 587, 523, 546, 577 ,534,577] + } + ] + } +} + +var charStyle = [ + + { + backgroundColor: "rgba(246,179,107,0.2)", + borderColor: "rgba(246,179,107,1)", + pointBorderColor: "rgba(246,179,107,1)", + pointBackgroundColor: "#fff", + pointBorderWidth: 1, + pointHoverRadius: 5, + pointHoverBackgroundColor: "rgba(246,179,107,1)", + pointHoverBorderColor: "rgba(246,179,107,1)", + pointHoverBorderWidth: 2, + }, + { + backgroundColor: "rgba(61,134,198,0.2)", + borderColor: "rgba(61,134,198,1)", + pointBorderColor: "rgba(61,134,198,1)", + pointBackgroundColor: "#fff", + pointBorderWidth: 1, + pointHoverRadius: 5, + pointHoverBackgroundColor: "rgba(61,134,198,1)", + pointHoverBorderColor: "rgba(61,134,198,1)", + pointHoverBorderWidth: 2, + } +] \ No newline at end of file diff --git a/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.eot b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000..4a4ca865d67e8 Binary files /dev/null and b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.eot differ diff --git a/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.svg b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000000000..e3e2dc739dd85 --- /dev/null +++ b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.ttf b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000..67fa00bf83801 Binary files /dev/null and b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.ttf differ diff --git a/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.woff b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000000000..8c54182aa5d4d Binary files /dev/null and b/sharding-jdbc-doc/public/fonts/glyphicons-halflings-regular.woff differ diff --git a/sharding-jdbc-doc/public/img/AlgorithmClass.900.png b/sharding-jdbc-doc/public/img/AlgorithmClass.900.png new file mode 100644 index 0000000000000..8ca80c9d0035c Binary files /dev/null and b/sharding-jdbc-doc/public/img/AlgorithmClass.900.png differ diff --git a/sharding-jdbc-doc/public/img/AlgorithmClass.png b/sharding-jdbc-doc/public/img/AlgorithmClass.png new file mode 100644 index 0000000000000..a22ac2f38e8bd Binary files /dev/null and b/sharding-jdbc-doc/public/img/AlgorithmClass.png differ diff --git a/sharding-jdbc-doc/public/img/StrategyClass.900.png b/sharding-jdbc-doc/public/img/StrategyClass.900.png new file mode 100644 index 0000000000000..731d8d4af380f Binary files /dev/null and b/sharding-jdbc-doc/public/img/StrategyClass.900.png differ diff --git a/sharding-jdbc-doc/public/img/StrategyClass.png b/sharding-jdbc-doc/public/img/StrategyClass.png new file mode 100644 index 0000000000000..b34033053482a Binary files /dev/null and b/sharding-jdbc-doc/public/img/StrategyClass.png differ diff --git a/sharding-jdbc-doc/public/img/architecture.png b/sharding-jdbc-doc/public/img/architecture.png new file mode 100644 index 0000000000000..34ca570be69bc Binary files /dev/null and b/sharding-jdbc-doc/public/img/architecture.png differ diff --git a/sharding-jdbc-doc/public/img/execute.png b/sharding-jdbc-doc/public/img/execute.png new file mode 100644 index 0000000000000..ec4f62911ebbc Binary files /dev/null and b/sharding-jdbc-doc/public/img/execute.png differ diff --git a/sharding-jdbc-doc/public/img/intro-bg.svg b/sharding-jdbc-doc/public/img/intro-bg.svg new file mode 100644 index 0000000000000..b823836f4ccbc --- /dev/null +++ b/sharding-jdbc-doc/public/img/intro-bg.svg @@ -0,0 +1,65 @@ + + + + app-icon-board + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sharding-jdbc-doc/public/img/license.svg b/sharding-jdbc-doc/public/img/license.svg new file mode 100644 index 0000000000000..a05f3f740458e --- /dev/null +++ b/sharding-jdbc-doc/public/img/license.svg @@ -0,0 +1 @@ +licenselicenseApache 2Apache 2 \ No newline at end of file diff --git a/sharding-jdbc-doc/public/img/merge.png b/sharding-jdbc-doc/public/img/merge.png new file mode 100644 index 0000000000000..d7acf81dc3105 Binary files /dev/null and b/sharding-jdbc-doc/public/img/merge.png differ diff --git a/sharding-jdbc-doc/public/img/parse.png b/sharding-jdbc-doc/public/img/parse.png new file mode 100644 index 0000000000000..75a5e109bec2e Binary files /dev/null and b/sharding-jdbc-doc/public/img/parse.png differ diff --git a/sharding-jdbc-doc/public/img/route.png b/sharding-jdbc-doc/public/img/route.png new file mode 100644 index 0000000000000..52c3866f5a4b9 Binary files /dev/null and b/sharding-jdbc-doc/public/img/route.png differ diff --git a/sharding-jdbc-doc/public/img/stress_test_arch.png b/sharding-jdbc-doc/public/img/stress_test_arch.png new file mode 100644 index 0000000000000..2220631535e2f Binary files /dev/null and b/sharding-jdbc-doc/public/img/stress_test_arch.png differ diff --git a/sharding-jdbc-doc/public/index.html b/sharding-jdbc-doc/public/index.html new file mode 100644 index 0000000000000..a41a5ddb3456d --- /dev/null +++ b/sharding-jdbc-doc/public/index.html @@ -0,0 +1,355 @@ + + + + + + + + + Sharding-JDBC + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+

Sharding-JDBC

+

A JDBC driver for shard databases and tables

+ + + + + +
+
+
+
+ +
+ +
+ +
+ + + +
+
+
+
+ + +

主要贡献者

+ +
    +
  • 张亮    当当 zhangliang@dangdang.com
  • +
  • 高洪涛 当当 gaohongtao@dangdang.com
  • +
  • 曹昊    当当 caohao@dangdang.com
  • +
  • 岳令    当当 yueling@dangdang.com
  • +
+ +

讨论QQ群:532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流)

+ +

简介

+ +

Sharding-JDBC是当当应用框架ddframe中,关系型数据库模块dd-rdb中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。

+ +

Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:

+ +
    +
  • 可适用于任何基于javaORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC
  • +
  • 可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等。
  • +
  • 理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持OracleSQLServerDB2等数据库的计划。
  • +
+ +

Sharding-JDBC定位为轻量级java框架,使用客户端直连数据库,以jar包形式提供服务,未使用中间层,无需额外部署,无其他依赖,DBA也无需改变原有的运维方式。SQL解析使用Druid解析器,是目前性能最高的SQL解析器。

+ +

Sharding-JDBC功能灵活且全面:

+ +
    +
  • 分片策略灵活,可支持=BETWEENIN等多维度分片,也可支持多分片键共用。
  • +
  • SQL解析功能完善,支持聚合,分组,排序,LimitOR等查询,并且支持Binding Table以及笛卡尔积的表查询。
  • +
+ +
+ +

以下是常见的分库分表产品和Sharding-JDBC的对比:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能CobarCobar-clientTDDLSharding-JDBC
分库未开源
分表未开源
中间层
ORM支持任意仅MyBatis任意任意
数据库支持仅MySQL任意任意任意
异构语言仅Java仅Java仅Java
外部依赖Diamond
+ +
+ +

整体架构图

+ +

整体架构图1

+ +

Quick Start

+ +

引入maven依赖

+ +
<!-- 引入sharding-jdbc核心模块 -->
+<dependency>
+    <groupId>com.dangdang</groupId>
+    <artifactId>sharding-jdbc-core</artifactId>
+    <version>1.0.0</version>
+</dependency>
+
+ +

规则配置

+ +

Sharding-JDBC的分库分表通过规则配置描述,请简单浏览配置全貌:

+ +
 ShardingRule shardingRule = new ShardingRule(
+                dataSourceRule, 
+                Arrays.asList(tableRule), 
+                new DatabaseShardingStrategy("sharding_column_1", new XXXShardingAlgorithm()),
+                new TableShardingStrategy("sharding_column_2", new XXXShardingAlgorithm()));
+
+ +

规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和tableRule绑定等。

+ +
+

详细的规则配置请参考用户指南

+
+ +

使用基于ShardingDataSource的JDBC接口

+ +

通过规则配置对象获取ShardingDataSourceShardingDataSource实现自JDBC的标准接口DataSource。然后可通过DataSource选择使用原生JDBC开发,或者使用JPA, MyBatisORM工具。 +以JDBC原生实现为例:

+ +
DataSource dataSource = new ShardingDataSource(shardingRule);
+String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
+try (
+        Connection conn = dataSource.getConnection();
+        PreparedStatement pstmt = conn.prepareStatement(sql)) {
+    pstmt.setInt(1, 10);
+    pstmt.setInt(2, 1001);
+    try (ResultSet rs = pstmt.executeQuery()) {
+        while(rs.next()) {
+            System.out.println(rs.getInt(1));
+            System.out.println(rs.getInt(2));
+            System.out.println(rs.getInt(3));
+        }
+    }
+}
+
+ +
+
+
+ + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/index.xml b/sharding-jdbc-doc/public/index.xml new file mode 100644 index 0000000000000..e32c70d095ff6 --- /dev/null +++ b/sharding-jdbc-doc/public/index.xml @@ -0,0 +1,1037 @@ + + + + Sharding-JDBC + http://dangdangdotcom.github.io/sharding-jdbc/ + Recent content on Sharding-JDBC + Hugo -- gohugo.io + en-us + + + + + http://dangdangdotcom.github.io/sharding-jdbc/index/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://dangdangdotcom.github.io/sharding-jdbc/index/ + + +<h1 id="主要贡献者:d680e8a854a7cbad6d490c445cba2eba">主要贡献者</h1> + +<ul> +<li>张亮 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> zhangliang@dangdang.com</li> +<li>高洪涛 <a href="http://www.dangdang.com/">当当</a> gaohongtao@dangdang.com</li> +<li>曹昊 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> caohao@dangdang.com</li> +<li>岳令 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> yueling@dangdang.com</li> +</ul> + +<p><strong>讨论QQ群:</strong>532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流)</p> + +<h1 id="简介:d680e8a854a7cbad6d490c445cba2eba">简介</h1> + +<p><code>Sharding-JDBC</code>是当当应用框架<code>ddframe</code>中,关系型数据库模块<code>dd-rdb</code>中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。</p> + +<p><code>Sharding-JDBC</code>直接封装<code>JDBC API</code>,可以理解为增强版的<code>JDBC</code>驱动,旧代码迁移成本几乎为零:</p> + +<ul> +<li>可适用于任何基于<code>java</code>的<code>ORM</code>框架,如:<code>JPA</code>, <code>Hibernate</code>, <code>Mybatis</code>, <code>Spring JDBC Template</code>或直接使用<code>JDBC</code>。</li> +<li>可基于任何第三方的数据库连接池,如:<code>DBCP</code>, <code>C3P0</code>, <code>BoneCP</code>, <code>Druid</code>等。</li> +<li>理论上可支持任意实现<code>JDBC</code>规范的数据库。虽然目前仅支持<code>MySQL</code>,但已有支持<code>Oracle</code>,<code>SQLServer</code>,<code>DB2</code>等数据库的计划。</li> +</ul> + +<p><code>Sharding-JDBC</code>定位为轻量级<code>java</code>框架,使用客户端直连数据库,以<code>jar</code>包形式提供服务,未使用中间层,无需额外部署,无其他依赖,<code>DBA</code>也无需改变原有的运维方式。<code>SQL</code>解析使用<code>Druid</code>解析器,是目前性能最高的<code>SQL</code>解析器。</p> + +<p><code>Sharding-JDBC</code>功能灵活且全面:</p> + +<ul> +<li>分片策略灵活,可支持<code>=</code>,<code>BETWEEN</code>,<code>IN</code>等多维度分片,也可支持多分片键共用。</li> +<li><code>SQL</code>解析功能完善,支持聚合,分组,排序,<code>Limit</code>,<code>OR</code>等查询,并且支持<code>Binding Table</code>以及笛卡尔积的表查询。</li> +</ul> + +<hr /> + +<p>以下是常见的分库分表产品和<code>Sharding-JDBC</code>的对比:</p> + +<table> +<thead> +<tr> +<th>功能</th> +<th align="center">Cobar</th> +<th align="right">Cobar-client</th> +<th align="right">TDDL</th> +<th align="right">Sharding-JDBC</th> +</tr> +</thead> + +<tbody> +<tr> +<td>分库</td> +<td align="center">有</td> +<td align="right">有</td> +<td align="right">未开源</td> +<td align="right">有</td> +</tr> + +<tr> +<td>分表</td> +<td align="center">无</td> +<td align="right">无</td> +<td align="right">未开源</td> +<td align="right">有</td> +</tr> + +<tr> +<td>中间层</td> +<td align="center">是</td> +<td align="right">否</td> +<td align="right">否</td> +<td align="right">否</td> +</tr> + +<tr> +<td>ORM支持</td> +<td align="center">任意</td> +<td align="right">仅MyBatis</td> +<td align="right">任意</td> +<td align="right">任意</td> +</tr> + +<tr> +<td>数据库支持</td> +<td align="center">仅MySQL</td> +<td align="right">任意</td> +<td align="right">任意</td> +<td align="right">任意</td> +</tr> + +<tr> +<td>异构语言</td> +<td align="center">可</td> +<td align="right">仅Java</td> +<td align="right">仅Java</td> +<td align="right">仅Java</td> +</tr> + +<tr> +<td>外部依赖</td> +<td align="center">无</td> +<td align="right">无</td> +<td align="right">Diamond</td> +<td align="right">无</td> +</tr> +</tbody> +</table> + +<hr /> + +<h1 id="整体架构图:d680e8a854a7cbad6d490c445cba2eba">整体架构图</h1> + +<p><img src="img/architecture.png" alt="整体架构图1" /></p> + +<h1 id="quick-start:d680e8a854a7cbad6d490c445cba2eba">Quick Start</h1> + +<h2 id="引入maven依赖:d680e8a854a7cbad6d490c445cba2eba">引入maven依赖</h2> + +<pre><code class="language-xml">&lt;!-- 引入sharding-jdbc核心模块 --&gt; +&lt;dependency&gt; + &lt;groupId&gt;com.dangdang&lt;/groupId&gt; + &lt;artifactId&gt;sharding-jdbc-core&lt;/artifactId&gt; + &lt;version&gt;1.0.0&lt;/version&gt; +&lt;/dependency&gt; +</code></pre> + +<h2 id="规则配置:d680e8a854a7cbad6d490c445cba2eba">规则配置</h2> + +<p><code>Sharding-JDBC</code>的分库分表通过规则配置描述,请简单浏览配置全貌:</p> + +<pre><code class="language-java"> ShardingRule shardingRule = new ShardingRule( + dataSourceRule, + Arrays.asList(tableRule), + new DatabaseShardingStrategy(&quot;sharding_column_1&quot;, new XXXShardingAlgorithm()), + new TableShardingStrategy(&quot;sharding_column_2&quot;, new XXXShardingAlgorithm())); +</code></pre> + +<p>规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和<code>tableRule</code>绑定等。</p> + +<blockquote> +<p>详细的规则配置请参考<a href="post/user_guide">用户指南</a></p> +</blockquote> + +<h2 id="使用基于shardingdatasource的jdbc接口:d680e8a854a7cbad6d490c445cba2eba">使用基于ShardingDataSource的JDBC接口</h2> + +<p>通过规则配置对象获取<code>ShardingDataSource</code>,<code>ShardingDataSource</code>实现自<code>JDBC</code>的标准接口<code>DataSource</code>。然后可通过<code>DataSource</code>选择使用原生<code>JDBC</code>开发,或者使用<code>JPA</code>, <code>MyBatis</code>等<code>ORM</code>工具。 +以<code>JDBC</code>原生实现为例:</p> + +<pre><code class="language-java">DataSource dataSource = new ShardingDataSource(shardingRule); +String sql = &quot;SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?&quot;; +try ( + Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, 10); + pstmt.setInt(2, 1001); + try (ResultSet rs = pstmt.executeQuery()) { + while(rs.next()) { + System.out.println(rs.getInt(1)); + System.out.println(rs.getInt(2)); + System.out.println(rs.getInt(3)); + } + } +} +</code></pre> + + + + + 使用指南 + http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/ + + +<h1 id="使用指南:74c632aa9613b8dd6b95bfab1ba313e2">使用指南</h1> + +<p>阅读本指南前,请先阅读快速起步。本文档使用更复杂的场景进一步介绍<code>Sharding-JDBC</code>的分库分表能力。</p> + +<h2 id="数据库模式:74c632aa9613b8dd6b95bfab1ba313e2">数据库模式</h2> + +<p>本文档中提供了两个数据源<code>db0</code>和<code>db1</code>,每个数据源之中包含了两组表<code>t_order_0</code>和<code>t_order_1</code>,<code>t_order_item_0</code>和<code>t_order_item_1</code>。这两组表的建表语句为:</p> + +<pre><code class="language-sql">CREATE TABLE IF NOT EXISTS `t_order_x` ( + `order_id` INT NOT NULL, + `user_id` INT NOT NULL, + PRIMARY KEY (`order_id`) +); +CREATE TABLE IF NOT EXISTS `t_order_item_x` ( + `item_id` INT NOT NULL, + `order_id` INT NOT NULL, + `user_id` INT NOT NULL, + PRIMARY KEY (`item_id`) +); +</code></pre> + +<h2 id="逻辑表与实际表映射关系:74c632aa9613b8dd6b95bfab1ba313e2">逻辑表与实际表映射关系</h2> + +<h3 id="均匀分布:74c632aa9613b8dd6b95bfab1ba313e2">均匀分布</h3> + +<p>数据表在每个数据源内呈现均匀分布的态势</p> + +<pre><code>db0 + ├── t_order_0 + └── t_order_1 +db1 + ├── t_order_0 + └── t_order_1 +</code></pre> + +<p>表规则可以使用默认的配置</p> + +<pre><code class="language-java"> TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule); +</code></pre> + +<h3 id="自定义分布:74c632aa9613b8dd6b95bfab1ba313e2">自定义分布</h3> + +<p>数据表呈现有特定规则的分布</p> + +<pre><code>db0 + ├── t_order_0 + └── t_order_1 +db1 + ├── t_order_2 + ├── t_order_3 + └── t_order_4 +</code></pre> + +<p>表规则可以指定每张表在数据源中的分布情况</p> + +<pre><code class="language-java"> TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;db0.t_order_0&quot;, &quot;db0.t_order_1&quot;, &quot;db1.t_order_2&quot;, &quot;db1.t_order_3&quot;, &quot;db1.t_order_4&quot;), dataSourceRule); +</code></pre> + +<h3 id="本教程采用的数据分布例子:74c632aa9613b8dd6b95bfab1ba313e2">本教程采用的数据分布例子</h3> + +<pre><code>db0 + ├── t_order_0 user_id为偶数 order_id为偶数 + ├── t_order_1 user_id为偶数 order_id为奇数 + ├── t_order_item_0 user_id为偶数 order_id为偶数 + └── t_order_item_1 user_id为偶数 order_id为奇数 +db1 + ├── t_order_0 user_id为奇数 order_id为偶数 + ├── t_order_1 user_id为奇数 order_id为奇数 + ├── t_order_item_0 user_id为奇数 order_id为偶数 + └── t_order_item_1 user_id为奇数 order_id为奇数 +</code></pre> + +<h2 id="逻辑表与实际表:74c632aa9613b8dd6b95bfab1ba313e2">逻辑表与实际表</h2> + +<p>配置分库分表的目的是将原有一张表的数据分散到不同库不同表中,且不改变原有<code>SQL</code>语句的情况下来使用这一张表。那么从一张表到多张的映射关系需要使用逻辑表与实际表这两种概念。下面通过一个例子来解释一下。假设在使用<code>PreparedStatement</code>访问数据库,<code>SQL</code>如下:</p> + +<pre><code class="language-sql">select * from t_order where user_id = ? and order_id = ?; +</code></pre> + +<p>当<code>user_id=0</code>且<code>order=0</code>时,<code>Sharding-JDBC</code>将会将<code>SQL</code>语句转换为如下形式:</p> + +<pre><code class="language-sql">select * from db0.t_order_0 where user_id = ? and order_id = ?; +</code></pre> + +<p>其中原始<code>SQL</code>中的<code>t_order</code>就是 <strong>逻辑表</strong>,而转换后的<code>db0.t_order_0</code>就是 <strong>实际表</strong></p> + +<h2 id="规则配置:74c632aa9613b8dd6b95bfab1ba313e2">规则配置</h2> + +<p>以上分库分表的形式<code>Sharding-JDBC</code>是通过规则配置来进行的描述的,下面讲通过几个小节来描述规则的详细配置:</p> + +<pre><code class="language-java"> ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); +</code></pre> + +<h2 id="数据源配置:74c632aa9613b8dd6b95bfab1ba313e2">数据源配置</h2> + +<p>首先我们来构造<code>DataSourceRule</code>对象,它是来描述数据源的分布规则的。</p> + +<pre><code class="language-java"> DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap); +</code></pre> + +<p>这里构造器需要一个入参:数据源名称与真实数据源之间的映射关系,这个关系的构造方法如下</p> + +<pre><code class="language-java">Map&lt;String, DataSource&gt; dataSourceMap = new HashMap&lt;&gt;(2); +dataSourceMap.put(&quot;ds_0&quot;, createDataSource(&quot;ds_0&quot;)); +dataSourceMap.put(&quot;ds_1&quot;, createDataSource(&quot;ds_1&quot;)); +</code></pre> + +<p>真实的数据源可以使用任意一种数据库连接池,这里使用DBCP来举例</p> + +<pre><code class="language-java">private static DataSource createDataSource(final String dataSourceName) { + BasicDataSource result = new BasicDataSource(); + result.setDriverClassName(com.mysql.jdbc.Driver.class.getName()); + result.setUrl(String.format(&quot;jdbc:mysql://localhost:3306/%s&quot;, dataSourceName)); + result.setUsername(&quot;root&quot;); + result.setPassword(&quot;&quot;); + return result; +} +</code></pre> + +<h2 id="策略配置:74c632aa9613b8dd6b95bfab1ba313e2">策略配置</h2> + +<h3 id="数据源策略与表策略:74c632aa9613b8dd6b95bfab1ba313e2">数据源策略与表策略</h3> + +<p><img src="../../img/StrategyClass.900.png" alt="策略类图" /> +Sharding-JDBC认为对于分片策略存有两种维度 +- 数据源分片策略<code>DatabaseShardingStrategy</code>:数据被分配的目标数据源 +- 表分片策略<code>TableShardingStrategy</code>:数据被分配的目标表,该目标表存在与该数据的目标数据源内。故表分片策略是依赖与数据源分片策略的结果的 +这里注意的是两种策略的API完全相同,以下针对策略API的讲解将适用于这两种策略</p> + +<h3 id="全局默认策略与特定表策略:74c632aa9613b8dd6b95bfab1ba313e2">全局默认策略与特定表策略</h3> + +<p>策略是作用在特定的表规则上的,数据源策略与表策略与特定表相关</p> + +<pre><code class="language-java">TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()), + dataSourceRule); +</code></pre> + +<p>如果分片规则中的所有表或大部分表的分片策略相同,可以使用默认策略来简化配置。一下两种配置是等价的</p> + +<pre><code class="language-java"> //使用了默认策略配置 + TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule); + TableRule orderItemTableRule = new TableRule(&quot;t_order_item&quot;, Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;), dataSourceRule); + ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); +</code></pre> + +<pre><code class="language-java"> //未使用默认策略配置 + TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule, + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); + TableRule orderItemTableRule = new TableRule(&quot;t_order_item&quot;, Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;), dataSourceRule, + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); + ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)))); +</code></pre> + +<h3 id="分片键:74c632aa9613b8dd6b95bfab1ba313e2">分片键</h3> + +<p>分片键是分片策略的第一个参数。分片键表示的是SQL语句中WHERE中的条件列。分片键可以配置多个</p> + +<ul> +<li>单分片策略</li> +</ul> + +<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm())) +</code></pre> + +<ul> +<li>多分片策略</li> +</ul> + +<pre><code class="language-java">new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;,&quot;order_type&quot;, &quot;order_date&quot;), new MultiKeyShardingAlgorithm())) +</code></pre> + +<h3 id="分片算法:74c632aa9613b8dd6b95bfab1ba313e2">分片算法</h3> + +<p>分片算法接口类图关系如下:</p> + +<p><img src="../../img/AlgorithmClass.900.png" alt="算法" /></p> + +<h3 id="绑定表:74c632aa9613b8dd6b95bfab1ba313e2">绑定表</h3> + +<p>绑定表代表一组表,这组表的逻辑表与实际表之间的映射关系是相同的。比如<code>t_order</code>与<code>t_order_item</code>就是这样一组绑定表关系,它们的分库与分表策略是完全相同的,那么可以使用它们的表规则将它们配置成绑定表</p> + +<pre><code class="language-java">new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)) +</code></pre> + +<p>那么在进行SQL路由时,如果SQL为</p> + +<pre><code class="language-sql">SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=? +</code></pre> + +<p>其中<code>t_order</code>在FROM的最左侧,Sharding-JDBC将会以它作为整个绑定表的主表。所有路由计算将会只使用主表的策略,那么<code>t_order_item</code>表的分片计算将会使用<code>t_order</code>的条件。故绑定表之间的分区键要完全相同。</p> + +<h2 id="分片算法详解:74c632aa9613b8dd6b95bfab1ba313e2">分片算法详解</h2> + +<h3 id="单分片键算法与多分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">单分片键算法与多分片键算法</h3> + +<p>这两种算法从名字上就可以知道前者是针对只有一个分片键,后者是针对有多个分片键的。单分片键算法是多分片键算法的一种简便形式,所以完全可以使用多分片算法去替代单分片键算法。下面两种形式是等价的</p> + +<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm())) +new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;), new MultiKeyShardingAlgorithm())) +</code></pre> + +<p>同时在算法内部,<code>doSharding</code>等方法的<code>shardingValue</code>入参根据使用算法类型不同而不同 +单分片键算法,方法签名</p> + +<pre><code class="language-java">public String doEqualSharding(final Collection&lt;String&gt; dataSourceNames, final ShardingValue&lt;Integer&gt; shardingValue) +</code></pre> + +<p>多分片键算法,方法签名</p> + +<pre><code class="language-java">public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) +</code></pre> + +<h3 id="分片键算法类型:74c632aa9613b8dd6b95bfab1ba313e2">分片键算法类型</h3> + +<p>根据数据源策略与表策略、单分片与多分片,这两种组合,一共产生了4种可供实现的分片算法的接口</p> + +<ul> +<li>单分片键数据源分片算法<code>SingleKeyDatabaseShardingAlgorithm</code></li> +<li>单分片表分片算法<code>SingleKeyTableShardingAlgorithm</code></li> +<li>多分片键数据源分片算法<code>MultipleKeyDatabaseShardingAlgorithm</code></li> +<li>多分片表分片算法<code>MultipleKeyTableShardingAlgorithm</code></li> +</ul> + +<h3 id="单分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">单分片键算法</h3> + +<p>单分片键算法需要实现三个方法,下面以”单分片键数据源分片算法“举例</p> + +<pre><code class="language-java">@Override +public String doEqualSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) + +@Override +public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) + +@Override +public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) +</code></pre> + +<p>这三种算法作用如下 +- <code>doEqualSharding</code>在WHERE使用<code>=</code>作为条件分片键。算法中使用<code>shardingValue.getValue()</code>获取等<code>=</code>后的值 +- <code>doInSharding</code>在WHERE使用<code>IN</code>作为条件分片键。算法中使用<code>shardingValue.getValues()</code>获取<code>IN</code>后的值 +- <code>doBetweenSharding</code>在WHERE使用<code>BETWEEN</code>作为条件分片键。算法中使用<code>shardingValue.getValueRange()</code>获取<code>BETWEEN</code>后的值</p> + +<p>下面是一个余2的算法的例子,当分片键的值除以2余数就是实际表的结尾。注意注释中提供了一些算法生成SQL的结果,参数<code>tableNames</code>集合中有两个参数<code>t_order_0</code>和<code>t_order_1</code></p> + +<pre><code class="language-java"> public final class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm&lt;Integer&gt; { + + /** + * select * from t_order from t_order where order_id = 11 + * └── SELECT * FROM t_order_1 WHERE order_id = 11 + * select * from t_order from t_order where order_id = 44 + * └── SELECT * FROM t_order_0 WHERE order_id = 44 + */ + public String doEqualSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + for (String each : tableNames) { + if (each.endsWith(shardingValue.getValue() % 2 + &quot;&quot;)) { + return each; + } + } + throw new IllegalArgumentException(); + } + + /** + * select * from t_order from t_order where order_id in (11,44) + * ├── SELECT * FROM t_order_0 WHERE order_id IN (11,44) + * └── SELECT * FROM t_order_1 WHERE order_id IN (11,44) + * select * from t_order from t_order where order_id in (11,13,15) + * └── SELECT * FROM t_order_1 WHERE order_id IN (11,13,15) + * select * from t_order from t_order where order_id in (22,24,26) + * └──SELECT * FROM t_order_0 WHERE order_id IN (22,24,26) + */ + public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size()); + for (Integer value : shardingValue.getValues()) { + for (String dataSourceName : tableNames) { + if (dataSourceName.endsWith(value % 2 + &quot;&quot;)) { + result.add(dataSourceName); + } + } + } + return result; + } + + /** + * select * from t_order from t_order where order_id between 10 and 20 + * ├── SELECT * FROM t_order_0 WHERE order_id BETWEEN 10 AND 20 + * └── SELECT * FROM t_order_1 WHERE order_id BETWEEN 10 AND 20 + */ + public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size()); + Range&lt;Integer&gt; range = (Range&lt;Integer&gt;) shardingValue.getValueRange(); + for (Integer i = range.lowerEndpoint(); i &lt;= range.upperEndpoint(); i++) { + for (String each : tableNames) { + if (each.endsWith(i % 2 + &quot;&quot;)) { + result.add(each); + } + } + } + return result; + } +} +</code></pre> + +<h3 id="多分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">多分片键算法</h3> + +<p>多分片键试用于使用场景比较复杂,为了能提供更高的灵活性,故只提供实现一个方法。</p> + +<pre><code class="language-java">@Override +public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) +</code></pre> + +<p>算法实现的时候根据<code>shardingValue.getType()</code>来获取条件是<code>=</code>,<code>IN</code>或者<code>BETWEEN</code>。然后根据业务进行灵活的实现。</p> + +<p>如果表的数据分布如下</p> + +<pre><code>db0 + ├── t_order_00 user_id以a偶数 order_id为偶数 + ├── t_order_01 user_id以a偶数 order_id为奇数 + ├── t_order_10 user_id以b奇数 order_id为偶数 + └── t_order_11 user_id以b奇数 order_id为奇数 + +</code></pre> + +<p>算法实现如下:</p> + +<pre><code class="language-java">public final class MultipleKeysModuloTableShardingAlgorithm implements MultipleKeysTableShardingAlgorithm { + + @Override + public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) { + Set&lt;Integer&gt; orderIdValueSet = getShardingValue(shardingValues, &quot;order_id&quot;); + Set&lt;Integer&gt; userIdValueSet = getShardingValue(shardingValues, &quot;user_id&quot;); + + List&lt;String&gt; result = new ArrayList&lt;&gt;(); + /* + userIdValueSet[10,11] + orderIdValueSet[101,102] =&gt; valueResult[[10,101],[10,102],[11,101],[11,102]] + */ + Set&lt;List&lt;Integer&gt;&gt; valueResult = Sets.cartesianProduct(userIdValueSet, orderIdValueSet); + for (List&lt;Integer&gt; value : valueResult) { + String suffix = Joiner.on(&quot;&quot;).join(value.get(0) % 2, value.get(1) % 2); + for (String tableName : availableTargetNames) { + if (tableName.endsWith(suffix)) { + result.add(tableName); + } + } + + } + return result; + } + + private Set&lt;Integer&gt; getShardingValue(final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues, final String shardingKey) { + Set&lt;Integer&gt; valueSet = new HashSet&lt;&gt;(); + ShardingValue&lt;Integer&gt; shardingValue = null; + for (ShardingValue&lt;?&gt; each : shardingValues) { + if (each.getColumnName().equals(shardingKey)) { + shardingValue = (ShardingValue&lt;Integer&gt;) each; + break; + } + } + if (null == shardingValue) { + return valueSet; + } + switch (shardingValue.getType()) { + case SINGLE: + valueSet.add(shardingValue.getValue()); + break; + case LIST: + valueSet.addAll(shardingValue.getValues()); + break; + case RANGE: + for (Integer i = shardingValue.getValueRange().lowerEndpoint(); i &lt;= shardingValue.getValueRange().upperEndpoint(); i++) { + valueSet.add(i); + } + break; + default: + throw new UnsupportedOperationException(); + } + return valueSet; + } +} +</code></pre> + +<h2 id="构造shardingdatasource:74c632aa9613b8dd6b95bfab1ba313e2">构造ShardingDataSource</h2> + +<p>完成规则配置后,我们就可以得到<code>ShardingDataSource</code></p> + +<pre><code class="language-java">new ShardingDataSource(shardingRule); +</code></pre> + +<h2 id="使用shardingdatasource:74c632aa9613b8dd6b95bfab1ba313e2">使用ShardingDataSource</h2> + +<p>通过一个例子来看看如何使用该数据源</p> + +<pre><code class="language-java">String sql = &quot;SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?&quot;; + try ( + Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql); + ) { + pstmt.setInt(1, 10); + pstmt.setInt(2, 1001); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + System.out.println(rs.getInt(1)); + System.out.println(rs.getInt(2)); + System.out.println(rs.getInt(3)); + } + rs.close(); + } +</code></pre> + +<p>该数据源与普通数据源完全相同,你可以通过上例的API形式来使用,也可以将其配置在Spring,Hibernate等框架中使用。</p> + + + + + 详细功能列表 + http://dangdangdotcom.github.io/sharding-jdbc/post/features/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/features/ + + +<h1 id="详细功能列表:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">详细功能列表</h1> + +<h2 id="功能性需求:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">功能性需求</h2> + +<h3 id="分库分表-同时支持分库和分表:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">分库分表:同时支持分库和分表</h3> + +<ol> +<li>分片规则自由定制</li> +<li>支持多分片键</li> +<li>支持通过<code>=</code>,<code>BETWEEN</code>,<code>IN</code>分片</li> +<li>支持<code>Binding Table</code></li> +<li>支持多表笛卡尔积查询</li> +<li>支持多表结果归并</li> +<li>支持聚合查询结果归并</li> +<li>支持<code>AVG</code>函数改写为<code>SUM/COUNT</code></li> +<li>支持<code>Order By</code>结果归并</li> +<li>支持<code>Group By</code>结果归并</li> +<li>支持<code>LIMIT</code>分页查询以及多库表结果改写及归并</li> +<li>支持<code>OR</code>查询</li> +</ol> + +<h2 id="易用性:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">易用性</h2> + +<ol> +<li><p><code>JDBC</code>协议适配</p> + +<p>1.1. 全<code>ORM</code>支持</p> + +<p>1.2. 全数据库连接池支持</p> + +<p>1.3. 多数据库支持(目前仅<code>MySQL</code>,未来计划支持<code>Oracle</code>,<code>SQLServer</code>和<code>DB2</code>)</p></li> + +<li><p><code>Spring</code>命名空间支持(待开源)</p></li> + +<li><p>基于动态语言的分片策略配置(待开源)</p></li> + +<li><p><code>Metrics</code>统计监控</p></li> +</ol> + +<h2 id="性能:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">性能</h2> + +<ol> +<li>基于<code>Druid</code>的高性能<code>SQL</code>解析</li> +<li>多线程处理结果归并</li> +<li>性能损失率不足<code>10%</code></li> +</ol> + +<h2 id="稳定性:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">稳定性</h2> + +<p>完善的疲劳测试,普通查询无<code>Full GC</code>(<code>Group By</code>除外)</p> + + + + + 架构图 + http://dangdangdotcom.github.io/sharding-jdbc/post/architecture/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/architecture/ + + +<h1 id="架构图:1bf455b3a3c6e1e40be41ef6023b75eb">架构图</h1> + +<p><img src="../../img/architecture.png" alt="整体架构图1" /></p> + +<p><img src="../../img/parse.png" alt="SQL解析" /></p> + +<p><img src="../../img/route.png" alt="SQL路由" /></p> + +<p><img src="../../img/execute.png" alt="SQL执行" /></p> + +<p><img src="../../img/merge.png" alt="结果归并" /></p> + + + + + 目录结构说明 + http://dangdangdotcom.github.io/sharding-jdbc/post/directory_structure/ + Thu, 28 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/directory_structure/ + + +<h1 id="目录结构说明:b4b5a29fe5be663d2644d30f96759d37">目录结构说明</h1> + +<h2 id="sharding-jdbc-core:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-core</h2> + +<p><code>sharding-jdbc</code>分库分表核心模块。</p> + +<h2 id="sharding-jdbc-spring-待开源:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-spring(待开源)</h2> + +<p><code>sharding-jdbc</code>对<code>spring</code>支持的模块,包括命名空间等。</p> + +<h2 id="sharding-jdbc-config-待开源:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-config(待开源)</h2> + +<p><code>sharding-jdbc</code>动态分片规则配置模块。</p> + +<h2 id="sharding-jdbc-example:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-example</h2> + +<p>使用示例。有<code>sharding-jdbc-example-jdbc</code>,<code>sharding-jdbc-example-jpa</code>和<code>sharding-jdbc-example-mybatis</code>3个子项目。</p> + +<h2 id="sharding-jdbc-doc:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-doc</h2> + +<p>使用<code>markdown</code>生成文档的项目,使用方无需关注。</p> + + + + + 使用限制 + http://dangdangdotcom.github.io/sharding-jdbc/post/limitations/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/limitations/ + + +<h1 id="使用限制:187f2cad6c4cc3b3972d4d058186f234">使用限制</h1> + +<h2 id="jdbc-未支持列表:187f2cad6c4cc3b3972d4d058186f234"><code>JDBC</code>未支持列表</h2> + +<p><code>Sharding-JDBC</code>暂时未支持不常用的<code>JDBC</code>方法。</p> + +<h3 id="datasource-接口:187f2cad6c4cc3b3972d4d058186f234"><code>DataSource</code>接口</h3> + +<ul> +<li>不支持<code>timeout</code>相关操作</li> +</ul> + +<h3 id="connection-接口:187f2cad6c4cc3b3972d4d058186f234"><code>Connection</code>接口</h3> + +<ul> +<li>不支持存储过程,函数,游标的操作</li> +<li>不支持执行<code>native</code>的<code>SQL</code></li> +<li>不支持<code>savepoint</code>相关操作</li> +<li>不支持<code>Schema/Catalog</code>的操作</li> +<li>不支持自定义类型映射</li> +</ul> + +<h3 id="statement-和-preparedstatement-接口:187f2cad6c4cc3b3972d4d058186f234"><code>Statement</code>和<code>PreparedStatement</code>接口</h3> + +<ul> +<li>不支持返回多结果集的语句(即存储过程,非<code>SELECT</code>多条数据)</li> +<li>不支持国际化字符的操作</li> +</ul> + +<h3 id="对于-resultset-接口:187f2cad6c4cc3b3972d4d058186f234">对于<code>ResultSet</code>接口</h3> + +<ul> +<li>不支持对于结果集指针位置判断</li> +<li>不支持通过非next方法改变结果指针位置</li> +<li>不支持修改结果集内容</li> +<li>不支持获取国际化字符</li> +<li>不支持获取<code>Array</code></li> +</ul> + +<h3 id="jdbc-4-1:187f2cad6c4cc3b3972d4d058186f234">JDBC 4.1</h3> + +<ul> +<li>不支持JDBC 4.1接口新功能</li> +</ul> + +<p>查询所有未支持方法,请阅读<code>com.dangdang.ddframe.rdb.sharding.jdbc.unsupported</code>包。</p> + +<h2 id="sql语句限制:187f2cad6c4cc3b3972d4d058186f234">SQL语句限制</h2> + +<h3 id="不支持ddl语句:187f2cad6c4cc3b3972d4d058186f234">不支持DDL语句</h3> + +<h3 id="不支持子语句:187f2cad6c4cc3b3972d4d058186f234">不支持子语句</h3> + +<h3 id="不支持-union-和-union-all:187f2cad6c4cc3b3972d4d058186f234">不支持<code>UNION</code> 和 <code>UNION ALL</code></h3> + +<h3 id="不支持特殊-insert:187f2cad6c4cc3b3972d4d058186f234">不支持特殊<code>INSERT</code></h3> + +<p>每条<code>INSERT</code>语句只能插入一条数据,不支持<code>VALUES</code>后有多行数据的语句</p> + +<h3 id="不支持-distinct-聚合:187f2cad6c4cc3b3972d4d058186f234">不支持<code>DISTINCT</code>聚合</h3> + +<h3 id="对于-谨慎使用:187f2cad6c4cc3b3972d4d058186f234">对于<code>*</code>谨慎使用</h3> + +<p>一般情况下<code>SELECT</code>语句中是可以使用<code>*</code>的,如下的<code>SQL</code>可以正常在<code>Sharding-JDBC</code>中使用。</p> + +<pre><code class="language-sql">select * from order; +</code></pre> + +<p>但以下几种SQL不允许使用<code>*</code></p> + +<ul> +<li>语句中存在聚合函数<code>AVG</code></li> +<li><code>GROUP BY</code>语句</li> +<li><code>ORDER BY</code>语句</li> +</ul> + + + + + 压力测试报告 + http://dangdangdotcom.github.io/sharding-jdbc/post/stress_test/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/stress_test/ + + +<h1 id="压力测试报告:da68abc810593941936aaba3d62b3b96">压力测试报告</h1> + +<h2 id="测试目的:da68abc810593941936aaba3d62b3b96">测试目的</h2> + +<p>对<code>Sharding-JDBC</code>进行性能测试,客观、公正评估系统的性能,目的有三:</p> + +<ol> +<li>对比<code>Sharding-JDBC</code>和<code>JDBC</code>的性能。</li> +<li><code>Sharding-JDBC</code>是否通过扩展数据库解决<code>JDBC</code>吞吐量不足的问题。</li> +<li><code>Sharding-JDBC</code>的稳定性。</li> +</ol> + +<h2 id="测试数据库配置:da68abc810593941936aaba3d62b3b96">测试数据库配置</h2> + +<table> +<thead> +<tr> +<th>数据库实例</th> +<th align="center">DB1</th> +<th align="center">DB2</th> +</tr> +</thead> + +<tbody> +<tr> +<td>操作系统</td> +<td align="center">centOS5.4</td> +<td align="center">centOS5.4</td> +</tr> + +<tr> +<td>CPU</td> +<td align="center">2C四核</td> +<td align="center">2C四核</td> +</tr> + +<tr> +<td>内存</td> +<td align="center">32GB</td> +<td align="center">32GB</td> +</tr> + +<tr> +<td>硬盘</td> +<td align="center">250G*2_RAID1+600G*4_RAID10</td> +<td align="center">250G*2_RAID1+600G*4_RAID10</td> +</tr> + +<tr> +<td>Mysql版本</td> +<td align="center">5.5.19</td> +<td align="center">5.5.19</td> +</tr> + +<tr> +<td>数据表字段数量</td> +<td align="center">70</td> +<td align="center">70</td> +</tr> + +<tr> +<td>数据表行数</td> +<td align="center">1000万</td> +<td align="center">1000万</td> +</tr> +</tbody> +</table> + +<h2 id="网络拓扑:da68abc810593941936aaba3d62b3b96">网络拓扑</h2> + +<p><img src="img/stress_test_arch.png" alt="网络拓扑图" /></p> + +<h2 id="单库情况下sharding-jdbc与jdbc性能对比:da68abc810593941936aaba3d62b3b96">单库情况下Sharding-JDBC与JDBC性能对比</h2> + +<p>测试结论:</p> + +<ul> +<li>查询操作,Sharding-JDBC的TPS为JDBC的TPS的99.8%</li> +<li>插入操作,Sharding-JDBC的TPS为JDBC的TPS的90.2%</li> +<li>更新操作,Sharding-JDBC的TPS为JDBC的TPS的93.1%</li> +</ul> + +<h3 id="查询:da68abc810593941936aaba3d62b3b96">查询</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareQuery" width="400" height="150"></canvas> + +<h3 id="插入:da68abc810593941936aaba3d62b3b96">插入</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareInsert" width="400" height="150"></canvas> + +<h3 id="更新:da68abc810593941936aaba3d62b3b96">更新</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareUpdate" width="400" height="150"></canvas> + +<h2 id="sharding-jdbc单库与双库性能对比:da68abc810593941936aaba3d62b3b96">Sharding-JDBC单库与双库性能对比</h2> + +<p>对比测试:</p> + +<ul> +<li>单库用例中所有数据全部在DB1中</li> +<li>双库用例中所有数据均匀分布在DB1与DB2中</li> +</ul> + +<p>结论:</p> + +<ul> +<li>查询操作,TPS双库比单库可以增加大约94%的性能</li> +<li>插入操作,TPS双库比单库可以增加大约60%的性能</li> +<li>更新操作,TPS双库比单库可以增加大约89%的性能</li> +</ul> + +<h3 id="查询-1:da68abc810593941936aaba3d62b3b96">查询</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleQuery" width="400" height="150"></canvas> + +<h3 id="插入-1:da68abc810593941936aaba3d62b3b96">插入</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleInsert" width="400" height="150"></canvas> + +<h3 id="更新-1:da68abc810593941936aaba3d62b3b96">更新</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleUpdate" width="400" height="150"></canvas> + +<h2 id="sharding-jdbc疲劳测试:da68abc810593941936aaba3d62b3b96">Sharding-JDBC疲劳测试</h2> + +<p>经过8个小时的疲劳测试,jvm的堆大约占用不到600MB的内存,且使用量比较稳定。没有发生fullgc。 +<canvas id="fatigueTest" width="400" height="150"></canvas></p> + + + + + 未来线路规划 + http://dangdangdotcom.github.io/sharding-jdbc/post/roadmap/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/roadmap/ + + +<h1 id="未来线路规划:cd4a1b36ed2b93cfc52abf77a7d25d03">未来线路规划</h1> + +<ol> +<li>读写分离</li> +<li>柔性分布式事务</li> +<li>分布式主键生成策略</li> +<li>SQL重写优化,进一步提升性能</li> +<li>SQL Hint,可指定某SQL在某具体库表执行,基于业务规则而非SQL解析路由</li> +<li>小表广播</li> +<li>HA相关</li> +<li>流量控制</li> +<li>数据库建表工具</li> +<li>数据迁移</li> +<li>复杂SQL解析支持,如子查询,存储过程等</li> +<li>Oracle, SQLServer,DB2支持</li> +<li>配置中心</li> +</ol> + + + + + 事务支持说明 + http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/ + Fri, 29 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/ + + +<h1 id="事务支持说明:2e47673b0e2fecf4f97d6b00d496cdc9">事务支持说明</h1> + +<p><code>Sharding-JDBC</code>目前不支持分布式事务。我们已明确规划roadmap,在未来的一两个版本中会支持最终一致性的柔性事务。</p> + +<p>基于目前状况的事务,有以下几点说明:</p> + +<ul> +<li><p>完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。</p></li> + +<li><p>完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。</p></li> + +<li><p>不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库死机,则只有第二个库数据提交。</p></li> +</ul> + + + + + \ No newline at end of file diff --git a/sharding-jdbc-doc/public/index/index.html b/sharding-jdbc-doc/public/index/index.html new file mode 100644 index 0000000000000..97371de7c3d5a --- /dev/null +++ b/sharding-jdbc-doc/public/index/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

主要贡献者

+ +
    +
  • 张亮    当当 zhangliang@dangdang.com
  • +
  • 高洪涛 当当 gaohongtao@dangdang.com
  • +
  • 曹昊    当当 caohao@dangdang.com
  • +
  • 岳令    当当 yueling@dangdang.com
  • +
+ +

讨论QQ群:532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流)

+ +

简介

+ +

Sharding-JDBC是当当应用框架ddframe中,关系型数据库模块dd-rdb中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。

+ +

Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:

+ +
    +
  • 可适用于任何基于javaORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC
  • +
  • 可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等。
  • +
  • 理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持OracleSQLServerDB2等数据库的计划。
  • +
+ +

Sharding-JDBC定位为轻量级java框架,使用客户端直连数据库,以jar包形式提供服务,未使用中间层,无需额外部署,无其他依赖,DBA也无需改变原有的运维方式。SQL解析使用Druid解析器,是目前性能最高的SQL解析器。

+ +

Sharding-JDBC功能灵活且全面:

+ +
    +
  • 分片策略灵活,可支持=BETWEENIN等多维度分片,也可支持多分片键共用。
  • +
  • SQL解析功能完善,支持聚合,分组,排序,LimitOR等查询,并且支持Binding Table以及笛卡尔积的表查询。
  • +
+ +
+ +

以下是常见的分库分表产品和Sharding-JDBC的对比:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能CobarCobar-clientTDDLSharding-JDBC
分库未开源
分表未开源
中间层
ORM支持任意仅MyBatis任意任意
数据库支持仅MySQL任意任意任意
异构语言仅Java仅Java仅Java
外部依赖Diamond
+ +
+ +

整体架构图

+ +

整体架构图1

+ +

Quick Start

+ +

引入maven依赖

+ +
<!-- 引入sharding-jdbc核心模块 -->
+<dependency>
+    <groupId>com.dangdang</groupId>
+    <artifactId>sharding-jdbc-core</artifactId>
+    <version>1.0.0</version>
+</dependency>
+
+ +

规则配置

+ +

Sharding-JDBC的分库分表通过规则配置描述,请简单浏览配置全貌:

+ +
 ShardingRule shardingRule = new ShardingRule(
+                dataSourceRule, 
+                Arrays.asList(tableRule), 
+                new DatabaseShardingStrategy("sharding_column_1", new XXXShardingAlgorithm()),
+                new TableShardingStrategy("sharding_column_2", new XXXShardingAlgorithm()));
+
+ +

规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和tableRule绑定等。

+ +
+

详细的规则配置请参考用户指南

+
+ +

使用基于ShardingDataSource的JDBC接口

+ +

通过规则配置对象获取ShardingDataSourceShardingDataSource实现自JDBC的标准接口DataSource。然后可通过DataSource选择使用原生JDBC开发,或者使用JPA, MyBatisORM工具。 +以JDBC原生实现为例:

+ +
DataSource dataSource = new ShardingDataSource(shardingRule);
+String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
+try (
+        Connection conn = dataSource.getConnection();
+        PreparedStatement pstmt = conn.prepareStatement(sql)) {
+    pstmt.setInt(1, 10);
+    pstmt.setInt(2, 1001);
+    try (ResultSet rs = pstmt.executeQuery()) {
+        while(rs.next()) {
+            System.out.println(rs.getInt(1));
+            System.out.println(rs.getInt(2));
+            System.out.println(rs.getInt(3));
+        }
+    }
+}
+
+ +
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/index/index.xml b/sharding-jdbc-doc/public/index/index.xml new file mode 100644 index 0000000000000..08941cb8b06e8 --- /dev/null +++ b/sharding-jdbc-doc/public/index/index.xml @@ -0,0 +1,185 @@ + + + + Indexes on Sharding-JDBC + http://dangdangdotcom.github.io/sharding-jdbc/index/ + Recent content in Indexes on Sharding-JDBC + Hugo -- gohugo.io + en-us + + + + + http://dangdangdotcom.github.io/sharding-jdbc/index/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://dangdangdotcom.github.io/sharding-jdbc/index/ + + +<h1 id="主要贡献者:d680e8a854a7cbad6d490c445cba2eba">主要贡献者</h1> + +<ul> +<li>张亮 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> zhangliang@dangdang.com</li> +<li>高洪涛 <a href="http://www.dangdang.com/">当当</a> gaohongtao@dangdang.com</li> +<li>曹昊 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> caohao@dangdang.com</li> +<li>岳令 &nbsp;&nbsp;&nbsp;<a href="http://www.dangdang.com/">当当</a> yueling@dangdang.com</li> +</ul> + +<p><strong>讨论QQ群:</strong>532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流)</p> + +<h1 id="简介:d680e8a854a7cbad6d490c445cba2eba">简介</h1> + +<p><code>Sharding-JDBC</code>是当当应用框架<code>ddframe</code>中,关系型数据库模块<code>dd-rdb</code>中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。</p> + +<p><code>Sharding-JDBC</code>直接封装<code>JDBC API</code>,可以理解为增强版的<code>JDBC</code>驱动,旧代码迁移成本几乎为零:</p> + +<ul> +<li>可适用于任何基于<code>java</code>的<code>ORM</code>框架,如:<code>JPA</code>, <code>Hibernate</code>, <code>Mybatis</code>, <code>Spring JDBC Template</code>或直接使用<code>JDBC</code>。</li> +<li>可基于任何第三方的数据库连接池,如:<code>DBCP</code>, <code>C3P0</code>, <code>BoneCP</code>, <code>Druid</code>等。</li> +<li>理论上可支持任意实现<code>JDBC</code>规范的数据库。虽然目前仅支持<code>MySQL</code>,但已有支持<code>Oracle</code>,<code>SQLServer</code>,<code>DB2</code>等数据库的计划。</li> +</ul> + +<p><code>Sharding-JDBC</code>定位为轻量级<code>java</code>框架,使用客户端直连数据库,以<code>jar</code>包形式提供服务,未使用中间层,无需额外部署,无其他依赖,<code>DBA</code>也无需改变原有的运维方式。<code>SQL</code>解析使用<code>Druid</code>解析器,是目前性能最高的<code>SQL</code>解析器。</p> + +<p><code>Sharding-JDBC</code>功能灵活且全面:</p> + +<ul> +<li>分片策略灵活,可支持<code>=</code>,<code>BETWEEN</code>,<code>IN</code>等多维度分片,也可支持多分片键共用。</li> +<li><code>SQL</code>解析功能完善,支持聚合,分组,排序,<code>Limit</code>,<code>OR</code>等查询,并且支持<code>Binding Table</code>以及笛卡尔积的表查询。</li> +</ul> + +<hr /> + +<p>以下是常见的分库分表产品和<code>Sharding-JDBC</code>的对比:</p> + +<table> +<thead> +<tr> +<th>功能</th> +<th align="center">Cobar</th> +<th align="right">Cobar-client</th> +<th align="right">TDDL</th> +<th align="right">Sharding-JDBC</th> +</tr> +</thead> + +<tbody> +<tr> +<td>分库</td> +<td align="center">有</td> +<td align="right">有</td> +<td align="right">未开源</td> +<td align="right">有</td> +</tr> + +<tr> +<td>分表</td> +<td align="center">无</td> +<td align="right">无</td> +<td align="right">未开源</td> +<td align="right">有</td> +</tr> + +<tr> +<td>中间层</td> +<td align="center">是</td> +<td align="right">否</td> +<td align="right">否</td> +<td align="right">否</td> +</tr> + +<tr> +<td>ORM支持</td> +<td align="center">任意</td> +<td align="right">仅MyBatis</td> +<td align="right">任意</td> +<td align="right">任意</td> +</tr> + +<tr> +<td>数据库支持</td> +<td align="center">仅MySQL</td> +<td align="right">任意</td> +<td align="right">任意</td> +<td align="right">任意</td> +</tr> + +<tr> +<td>异构语言</td> +<td align="center">可</td> +<td align="right">仅Java</td> +<td align="right">仅Java</td> +<td align="right">仅Java</td> +</tr> + +<tr> +<td>外部依赖</td> +<td align="center">无</td> +<td align="right">无</td> +<td align="right">Diamond</td> +<td align="right">无</td> +</tr> +</tbody> +</table> + +<hr /> + +<h1 id="整体架构图:d680e8a854a7cbad6d490c445cba2eba">整体架构图</h1> + +<p><img src="img/architecture.png" alt="整体架构图1" /></p> + +<h1 id="quick-start:d680e8a854a7cbad6d490c445cba2eba">Quick Start</h1> + +<h2 id="引入maven依赖:d680e8a854a7cbad6d490c445cba2eba">引入maven依赖</h2> + +<pre><code class="language-xml">&lt;!-- 引入sharding-jdbc核心模块 --&gt; +&lt;dependency&gt; + &lt;groupId&gt;com.dangdang&lt;/groupId&gt; + &lt;artifactId&gt;sharding-jdbc-core&lt;/artifactId&gt; + &lt;version&gt;1.0.0&lt;/version&gt; +&lt;/dependency&gt; +</code></pre> + +<h2 id="规则配置:d680e8a854a7cbad6d490c445cba2eba">规则配置</h2> + +<p><code>Sharding-JDBC</code>的分库分表通过规则配置描述,请简单浏览配置全貌:</p> + +<pre><code class="language-java"> ShardingRule shardingRule = new ShardingRule( + dataSourceRule, + Arrays.asList(tableRule), + new DatabaseShardingStrategy(&quot;sharding_column_1&quot;, new XXXShardingAlgorithm()), + new TableShardingStrategy(&quot;sharding_column_2&quot;, new XXXShardingAlgorithm())); +</code></pre> + +<p>规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和<code>tableRule</code>绑定等。</p> + +<blockquote> +<p>详细的规则配置请参考<a href="post/user_guide">用户指南</a></p> +</blockquote> + +<h2 id="使用基于shardingdatasource的jdbc接口:d680e8a854a7cbad6d490c445cba2eba">使用基于ShardingDataSource的JDBC接口</h2> + +<p>通过规则配置对象获取<code>ShardingDataSource</code>,<code>ShardingDataSource</code>实现自<code>JDBC</code>的标准接口<code>DataSource</code>。然后可通过<code>DataSource</code>选择使用原生<code>JDBC</code>开发,或者使用<code>JPA</code>, <code>MyBatis</code>等<code>ORM</code>工具。 +以<code>JDBC</code>原生实现为例:</p> + +<pre><code class="language-java">DataSource dataSource = new ShardingDataSource(shardingRule); +String sql = &quot;SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?&quot;; +try ( + Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setInt(1, 10); + pstmt.setInt(2, 1001); + try (ResultSet rs = pstmt.executeQuery()) { + while(rs.next()) { + System.out.println(rs.getInt(1)); + System.out.println(rs.getInt(2)); + System.out.println(rs.getInt(3)); + } + } +} +</code></pre> + + + + + \ No newline at end of file diff --git a/sharding-jdbc-doc/public/js/bootstrap.js b/sharding-jdbc-doc/public/js/bootstrap.js new file mode 100644 index 0000000000000..53da1c77c084d --- /dev/null +++ b/sharding-jdbc-doc/public/js/bootstrap.js @@ -0,0 +1,2114 @@ +/*! + * Bootstrap v3.2.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } + +/* ======================================================================== + * Bootstrap: transition.js v3.2.0 + * http://getbootstrap.com/javascript/#transitions + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false + var $el = this + $(this).one('bsTransitionEnd', function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + + if (!$.support.transition) return + + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function (e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) + } + } + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.2.0 + * http://getbootstrap.com/javascript/#alerts + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.VERSION = '3.2.0' + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.hasClass('alert') ? $this : $this.parent() + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + // detach from parent, fire event then clean up data + $parent.detach().trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one('bsTransitionEnd', removeElement) + .emulateTransitionEnd(150) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.alert + + $.fn.alert = Plugin + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.2.0 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.2.0' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state = state + 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + $el[val](data[state] == null ? this.options[state] : data[state]) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false + else $parent.find('.active').removeClass('active') + } + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } + + if (changed) this.$element.toggleClass('active') + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + var old = $.fn.button + + $.fn.button = Plugin + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + e.preventDefault() + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.2.0 + * http://getbootstrap.com/javascript/#carousel + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this)) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = + this.sliding = + this.interval = + this.$active = + this.$items = null + + this.options.pause == 'hover' && this.$element + .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) + } + + Carousel.VERSION = '3.2.0' + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true + } + + Carousel.prototype.keydown = function (e) { + switch (e.which) { + case 37: this.prev(); break + case 39: this.next(); break + default: return + } + + e.preventDefault() + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } + + if ($next.hasClass('active')) return (this.sliding = false) + + var relatedTarget = $next[0] + var slideEvent = $.Event('slide.bs.carousel', { + relatedTarget: relatedTarget, + direction: direction + }) + this.$element.trigger(slideEvent) + if (slideEvent.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') + } + + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one('bsTransitionEnd', function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger(slidEvent) + }, 0) + }) + .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger(slidEvent) + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + var old = $.fn.carousel + + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var href + var $this = $(this) + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + if (!$target.hasClass('carousel')) return + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + Plugin.call($target, options) + + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + }) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.2.0 + * http://getbootstrap.com/javascript/#collapse + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null + + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } + + Collapse.VERSION = '3.2.0' + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var actives = this.$parent && this.$parent.find('> .panel > .in') + + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + Plugin.call(actives, 'hide') + hasData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing')[dimension](0) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in')[dimension]('') + this.transitioning = 0 + this.$element + .trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element[dimension](this.$element[dimension]())[0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(350) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && option == 'show') option = !option + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.collapse + + $.fn.collapse = Plugin + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { + var href + var $this = $(this) + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) + + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } + + Plugin.call($target, option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.2.0 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.2.0' + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(' + + + + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/index.html b/sharding-jdbc-doc/public/post/index.html new file mode 100644 index 0000000000000..26f8b0fa21690 --- /dev/null +++ b/sharding-jdbc-doc/public/post/index.html @@ -0,0 +1,149 @@ + + + + + + + + + Posts + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+

Sharding-JDBC

+

A JDBC driver for shard databases and tables

+ + + + + +
+
+
+
+ +
+ +
+ +
+ + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/index.xml b/sharding-jdbc-doc/public/post/index.xml new file mode 100644 index 0000000000000..090a2c9cfc1f5 --- /dev/null +++ b/sharding-jdbc-doc/public/post/index.xml @@ -0,0 +1,865 @@ + + + + Posts on Sharding-JDBC + http://dangdangdotcom.github.io/sharding-jdbc/post/ + Recent content in Posts on Sharding-JDBC + Hugo -- gohugo.io + en-us + Fri, 08 Jan 2016 16:14:21 +0800 + + + + 使用指南 + http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/ + + +<h1 id="使用指南:74c632aa9613b8dd6b95bfab1ba313e2">使用指南</h1> + +<p>阅读本指南前,请先阅读快速起步。本文档使用更复杂的场景进一步介绍<code>Sharding-JDBC</code>的分库分表能力。</p> + +<h2 id="数据库模式:74c632aa9613b8dd6b95bfab1ba313e2">数据库模式</h2> + +<p>本文档中提供了两个数据源<code>db0</code>和<code>db1</code>,每个数据源之中包含了两组表<code>t_order_0</code>和<code>t_order_1</code>,<code>t_order_item_0</code>和<code>t_order_item_1</code>。这两组表的建表语句为:</p> + +<pre><code class="language-sql">CREATE TABLE IF NOT EXISTS `t_order_x` ( + `order_id` INT NOT NULL, + `user_id` INT NOT NULL, + PRIMARY KEY (`order_id`) +); +CREATE TABLE IF NOT EXISTS `t_order_item_x` ( + `item_id` INT NOT NULL, + `order_id` INT NOT NULL, + `user_id` INT NOT NULL, + PRIMARY KEY (`item_id`) +); +</code></pre> + +<h2 id="逻辑表与实际表映射关系:74c632aa9613b8dd6b95bfab1ba313e2">逻辑表与实际表映射关系</h2> + +<h3 id="均匀分布:74c632aa9613b8dd6b95bfab1ba313e2">均匀分布</h3> + +<p>数据表在每个数据源内呈现均匀分布的态势</p> + +<pre><code>db0 + ├── t_order_0 + └── t_order_1 +db1 + ├── t_order_0 + └── t_order_1 +</code></pre> + +<p>表规则可以使用默认的配置</p> + +<pre><code class="language-java"> TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule); +</code></pre> + +<h3 id="自定义分布:74c632aa9613b8dd6b95bfab1ba313e2">自定义分布</h3> + +<p>数据表呈现有特定规则的分布</p> + +<pre><code>db0 + ├── t_order_0 + └── t_order_1 +db1 + ├── t_order_2 + ├── t_order_3 + └── t_order_4 +</code></pre> + +<p>表规则可以指定每张表在数据源中的分布情况</p> + +<pre><code class="language-java"> TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;db0.t_order_0&quot;, &quot;db0.t_order_1&quot;, &quot;db1.t_order_2&quot;, &quot;db1.t_order_3&quot;, &quot;db1.t_order_4&quot;), dataSourceRule); +</code></pre> + +<h3 id="本教程采用的数据分布例子:74c632aa9613b8dd6b95bfab1ba313e2">本教程采用的数据分布例子</h3> + +<pre><code>db0 + ├── t_order_0 user_id为偶数 order_id为偶数 + ├── t_order_1 user_id为偶数 order_id为奇数 + ├── t_order_item_0 user_id为偶数 order_id为偶数 + └── t_order_item_1 user_id为偶数 order_id为奇数 +db1 + ├── t_order_0 user_id为奇数 order_id为偶数 + ├── t_order_1 user_id为奇数 order_id为奇数 + ├── t_order_item_0 user_id为奇数 order_id为偶数 + └── t_order_item_1 user_id为奇数 order_id为奇数 +</code></pre> + +<h2 id="逻辑表与实际表:74c632aa9613b8dd6b95bfab1ba313e2">逻辑表与实际表</h2> + +<p>配置分库分表的目的是将原有一张表的数据分散到不同库不同表中,且不改变原有<code>SQL</code>语句的情况下来使用这一张表。那么从一张表到多张的映射关系需要使用逻辑表与实际表这两种概念。下面通过一个例子来解释一下。假设在使用<code>PreparedStatement</code>访问数据库,<code>SQL</code>如下:</p> + +<pre><code class="language-sql">select * from t_order where user_id = ? and order_id = ?; +</code></pre> + +<p>当<code>user_id=0</code>且<code>order=0</code>时,<code>Sharding-JDBC</code>将会将<code>SQL</code>语句转换为如下形式:</p> + +<pre><code class="language-sql">select * from db0.t_order_0 where user_id = ? and order_id = ?; +</code></pre> + +<p>其中原始<code>SQL</code>中的<code>t_order</code>就是 <strong>逻辑表</strong>,而转换后的<code>db0.t_order_0</code>就是 <strong>实际表</strong></p> + +<h2 id="规则配置:74c632aa9613b8dd6b95bfab1ba313e2">规则配置</h2> + +<p>以上分库分表的形式<code>Sharding-JDBC</code>是通过规则配置来进行的描述的,下面讲通过几个小节来描述规则的详细配置:</p> + +<pre><code class="language-java"> ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); +</code></pre> + +<h2 id="数据源配置:74c632aa9613b8dd6b95bfab1ba313e2">数据源配置</h2> + +<p>首先我们来构造<code>DataSourceRule</code>对象,它是来描述数据源的分布规则的。</p> + +<pre><code class="language-java"> DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap); +</code></pre> + +<p>这里构造器需要一个入参:数据源名称与真实数据源之间的映射关系,这个关系的构造方法如下</p> + +<pre><code class="language-java">Map&lt;String, DataSource&gt; dataSourceMap = new HashMap&lt;&gt;(2); +dataSourceMap.put(&quot;ds_0&quot;, createDataSource(&quot;ds_0&quot;)); +dataSourceMap.put(&quot;ds_1&quot;, createDataSource(&quot;ds_1&quot;)); +</code></pre> + +<p>真实的数据源可以使用任意一种数据库连接池,这里使用DBCP来举例</p> + +<pre><code class="language-java">private static DataSource createDataSource(final String dataSourceName) { + BasicDataSource result = new BasicDataSource(); + result.setDriverClassName(com.mysql.jdbc.Driver.class.getName()); + result.setUrl(String.format(&quot;jdbc:mysql://localhost:3306/%s&quot;, dataSourceName)); + result.setUsername(&quot;root&quot;); + result.setPassword(&quot;&quot;); + return result; +} +</code></pre> + +<h2 id="策略配置:74c632aa9613b8dd6b95bfab1ba313e2">策略配置</h2> + +<h3 id="数据源策略与表策略:74c632aa9613b8dd6b95bfab1ba313e2">数据源策略与表策略</h3> + +<p><img src="../../img/StrategyClass.900.png" alt="策略类图" /> +Sharding-JDBC认为对于分片策略存有两种维度 +- 数据源分片策略<code>DatabaseShardingStrategy</code>:数据被分配的目标数据源 +- 表分片策略<code>TableShardingStrategy</code>:数据被分配的目标表,该目标表存在与该数据的目标数据源内。故表分片策略是依赖与数据源分片策略的结果的 +这里注意的是两种策略的API完全相同,以下针对策略API的讲解将适用于这两种策略</p> + +<h3 id="全局默认策略与特定表策略:74c632aa9613b8dd6b95bfab1ba313e2">全局默认策略与特定表策略</h3> + +<p>策略是作用在特定的表规则上的,数据源策略与表策略与特定表相关</p> + +<pre><code class="language-java">TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm()), + dataSourceRule); +</code></pre> + +<p>如果分片规则中的所有表或大部分表的分片策略相同,可以使用默认策略来简化配置。一下两种配置是等价的</p> + +<pre><code class="language-java"> //使用了默认策略配置 + TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule); + TableRule orderItemTableRule = new TableRule(&quot;t_order_item&quot;, Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;), dataSourceRule); + ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))), + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); +</code></pre> + +<pre><code class="language-java"> //未使用默认策略配置 + TableRule orderTableRule = new TableRule(&quot;t_order&quot;, Arrays.asList(&quot;t_order_0&quot;, &quot;t_order_1&quot;), dataSourceRule, + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); + TableRule orderItemTableRule = new TableRule(&quot;t_order_item&quot;, Arrays.asList(&quot;t_order_item_0&quot;, &quot;t_order_item_1&quot;), dataSourceRule, + new DatabaseShardingStrategy(&quot;user_id&quot;, new ModuloDatabaseShardingAlgorithm()), + new TableShardingStrategy(&quot;order_id&quot;, new ModuloTableShardingAlgorithm())); + ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule), + Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)))); +</code></pre> + +<h3 id="分片键:74c632aa9613b8dd6b95bfab1ba313e2">分片键</h3> + +<p>分片键是分片策略的第一个参数。分片键表示的是SQL语句中WHERE中的条件列。分片键可以配置多个</p> + +<ul> +<li>单分片策略</li> +</ul> + +<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm())) +</code></pre> + +<ul> +<li>多分片策略</li> +</ul> + +<pre><code class="language-java">new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;,&quot;order_type&quot;, &quot;order_date&quot;), new MultiKeyShardingAlgorithm())) +</code></pre> + +<h3 id="分片算法:74c632aa9613b8dd6b95bfab1ba313e2">分片算法</h3> + +<p>分片算法接口类图关系如下:</p> + +<p><img src="../../img/AlgorithmClass.900.png" alt="算法" /></p> + +<h3 id="绑定表:74c632aa9613b8dd6b95bfab1ba313e2">绑定表</h3> + +<p>绑定表代表一组表,这组表的逻辑表与实际表之间的映射关系是相同的。比如<code>t_order</code>与<code>t_order_item</code>就是这样一组绑定表关系,它们的分库与分表策略是完全相同的,那么可以使用它们的表规则将它们配置成绑定表</p> + +<pre><code class="language-java">new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)) +</code></pre> + +<p>那么在进行SQL路由时,如果SQL为</p> + +<pre><code class="language-sql">SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=? +</code></pre> + +<p>其中<code>t_order</code>在FROM的最左侧,Sharding-JDBC将会以它作为整个绑定表的主表。所有路由计算将会只使用主表的策略,那么<code>t_order_item</code>表的分片计算将会使用<code>t_order</code>的条件。故绑定表之间的分区键要完全相同。</p> + +<h2 id="分片算法详解:74c632aa9613b8dd6b95bfab1ba313e2">分片算法详解</h2> + +<h3 id="单分片键算法与多分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">单分片键算法与多分片键算法</h3> + +<p>这两种算法从名字上就可以知道前者是针对只有一个分片键,后者是针对有多个分片键的。单分片键算法是多分片键算法的一种简便形式,所以完全可以使用多分片算法去替代单分片键算法。下面两种形式是等价的</p> + +<pre><code class="language-java">new TableShardingStrategy(&quot;order_id&quot;, new SingleKeyShardingAlgorithm())) +new TableShardingStrategy(Arrays.asList(&quot;order_id&quot;), new MultiKeyShardingAlgorithm())) +</code></pre> + +<p>同时在算法内部,<code>doSharding</code>等方法的<code>shardingValue</code>入参根据使用算法类型不同而不同 +单分片键算法,方法签名</p> + +<pre><code class="language-java">public String doEqualSharding(final Collection&lt;String&gt; dataSourceNames, final ShardingValue&lt;Integer&gt; shardingValue) +</code></pre> + +<p>多分片键算法,方法签名</p> + +<pre><code class="language-java">public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) +</code></pre> + +<h3 id="分片键算法类型:74c632aa9613b8dd6b95bfab1ba313e2">分片键算法类型</h3> + +<p>根据数据源策略与表策略、单分片与多分片,这两种组合,一共产生了4种可供实现的分片算法的接口</p> + +<ul> +<li>单分片键数据源分片算法<code>SingleKeyDatabaseShardingAlgorithm</code></li> +<li>单分片表分片算法<code>SingleKeyTableShardingAlgorithm</code></li> +<li>多分片键数据源分片算法<code>MultipleKeyDatabaseShardingAlgorithm</code></li> +<li>多分片表分片算法<code>MultipleKeyTableShardingAlgorithm</code></li> +</ul> + +<h3 id="单分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">单分片键算法</h3> + +<p>单分片键算法需要实现三个方法,下面以”单分片键数据源分片算法“举例</p> + +<pre><code class="language-java">@Override +public String doEqualSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) + +@Override +public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) + +@Override +public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; availableTargetNames, final ShardingValue&lt;Integer&gt; shardingValue) +</code></pre> + +<p>这三种算法作用如下 +- <code>doEqualSharding</code>在WHERE使用<code>=</code>作为条件分片键。算法中使用<code>shardingValue.getValue()</code>获取等<code>=</code>后的值 +- <code>doInSharding</code>在WHERE使用<code>IN</code>作为条件分片键。算法中使用<code>shardingValue.getValues()</code>获取<code>IN</code>后的值 +- <code>doBetweenSharding</code>在WHERE使用<code>BETWEEN</code>作为条件分片键。算法中使用<code>shardingValue.getValueRange()</code>获取<code>BETWEEN</code>后的值</p> + +<p>下面是一个余2的算法的例子,当分片键的值除以2余数就是实际表的结尾。注意注释中提供了一些算法生成SQL的结果,参数<code>tableNames</code>集合中有两个参数<code>t_order_0</code>和<code>t_order_1</code></p> + +<pre><code class="language-java"> public final class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm&lt;Integer&gt; { + + /** + * select * from t_order from t_order where order_id = 11 + * └── SELECT * FROM t_order_1 WHERE order_id = 11 + * select * from t_order from t_order where order_id = 44 + * └── SELECT * FROM t_order_0 WHERE order_id = 44 + */ + public String doEqualSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + for (String each : tableNames) { + if (each.endsWith(shardingValue.getValue() % 2 + &quot;&quot;)) { + return each; + } + } + throw new IllegalArgumentException(); + } + + /** + * select * from t_order from t_order where order_id in (11,44) + * ├── SELECT * FROM t_order_0 WHERE order_id IN (11,44) + * └── SELECT * FROM t_order_1 WHERE order_id IN (11,44) + * select * from t_order from t_order where order_id in (11,13,15) + * └── SELECT * FROM t_order_1 WHERE order_id IN (11,13,15) + * select * from t_order from t_order where order_id in (22,24,26) + * └──SELECT * FROM t_order_0 WHERE order_id IN (22,24,26) + */ + public Collection&lt;String&gt; doInSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size()); + for (Integer value : shardingValue.getValues()) { + for (String dataSourceName : tableNames) { + if (dataSourceName.endsWith(value % 2 + &quot;&quot;)) { + result.add(dataSourceName); + } + } + } + return result; + } + + /** + * select * from t_order from t_order where order_id between 10 and 20 + * ├── SELECT * FROM t_order_0 WHERE order_id BETWEEN 10 AND 20 + * └── SELECT * FROM t_order_1 WHERE order_id BETWEEN 10 AND 20 + */ + public Collection&lt;String&gt; doBetweenSharding(final Collection&lt;String&gt; tableNames, final ShardingValue&lt;Integer&gt; shardingValue) { + Collection&lt;String&gt; result = new LinkedHashSet&lt;&gt;(tableNames.size()); + Range&lt;Integer&gt; range = (Range&lt;Integer&gt;) shardingValue.getValueRange(); + for (Integer i = range.lowerEndpoint(); i &lt;= range.upperEndpoint(); i++) { + for (String each : tableNames) { + if (each.endsWith(i % 2 + &quot;&quot;)) { + result.add(each); + } + } + } + return result; + } +} +</code></pre> + +<h3 id="多分片键算法:74c632aa9613b8dd6b95bfab1ba313e2">多分片键算法</h3> + +<p>多分片键试用于使用场景比较复杂,为了能提供更高的灵活性,故只提供实现一个方法。</p> + +<pre><code class="language-java">@Override +public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) +</code></pre> + +<p>算法实现的时候根据<code>shardingValue.getType()</code>来获取条件是<code>=</code>,<code>IN</code>或者<code>BETWEEN</code>。然后根据业务进行灵活的实现。</p> + +<p>如果表的数据分布如下</p> + +<pre><code>db0 + ├── t_order_00 user_id以a偶数 order_id为偶数 + ├── t_order_01 user_id以a偶数 order_id为奇数 + ├── t_order_10 user_id以b奇数 order_id为偶数 + └── t_order_11 user_id以b奇数 order_id为奇数 + +</code></pre> + +<p>算法实现如下:</p> + +<pre><code class="language-java">public final class MultipleKeysModuloTableShardingAlgorithm implements MultipleKeysTableShardingAlgorithm { + + @Override + public Collection&lt;String&gt; doSharding(final Collection&lt;String&gt; availableTargetNames, final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues) { + Set&lt;Integer&gt; orderIdValueSet = getShardingValue(shardingValues, &quot;order_id&quot;); + Set&lt;Integer&gt; userIdValueSet = getShardingValue(shardingValues, &quot;user_id&quot;); + + List&lt;String&gt; result = new ArrayList&lt;&gt;(); + /* + userIdValueSet[10,11] + orderIdValueSet[101,102] =&gt; valueResult[[10,101],[10,102],[11,101],[11,102]] + */ + Set&lt;List&lt;Integer&gt;&gt; valueResult = Sets.cartesianProduct(userIdValueSet, orderIdValueSet); + for (List&lt;Integer&gt; value : valueResult) { + String suffix = Joiner.on(&quot;&quot;).join(value.get(0) % 2, value.get(1) % 2); + for (String tableName : availableTargetNames) { + if (tableName.endsWith(suffix)) { + result.add(tableName); + } + } + + } + return result; + } + + private Set&lt;Integer&gt; getShardingValue(final Collection&lt;ShardingValue&lt;?&gt;&gt; shardingValues, final String shardingKey) { + Set&lt;Integer&gt; valueSet = new HashSet&lt;&gt;(); + ShardingValue&lt;Integer&gt; shardingValue = null; + for (ShardingValue&lt;?&gt; each : shardingValues) { + if (each.getColumnName().equals(shardingKey)) { + shardingValue = (ShardingValue&lt;Integer&gt;) each; + break; + } + } + if (null == shardingValue) { + return valueSet; + } + switch (shardingValue.getType()) { + case SINGLE: + valueSet.add(shardingValue.getValue()); + break; + case LIST: + valueSet.addAll(shardingValue.getValues()); + break; + case RANGE: + for (Integer i = shardingValue.getValueRange().lowerEndpoint(); i &lt;= shardingValue.getValueRange().upperEndpoint(); i++) { + valueSet.add(i); + } + break; + default: + throw new UnsupportedOperationException(); + } + return valueSet; + } +} +</code></pre> + +<h2 id="构造shardingdatasource:74c632aa9613b8dd6b95bfab1ba313e2">构造ShardingDataSource</h2> + +<p>完成规则配置后,我们就可以得到<code>ShardingDataSource</code></p> + +<pre><code class="language-java">new ShardingDataSource(shardingRule); +</code></pre> + +<h2 id="使用shardingdatasource:74c632aa9613b8dd6b95bfab1ba313e2">使用ShardingDataSource</h2> + +<p>通过一个例子来看看如何使用该数据源</p> + +<pre><code class="language-java">String sql = &quot;SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?&quot;; + try ( + Connection conn = dataSource.getConnection(); + PreparedStatement pstmt = conn.prepareStatement(sql); + ) { + pstmt.setInt(1, 10); + pstmt.setInt(2, 1001); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + System.out.println(rs.getInt(1)); + System.out.println(rs.getInt(2)); + System.out.println(rs.getInt(3)); + } + rs.close(); + } +</code></pre> + +<p>该数据源与普通数据源完全相同,你可以通过上例的API形式来使用,也可以将其配置在Spring,Hibernate等框架中使用。</p> + + + + + 详细功能列表 + http://dangdangdotcom.github.io/sharding-jdbc/post/features/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/features/ + + +<h1 id="详细功能列表:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">详细功能列表</h1> + +<h2 id="功能性需求:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">功能性需求</h2> + +<h3 id="分库分表-同时支持分库和分表:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">分库分表:同时支持分库和分表</h3> + +<ol> +<li>分片规则自由定制</li> +<li>支持多分片键</li> +<li>支持通过<code>=</code>,<code>BETWEEN</code>,<code>IN</code>分片</li> +<li>支持<code>Binding Table</code></li> +<li>支持多表笛卡尔积查询</li> +<li>支持多表结果归并</li> +<li>支持聚合查询结果归并</li> +<li>支持<code>AVG</code>函数改写为<code>SUM/COUNT</code></li> +<li>支持<code>Order By</code>结果归并</li> +<li>支持<code>Group By</code>结果归并</li> +<li>支持<code>LIMIT</code>分页查询以及多库表结果改写及归并</li> +<li>支持<code>OR</code>查询</li> +</ol> + +<h2 id="易用性:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">易用性</h2> + +<ol> +<li><p><code>JDBC</code>协议适配</p> + +<p>1.1. 全<code>ORM</code>支持</p> + +<p>1.2. 全数据库连接池支持</p> + +<p>1.3. 多数据库支持(目前仅<code>MySQL</code>,未来计划支持<code>Oracle</code>,<code>SQLServer</code>和<code>DB2</code>)</p></li> + +<li><p><code>Spring</code>命名空间支持(待开源)</p></li> + +<li><p>基于动态语言的分片策略配置(待开源)</p></li> + +<li><p><code>Metrics</code>统计监控</p></li> +</ol> + +<h2 id="性能:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">性能</h2> + +<ol> +<li>基于<code>Druid</code>的高性能<code>SQL</code>解析</li> +<li>多线程处理结果归并</li> +<li>性能损失率不足<code>10%</code></li> +</ol> + +<h2 id="稳定性:e1ec7fcfd5aa4d3ea3e990d9b707a3b4">稳定性</h2> + +<p>完善的疲劳测试,普通查询无<code>Full GC</code>(<code>Group By</code>除外)</p> + + + + + 架构图 + http://dangdangdotcom.github.io/sharding-jdbc/post/architecture/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/architecture/ + + +<h1 id="架构图:1bf455b3a3c6e1e40be41ef6023b75eb">架构图</h1> + +<p><img src="../../img/architecture.png" alt="整体架构图1" /></p> + +<p><img src="../../img/parse.png" alt="SQL解析" /></p> + +<p><img src="../../img/route.png" alt="SQL路由" /></p> + +<p><img src="../../img/execute.png" alt="SQL执行" /></p> + +<p><img src="../../img/merge.png" alt="结果归并" /></p> + + + + + 目录结构说明 + http://dangdangdotcom.github.io/sharding-jdbc/post/directory_structure/ + Thu, 28 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/directory_structure/ + + +<h1 id="目录结构说明:b4b5a29fe5be663d2644d30f96759d37">目录结构说明</h1> + +<h2 id="sharding-jdbc-core:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-core</h2> + +<p><code>sharding-jdbc</code>分库分表核心模块。</p> + +<h2 id="sharding-jdbc-spring-待开源:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-spring(待开源)</h2> + +<p><code>sharding-jdbc</code>对<code>spring</code>支持的模块,包括命名空间等。</p> + +<h2 id="sharding-jdbc-config-待开源:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-config(待开源)</h2> + +<p><code>sharding-jdbc</code>动态分片规则配置模块。</p> + +<h2 id="sharding-jdbc-example:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-example</h2> + +<p>使用示例。有<code>sharding-jdbc-example-jdbc</code>,<code>sharding-jdbc-example-jpa</code>和<code>sharding-jdbc-example-mybatis</code>3个子项目。</p> + +<h2 id="sharding-jdbc-doc:b4b5a29fe5be663d2644d30f96759d37">sharding-jdbc-doc</h2> + +<p>使用<code>markdown</code>生成文档的项目,使用方无需关注。</p> + + + + + 使用限制 + http://dangdangdotcom.github.io/sharding-jdbc/post/limitations/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/limitations/ + + +<h1 id="使用限制:187f2cad6c4cc3b3972d4d058186f234">使用限制</h1> + +<h2 id="jdbc-未支持列表:187f2cad6c4cc3b3972d4d058186f234"><code>JDBC</code>未支持列表</h2> + +<p><code>Sharding-JDBC</code>暂时未支持不常用的<code>JDBC</code>方法。</p> + +<h3 id="datasource-接口:187f2cad6c4cc3b3972d4d058186f234"><code>DataSource</code>接口</h3> + +<ul> +<li>不支持<code>timeout</code>相关操作</li> +</ul> + +<h3 id="connection-接口:187f2cad6c4cc3b3972d4d058186f234"><code>Connection</code>接口</h3> + +<ul> +<li>不支持存储过程,函数,游标的操作</li> +<li>不支持执行<code>native</code>的<code>SQL</code></li> +<li>不支持<code>savepoint</code>相关操作</li> +<li>不支持<code>Schema/Catalog</code>的操作</li> +<li>不支持自定义类型映射</li> +</ul> + +<h3 id="statement-和-preparedstatement-接口:187f2cad6c4cc3b3972d4d058186f234"><code>Statement</code>和<code>PreparedStatement</code>接口</h3> + +<ul> +<li>不支持返回多结果集的语句(即存储过程,非<code>SELECT</code>多条数据)</li> +<li>不支持国际化字符的操作</li> +</ul> + +<h3 id="对于-resultset-接口:187f2cad6c4cc3b3972d4d058186f234">对于<code>ResultSet</code>接口</h3> + +<ul> +<li>不支持对于结果集指针位置判断</li> +<li>不支持通过非next方法改变结果指针位置</li> +<li>不支持修改结果集内容</li> +<li>不支持获取国际化字符</li> +<li>不支持获取<code>Array</code></li> +</ul> + +<h3 id="jdbc-4-1:187f2cad6c4cc3b3972d4d058186f234">JDBC 4.1</h3> + +<ul> +<li>不支持JDBC 4.1接口新功能</li> +</ul> + +<p>查询所有未支持方法,请阅读<code>com.dangdang.ddframe.rdb.sharding.jdbc.unsupported</code>包。</p> + +<h2 id="sql语句限制:187f2cad6c4cc3b3972d4d058186f234">SQL语句限制</h2> + +<h3 id="不支持ddl语句:187f2cad6c4cc3b3972d4d058186f234">不支持DDL语句</h3> + +<h3 id="不支持子语句:187f2cad6c4cc3b3972d4d058186f234">不支持子语句</h3> + +<h3 id="不支持-union-和-union-all:187f2cad6c4cc3b3972d4d058186f234">不支持<code>UNION</code> 和 <code>UNION ALL</code></h3> + +<h3 id="不支持特殊-insert:187f2cad6c4cc3b3972d4d058186f234">不支持特殊<code>INSERT</code></h3> + +<p>每条<code>INSERT</code>语句只能插入一条数据,不支持<code>VALUES</code>后有多行数据的语句</p> + +<h3 id="不支持-distinct-聚合:187f2cad6c4cc3b3972d4d058186f234">不支持<code>DISTINCT</code>聚合</h3> + +<h3 id="对于-谨慎使用:187f2cad6c4cc3b3972d4d058186f234">对于<code>*</code>谨慎使用</h3> + +<p>一般情况下<code>SELECT</code>语句中是可以使用<code>*</code>的,如下的<code>SQL</code>可以正常在<code>Sharding-JDBC</code>中使用。</p> + +<pre><code class="language-sql">select * from order; +</code></pre> + +<p>但以下几种SQL不允许使用<code>*</code></p> + +<ul> +<li>语句中存在聚合函数<code>AVG</code></li> +<li><code>GROUP BY</code>语句</li> +<li><code>ORDER BY</code>语句</li> +</ul> + + + + + 压力测试报告 + http://dangdangdotcom.github.io/sharding-jdbc/post/stress_test/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/stress_test/ + + +<h1 id="压力测试报告:da68abc810593941936aaba3d62b3b96">压力测试报告</h1> + +<h2 id="测试目的:da68abc810593941936aaba3d62b3b96">测试目的</h2> + +<p>对<code>Sharding-JDBC</code>进行性能测试,客观、公正评估系统的性能,目的有三:</p> + +<ol> +<li>对比<code>Sharding-JDBC</code>和<code>JDBC</code>的性能。</li> +<li><code>Sharding-JDBC</code>是否通过扩展数据库解决<code>JDBC</code>吞吐量不足的问题。</li> +<li><code>Sharding-JDBC</code>的稳定性。</li> +</ol> + +<h2 id="测试数据库配置:da68abc810593941936aaba3d62b3b96">测试数据库配置</h2> + +<table> +<thead> +<tr> +<th>数据库实例</th> +<th align="center">DB1</th> +<th align="center">DB2</th> +</tr> +</thead> + +<tbody> +<tr> +<td>操作系统</td> +<td align="center">centOS5.4</td> +<td align="center">centOS5.4</td> +</tr> + +<tr> +<td>CPU</td> +<td align="center">2C四核</td> +<td align="center">2C四核</td> +</tr> + +<tr> +<td>内存</td> +<td align="center">32GB</td> +<td align="center">32GB</td> +</tr> + +<tr> +<td>硬盘</td> +<td align="center">250G*2_RAID1+600G*4_RAID10</td> +<td align="center">250G*2_RAID1+600G*4_RAID10</td> +</tr> + +<tr> +<td>Mysql版本</td> +<td align="center">5.5.19</td> +<td align="center">5.5.19</td> +</tr> + +<tr> +<td>数据表字段数量</td> +<td align="center">70</td> +<td align="center">70</td> +</tr> + +<tr> +<td>数据表行数</td> +<td align="center">1000万</td> +<td align="center">1000万</td> +</tr> +</tbody> +</table> + +<h2 id="网络拓扑:da68abc810593941936aaba3d62b3b96">网络拓扑</h2> + +<p><img src="img/stress_test_arch.png" alt="网络拓扑图" /></p> + +<h2 id="单库情况下sharding-jdbc与jdbc性能对比:da68abc810593941936aaba3d62b3b96">单库情况下Sharding-JDBC与JDBC性能对比</h2> + +<p>测试结论:</p> + +<ul> +<li>查询操作,Sharding-JDBC的TPS为JDBC的TPS的99.8%</li> +<li>插入操作,Sharding-JDBC的TPS为JDBC的TPS的90.2%</li> +<li>更新操作,Sharding-JDBC的TPS为JDBC的TPS的93.1%</li> +</ul> + +<h3 id="查询:da68abc810593941936aaba3d62b3b96">查询</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareQuery" width="400" height="150"></canvas> + +<h3 id="插入:da68abc810593941936aaba3d62b3b96">插入</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareInsert" width="400" height="150"></canvas> + +<h3 id="更新:da68abc810593941936aaba3d62b3b96">更新</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="compareUpdate" width="400" height="150"></canvas> + +<h2 id="sharding-jdbc单库与双库性能对比:da68abc810593941936aaba3d62b3b96">Sharding-JDBC单库与双库性能对比</h2> + +<p>对比测试:</p> + +<ul> +<li>单库用例中所有数据全部在DB1中</li> +<li>双库用例中所有数据均匀分布在DB1与DB2中</li> +</ul> + +<p>结论:</p> + +<ul> +<li>查询操作,TPS双库比单库可以增加大约94%的性能</li> +<li>插入操作,TPS双库比单库可以增加大约60%的性能</li> +<li>更新操作,TPS双库比单库可以增加大约89%的性能</li> +</ul> + +<h3 id="查询-1:da68abc810593941936aaba3d62b3b96">查询</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleQuery" width="400" height="150"></canvas> + +<h3 id="插入-1:da68abc810593941936aaba3d62b3b96">插入</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleInsert" width="400" height="150"></canvas> + +<h3 id="更新-1:da68abc810593941936aaba3d62b3b96">更新</h3> + +<ul> +<li>横坐标:并发用户数</li> +<li>纵坐标:TPS</li> +</ul> + +<canvas id="singleAndDubbleUpdate" width="400" height="150"></canvas> + +<h2 id="sharding-jdbc疲劳测试:da68abc810593941936aaba3d62b3b96">Sharding-JDBC疲劳测试</h2> + +<p>经过8个小时的疲劳测试,jvm的堆大约占用不到600MB的内存,且使用量比较稳定。没有发生fullgc。 +<canvas id="fatigueTest" width="400" height="150"></canvas></p> + + + + + 未来线路规划 + http://dangdangdotcom.github.io/sharding-jdbc/post/roadmap/ + Fri, 08 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/roadmap/ + + +<h1 id="未来线路规划:cd4a1b36ed2b93cfc52abf77a7d25d03">未来线路规划</h1> + +<ol> +<li>读写分离</li> +<li>柔性分布式事务</li> +<li>分布式主键生成策略</li> +<li>SQL重写优化,进一步提升性能</li> +<li>SQL Hint,可指定某SQL在某具体库表执行,基于业务规则而非SQL解析路由</li> +<li>小表广播</li> +<li>HA相关</li> +<li>流量控制</li> +<li>数据库建表工具</li> +<li>数据迁移</li> +<li>复杂SQL解析支持,如子查询,存储过程等</li> +<li>Oracle, SQLServer,DB2支持</li> +<li>配置中心</li> +</ol> + + + + + 事务支持说明 + http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/ + Fri, 29 Jan 2016 16:14:21 +0800 + + http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/ + + +<h1 id="事务支持说明:2e47673b0e2fecf4f97d6b00d496cdc9">事务支持说明</h1> + +<p><code>Sharding-JDBC</code>目前不支持分布式事务。我们已明确规划roadmap,在未来的一两个版本中会支持最终一致性的柔性事务。</p> + +<p>基于目前状况的事务,有以下几点说明:</p> + +<ul> +<li><p>完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。</p></li> + +<li><p>完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。</p></li> + +<li><p>不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库死机,则只有第二个库数据提交。</p></li> +</ul> + + + + + \ No newline at end of file diff --git a/sharding-jdbc-doc/public/post/limitations/index.html b/sharding-jdbc-doc/public/post/limitations/index.html new file mode 100644 index 0000000000000..455414ee3fece --- /dev/null +++ b/sharding-jdbc-doc/public/post/limitations/index.html @@ -0,0 +1,248 @@ + + + + + + + + + 使用限制 + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

使用限制

+ +

JDBC未支持列表

+ +

Sharding-JDBC暂时未支持不常用的JDBC方法。

+ +

DataSource接口

+ +
    +
  • 不支持timeout相关操作
  • +
+ +

Connection接口

+ +
    +
  • 不支持存储过程,函数,游标的操作
  • +
  • 不支持执行nativeSQL
  • +
  • 不支持savepoint相关操作
  • +
  • 不支持Schema/Catalog的操作
  • +
  • 不支持自定义类型映射
  • +
+ +

StatementPreparedStatement接口

+ +
    +
  • 不支持返回多结果集的语句(即存储过程,非SELECT多条数据)
  • +
  • 不支持国际化字符的操作
  • +
+ +

对于ResultSet接口

+ +
    +
  • 不支持对于结果集指针位置判断
  • +
  • 不支持通过非next方法改变结果指针位置
  • +
  • 不支持修改结果集内容
  • +
  • 不支持获取国际化字符
  • +
  • 不支持获取Array
  • +
+ +

JDBC 4.1

+ +
    +
  • 不支持JDBC 4.1接口新功能
  • +
+ +

查询所有未支持方法,请阅读com.dangdang.ddframe.rdb.sharding.jdbc.unsupported包。

+ +

SQL语句限制

+ +

不支持DDL语句

+ +

不支持子语句

+ +

不支持UNIONUNION ALL

+ +

不支持特殊INSERT

+ +

每条INSERT语句只能插入一条数据,不支持VALUES后有多行数据的语句

+ +

不支持DISTINCT聚合

+ +

对于*谨慎使用

+ +

一般情况下SELECT语句中是可以使用*的,如下的SQL可以正常在Sharding-JDBC中使用。

+ +
select * from order;
+
+ +

但以下几种SQL不允许使用*

+ +
    +
  • 语句中存在聚合函数AVG
  • +
  • GROUP BY语句
  • +
  • ORDER BY语句
  • +
+ +
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/roadmap/index.html b/sharding-jdbc-doc/public/post/roadmap/index.html new file mode 100644 index 0000000000000..e8e1253cc9136 --- /dev/null +++ b/sharding-jdbc-doc/public/post/roadmap/index.html @@ -0,0 +1,171 @@ + + + + + + + + + 未来线路规划 + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

未来线路规划

+ +
    +
  1. 读写分离
  2. +
  3. 柔性分布式事务
  4. +
  5. 分布式主键生成策略
  6. +
  7. SQL重写优化,进一步提升性能
  8. +
  9. SQL Hint,可指定某SQL在某具体库表执行,基于业务规则而非SQL解析路由
  10. +
  11. 小表广播
  12. +
  13. HA相关
  14. +
  15. 流量控制
  16. +
  17. 数据库建表工具
  18. +
  19. 数据迁移
  20. +
  21. 复杂SQL解析支持,如子查询,存储过程等
  22. +
  23. Oracle, SQLServer,DB2支持
  24. +
  25. 配置中心
  26. +
+ +
+
+ +
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/stress_test/index.html b/sharding-jdbc-doc/public/post/stress_test/index.html new file mode 100644 index 0000000000000..5486e4fd2535a --- /dev/null +++ b/sharding-jdbc-doc/public/post/stress_test/index.html @@ -0,0 +1,346 @@ + + + + + + + + + 压力测试报告 + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

压力测试报告

+ +

测试目的

+ +

Sharding-JDBC进行性能测试,客观、公正评估系统的性能,目的有三:

+ +
    +
  1. 对比Sharding-JDBCJDBC的性能。
  2. +
  3. Sharding-JDBC是否通过扩展数据库解决JDBC吞吐量不足的问题。
  4. +
  5. Sharding-JDBC的稳定性。
  6. +
+ +

测试数据库配置

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
数据库实例DB1DB2
操作系统centOS5.4centOS5.4
CPU2C四核2C四核
内存32GB32GB
硬盘250G*2_RAID1+600G*4_RAID10250G*2_RAID1+600G*4_RAID10
Mysql版本5.5.195.5.19
数据表字段数量7070
数据表行数1000万1000万
+ +

网络拓扑

+ +

网络拓扑图

+ +

单库情况下Sharding-JDBC与JDBC性能对比

+ +

测试结论:

+ +
    +
  • 查询操作,Sharding-JDBC的TPS为JDBC的TPS的99.8%
  • +
  • 插入操作,Sharding-JDBC的TPS为JDBC的TPS的90.2%
  • +
  • 更新操作,Sharding-JDBC的TPS为JDBC的TPS的93.1%
  • +
+ +

查询

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

插入

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

更新

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

Sharding-JDBC单库与双库性能对比

+ +

对比测试:

+ +
    +
  • 单库用例中所有数据全部在DB1中
  • +
  • 双库用例中所有数据均匀分布在DB1与DB2中
  • +
+ +

结论:

+ +
    +
  • 查询操作,TPS双库比单库可以增加大约94%的性能
  • +
  • 插入操作,TPS双库比单库可以增加大约60%的性能
  • +
  • 更新操作,TPS双库比单库可以增加大约89%的性能
  • +
+ +

查询

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

插入

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

更新

+ +
    +
  • 横坐标:并发用户数
  • +
  • 纵坐标:TPS
  • +
+ + + +

Sharding-JDBC疲劳测试

+ +

经过8个小时的疲劳测试,jvm的堆大约占用不到600MB的内存,且使用量比较稳定。没有发生fullgc。 +

+ +
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/transaction/index.html b/sharding-jdbc-doc/public/post/transaction/index.html new file mode 100644 index 0000000000000..5100e2c1d4928 --- /dev/null +++ b/sharding-jdbc-doc/public/post/transaction/index.html @@ -0,0 +1,167 @@ + + + + + + + + + 事务支持说明 + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

事务支持说明

+ +

Sharding-JDBC目前不支持分布式事务。我们已明确规划roadmap,在未来的一两个版本中会支持最终一致性的柔性事务。

+ +

基于目前状况的事务,有以下几点说明:

+ +
    +
  • 完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。

  • + +
  • 完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。

  • + +
  • 不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库死机,则只有第二个库数据提交。

  • +
+ +
+
+ +
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/post/user_guide/index.html b/sharding-jdbc-doc/public/post/user_guide/index.html new file mode 100644 index 0000000000000..41886a2393cf4 --- /dev/null +++ b/sharding-jdbc-doc/public/post/user_guide/index.html @@ -0,0 +1,603 @@ + + + + + + + + + 使用指南 + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ +
+ + +

使用指南

+ +

阅读本指南前,请先阅读快速起步。本文档使用更复杂的场景进一步介绍Sharding-JDBC的分库分表能力。

+ +

数据库模式

+ +

本文档中提供了两个数据源db0db1,每个数据源之中包含了两组表t_order_0t_order_1t_order_item_0t_order_item_1。这两组表的建表语句为:

+ +
CREATE TABLE IF NOT EXISTS `t_order_x` (
+  `order_id` INT NOT NULL,
+  `user_id`  INT NOT NULL,
+  PRIMARY KEY (`order_id`)
+);
+CREATE TABLE IF NOT EXISTS `t_order_item_x` (
+  `item_id`  INT NOT NULL,
+  `order_id` INT NOT NULL,
+  `user_id`  INT NOT NULL,
+  PRIMARY KEY (`item_id`)
+);
+
+ +

逻辑表与实际表映射关系

+ +

均匀分布

+ +

数据表在每个数据源内呈现均匀分布的态势

+ +
db0
+  ├── t_order_0 
+  └── t_order_1 
+db1
+  ├── t_order_0 
+  └── t_order_1
+
+ +

表规则可以使用默认的配置

+ +
 TableRule orderTableRule = new TableRule("t_order", Arrays.asList("t_order_0", "t_order_1"), dataSourceRule);
+
+ +

自定义分布

+ +

数据表呈现有特定规则的分布

+ +
db0
+  ├── t_order_0 
+  └── t_order_1 
+db1
+  ├── t_order_2
+  ├── t_order_3
+  └── t_order_4
+
+ +

表规则可以指定每张表在数据源中的分布情况

+ +
 TableRule orderTableRule = new TableRule("t_order", Arrays.asList("db0.t_order_0", "db0.t_order_1", "db1.t_order_2", "db1.t_order_3", "db1.t_order_4"), dataSourceRule);
+
+ +

本教程采用的数据分布例子

+ +
db0
+  ├── t_order_0               user_id为偶数   order_id为偶数
+  ├── t_order_1               user_id为偶数   order_id为奇数
+  ├── t_order_item_0          user_id为偶数   order_id为偶数
+  └── t_order_item_1          user_id为偶数   order_id为奇数
+db1
+  ├── t_order_0               user_id为奇数   order_id为偶数
+  ├── t_order_1               user_id为奇数   order_id为奇数
+  ├── t_order_item_0          user_id为奇数   order_id为偶数
+  └── t_order_item_1          user_id为奇数   order_id为奇数
+
+ +

逻辑表与实际表

+ +

配置分库分表的目的是将原有一张表的数据分散到不同库不同表中,且不改变原有SQL语句的情况下来使用这一张表。那么从一张表到多张的映射关系需要使用逻辑表与实际表这两种概念。下面通过一个例子来解释一下。假设在使用PreparedStatement访问数据库,SQL如下:

+ +
select * from t_order where user_id = ? and order_id = ?;
+
+ +

user_id=0order=0时,Sharding-JDBC将会将SQL语句转换为如下形式:

+ +
select * from db0.t_order_0 where user_id = ? and order_id = ?;
+
+ +

其中原始SQL中的t_order就是 逻辑表,而转换后的db0.t_order_0就是 实际表

+ +

规则配置

+ +

以上分库分表的形式Sharding-JDBC是通过规则配置来进行的描述的,下面讲通过几个小节来描述规则的详细配置:

+ +
 ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule),
+                Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))),
+                new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
+                new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()));
+
+ +

数据源配置

+ +

首先我们来构造DataSourceRule对象,它是来描述数据源的分布规则的。

+ +
 DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);
+
+ +

这里构造器需要一个入参:数据源名称与真实数据源之间的映射关系,这个关系的构造方法如下

+ +
Map<String, DataSource> dataSourceMap = new HashMap<>(2);
+dataSourceMap.put("ds_0", createDataSource("ds_0"));
+dataSourceMap.put("ds_1", createDataSource("ds_1"));
+
+ +

真实的数据源可以使用任意一种数据库连接池,这里使用DBCP来举例

+ +
private static DataSource createDataSource(final String dataSourceName) {
+    BasicDataSource result = new BasicDataSource();
+    result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
+    result.setUrl(String.format("jdbc:mysql://localhost:3306/%s", dataSourceName));
+    result.setUsername("root");
+    result.setPassword("");
+    return result;
+}
+
+ +

策略配置

+ +

数据源策略与表策略

+ +

策略类图 +Sharding-JDBC认为对于分片策略存有两种维度 +- 数据源分片策略DatabaseShardingStrategy:数据被分配的目标数据源 +- 表分片策略TableShardingStrategy:数据被分配的目标表,该目标表存在与该数据的目标数据源内。故表分片策略是依赖与数据源分片策略的结果的 +这里注意的是两种策略的API完全相同,以下针对策略API的讲解将适用于这两种策略

+ +

全局默认策略与特定表策略

+ +

策略是作用在特定的表规则上的,数据源策略与表策略与特定表相关

+ +
TableRule orderTableRule = new TableRule("t_order", Arrays.asList("t_order_0", "t_order_1"),
+                  new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
+                  new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()),
+                  dataSourceRule);
+
+ +

如果分片规则中的所有表或大部分表的分片策略相同,可以使用默认策略来简化配置。一下两种配置是等价的

+ +
  //使用了默认策略配置
+  TableRule orderTableRule = new TableRule("t_order", Arrays.asList("t_order_0", "t_order_1"), dataSourceRule);
+  TableRule orderItemTableRule = new TableRule("t_order_item", Arrays.asList("t_order_item_0", "t_order_item_1"), dataSourceRule);
+  ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule),
+                Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))),
+                new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
+                new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()));
+
+ +
  //未使用默认策略配置
+  TableRule orderTableRule = new TableRule("t_order", Arrays.asList("t_order_0", "t_order_1"), dataSourceRule,
+          new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
+          new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()));
+  TableRule orderItemTableRule = new TableRule("t_order_item", Arrays.asList("t_order_item_0", "t_order_item_1"), dataSourceRule,
+          new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
+          new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()));
+  ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule),
+          Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))));
+
+ +

分片键

+ +

分片键是分片策略的第一个参数。分片键表示的是SQL语句中WHERE中的条件列。分片键可以配置多个

+ +
    +
  • 单分片策略
  • +
+ +
new TableShardingStrategy("order_id", new SingleKeyShardingAlgorithm()))
+
+ +
    +
  • 多分片策略
  • +
+ +
new TableShardingStrategy(Arrays.asList("order_id","order_type", "order_date"), new MultiKeyShardingAlgorithm()))
+
+ +

分片算法

+ +

分片算法接口类图关系如下:

+ +

算法

+ +

绑定表

+ +

绑定表代表一组表,这组表的逻辑表与实际表之间的映射关系是相同的。比如t_ordert_order_item就是这样一组绑定表关系,它们的分库与分表策略是完全相同的,那么可以使用它们的表规则将它们配置成绑定表

+ +
new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))
+
+ +

那么在进行SQL路由时,如果SQL为

+ +
SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?
+
+ +

其中t_order在FROM的最左侧,Sharding-JDBC将会以它作为整个绑定表的主表。所有路由计算将会只使用主表的策略,那么t_order_item表的分片计算将会使用t_order的条件。故绑定表之间的分区键要完全相同。

+ +

分片算法详解

+ +

单分片键算法与多分片键算法

+ +

这两种算法从名字上就可以知道前者是针对只有一个分片键,后者是针对有多个分片键的。单分片键算法是多分片键算法的一种简便形式,所以完全可以使用多分片算法去替代单分片键算法。下面两种形式是等价的

+ +
new TableShardingStrategy("order_id", new SingleKeyShardingAlgorithm()))
+new TableShardingStrategy(Arrays.asList("order_id"), new MultiKeyShardingAlgorithm()))
+
+ +

同时在算法内部,doSharding等方法的shardingValue入参根据使用算法类型不同而不同 +单分片键算法,方法签名

+ +
public String doEqualSharding(final Collection<String> dataSourceNames, final ShardingValue<Integer> shardingValue) 
+
+ +

多分片键算法,方法签名

+ +
public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue<?>> shardingValues)
+
+ +

分片键算法类型

+ +

根据数据源策略与表策略、单分片与多分片,这两种组合,一共产生了4种可供实现的分片算法的接口

+ +
    +
  • 单分片键数据源分片算法SingleKeyDatabaseShardingAlgorithm
  • +
  • 单分片表分片算法SingleKeyTableShardingAlgorithm
  • +
  • 多分片键数据源分片算法MultipleKeyDatabaseShardingAlgorithm
  • +
  • 多分片表分片算法MultipleKeyTableShardingAlgorithm
  • +
+ +

单分片键算法

+ +

单分片键算法需要实现三个方法,下面以”单分片键数据源分片算法“举例

+ +
@Override
+public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue)
+
+@Override
+public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue)
+
+@Override
+public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue)
+
+ +

这三种算法作用如下 +- doEqualSharding在WHERE使用=作为条件分片键。算法中使用shardingValue.getValue()获取等=后的值 +- doInSharding在WHERE使用IN作为条件分片键。算法中使用shardingValue.getValues()获取IN后的值 +- doBetweenSharding在WHERE使用BETWEEN作为条件分片键。算法中使用shardingValue.getValueRange()获取BETWEEN后的值

+ +

下面是一个余2的算法的例子,当分片键的值除以2余数就是实际表的结尾。注意注释中提供了一些算法生成SQL的结果,参数tableNames集合中有两个参数t_order_0t_order_1

+ +
 public final class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer> {
+    
+    /**
+    *  select * from t_order from t_order where order_id = 11 
+    *          └── SELECT *  FROM t_order_1 WHERE order_id = 11
+    *  select * from t_order from t_order where order_id = 44
+    *          └── SELECT *  FROM t_order_0 WHERE order_id = 44
+    */
+    public String doEqualSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
+        for (String each : tableNames) {
+            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
+                return each;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    /**
+    *  select * from t_order from t_order where order_id in (11,44)  
+    *          ├── SELECT *  FROM t_order_0 WHERE order_id IN (11,44) 
+    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,44) 
+    *  select * from t_order from t_order where order_id in (11,13,15)  
+    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,13,15)  
+    *  select * from t_order from t_order where order_id in (22,24,26)  
+    *          └──SELECT *  FROM t_order_0 WHERE order_id IN (22,24,26) 
+    */
+    public Collection<String> doInSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
+        Collection<String> result = new LinkedHashSet<>(tableNames.size());
+        for (Integer value : shardingValue.getValues()) {
+            for (String dataSourceName : tableNames) {
+                if (dataSourceName.endsWith(value % 2 + "")) {
+                    result.add(dataSourceName);
+                }
+            }
+        }
+        return result;
+    }
+    
+    /**
+    *  select * from t_order from t_order where order_id between 10 and 20 
+    *          ├── SELECT *  FROM t_order_0 WHERE order_id BETWEEN 10 AND 20 
+    *          └── SELECT *  FROM t_order_1 WHERE order_id BETWEEN 10 AND 20 
+    */
+    public Collection<String> doBetweenSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
+        Collection<String> result = new LinkedHashSet<>(tableNames.size());
+        Range<Integer> range = (Range<Integer>) shardingValue.getValueRange();
+        for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
+            for (String each : tableNames) {
+                if (each.endsWith(i % 2 + "")) {
+                    result.add(each);
+                }
+            }
+        }
+        return result;
+    }
+}
+
+ +

多分片键算法

+ +

多分片键试用于使用场景比较复杂,为了能提供更高的灵活性,故只提供实现一个方法。

+ +
@Override
+public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue<?>> shardingValues)
+
+ +

算法实现的时候根据shardingValue.getType()来获取条件是=IN或者BETWEEN。然后根据业务进行灵活的实现。

+ +

如果表的数据分布如下

+ +
db0
+  ├── t_order_00               user_id以a偶数   order_id为偶数
+  ├── t_order_01               user_id以a偶数   order_id为奇数
+  ├── t_order_10               user_id以b奇数   order_id为偶数
+  └── t_order_11               user_id以b奇数   order_id为奇数
+
+
+ +

算法实现如下:

+ +
public final class MultipleKeysModuloTableShardingAlgorithm implements MultipleKeysTableShardingAlgorithm {
+    
+    @Override
+    public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue<?>> shardingValues) {
+        Set<Integer> orderIdValueSet = getShardingValue(shardingValues, "order_id");
+        Set<Integer> userIdValueSet = getShardingValue(shardingValues, "user_id");
+    
+        List<String> result = new ArrayList<>();
+        /*
+        userIdValueSet[10,11] + orderIdValueSet[101,102] => valueResult[[10,101],[10,102],[11,101],[11,102]]
+         */
+        Set<List<Integer>> valueResult = Sets.cartesianProduct(userIdValueSet, orderIdValueSet);
+        for (List<Integer> value : valueResult) {
+            String suffix = Joiner.on("").join(value.get(0) % 2, value.get(1) % 2);
+            for (String tableName : availableTargetNames) {
+                if (tableName.endsWith(suffix)) {
+                    result.add(tableName);
+                }
+            }
+        
+        }
+        return result;
+    }
+    
+    private Set<Integer> getShardingValue(final Collection<ShardingValue<?>> shardingValues, final String shardingKey) {
+        Set<Integer> valueSet = new HashSet<>();
+        ShardingValue<Integer> shardingValue = null;
+        for (ShardingValue<?> each : shardingValues) {
+            if (each.getColumnName().equals(shardingKey)) {
+                shardingValue = (ShardingValue<Integer>) each;
+                break;
+            }
+        }
+        if (null == shardingValue) {
+            return valueSet;
+        }
+        switch (shardingValue.getType()) {
+            case SINGLE:
+                valueSet.add(shardingValue.getValue());
+                break;
+            case LIST:
+                valueSet.addAll(shardingValue.getValues());
+                break;
+            case RANGE:
+                for (Integer i = shardingValue.getValueRange().lowerEndpoint(); i <= shardingValue.getValueRange().upperEndpoint(); i++) {
+                    valueSet.add(i);
+                }
+                break;
+            default:
+                throw new UnsupportedOperationException();
+        }
+        return valueSet;
+    }
+}
+
+ +

构造ShardingDataSource

+ +

完成规则配置后,我们就可以得到ShardingDataSource

+ +
new ShardingDataSource(shardingRule);
+
+ +

使用ShardingDataSource

+ +

通过一个例子来看看如何使用该数据源

+ +
String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement pstmt = conn.prepareStatement(sql);
+                ) {
+            pstmt.setInt(1, 10);
+            pstmt.setInt(2, 1001);
+            ResultSet rs = pstmt.executeQuery();
+            while (rs.next()) {
+                System.out.println(rs.getInt(1));
+                System.out.println(rs.getInt(2));
+                System.out.println(rs.getInt(3));
+            }
+            rs.close();
+        }
+
+ +

该数据源与普通数据源完全相同,你可以通过上例的API形式来使用,也可以将其配置在Spring,Hibernate等框架中使用。

+ +
+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + diff --git a/sharding-jdbc-doc/public/sitemap.xml b/sharding-jdbc-doc/public/sitemap.xml new file mode 100644 index 0000000000000..90492f9124c88 --- /dev/null +++ b/sharding-jdbc-doc/public/sitemap.xml @@ -0,0 +1,53 @@ + + + + + http://dangdangdotcom.github.io/sharding-jdbc/ + 0 + + + + http://dangdangdotcom.github.io/sharding-jdbc/index/ + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/features/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/architecture/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/directory_structure/ + 2016-01-28T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/limitations/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/stress_test/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/roadmap/ + 2016-01-08T16:14:21+08:00 + + + + http://dangdangdotcom.github.io/sharding-jdbc/post/transaction/ + 2016-01-29T16:14:21+08:00 + + + \ No newline at end of file