From 3e9b203a873fa7fa25ca00661e858e53798b4aab Mon Sep 17 00:00:00 2001 From: Alex Bobko Date: Fri, 11 Mar 2016 20:04:45 +0300 Subject: [PATCH] v1.0.0-b --- .gitignore | 2 - dist/css/application.css | 11410 +++++++++++++ dist/css/lib/getmdl-select.min.css | 3 + dist/css/lib/nv.d3.css | 647 + dist/forms.html | 515 + "dist/images/DB_16\321\20516.png" | Bin 0 -> 20532 bytes dist/images/Dark_background_1920x1080.png | Bin 0 -> 54515 bytes dist/images/Icon.png | Bin 0 -> 36988 bytes dist/images/Icon_header.png | Bin 0 -> 35130 bytes dist/images/card.jpg | Bin 0 -> 1799 bytes dist/images/cloudy_and_snow.svg | 26 + dist/images/cotoneaster.jpg | Bin 0 -> 87201 bytes dist/images/imgo.png | Bin 0 -> 1333 bytes dist/images/robot.png | Bin 0 -> 139132 bytes dist/images/skype.svg | 17 + dist/images/tick-mask.svg | 30 + dist/images/tick.svg | 15 + dist/images/tick_dark.svg | 15 + dist/images/watch_white.svg | 5 + dist/images/weather_bck.png | Bin 0 -> 211795 bytes dist/index.html | 530 + dist/js/d3.js | 9554 +++++++++++ dist/js/getmdl-select.min.js | 2 + dist/js/material.js | 3946 +++++ dist/js/nv.d3.js | 13789 ++++++++++++++++ .../js/widgets/employer-form/employer-form.js | 13 + dist/js/widgets/line-chart/line-chart-nvd3.js | 242 + dist/js/widgets/pie-chart/pie-chart-nvd3.js | 93 + dist/js/widgets/table/table.js | 24 + dist/js/widgets/todo/todo.js | 248 + 30 files changed, 41124 insertions(+), 2 deletions(-) create mode 100644 dist/css/application.css create mode 100644 dist/css/lib/getmdl-select.min.css create mode 100644 dist/css/lib/nv.d3.css create mode 100644 dist/forms.html create mode 100644 "dist/images/DB_16\321\20516.png" create mode 100644 dist/images/Dark_background_1920x1080.png create mode 100644 dist/images/Icon.png create mode 100644 dist/images/Icon_header.png create mode 100644 dist/images/card.jpg create mode 100644 dist/images/cloudy_and_snow.svg create mode 100644 dist/images/cotoneaster.jpg create mode 100644 dist/images/imgo.png create mode 100644 dist/images/robot.png create mode 100644 dist/images/skype.svg create mode 100644 dist/images/tick-mask.svg create mode 100644 dist/images/tick.svg create mode 100644 dist/images/tick_dark.svg create mode 100644 dist/images/watch_white.svg create mode 100644 dist/images/weather_bck.png create mode 100644 dist/index.html create mode 100644 dist/js/d3.js create mode 100644 dist/js/getmdl-select.min.js create mode 100644 dist/js/material.js create mode 100644 dist/js/nv.d3.js create mode 100644 dist/js/widgets/employer-form/employer-form.js create mode 100644 dist/js/widgets/line-chart/line-chart-nvd3.js create mode 100644 dist/js/widgets/pie-chart/pie-chart-nvd3.js create mode 100644 dist/js/widgets/table/table.js create mode 100644 dist/js/widgets/todo/todo.js diff --git a/.gitignore b/.gitignore index b8878d9..49ed185 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,6 @@ bower_components src/.sass-cache/ -dist/ - .idea .temp \ No newline at end of file diff --git a/dist/css/application.css b/dist/css/application.css new file mode 100644 index 0000000..e8f9034 --- /dev/null +++ b/dist/css/application.css @@ -0,0 +1,11410 @@ +@charset "UTF-8"; +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* TOOLTIP */ +/* WIDGETS & COMPONENTS */ +/* Trending */ +/* label */ +/* charts */ +/* employer form */ +/* row */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Material Design Lite */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/* + * What follows is the result of much research on cross-browser styling. + * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, + * Kroc Camen, and the H5BP dev community and team. + */ +/* ========================================================================== + Base styles: opinionated defaults + ========================================================================== */ +html { + color: rgba(0,0,0, 0.87); + font-size: 1em; + line-height: 1.4; } + +/* + * Remove text-shadow in selection highlight: + * https://twitter.com/miketaylr/status/12228805301 + * + * These selection rule sets have to be separate. + * Customize the background color to match your design. + */ +::selection { + background: #b3d4fc; + text-shadow: none; } + +/* + * A better looking default horizontal rule + */ +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; + margin: 1em 0; + padding: 0; } + +/* + * Remove the gap between audio, canvas, iframes, + * images, videos and the bottom of their containers: + * https://github.com/h5bp/html5-boilerplate/issues/440 + */ +audio, +canvas, +iframe, +img, +svg, +video { + vertical-align: middle; } + +/* + * Remove default fieldset styles. + */ +fieldset { + border: 0; + margin: 0; + padding: 0; } + +/* + * Allow only vertical resizing of textareas. + */ +textarea { + resize: vertical; } + +/* ========================================================================== + Browser Upgrade Prompt + ========================================================================== */ +.browserupgrade { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; } + +/* ========================================================================== + Author's custom styles + ========================================================================== */ +/* ========================================================================== + Helper classes + ========================================================================== */ +/* + * Hide visually and from screen readers: + */ +.hidden { + display: none !important; } + +/* + * Hide only visually, but have it available for screen readers: + * http://snook.ca/archives/html_and_css/hiding-content-for-accessibility + */ +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +/* + * Extends the .visuallyhidden class to allow the element + * to be focusable when navigated to via the keyboard: + * https://www.drupal.org/node/897638 + */ +.visuallyhidden.focusable:active, +.visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } + +/* + * Hide visually and from screen readers, but maintain layout + */ +.invisible { + visibility: hidden; } + +/* + * Clearfix: contain floats + * + * For modern browsers + * 1. The space content is one way to avoid an Opera bug when the + * `contenteditable` attribute is included anywhere else in the document. + * Otherwise it causes space to appear at the top and bottom of elements + * that receive the `clearfix` class. + * 2. The use of `table` rather than `block` is only necessary if using + * `:before` to contain the top-margins of child elements. + */ +.clearfix:before, +.clearfix:after { + content: " "; + /* 1 */ + display: table; + /* 2 */ } + +.clearfix:after { + clear: both; } + +/* ========================================================================== + EXAMPLE Media Queries for Responsive Design. + These examples override the primary ('mobile first') styles. + Modify as content requires. + ========================================================================== */ +/* ========================================================================== + Print styles. + Inlined to avoid the additional HTTP request: + http://www.phpied.com/delay-loading-your-print-css/ + ========================================================================== */ +@media print { + *, + *:before, + *:after, + *:first-letter, + *:first-line { + background: transparent !important; + color: #000 !important; + /* Black prints faster: http://www.sanbeiji.com/archives/953 */ + box-shadow: none !important; + text-shadow: none !important; } + a, + a:visited { + text-decoration: underline; } + a[href]:after { + content: " (" attr(href) ")"; } + abbr[title]:after { + content: " (" attr(title) ")"; } + /* + * Don't show links that are fragment identifiers, + * or use the `javascript:` pseudo protocol + */ + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; } + /* + * Printing Tables: + * http://css-discuss.incutio.com/wiki/Printing_Tables + */ + 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; } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Remove the unwanted box around FAB buttons */ +/* More info: http://goo.gl/IPwKi */ +a, .mdl-accordion, .mdl-button, .mdl-card, .mdl-checkbox, .mdl-dropdown-menu, +.mdl-icon-toggle, .mdl-item, .mdl-radio, .mdl-slider, .mdl-switch, .mdl-tabs__tab { + -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); } + +/* + * Make html take up the entire screen + * Then set touch-action to avoid touch delay on mobile IE + */ +html { + width: 100%; + height: 100%; + -ms-touch-action: manipulation; + touch-action: manipulation; } + +/* +* Make body take up the entire screen +* Remove body margin so layout containers don't cause extra overflow. +*/ +body { + width: 100%; + min-height: 100%; + margin: 0; } + +/* + * Main display reset for IE support. + * Source: http://weblog.west-wind.com/posts/2015/Jan/12/main-HTML5-Tag-not-working-in-Internet-Explorer-91011 + */ +main { + display: block; } + +/* +* Apply no display to elements with the hidden attribute. +* IE 9 and 10 support. +*/ +*[hidden] { + display: none !important; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +html, body { + font-family: "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 20px; } + +h1, h2, h3, h4, h5, h6, p { + margin: 0; + padding: 0; } + +/** + * Styles for HTML elements + */ +h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 56px; + font-weight: 400; + line-height: 1.35; + letter-spacing: -0.02em; + opacity: 0.54; + font-size: 0.6em; } + +h1 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 56px; + font-weight: 400; + line-height: 1.35; + letter-spacing: -0.02em; + margin-top: 24px; + margin-bottom: 24px; } + +h2 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 45px; + font-weight: 400; + line-height: 48px; + margin-top: 24px; + margin-bottom: 24px; } + +h3 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 34px; + font-weight: 400; + line-height: 40px; + margin-top: 24px; + margin-bottom: 24px; } + +h4 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 24px; + font-weight: 400; + line-height: 32px; + -moz-osx-font-smoothing: grayscale; + margin-top: 24px; + margin-bottom: 16px; } + +h5 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 20px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.02em; + margin-top: 24px; + margin-bottom: 16px; } + +h6 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.04em; + margin-top: 24px; + margin-bottom: 16px; } + +p { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + margin-bottom: 16px; } + +a { + color: rgb(255,64,129); + font-weight: 500; } + +blockquote { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + position: relative; + font-size: 24px; + font-weight: 300; + font-style: italic; + line-height: 1.35; + letter-spacing: 0.08em; } + blockquote:before { + position: absolute; + left: -0.5em; + content: '“'; } + blockquote:after { + content: '”'; + margin-left: -0.05em; } + +mark { + background-color: #f4ff81; } + +dt { + font-weight: 700; } + +address { + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; + font-style: normal; } + +ul, ol { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; } + +/** + * Class Name Styles + */ +.mdl-typography--display-4 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 112px; + font-weight: 300; + line-height: 1; + letter-spacing: -0.04em; } + +.mdl-typography--display-4-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 112px; + font-weight: 300; + line-height: 1; + letter-spacing: -0.04em; + opacity: 0.54; } + +.mdl-typography--display-3 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 56px; + font-weight: 400; + line-height: 1.35; + letter-spacing: -0.02em; } + +.mdl-typography--display-3-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 56px; + font-weight: 400; + line-height: 1.35; + letter-spacing: -0.02em; + opacity: 0.54; } + +.mdl-typography--display-2 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 45px; + font-weight: 400; + line-height: 48px; } + +.mdl-typography--display-2-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 45px; + font-weight: 400; + line-height: 48px; + opacity: 0.54; } + +.mdl-typography--display-1 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 34px; + font-weight: 400; + line-height: 40px; } + +.mdl-typography--display-1-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 34px; + font-weight: 400; + line-height: 40px; + opacity: 0.54; } + +.mdl-typography--headline { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 24px; + font-weight: 400; + line-height: 32px; + -moz-osx-font-smoothing: grayscale; } + +.mdl-typography--headline-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 24px; + font-weight: 400; + line-height: 32px; + -moz-osx-font-smoothing: grayscale; + opacity: 0.87; } + +.mdl-typography--title { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 20px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.02em; } + +.mdl-typography--title-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 20px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.02em; + opacity: 0.87; } + +.mdl-typography--subhead { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.04em; } + +.mdl-typography--subhead-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.04em; + opacity: 0.87; } + +.mdl-typography--body-2 { + font-size: 14px; + font-weight: bold; + line-height: 24px; + letter-spacing: 0; } + +.mdl-typography--body-2-color-contrast { + font-size: 14px; + font-weight: bold; + line-height: 24px; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--body-1 { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; } + +.mdl-typography--body-1-color-contrast { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--body-2-force-preferred-font { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0; } + +.mdl-typography--body-2-force-preferred-font-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--body-1-force-preferred-font { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; } + +.mdl-typography--body-1-force-preferred-font-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--caption { + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; } + +.mdl-typography--caption-force-preferred-font { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; } + +.mdl-typography--caption-color-contrast { + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; + opacity: 0.54; } + +.mdl-typography--caption-force-preferred-font-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; + opacity: 0.54; } + +.mdl-typography--menu { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + line-height: 1; + letter-spacing: 0; } + +.mdl-typography--menu-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + line-height: 1; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--button { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + line-height: 1; + letter-spacing: 0; } + +.mdl-typography--button-color-contrast { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + line-height: 1; + letter-spacing: 0; + opacity: 0.87; } + +.mdl-typography--text-left { + text-align: left; } + +.mdl-typography--text-right { + text-align: right; } + +.mdl-typography--text-center { + text-align: center; } + +.mdl-typography--text-justify { + text-align: justify; } + +.mdl-typography--text-nowrap { + white-space: nowrap; } + +.mdl-typography--text-lowercase { + text-transform: lowercase; } + +.mdl-typography--text-uppercase { + text-transform: uppercase; } + +.mdl-typography--text-capitalize { + text-transform: capitalize; } + +.mdl-typography--font-thin { + font-weight: 200 !important; } + +.mdl-typography--font-light { + font-weight: 300 !important; } + +.mdl-typography--font-regular { + font-weight: 400 !important; } + +.mdl-typography--font-medium { + font-weight: 500 !important; } + +.mdl-typography--font-bold { + font-weight: 700 !important; } + +.mdl-typography--font-black { + font-weight: 900 !important; } + +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + word-wrap: normal; + font-feature-settings: 'liga'; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-color-text--red { + color: rgb(244,67,54) !important; } + +.mdl-color--red { + background-color: rgb(244,67,54) !important; } + +.mdl-color-text--red-50 { + color: rgb(255,235,238) !important; } + +.mdl-color--red-50 { + background-color: rgb(255,235,238) !important; } + +.mdl-color-text--red-100 { + color: rgb(255,205,210) !important; } + +.mdl-color--red-100 { + background-color: rgb(255,205,210) !important; } + +.mdl-color-text--red-200 { + color: rgb(239,154,154) !important; } + +.mdl-color--red-200 { + background-color: rgb(239,154,154) !important; } + +.mdl-color-text--red-300 { + color: rgb(229,115,115) !important; } + +.mdl-color--red-300 { + background-color: rgb(229,115,115) !important; } + +.mdl-color-text--red-400 { + color: rgb(239,83,80) !important; } + +.mdl-color--red-400 { + background-color: rgb(239,83,80) !important; } + +.mdl-color-text--red-500 { + color: rgb(244,67,54) !important; } + +.mdl-color--red-500 { + background-color: rgb(244,67,54) !important; } + +.mdl-color-text--red-600 { + color: rgb(229,57,53) !important; } + +.mdl-color--red-600 { + background-color: rgb(229,57,53) !important; } + +.mdl-color-text--red-700 { + color: rgb(211,47,47) !important; } + +.mdl-color--red-700 { + background-color: rgb(211,47,47) !important; } + +.mdl-color-text--red-800 { + color: rgb(198,40,40) !important; } + +.mdl-color--red-800 { + background-color: rgb(198,40,40) !important; } + +.mdl-color-text--red-900 { + color: rgb(183,28,28) !important; } + +.mdl-color--red-900 { + background-color: rgb(183,28,28) !important; } + +.mdl-color-text--red-A100 { + color: rgb(255,138,128) !important; } + +.mdl-color--red-A100 { + background-color: rgb(255,138,128) !important; } + +.mdl-color-text--red-A200 { + color: rgb(255,82,82) !important; } + +.mdl-color--red-A200 { + background-color: rgb(255,82,82) !important; } + +.mdl-color-text--red-A400 { + color: rgb(255,23,68) !important; } + +.mdl-color--red-A400 { + background-color: rgb(255,23,68) !important; } + +.mdl-color-text--red-A700 { + color: rgb(213,0,0) !important; } + +.mdl-color--red-A700 { + background-color: rgb(213,0,0) !important; } + +.mdl-color-text--pink { + color: rgb(233,30,99) !important; } + +.mdl-color--pink { + background-color: rgb(233,30,99) !important; } + +.mdl-color-text--pink-50 { + color: rgb(252,228,236) !important; } + +.mdl-color--pink-50 { + background-color: rgb(252,228,236) !important; } + +.mdl-color-text--pink-100 { + color: rgb(248,187,208) !important; } + +.mdl-color--pink-100 { + background-color: rgb(248,187,208) !important; } + +.mdl-color-text--pink-200 { + color: rgb(244,143,177) !important; } + +.mdl-color--pink-200 { + background-color: rgb(244,143,177) !important; } + +.mdl-color-text--pink-300 { + color: rgb(240,98,146) !important; } + +.mdl-color--pink-300 { + background-color: rgb(240,98,146) !important; } + +.mdl-color-text--pink-400 { + color: rgb(236,64,122) !important; } + +.mdl-color--pink-400 { + background-color: rgb(236,64,122) !important; } + +.mdl-color-text--pink-500 { + color: rgb(233,30,99) !important; } + +.mdl-color--pink-500 { + background-color: rgb(233,30,99) !important; } + +.mdl-color-text--pink-600 { + color: rgb(216,27,96) !important; } + +.mdl-color--pink-600 { + background-color: rgb(216,27,96) !important; } + +.mdl-color-text--pink-700 { + color: rgb(194,24,91) !important; } + +.mdl-color--pink-700 { + background-color: rgb(194,24,91) !important; } + +.mdl-color-text--pink-800 { + color: rgb(173,20,87) !important; } + +.mdl-color--pink-800 { + background-color: rgb(173,20,87) !important; } + +.mdl-color-text--pink-900 { + color: rgb(136,14,79) !important; } + +.mdl-color--pink-900 { + background-color: rgb(136,14,79) !important; } + +.mdl-color-text--pink-A100 { + color: rgb(255,128,171) !important; } + +.mdl-color--pink-A100 { + background-color: rgb(255,128,171) !important; } + +.mdl-color-text--pink-A200 { + color: rgb(255,64,129) !important; } + +.mdl-color--pink-A200 { + background-color: rgb(255,64,129) !important; } + +.mdl-color-text--pink-A400 { + color: rgb(245,0,87) !important; } + +.mdl-color--pink-A400 { + background-color: rgb(245,0,87) !important; } + +.mdl-color-text--pink-A700 { + color: rgb(197,17,98) !important; } + +.mdl-color--pink-A700 { + background-color: rgb(197,17,98) !important; } + +.mdl-color-text--purple { + color: rgb(156,39,176) !important; } + +.mdl-color--purple { + background-color: rgb(156,39,176) !important; } + +.mdl-color-text--purple-50 { + color: rgb(243,229,245) !important; } + +.mdl-color--purple-50 { + background-color: rgb(243,229,245) !important; } + +.mdl-color-text--purple-100 { + color: rgb(225,190,231) !important; } + +.mdl-color--purple-100 { + background-color: rgb(225,190,231) !important; } + +.mdl-color-text--purple-200 { + color: rgb(206,147,216) !important; } + +.mdl-color--purple-200 { + background-color: rgb(206,147,216) !important; } + +.mdl-color-text--purple-300 { + color: rgb(186,104,200) !important; } + +.mdl-color--purple-300 { + background-color: rgb(186,104,200) !important; } + +.mdl-color-text--purple-400 { + color: rgb(171,71,188) !important; } + +.mdl-color--purple-400 { + background-color: rgb(171,71,188) !important; } + +.mdl-color-text--purple-500 { + color: rgb(156,39,176) !important; } + +.mdl-color--purple-500 { + background-color: rgb(156,39,176) !important; } + +.mdl-color-text--purple-600 { + color: rgb(142,36,170) !important; } + +.mdl-color--purple-600 { + background-color: rgb(142,36,170) !important; } + +.mdl-color-text--purple-700 { + color: rgb(123,31,162) !important; } + +.mdl-color--purple-700 { + background-color: rgb(123,31,162) !important; } + +.mdl-color-text--purple-800 { + color: rgb(106,27,154) !important; } + +.mdl-color--purple-800 { + background-color: rgb(106,27,154) !important; } + +.mdl-color-text--purple-900 { + color: rgb(74,20,140) !important; } + +.mdl-color--purple-900 { + background-color: rgb(74,20,140) !important; } + +.mdl-color-text--purple-A100 { + color: rgb(234,128,252) !important; } + +.mdl-color--purple-A100 { + background-color: rgb(234,128,252) !important; } + +.mdl-color-text--purple-A200 { + color: rgb(224,64,251) !important; } + +.mdl-color--purple-A200 { + background-color: rgb(224,64,251) !important; } + +.mdl-color-text--purple-A400 { + color: rgb(213,0,249) !important; } + +.mdl-color--purple-A400 { + background-color: rgb(213,0,249) !important; } + +.mdl-color-text--purple-A700 { + color: rgb(170,0,255) !important; } + +.mdl-color--purple-A700 { + background-color: rgb(170,0,255) !important; } + +.mdl-color-text--deep-purple { + color: rgb(103,58,183) !important; } + +.mdl-color--deep-purple { + background-color: rgb(103,58,183) !important; } + +.mdl-color-text--deep-purple-50 { + color: rgb(237,231,246) !important; } + +.mdl-color--deep-purple-50 { + background-color: rgb(237,231,246) !important; } + +.mdl-color-text--deep-purple-100 { + color: rgb(209,196,233) !important; } + +.mdl-color--deep-purple-100 { + background-color: rgb(209,196,233) !important; } + +.mdl-color-text--deep-purple-200 { + color: rgb(179,157,219) !important; } + +.mdl-color--deep-purple-200 { + background-color: rgb(179,157,219) !important; } + +.mdl-color-text--deep-purple-300 { + color: rgb(149,117,205) !important; } + +.mdl-color--deep-purple-300 { + background-color: rgb(149,117,205) !important; } + +.mdl-color-text--deep-purple-400 { + color: rgb(126,87,194) !important; } + +.mdl-color--deep-purple-400 { + background-color: rgb(126,87,194) !important; } + +.mdl-color-text--deep-purple-500 { + color: rgb(103,58,183) !important; } + +.mdl-color--deep-purple-500 { + background-color: rgb(103,58,183) !important; } + +.mdl-color-text--deep-purple-600 { + color: rgb(94,53,177) !important; } + +.mdl-color--deep-purple-600 { + background-color: rgb(94,53,177) !important; } + +.mdl-color-text--deep-purple-700 { + color: rgb(81,45,168) !important; } + +.mdl-color--deep-purple-700 { + background-color: rgb(81,45,168) !important; } + +.mdl-color-text--deep-purple-800 { + color: rgb(69,39,160) !important; } + +.mdl-color--deep-purple-800 { + background-color: rgb(69,39,160) !important; } + +.mdl-color-text--deep-purple-900 { + color: rgb(49,27,146) !important; } + +.mdl-color--deep-purple-900 { + background-color: rgb(49,27,146) !important; } + +.mdl-color-text--deep-purple-A100 { + color: rgb(179,136,255) !important; } + +.mdl-color--deep-purple-A100 { + background-color: rgb(179,136,255) !important; } + +.mdl-color-text--deep-purple-A200 { + color: rgb(124,77,255) !important; } + +.mdl-color--deep-purple-A200 { + background-color: rgb(124,77,255) !important; } + +.mdl-color-text--deep-purple-A400 { + color: rgb(101,31,255) !important; } + +.mdl-color--deep-purple-A400 { + background-color: rgb(101,31,255) !important; } + +.mdl-color-text--deep-purple-A700 { + color: rgb(98,0,234) !important; } + +.mdl-color--deep-purple-A700 { + background-color: rgb(98,0,234) !important; } + +.mdl-color-text--indigo { + color: rgb(63,81,181) !important; } + +.mdl-color--indigo { + background-color: rgb(63,81,181) !important; } + +.mdl-color-text--indigo-50 { + color: rgb(232,234,246) !important; } + +.mdl-color--indigo-50 { + background-color: rgb(232,234,246) !important; } + +.mdl-color-text--indigo-100 { + color: rgb(197,202,233) !important; } + +.mdl-color--indigo-100 { + background-color: rgb(197,202,233) !important; } + +.mdl-color-text--indigo-200 { + color: rgb(159,168,218) !important; } + +.mdl-color--indigo-200 { + background-color: rgb(159,168,218) !important; } + +.mdl-color-text--indigo-300 { + color: rgb(121,134,203) !important; } + +.mdl-color--indigo-300 { + background-color: rgb(121,134,203) !important; } + +.mdl-color-text--indigo-400 { + color: rgb(92,107,192) !important; } + +.mdl-color--indigo-400 { + background-color: rgb(92,107,192) !important; } + +.mdl-color-text--indigo-500 { + color: rgb(63,81,181) !important; } + +.mdl-color--indigo-500 { + background-color: rgb(63,81,181) !important; } + +.mdl-color-text--indigo-600 { + color: rgb(57,73,171) !important; } + +.mdl-color--indigo-600 { + background-color: rgb(57,73,171) !important; } + +.mdl-color-text--indigo-700 { + color: rgb(48,63,159) !important; } + +.mdl-color--indigo-700 { + background-color: rgb(48,63,159) !important; } + +.mdl-color-text--indigo-800 { + color: rgb(40,53,147) !important; } + +.mdl-color--indigo-800 { + background-color: rgb(40,53,147) !important; } + +.mdl-color-text--indigo-900 { + color: rgb(26,35,126) !important; } + +.mdl-color--indigo-900 { + background-color: rgb(26,35,126) !important; } + +.mdl-color-text--indigo-A100 { + color: rgb(140,158,255) !important; } + +.mdl-color--indigo-A100 { + background-color: rgb(140,158,255) !important; } + +.mdl-color-text--indigo-A200 { + color: rgb(83,109,254) !important; } + +.mdl-color--indigo-A200 { + background-color: rgb(83,109,254) !important; } + +.mdl-color-text--indigo-A400 { + color: rgb(61,90,254) !important; } + +.mdl-color--indigo-A400 { + background-color: rgb(61,90,254) !important; } + +.mdl-color-text--indigo-A700 { + color: rgb(48,79,254) !important; } + +.mdl-color--indigo-A700 { + background-color: rgb(48,79,254) !important; } + +.mdl-color-text--blue { + color: rgb(33,150,243) !important; } + +.mdl-color--blue { + background-color: rgb(33,150,243) !important; } + +.mdl-color-text--blue-50 { + color: rgb(227,242,253) !important; } + +.mdl-color--blue-50 { + background-color: rgb(227,242,253) !important; } + +.mdl-color-text--blue-100 { + color: rgb(187,222,251) !important; } + +.mdl-color--blue-100 { + background-color: rgb(187,222,251) !important; } + +.mdl-color-text--blue-200 { + color: rgb(144,202,249) !important; } + +.mdl-color--blue-200 { + background-color: rgb(144,202,249) !important; } + +.mdl-color-text--blue-300 { + color: rgb(100,181,246) !important; } + +.mdl-color--blue-300 { + background-color: rgb(100,181,246) !important; } + +.mdl-color-text--blue-400 { + color: rgb(66,165,245) !important; } + +.mdl-color--blue-400 { + background-color: rgb(66,165,245) !important; } + +.mdl-color-text--blue-500 { + color: rgb(33,150,243) !important; } + +.mdl-color--blue-500 { + background-color: rgb(33,150,243) !important; } + +.mdl-color-text--blue-600 { + color: rgb(30,136,229) !important; } + +.mdl-color--blue-600 { + background-color: rgb(30,136,229) !important; } + +.mdl-color-text--blue-700 { + color: rgb(25,118,210) !important; } + +.mdl-color--blue-700 { + background-color: rgb(25,118,210) !important; } + +.mdl-color-text--blue-800 { + color: rgb(21,101,192) !important; } + +.mdl-color--blue-800 { + background-color: rgb(21,101,192) !important; } + +.mdl-color-text--blue-900 { + color: rgb(13,71,161) !important; } + +.mdl-color--blue-900 { + background-color: rgb(13,71,161) !important; } + +.mdl-color-text--blue-A100 { + color: rgb(130,177,255) !important; } + +.mdl-color--blue-A100 { + background-color: rgb(130,177,255) !important; } + +.mdl-color-text--blue-A200 { + color: rgb(68,138,255) !important; } + +.mdl-color--blue-A200 { + background-color: rgb(68,138,255) !important; } + +.mdl-color-text--blue-A400 { + color: rgb(41,121,255) !important; } + +.mdl-color--blue-A400 { + background-color: rgb(41,121,255) !important; } + +.mdl-color-text--blue-A700 { + color: rgb(41,98,255) !important; } + +.mdl-color--blue-A700 { + background-color: rgb(41,98,255) !important; } + +.mdl-color-text--light-blue { + color: rgb(3,169,244) !important; } + +.mdl-color--light-blue { + background-color: rgb(3,169,244) !important; } + +.mdl-color-text--light-blue-50 { + color: rgb(225,245,254) !important; } + +.mdl-color--light-blue-50 { + background-color: rgb(225,245,254) !important; } + +.mdl-color-text--light-blue-100 { + color: rgb(179,229,252) !important; } + +.mdl-color--light-blue-100 { + background-color: rgb(179,229,252) !important; } + +.mdl-color-text--light-blue-200 { + color: rgb(129,212,250) !important; } + +.mdl-color--light-blue-200 { + background-color: rgb(129,212,250) !important; } + +.mdl-color-text--light-blue-300 { + color: rgb(79,195,247) !important; } + +.mdl-color--light-blue-300 { + background-color: rgb(79,195,247) !important; } + +.mdl-color-text--light-blue-400 { + color: rgb(41,182,246) !important; } + +.mdl-color--light-blue-400 { + background-color: rgb(41,182,246) !important; } + +.mdl-color-text--light-blue-500 { + color: rgb(3,169,244) !important; } + +.mdl-color--light-blue-500 { + background-color: rgb(3,169,244) !important; } + +.mdl-color-text--light-blue-600 { + color: rgb(3,155,229) !important; } + +.mdl-color--light-blue-600 { + background-color: rgb(3,155,229) !important; } + +.mdl-color-text--light-blue-700 { + color: rgb(2,136,209) !important; } + +.mdl-color--light-blue-700 { + background-color: rgb(2,136,209) !important; } + +.mdl-color-text--light-blue-800 { + color: rgb(2,119,189) !important; } + +.mdl-color--light-blue-800 { + background-color: rgb(2,119,189) !important; } + +.mdl-color-text--light-blue-900 { + color: rgb(1,87,155) !important; } + +.mdl-color--light-blue-900 { + background-color: rgb(1,87,155) !important; } + +.mdl-color-text--light-blue-A100 { + color: rgb(128,216,255) !important; } + +.mdl-color--light-blue-A100 { + background-color: rgb(128,216,255) !important; } + +.mdl-color-text--light-blue-A200 { + color: rgb(64,196,255) !important; } + +.mdl-color--light-blue-A200 { + background-color: rgb(64,196,255) !important; } + +.mdl-color-text--light-blue-A400 { + color: rgb(0,176,255) !important; } + +.mdl-color--light-blue-A400 { + background-color: rgb(0,176,255) !important; } + +.mdl-color-text--light-blue-A700 { + color: rgb(0,145,234) !important; } + +.mdl-color--light-blue-A700 { + background-color: rgb(0,145,234) !important; } + +.mdl-color-text--cyan { + color: rgb(0,188,212) !important; } + +.mdl-color--cyan { + background-color: rgb(0,188,212) !important; } + +.mdl-color-text--cyan-50 { + color: rgb(224,247,250) !important; } + +.mdl-color--cyan-50 { + background-color: rgb(224,247,250) !important; } + +.mdl-color-text--cyan-100 { + color: rgb(178,235,242) !important; } + +.mdl-color--cyan-100 { + background-color: rgb(178,235,242) !important; } + +.mdl-color-text--cyan-200 { + color: rgb(128,222,234) !important; } + +.mdl-color--cyan-200 { + background-color: rgb(128,222,234) !important; } + +.mdl-color-text--cyan-300 { + color: rgb(77,208,225) !important; } + +.mdl-color--cyan-300 { + background-color: rgb(77,208,225) !important; } + +.mdl-color-text--cyan-400 { + color: rgb(38,198,218) !important; } + +.mdl-color--cyan-400 { + background-color: rgb(38,198,218) !important; } + +.mdl-color-text--cyan-500 { + color: rgb(0,188,212) !important; } + +.mdl-color--cyan-500 { + background-color: rgb(0,188,212) !important; } + +.mdl-color-text--cyan-600 { + color: rgb(0,172,193) !important; } + +.mdl-color--cyan-600 { + background-color: rgb(0,172,193) !important; } + +.mdl-color-text--cyan-700 { + color: rgb(0,151,167) !important; } + +.mdl-color--cyan-700 { + background-color: rgb(0,151,167) !important; } + +.mdl-color-text--cyan-800 { + color: rgb(0,131,143) !important; } + +.mdl-color--cyan-800 { + background-color: rgb(0,131,143) !important; } + +.mdl-color-text--cyan-900 { + color: rgb(0,96,100) !important; } + +.mdl-color--cyan-900 { + background-color: rgb(0,96,100) !important; } + +.mdl-color-text--cyan-A100 { + color: rgb(132,255,255) !important; } + +.mdl-color--cyan-A100 { + background-color: rgb(132,255,255) !important; } + +.mdl-color-text--cyan-A200 { + color: rgb(24,255,255) !important; } + +.mdl-color--cyan-A200 { + background-color: rgb(24,255,255) !important; } + +.mdl-color-text--cyan-A400 { + color: rgb(0,229,255) !important; } + +.mdl-color--cyan-A400 { + background-color: rgb(0,229,255) !important; } + +.mdl-color-text--cyan-A700 { + color: rgb(0,184,212) !important; } + +.mdl-color--cyan-A700 { + background-color: rgb(0,184,212) !important; } + +.mdl-color-text--teal { + color: rgb(0,150,136) !important; } + +.mdl-color--teal { + background-color: rgb(0,150,136) !important; } + +.mdl-color-text--teal-50 { + color: rgb(224,242,241) !important; } + +.mdl-color--teal-50 { + background-color: rgb(224,242,241) !important; } + +.mdl-color-text--teal-100 { + color: rgb(178,223,219) !important; } + +.mdl-color--teal-100 { + background-color: rgb(178,223,219) !important; } + +.mdl-color-text--teal-200 { + color: rgb(128,203,196) !important; } + +.mdl-color--teal-200 { + background-color: rgb(128,203,196) !important; } + +.mdl-color-text--teal-300 { + color: rgb(77,182,172) !important; } + +.mdl-color--teal-300 { + background-color: rgb(77,182,172) !important; } + +.mdl-color-text--teal-400 { + color: rgb(38,166,154) !important; } + +.mdl-color--teal-400 { + background-color: rgb(38,166,154) !important; } + +.mdl-color-text--teal-500 { + color: rgb(0,150,136) !important; } + +.mdl-color--teal-500 { + background-color: rgb(0,150,136) !important; } + +.mdl-color-text--teal-600 { + color: rgb(0,137,123) !important; } + +.mdl-color--teal-600 { + background-color: rgb(0,137,123) !important; } + +.mdl-color-text--teal-700 { + color: rgb(0,121,107) !important; } + +.mdl-color--teal-700 { + background-color: rgb(0,121,107) !important; } + +.mdl-color-text--teal-800 { + color: rgb(0,105,92) !important; } + +.mdl-color--teal-800 { + background-color: rgb(0,105,92) !important; } + +.mdl-color-text--teal-900 { + color: rgb(0,77,64) !important; } + +.mdl-color--teal-900 { + background-color: rgb(0,77,64) !important; } + +.mdl-color-text--teal-A100 { + color: rgb(167,255,235) !important; } + +.mdl-color--teal-A100 { + background-color: rgb(167,255,235) !important; } + +.mdl-color-text--teal-A200 { + color: rgb(100,255,218) !important; } + +.mdl-color--teal-A200 { + background-color: rgb(100,255,218) !important; } + +.mdl-color-text--teal-A400 { + color: rgb(29,233,182) !important; } + +.mdl-color--teal-A400 { + background-color: rgb(29,233,182) !important; } + +.mdl-color-text--teal-A700 { + color: rgb(0,191,165) !important; } + +.mdl-color--teal-A700 { + background-color: rgb(0,191,165) !important; } + +.mdl-color-text--green { + color: rgb(76,175,80) !important; } + +.mdl-color--green { + background-color: rgb(76,175,80) !important; } + +.mdl-color-text--green-50 { + color: rgb(232,245,233) !important; } + +.mdl-color--green-50 { + background-color: rgb(232,245,233) !important; } + +.mdl-color-text--green-100 { + color: rgb(200,230,201) !important; } + +.mdl-color--green-100 { + background-color: rgb(200,230,201) !important; } + +.mdl-color-text--green-200 { + color: rgb(165,214,167) !important; } + +.mdl-color--green-200 { + background-color: rgb(165,214,167) !important; } + +.mdl-color-text--green-300 { + color: rgb(129,199,132) !important; } + +.mdl-color--green-300 { + background-color: rgb(129,199,132) !important; } + +.mdl-color-text--green-400 { + color: rgb(102,187,106) !important; } + +.mdl-color--green-400 { + background-color: rgb(102,187,106) !important; } + +.mdl-color-text--green-500 { + color: rgb(76,175,80) !important; } + +.mdl-color--green-500 { + background-color: rgb(76,175,80) !important; } + +.mdl-color-text--green-600 { + color: rgb(67,160,71) !important; } + +.mdl-color--green-600 { + background-color: rgb(67,160,71) !important; } + +.mdl-color-text--green-700 { + color: rgb(56,142,60) !important; } + +.mdl-color--green-700 { + background-color: rgb(56,142,60) !important; } + +.mdl-color-text--green-800 { + color: rgb(46,125,50) !important; } + +.mdl-color--green-800 { + background-color: rgb(46,125,50) !important; } + +.mdl-color-text--green-900 { + color: rgb(27,94,32) !important; } + +.mdl-color--green-900 { + background-color: rgb(27,94,32) !important; } + +.mdl-color-text--green-A100 { + color: rgb(185,246,202) !important; } + +.mdl-color--green-A100 { + background-color: rgb(185,246,202) !important; } + +.mdl-color-text--green-A200 { + color: rgb(105,240,174) !important; } + +.mdl-color--green-A200 { + background-color: rgb(105,240,174) !important; } + +.mdl-color-text--green-A400 { + color: rgb(0,230,118) !important; } + +.mdl-color--green-A400 { + background-color: rgb(0,230,118) !important; } + +.mdl-color-text--green-A700 { + color: rgb(0,200,83) !important; } + +.mdl-color--green-A700 { + background-color: rgb(0,200,83) !important; } + +.mdl-color-text--light-green { + color: rgb(139,195,74) !important; } + +.mdl-color--light-green { + background-color: rgb(139,195,74) !important; } + +.mdl-color-text--light-green-50 { + color: rgb(241,248,233) !important; } + +.mdl-color--light-green-50 { + background-color: rgb(241,248,233) !important; } + +.mdl-color-text--light-green-100 { + color: rgb(220,237,200) !important; } + +.mdl-color--light-green-100 { + background-color: rgb(220,237,200) !important; } + +.mdl-color-text--light-green-200 { + color: rgb(197,225,165) !important; } + +.mdl-color--light-green-200 { + background-color: rgb(197,225,165) !important; } + +.mdl-color-text--light-green-300 { + color: rgb(174,213,129) !important; } + +.mdl-color--light-green-300 { + background-color: rgb(174,213,129) !important; } + +.mdl-color-text--light-green-400 { + color: rgb(156,204,101) !important; } + +.mdl-color--light-green-400 { + background-color: rgb(156,204,101) !important; } + +.mdl-color-text--light-green-500 { + color: rgb(139,195,74) !important; } + +.mdl-color--light-green-500 { + background-color: rgb(139,195,74) !important; } + +.mdl-color-text--light-green-600 { + color: rgb(124,179,66) !important; } + +.mdl-color--light-green-600 { + background-color: rgb(124,179,66) !important; } + +.mdl-color-text--light-green-700 { + color: rgb(104,159,56) !important; } + +.mdl-color--light-green-700 { + background-color: rgb(104,159,56) !important; } + +.mdl-color-text--light-green-800 { + color: rgb(85,139,47) !important; } + +.mdl-color--light-green-800 { + background-color: rgb(85,139,47) !important; } + +.mdl-color-text--light-green-900 { + color: rgb(51,105,30) !important; } + +.mdl-color--light-green-900 { + background-color: rgb(51,105,30) !important; } + +.mdl-color-text--light-green-A100 { + color: rgb(204,255,144) !important; } + +.mdl-color--light-green-A100 { + background-color: rgb(204,255,144) !important; } + +.mdl-color-text--light-green-A200 { + color: rgb(178,255,89) !important; } + +.mdl-color--light-green-A200 { + background-color: rgb(178,255,89) !important; } + +.mdl-color-text--light-green-A400 { + color: rgb(118,255,3) !important; } + +.mdl-color--light-green-A400 { + background-color: rgb(118,255,3) !important; } + +.mdl-color-text--light-green-A700 { + color: rgb(100,221,23) !important; } + +.mdl-color--light-green-A700 { + background-color: rgb(100,221,23) !important; } + +.mdl-color-text--lime { + color: rgb(205,220,57) !important; } + +.mdl-color--lime { + background-color: rgb(205,220,57) !important; } + +.mdl-color-text--lime-50 { + color: rgb(249,251,231) !important; } + +.mdl-color--lime-50 { + background-color: rgb(249,251,231) !important; } + +.mdl-color-text--lime-100 { + color: rgb(240,244,195) !important; } + +.mdl-color--lime-100 { + background-color: rgb(240,244,195) !important; } + +.mdl-color-text--lime-200 { + color: rgb(230,238,156) !important; } + +.mdl-color--lime-200 { + background-color: rgb(230,238,156) !important; } + +.mdl-color-text--lime-300 { + color: rgb(220,231,117) !important; } + +.mdl-color--lime-300 { + background-color: rgb(220,231,117) !important; } + +.mdl-color-text--lime-400 { + color: rgb(212,225,87) !important; } + +.mdl-color--lime-400 { + background-color: rgb(212,225,87) !important; } + +.mdl-color-text--lime-500 { + color: rgb(205,220,57) !important; } + +.mdl-color--lime-500 { + background-color: rgb(205,220,57) !important; } + +.mdl-color-text--lime-600 { + color: rgb(192,202,51) !important; } + +.mdl-color--lime-600 { + background-color: rgb(192,202,51) !important; } + +.mdl-color-text--lime-700 { + color: rgb(175,180,43) !important; } + +.mdl-color--lime-700 { + background-color: rgb(175,180,43) !important; } + +.mdl-color-text--lime-800 { + color: rgb(158,157,36) !important; } + +.mdl-color--lime-800 { + background-color: rgb(158,157,36) !important; } + +.mdl-color-text--lime-900 { + color: rgb(130,119,23) !important; } + +.mdl-color--lime-900 { + background-color: rgb(130,119,23) !important; } + +.mdl-color-text--lime-A100 { + color: rgb(244,255,129) !important; } + +.mdl-color--lime-A100 { + background-color: rgb(244,255,129) !important; } + +.mdl-color-text--lime-A200 { + color: rgb(238,255,65) !important; } + +.mdl-color--lime-A200 { + background-color: rgb(238,255,65) !important; } + +.mdl-color-text--lime-A400 { + color: rgb(198,255,0) !important; } + +.mdl-color--lime-A400 { + background-color: rgb(198,255,0) !important; } + +.mdl-color-text--lime-A700 { + color: rgb(174,234,0) !important; } + +.mdl-color--lime-A700 { + background-color: rgb(174,234,0) !important; } + +.mdl-color-text--yellow { + color: rgb(255,235,59) !important; } + +.mdl-color--yellow { + background-color: rgb(255,235,59) !important; } + +.mdl-color-text--yellow-50 { + color: rgb(255,253,231) !important; } + +.mdl-color--yellow-50 { + background-color: rgb(255,253,231) !important; } + +.mdl-color-text--yellow-100 { + color: rgb(255,249,196) !important; } + +.mdl-color--yellow-100 { + background-color: rgb(255,249,196) !important; } + +.mdl-color-text--yellow-200 { + color: rgb(255,245,157) !important; } + +.mdl-color--yellow-200 { + background-color: rgb(255,245,157) !important; } + +.mdl-color-text--yellow-300 { + color: rgb(255,241,118) !important; } + +.mdl-color--yellow-300 { + background-color: rgb(255,241,118) !important; } + +.mdl-color-text--yellow-400 { + color: rgb(255,238,88) !important; } + +.mdl-color--yellow-400 { + background-color: rgb(255,238,88) !important; } + +.mdl-color-text--yellow-500 { + color: rgb(255,235,59) !important; } + +.mdl-color--yellow-500 { + background-color: rgb(255,235,59) !important; } + +.mdl-color-text--yellow-600 { + color: rgb(253,216,53) !important; } + +.mdl-color--yellow-600 { + background-color: rgb(253,216,53) !important; } + +.mdl-color-text--yellow-700 { + color: rgb(251,192,45) !important; } + +.mdl-color--yellow-700 { + background-color: rgb(251,192,45) !important; } + +.mdl-color-text--yellow-800 { + color: rgb(249,168,37) !important; } + +.mdl-color--yellow-800 { + background-color: rgb(249,168,37) !important; } + +.mdl-color-text--yellow-900 { + color: rgb(245,127,23) !important; } + +.mdl-color--yellow-900 { + background-color: rgb(245,127,23) !important; } + +.mdl-color-text--yellow-A100 { + color: rgb(255,255,141) !important; } + +.mdl-color--yellow-A100 { + background-color: rgb(255,255,141) !important; } + +.mdl-color-text--yellow-A200 { + color: rgb(255,255,0) !important; } + +.mdl-color--yellow-A200 { + background-color: rgb(255,255,0) !important; } + +.mdl-color-text--yellow-A400 { + color: rgb(255,234,0) !important; } + +.mdl-color--yellow-A400 { + background-color: rgb(255,234,0) !important; } + +.mdl-color-text--yellow-A700 { + color: rgb(255,214,0) !important; } + +.mdl-color--yellow-A700 { + background-color: rgb(255,214,0) !important; } + +.mdl-color-text--amber { + color: rgb(255,193,7) !important; } + +.mdl-color--amber { + background-color: rgb(255,193,7) !important; } + +.mdl-color-text--amber-50 { + color: rgb(255,248,225) !important; } + +.mdl-color--amber-50 { + background-color: rgb(255,248,225) !important; } + +.mdl-color-text--amber-100 { + color: rgb(255,236,179) !important; } + +.mdl-color--amber-100 { + background-color: rgb(255,236,179) !important; } + +.mdl-color-text--amber-200 { + color: rgb(255,224,130) !important; } + +.mdl-color--amber-200 { + background-color: rgb(255,224,130) !important; } + +.mdl-color-text--amber-300 { + color: rgb(255,213,79) !important; } + +.mdl-color--amber-300 { + background-color: rgb(255,213,79) !important; } + +.mdl-color-text--amber-400 { + color: rgb(255,202,40) !important; } + +.mdl-color--amber-400 { + background-color: rgb(255,202,40) !important; } + +.mdl-color-text--amber-500 { + color: rgb(255,193,7) !important; } + +.mdl-color--amber-500 { + background-color: rgb(255,193,7) !important; } + +.mdl-color-text--amber-600 { + color: rgb(255,179,0) !important; } + +.mdl-color--amber-600 { + background-color: rgb(255,179,0) !important; } + +.mdl-color-text--amber-700 { + color: rgb(255,160,0) !important; } + +.mdl-color--amber-700 { + background-color: rgb(255,160,0) !important; } + +.mdl-color-text--amber-800 { + color: rgb(255,143,0) !important; } + +.mdl-color--amber-800 { + background-color: rgb(255,143,0) !important; } + +.mdl-color-text--amber-900 { + color: rgb(255,111,0) !important; } + +.mdl-color--amber-900 { + background-color: rgb(255,111,0) !important; } + +.mdl-color-text--amber-A100 { + color: rgb(255,229,127) !important; } + +.mdl-color--amber-A100 { + background-color: rgb(255,229,127) !important; } + +.mdl-color-text--amber-A200 { + color: rgb(255,215,64) !important; } + +.mdl-color--amber-A200 { + background-color: rgb(255,215,64) !important; } + +.mdl-color-text--amber-A400 { + color: rgb(255,196,0) !important; } + +.mdl-color--amber-A400 { + background-color: rgb(255,196,0) !important; } + +.mdl-color-text--amber-A700 { + color: rgb(255,171,0) !important; } + +.mdl-color--amber-A700 { + background-color: rgb(255,171,0) !important; } + +.mdl-color-text--orange { + color: rgb(255,152,0) !important; } + +.mdl-color--orange { + background-color: rgb(255,152,0) !important; } + +.mdl-color-text--orange-50 { + color: rgb(255,243,224) !important; } + +.mdl-color--orange-50 { + background-color: rgb(255,243,224) !important; } + +.mdl-color-text--orange-100 { + color: rgb(255,224,178) !important; } + +.mdl-color--orange-100 { + background-color: rgb(255,224,178) !important; } + +.mdl-color-text--orange-200 { + color: rgb(255,204,128) !important; } + +.mdl-color--orange-200 { + background-color: rgb(255,204,128) !important; } + +.mdl-color-text--orange-300 { + color: rgb(255,183,77) !important; } + +.mdl-color--orange-300 { + background-color: rgb(255,183,77) !important; } + +.mdl-color-text--orange-400 { + color: rgb(255,167,38) !important; } + +.mdl-color--orange-400 { + background-color: rgb(255,167,38) !important; } + +.mdl-color-text--orange-500 { + color: rgb(255,152,0) !important; } + +.mdl-color--orange-500 { + background-color: rgb(255,152,0) !important; } + +.mdl-color-text--orange-600 { + color: rgb(251,140,0) !important; } + +.mdl-color--orange-600 { + background-color: rgb(251,140,0) !important; } + +.mdl-color-text--orange-700 { + color: rgb(245,124,0) !important; } + +.mdl-color--orange-700 { + background-color: rgb(245,124,0) !important; } + +.mdl-color-text--orange-800 { + color: rgb(239,108,0) !important; } + +.mdl-color--orange-800 { + background-color: rgb(239,108,0) !important; } + +.mdl-color-text--orange-900 { + color: rgb(230,81,0) !important; } + +.mdl-color--orange-900 { + background-color: rgb(230,81,0) !important; } + +.mdl-color-text--orange-A100 { + color: rgb(255,209,128) !important; } + +.mdl-color--orange-A100 { + background-color: rgb(255,209,128) !important; } + +.mdl-color-text--orange-A200 { + color: rgb(255,171,64) !important; } + +.mdl-color--orange-A200 { + background-color: rgb(255,171,64) !important; } + +.mdl-color-text--orange-A400 { + color: rgb(255,145,0) !important; } + +.mdl-color--orange-A400 { + background-color: rgb(255,145,0) !important; } + +.mdl-color-text--orange-A700 { + color: rgb(255,109,0) !important; } + +.mdl-color--orange-A700 { + background-color: rgb(255,109,0) !important; } + +.mdl-color-text--deep-orange { + color: rgb(255,87,34) !important; } + +.mdl-color--deep-orange { + background-color: rgb(255,87,34) !important; } + +.mdl-color-text--deep-orange-50 { + color: rgb(251,233,231) !important; } + +.mdl-color--deep-orange-50 { + background-color: rgb(251,233,231) !important; } + +.mdl-color-text--deep-orange-100 { + color: rgb(255,204,188) !important; } + +.mdl-color--deep-orange-100 { + background-color: rgb(255,204,188) !important; } + +.mdl-color-text--deep-orange-200 { + color: rgb(255,171,145) !important; } + +.mdl-color--deep-orange-200 { + background-color: rgb(255,171,145) !important; } + +.mdl-color-text--deep-orange-300 { + color: rgb(255,138,101) !important; } + +.mdl-color--deep-orange-300 { + background-color: rgb(255,138,101) !important; } + +.mdl-color-text--deep-orange-400 { + color: rgb(255,112,67) !important; } + +.mdl-color--deep-orange-400 { + background-color: rgb(255,112,67) !important; } + +.mdl-color-text--deep-orange-500 { + color: rgb(255,87,34) !important; } + +.mdl-color--deep-orange-500 { + background-color: rgb(255,87,34) !important; } + +.mdl-color-text--deep-orange-600 { + color: rgb(244,81,30) !important; } + +.mdl-color--deep-orange-600 { + background-color: rgb(244,81,30) !important; } + +.mdl-color-text--deep-orange-700 { + color: rgb(230,74,25) !important; } + +.mdl-color--deep-orange-700 { + background-color: rgb(230,74,25) !important; } + +.mdl-color-text--deep-orange-800 { + color: rgb(216,67,21) !important; } + +.mdl-color--deep-orange-800 { + background-color: rgb(216,67,21) !important; } + +.mdl-color-text--deep-orange-900 { + color: rgb(191,54,12) !important; } + +.mdl-color--deep-orange-900 { + background-color: rgb(191,54,12) !important; } + +.mdl-color-text--deep-orange-A100 { + color: rgb(255,158,128) !important; } + +.mdl-color--deep-orange-A100 { + background-color: rgb(255,158,128) !important; } + +.mdl-color-text--deep-orange-A200 { + color: rgb(255,110,64) !important; } + +.mdl-color--deep-orange-A200 { + background-color: rgb(255,110,64) !important; } + +.mdl-color-text--deep-orange-A400 { + color: rgb(255,61,0) !important; } + +.mdl-color--deep-orange-A400 { + background-color: rgb(255,61,0) !important; } + +.mdl-color-text--deep-orange-A700 { + color: rgb(221,44,0) !important; } + +.mdl-color--deep-orange-A700 { + background-color: rgb(221,44,0) !important; } + +.mdl-color-text--brown { + color: rgb(121,85,72) !important; } + +.mdl-color--brown { + background-color: rgb(121,85,72) !important; } + +.mdl-color-text--brown-50 { + color: rgb(239,235,233) !important; } + +.mdl-color--brown-50 { + background-color: rgb(239,235,233) !important; } + +.mdl-color-text--brown-100 { + color: rgb(215,204,200) !important; } + +.mdl-color--brown-100 { + background-color: rgb(215,204,200) !important; } + +.mdl-color-text--brown-200 { + color: rgb(188,170,164) !important; } + +.mdl-color--brown-200 { + background-color: rgb(188,170,164) !important; } + +.mdl-color-text--brown-300 { + color: rgb(161,136,127) !important; } + +.mdl-color--brown-300 { + background-color: rgb(161,136,127) !important; } + +.mdl-color-text--brown-400 { + color: rgb(141,110,99) !important; } + +.mdl-color--brown-400 { + background-color: rgb(141,110,99) !important; } + +.mdl-color-text--brown-500 { + color: rgb(121,85,72) !important; } + +.mdl-color--brown-500 { + background-color: rgb(121,85,72) !important; } + +.mdl-color-text--brown-600 { + color: rgb(109,76,65) !important; } + +.mdl-color--brown-600 { + background-color: rgb(109,76,65) !important; } + +.mdl-color-text--brown-700 { + color: rgb(93,64,55) !important; } + +.mdl-color--brown-700 { + background-color: rgb(93,64,55) !important; } + +.mdl-color-text--brown-800 { + color: rgb(78,52,46) !important; } + +.mdl-color--brown-800 { + background-color: rgb(78,52,46) !important; } + +.mdl-color-text--brown-900 { + color: rgb(62,39,35) !important; } + +.mdl-color--brown-900 { + background-color: rgb(62,39,35) !important; } + +.mdl-color-text--grey { + color: rgb(158,158,158) !important; } + +.mdl-color--grey { + background-color: rgb(158,158,158) !important; } + +.mdl-color-text--grey-50 { + color: rgb(250,250,250) !important; } + +.mdl-color--grey-50 { + background-color: rgb(250,250,250) !important; } + +.mdl-color-text--grey-100 { + color: rgb(245,245,245) !important; } + +.mdl-color--grey-100 { + background-color: rgb(245,245,245) !important; } + +.mdl-color-text--grey-200 { + color: rgb(238,238,238) !important; } + +.mdl-color--grey-200 { + background-color: rgb(238,238,238) !important; } + +.mdl-color-text--grey-300 { + color: rgb(224,224,224) !important; } + +.mdl-color--grey-300 { + background-color: rgb(224,224,224) !important; } + +.mdl-color-text--grey-400 { + color: rgb(189,189,189) !important; } + +.mdl-color--grey-400 { + background-color: rgb(189,189,189) !important; } + +.mdl-color-text--grey-500 { + color: rgb(158,158,158) !important; } + +.mdl-color--grey-500 { + background-color: rgb(158,158,158) !important; } + +.mdl-color-text--grey-600 { + color: rgb(117,117,117) !important; } + +.mdl-color--grey-600 { + background-color: rgb(117,117,117) !important; } + +.mdl-color-text--grey-700 { + color: rgb(97,97,97) !important; } + +.mdl-color--grey-700 { + background-color: rgb(97,97,97) !important; } + +.mdl-color-text--grey-800 { + color: rgb(66,66,66) !important; } + +.mdl-color--grey-800 { + background-color: rgb(66,66,66) !important; } + +.mdl-color-text--grey-900 { + color: rgb(33,33,33) !important; } + +.mdl-color--grey-900 { + background-color: rgb(33,33,33) !important; } + +.mdl-color-text--blue-grey { + color: rgb(96,125,139) !important; } + +.mdl-color--blue-grey { + background-color: rgb(96,125,139) !important; } + +.mdl-color-text--blue-grey-50 { + color: rgb(236,239,241) !important; } + +.mdl-color--blue-grey-50 { + background-color: rgb(236,239,241) !important; } + +.mdl-color-text--blue-grey-100 { + color: rgb(207,216,220) !important; } + +.mdl-color--blue-grey-100 { + background-color: rgb(207,216,220) !important; } + +.mdl-color-text--blue-grey-200 { + color: rgb(176,190,197) !important; } + +.mdl-color--blue-grey-200 { + background-color: rgb(176,190,197) !important; } + +.mdl-color-text--blue-grey-300 { + color: rgb(144,164,174) !important; } + +.mdl-color--blue-grey-300 { + background-color: rgb(144,164,174) !important; } + +.mdl-color-text--blue-grey-400 { + color: rgb(120,144,156) !important; } + +.mdl-color--blue-grey-400 { + background-color: rgb(120,144,156) !important; } + +.mdl-color-text--blue-grey-500 { + color: rgb(96,125,139) !important; } + +.mdl-color--blue-grey-500 { + background-color: rgb(96,125,139) !important; } + +.mdl-color-text--blue-grey-600 { + color: rgb(84,110,122) !important; } + +.mdl-color--blue-grey-600 { + background-color: rgb(84,110,122) !important; } + +.mdl-color-text--blue-grey-700 { + color: rgb(69,90,100) !important; } + +.mdl-color--blue-grey-700 { + background-color: rgb(69,90,100) !important; } + +.mdl-color-text--blue-grey-800 { + color: rgb(55,71,79) !important; } + +.mdl-color--blue-grey-800 { + background-color: rgb(55,71,79) !important; } + +.mdl-color-text--blue-grey-900 { + color: rgb(38,50,56) !important; } + +.mdl-color--blue-grey-900 { + background-color: rgb(38,50,56) !important; } + +.mdl-color--black { + background-color: rgb(0,0,0) !important; } + +.mdl-color-text--black { + color: rgb(0,0,0) !important; } + +.mdl-color--white { + background-color: rgb(255,255,255) !important; } + +.mdl-color-text--white { + color: rgb(255,255,255) !important; } + +.mdl-color--primary { + background-color: rgb(0, 188, 212) !important; } + +.mdl-color--primary-contrast { + background-color: rgb(255,255,255) !important; } + +.mdl-color--primary-dark { + background-color: rgb(48,63,159) !important; } + +.mdl-color--accent { + background-color: rgb(255,64,129) !important; } + +.mdl-color--accent-contrast { + background-color: rgb(255,255,255) !important; } + +.mdl-color-text--primary { + color: rgb(0, 188, 212) !important; } + +.mdl-color-text--primary-contrast { + color: rgb(255,255,255) !important; } + +.mdl-color-text--primary-dark { + color: rgb(48,63,159) !important; } + +.mdl-color-text--accent { + color: rgb(255,64,129) !important; } + +.mdl-color-text--accent-contrast { + color: rgb(255,255,255) !important; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-ripple { + background: rgb(0,0,0); + border-radius: 50%; + height: 50px; + left: 0; + opacity: 0; + pointer-events: none; + position: absolute; + top: 0; + transform: translate(-50%, -50%); + width: 50px; + overflow: hidden; } + .mdl-ripple.is-animating { + transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1), width 0.3s cubic-bezier(0, 0, 0.2, 1), height 0.3s cubic-bezier(0, 0, 0.2, 1), opacity 0.6s cubic-bezier(0, 0, 0.2, 1); } + .mdl-ripple.is-visible { + opacity: 0.3; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-animation--default { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } + +.mdl-animation--fast-out-slow-in { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } + +.mdl-animation--linear-out-slow-in { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } + +.mdl-animation--fast-out-linear-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-badge { + position: relative; + white-space: nowrap; + margin-right: 24px; } + .mdl-badge:not([data-badge]) { + margin-right: auto; } + .mdl-badge[data-badge]:after { + content: attr(data-badge); + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + align-content: center; + align-items: center; + position: absolute; + top: -11px; + right: -24px; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-weight: 600; + font-size: 12px; + width: 22px; + height: 22px; + border-radius: 50%; + background: rgb(0, 188, 212); + color: rgb(255, 255, 255); } + .mdl-button .mdl-badge[data-badge]:after { + top: -10px; + right: -5px; } + .mdl-badge.mdl-badge--no-background[data-badge]:after { + color: rgb(255,64,129); + background: rgba(255,255,255,0.2); + box-shadow: 0 0 1px gray; } + .mdl-badge.mdl-badge--overlap { + margin-right: 10px; } + .mdl-badge.mdl-badge--overlap:after { + right: -10px; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-button { + background: transparent; + border: none; + border-radius: 2px; + color: rgb(255, 255, 255); + position: relative; + height: 36px; + margin: 0; + min-width: 64px; + padding: 0 16px; + display: inline-block; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + line-height: 1; + letter-spacing: 0; + overflow: hidden; + will-change: box-shadow; + transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1); + outline: none; + cursor: pointer; + text-decoration: none; + text-align: center; + line-height: 36px; + vertical-align: middle; } + .mdl-button::-moz-focus-inner { + border: 0; } + .mdl-button:hover { + background-color: rgba(158,158,158, 0.20); } + .mdl-button:focus:not(:active) { + background-color: rgba(0,0,0, 0.12); } + .mdl-button:active { + background-color: rgba(158,158,158, 0.40); } + .mdl-button.mdl-button--colored { + color: rgb(255, 82, 82); } + .mdl-button.mdl-button--colored:focus:not(:active) { + background-color: rgba(0,0,0, 0.12); } + +input.mdl-button[type="submit"] { + -webkit-appearance: none; } + +.mdl-button--raised { + background: rgba(158,158,158, 0.20); + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + .mdl-button--raised:active { + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2); + background-color: rgba(158,158,158, 0.40); } + .mdl-button--raised:focus:not(:active) { + box-shadow: 0 0 8px rgba(0, 0, 0, 0.18), 0 8px 16px rgba(0, 0, 0, 0.36); + background-color: rgba(158,158,158, 0.40); } + .mdl-button--raised.mdl-button--colored { + background: rgb(255, 82, 82); + color: rgb(255,255,255); } + .mdl-button--raised.mdl-button--colored:hover { + background-color: rgb(0, 188, 212); } + .mdl-button--raised.mdl-button--colored:active { + background-color: rgb(0, 188, 212); } + .mdl-button--raised.mdl-button--colored:focus:not(:active) { + background-color: rgb(0, 188, 212); } + .mdl-button--raised.mdl-button--colored .mdl-ripple { + background: rgb(255,255,255); } + +.mdl-button--fab { + border-radius: 50%; + font-size: 24px; + height: 56px; + margin: auto; + min-width: 56px; + width: 56px; + padding: 0; + overflow: hidden; + background: rgba(158,158,158, 0.20); + box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, 0.12), 0 1px 1px 0 rgba(0, 0, 0, 0.24); + position: relative; + line-height: normal; } + .mdl-button--fab .material-icons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-12px, -12px); + line-height: 24px; + width: 24px; } + .mdl-button--fab.mdl-button--mini-fab { + height: 40px; + min-width: 40px; + width: 40px; } + .mdl-button--fab .mdl-button__ripple-container { + border-radius: 50%; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); } + .mdl-button--fab:active { + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2); + background-color: rgba(158,158,158, 0.40); } + .mdl-button--fab:focus:not(:active) { + box-shadow: 0 0 8px rgba(0, 0, 0, 0.18), 0 8px 16px rgba(0, 0, 0, 0.36); + background-color: rgba(158,158,158, 0.40); } + .mdl-button--fab.mdl-button--colored { + background: rgb(255, 82, 82); + color: #ffffff; } + .mdl-button--fab.mdl-button--colored:hover { + background-color: #ff4c4c; } + .mdl-button--fab.mdl-button--colored:focus:not(:active) { + background-color: #f23d3d; } + .mdl-button--fab.mdl-button--colored:active { + background-color: #f23d3d; } + .mdl-button--fab.mdl-button--colored .mdl-ripple { + background: rgb(255,255,255); } + +.mdl-button--icon { + border-radius: 50%; + font-size: 24px; + height: 32px; + margin-left: 0; + margin-right: 0; + min-width: 32px; + width: 32px; + padding: 0; + overflow: hidden; + color: inherit; + line-height: normal; } + .mdl-button--icon .material-icons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-12px, -12px); + line-height: 24px; + width: 24px; } + .mdl-button--icon.mdl-button--mini-icon { + height: 24px; + min-width: 24px; + width: 24px; } + .mdl-button--icon.mdl-button--mini-icon .material-icons { + top: 0px; + left: 0px; } + .mdl-button--icon .mdl-button__ripple-container { + border-radius: 50%; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); } + +.mdl-button__ripple-container { + display: block; + height: 100%; + left: 0px; + position: absolute; + top: 0px; + width: 100%; + z-index: 0; + overflow: hidden; } + .mdl-button[disabled] .mdl-button__ripple-container .mdl-ripple, + .mdl-button.mdl-button--disabled .mdl-button__ripple-container .mdl-ripple { + background-color: transparent; } + +.mdl-button--primary.mdl-button--primary { + color: rgb(255, 82, 82); } + .mdl-button--primary.mdl-button--primary .mdl-ripple { + background: rgb(255,255,255); } + .mdl-button--primary.mdl-button--primary.mdl-button--raised, .mdl-button--primary.mdl-button--primary.mdl-button--fab { + color: rgb(255,255,255); + background-color: rgb(255, 82, 82); } + +.mdl-button--accent.mdl-button--accent { + color: rgb(255, 82, 82); } + .mdl-button--accent.mdl-button--accent .mdl-ripple { + background: #ffffff; } + .mdl-button--accent.mdl-button--accent.mdl-button--raised, .mdl-button--accent.mdl-button--accent.mdl-button--fab { + color: #ffffff; + background-color: rgb(255, 82, 82); } + +.mdl-button[disabled][disabled], .mdl-button.mdl-button--disabled.mdl-button--disabled { + color: rgba(255, 255, 255, 0.3); + cursor: default; + background-color: transparent; } + +.mdl-button--fab[disabled][disabled], .mdl-button--fab.mdl-button--disabled.mdl-button--disabled { + background-color: #6b6b6b; + color: rgba(255, 255, 255, 0.3); } + +.mdl-button--raised[disabled][disabled], .mdl-button--raised.mdl-button--disabled.mdl-button--disabled { + background-color: #6b6b6b; + color: rgba(255, 255, 255, 0.3); + box-shadow: none; } + +.mdl-button--colored[disabled][disabled], .mdl-button--colored.mdl-button--disabled.mdl-button--disabled { + color: rgba(255, 255, 255, 0.3); } + +.mdl-button .material-icons { + vertical-align: middle; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-card { + display: flex; + flex-direction: column; + font-size: 16px; + font-weight: 400; + min-height: auto; + overflow: hidden; + width: auto; + z-index: 1; + position: relative; + background: #4e4e4e; + border-radius: 2px; + box-sizing: border-box; } + +.mdl-card__media { + background-color: rgb(255,64,129); + background-repeat: repeat; + background-position: 50% 50%; + background-size: cover; + background-origin: padding-box; + background-attachment: scroll; + box-sizing: border-box; } + +.mdl-card__title { + align-items: center; + color: rgba(255, 255, 255, 0.8); + display: block; + display: flex; + justify-content: stretch; + line-height: normal; + padding: 20px 16px; + perspective-origin: 165px 56px; + transform-origin: 165px 56px; + box-sizing: border-box; } + .mdl-card__title.mdl-card--border { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); } + +.mdl-card__title-text { + align-self: flex-end; + color: inherit; + display: block; + display: flex; + font-size: 24px; + font-weight: 400; + line-height: normal; + overflow: hidden; + transform-origin: 149px 48px; + margin: 0; } + +.mdl-card__subtitle-text { + font-size: 14px; + color: rgba(255, 255, 255, 0.5); + margin: 0; } + +.mdl-card__supporting-text { + color: rgba(255, 255, 255, 0.8); + font-size: 1rem; + line-height: 18px; + overflow: hidden; + padding: 20px 16px; + width: 90%; } + +.mdl-card__actions { + font-size: 16px; + line-height: normal; + width: 100%; + background-color: transparent; + padding: 8px; + box-sizing: border-box; } + .mdl-card__actions.mdl-card--border { + border-top: 1px solid rgba(0, 0, 0, 0.1); } + +.mdl-card--expand { + flex-grow: 1; } + +.mdl-card__menu { + position: absolute; + right: 16px; + top: 16px; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-checkbox { + position: relative; + z-index: 1; + vertical-align: middle; + display: inline-block; + box-sizing: border-box; + width: 100%; + height: 24px; + margin: 0; + padding: 0; } + .mdl-checkbox.is-upgraded { + padding-left: 18px; } + +.mdl-checkbox__input { + line-height: 24px; } + .mdl-checkbox.is-upgraded .mdl-checkbox__input { + position: absolute; + width: 0; + height: 0; + margin: 0; + padding: 0; + opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + border: none; } + +.mdl-checkbox__box-outline { + position: absolute; + top: 2px; + left: 0; + display: inline-block; + box-sizing: border-box; + width: 18px; + height: 18px; + margin: 0; + cursor: pointer; + overflow: hidden; + border: 2px solid rgb(255, 255, 255); + border-radius: 2px; + z-index: 2; } + .mdl-checkbox.is-checked .mdl-checkbox__box-outline { + border: 2px solid rgb(255, 82, 82); } + fieldset[disabled] .mdl-checkbox .mdl-checkbox__box-outline, + .mdl-checkbox.is-disabled .mdl-checkbox__box-outline { + border: 2px solid rgba(0,0,0, 0.26); + cursor: auto; } + +.mdl-checkbox__focus-helper { + position: absolute; + top: 2px; + left: 0; + display: inline-block; + box-sizing: border-box; + width: 18px; + height: 18px; + border-radius: 50%; + background-color: transparent; } + .mdl-checkbox.is-focused .mdl-checkbox__focus-helper { + box-shadow: 0 0 0px 9px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); } + .mdl-checkbox.is-focused.is-checked .mdl-checkbox__focus-helper { + box-shadow: 0 0 0px 9px rgba(0, 188, 212, 0.26); + background-color: rgba(0, 188, 212, 0.26); } + +.mdl-checkbox__tick-outline { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + mask: url("../images/tick-mask.svg?embed"); + background: transparent; + transition-duration: 0.28s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: background; } + .mdl-checkbox.is-checked .mdl-checkbox__tick-outline { + background: rgb(255, 82, 82) url("../images/tick.svg?embed"); } + fieldset[disabled] .mdl-checkbox.is-checked .mdl-checkbox__tick-outline, + .mdl-checkbox.is-checked.is-disabled .mdl-checkbox__tick-outline { + background: rgba(0,0,0, 0.26) url("../images/tick.svg?embed"); } + +.mdl-checkbox__label { + position: relative; + cursor: pointer; + font-size: 16px; + line-height: 24px; + margin: 0; } + fieldset[disabled] .mdl-checkbox .mdl-checkbox__label, + .mdl-checkbox.is-disabled .mdl-checkbox__label { + color: rgba(0,0,0, 0.26); + cursor: auto; } + +.mdl-checkbox__ripple-container { + position: absolute; + z-index: 2; + top: -6px; + left: -9px; + box-sizing: border-box; + width: 36px; + height: 36px; + border-radius: 50%; + cursor: pointer; + overflow: hidden; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); } + .mdl-checkbox__ripple-container .mdl-ripple { + background: rgb(255, 82, 82); } + fieldset[disabled] .mdl-checkbox .mdl-checkbox__ripple-container, + .mdl-checkbox.is-disabled .mdl-checkbox__ripple-container { + cursor: auto; } + fieldset[disabled] .mdl-checkbox .mdl-checkbox__ripple-container .mdl-ripple, + .mdl-checkbox.is-disabled .mdl-checkbox__ripple-container .mdl-ripple { + background: transparent; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-data-table { + position: relative; + border: 1px solid rgba(255, 255, 255,0.05); + border-collapse: collapse; + white-space: nowrap; + font-size: 16px; + background-color: rgb(255,255,255); } + .mdl-data-table thead { + padding-bottom: 3px; } + .mdl-data-table thead .mdl-data-table__select { + margin-top: 0; } + .mdl-data-table tbody tr { + position: relative; + height: 48px; + transition-duration: 0.28s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: background-color; } + .mdl-data-table tbody tr.is-selected { + background-color: #4e4e4e; } + .mdl-data-table tbody tr:hover { + background-color: rgba(0, 0, 0, 0.2); } + .mdl-data-table td, .mdl-data-table th { + padding: 0 8px 12px 8px; + text-align: right; } + .mdl-data-table td:first-of-type, .mdl-data-table th:first-of-type { + padding-left: 24px; } + .mdl-data-table td:last-of-type, .mdl-data-table th:last-of-type { + padding-right: 24px; } + .mdl-data-table td { + position: relative; + vertical-align: middle; + height: 48px; + border-top: 1px solid rgba(255, 255, 255,0.05); + border-bottom: 1px solid rgba(255, 255, 255,0.05); + padding-top: 12px; + box-sizing: border-box; } + .mdl-data-table td .mdl-data-table__select { + vertical-align: middle; } + .mdl-data-table th { + position: relative; + vertical-align: bottom; + text-overflow: ellipsis; + font-size: 14px; + font-weight: bold; + line-height: 24px; + letter-spacing: 0; + height: 48px; + font-size: 13px; + color: rgb(255, 255, 255); + padding-bottom: 8px; + box-sizing: border-box; } + .mdl-data-table th .mdl-data-table__header--sorted-ascending, .mdl-data-table th .mdl-data-table__header--sorted-descending { + color: rgba(0, 0, 0, 0.87); } + .mdl-data-table th .mdl-data-table__header--sorted-ascending:before, .mdl-data-table th .mdl-data-table__header--sorted-descending:before { + font-size: 16px; + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + word-wrap: normal; + font-feature-settings: 'liga'; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; } + .mdl-data-table th .mdl-data-table__header--sorted-ascending:before { + content: "\e5d8"; } + .mdl-data-table th .mdl-data-table__header--sorted-descending:before { + content: "\e5db"; } + +.mdl-data-table__select { + width: 16px; } + +.mdl-data-table__cell--non-numeric.mdl-data-table__cell--non-numeric { + text-align: left; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-dialog { + border: none; + box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); + width: 280px; } + .mdl-dialog__title { + padding: 24px 24px 0; + margin: 0; + font-size: 2.5rem; } + .mdl-dialog__actions { + padding: 8px 8px 8px 24px; + display: flex; + flex-direction: row-reverse; + flex-wrap: wrap; } + .mdl-dialog__actions > * { + margin-right: 8px; + height: 36px; } + .mdl-dialog__actions > *:first-child { + margin-right: 0; } + .mdl-dialog__actions--full-width { + padding: 0 0 8px 0; } + .mdl-dialog__actions--full-width > * { + height: 48px; + flex: 0 0 100%; + padding-right: 16px; + margin-right: 0; + text-align: right; } + .mdl-dialog__content { + padding: 20px 24px 24px 24px; + color: rgba(255, 255, 255, 0.8); } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-mega-footer { + padding: 16px 40px; + color: rgb(158,158,158); + background-color: rgb(66,66,66); } + +.mdl-mega-footer--top-section:after, +.mdl-mega-footer--middle-section:after, +.mdl-mega-footer--bottom-section:after, +.mdl-mega-footer__top-section:after, +.mdl-mega-footer__middle-section:after, +.mdl-mega-footer__bottom-section:after { + content: ''; + display: block; + clear: both; } + +.mdl-mega-footer--left-section, +.mdl-mega-footer__left-section { + margin-bottom: 16px; } + +.mdl-mega-footer--right-section, +.mdl-mega-footer__right-section { + margin-bottom: 16px; } + +.mdl-mega-footer--right-section a, +.mdl-mega-footer__right-section a { + display: block; + margin-bottom: 16px; + color: inherit; + text-decoration: none; } + +@media screen and (min-width: 760px) { + .mdl-mega-footer--left-section, + .mdl-mega-footer__left-section { + float: left; } + .mdl-mega-footer--right-section, + .mdl-mega-footer__right-section { + float: right; } + .mdl-mega-footer--right-section a, + .mdl-mega-footer__right-section a { + display: inline-block; + margin-left: 16px; + line-height: 36px; + vertical-align: middle; } } + +.mdl-mega-footer--social-btn, +.mdl-mega-footer__social-btn { + width: 36px; + height: 36px; + padding: 0; + margin: 0; + background-color: rgb(158,158,158); + border: none; } + +.mdl-mega-footer--drop-down-section, +.mdl-mega-footer__drop-down-section { + display: block; + position: relative; } + +@media screen and (min-width: 760px) { + .mdl-mega-footer--drop-down-section, + .mdl-mega-footer__drop-down-section { + width: 33%; } + .mdl-mega-footer--drop-down-section:nth-child(1), + .mdl-mega-footer--drop-down-section:nth-child(2), + .mdl-mega-footer__drop-down-section:nth-child(1), + .mdl-mega-footer__drop-down-section:nth-child(2) { + float: left; } + .mdl-mega-footer--drop-down-section:nth-child(3), + .mdl-mega-footer__drop-down-section:nth-child(3) { + float: right; } + .mdl-mega-footer--drop-down-section:nth-child(3):after, + .mdl-mega-footer__drop-down-section:nth-child(3):after { + clear: right; } + .mdl-mega-footer--drop-down-section:nth-child(4), + .mdl-mega-footer__drop-down-section:nth-child(4) { + clear: right; + float: right; } + .mdl-mega-footer--middle-section:after, + .mdl-mega-footer__middle-section:after { + content: ''; + display: block; + clear: both; } + .mdl-mega-footer--bottom-section, + .mdl-mega-footer__bottom-section { + padding-top: 0; } } + +@media screen and (min-width: 1024px) { + .mdl-mega-footer--drop-down-section, + .mdl-mega-footer--drop-down-section:nth-child(3), + .mdl-mega-footer--drop-down-section:nth-child(4), + .mdl-mega-footer__drop-down-section, + .mdl-mega-footer__drop-down-section:nth-child(3), + .mdl-mega-footer__drop-down-section:nth-child(4) { + width: 24%; + float: left; } } + +.mdl-mega-footer--heading-checkbox, +.mdl-mega-footer__heading-checkbox { + position: absolute; + width: 100%; + height: 55.8px; + padding: 32px; + margin: 0; + margin-top: -16px; + cursor: pointer; + z-index: 1; + opacity: 0; } + .mdl-mega-footer--heading-checkbox + .mdl-mega-footer--heading:after, + .mdl-mega-footer--heading-checkbox + .mdl-mega-footer__heading:after, + .mdl-mega-footer__heading-checkbox + .mdl-mega-footer--heading:after, + .mdl-mega-footer__heading-checkbox + .mdl-mega-footer__heading:after { + font-family: 'Material Icons'; + content: '\E5CE'; } + +.mdl-mega-footer--heading-checkbox:checked ~ .mdl-mega-footer--link-list, +.mdl-mega-footer--heading-checkbox:checked ~ .mdl-mega-footer__link-list, +.mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer--heading + .mdl-mega-footer--link-list, +.mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer__heading + .mdl-mega-footer__link-list, +.mdl-mega-footer__heading-checkbox:checked ~ .mdl-mega-footer--link-list, +.mdl-mega-footer__heading-checkbox:checked ~ .mdl-mega-footer__link-list, +.mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer--heading + .mdl-mega-footer--link-list, +.mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer__heading + .mdl-mega-footer__link-list { + display: none; } + +.mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer--heading:after, +.mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer__heading:after, +.mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer--heading:after, +.mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer__heading:after { + font-family: 'Material Icons'; + content: '\E5CF'; } + +.mdl-mega-footer--heading, +.mdl-mega-footer__heading { + position: relative; + width: 100%; + padding-right: 39.8px; + margin-bottom: 16px; + box-sizing: border-box; + font-size: 14px; + line-height: 23.8px; + font-weight: 500; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + color: rgb(224,224,224); } + +.mdl-mega-footer--heading:after, +.mdl-mega-footer__heading:after { + content: ''; + position: absolute; + top: 0; + right: 0; + display: block; + width: 23.8px; + height: 23.8px; + background-size: cover; } + +.mdl-mega-footer--link-list, +.mdl-mega-footer__link-list { + list-style: none; + margin: 0; + padding: 0; + margin-bottom: 32px; } + .mdl-mega-footer--link-list:after, + .mdl-mega-footer__link-list:after { + clear: both; + display: block; + content: ''; } + +.mdl-mega-footer--link-list li, +.mdl-mega-footer__link-list li { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + line-height: 20px; } + +.mdl-mega-footer--link-list a, +.mdl-mega-footer__link-list a { + color: inherit; + text-decoration: none; + white-space: nowrap; } + +@media screen and (min-width: 760px) { + .mdl-mega-footer--heading-checkbox, + .mdl-mega-footer__heading-checkbox { + display: none; } + .mdl-mega-footer--heading-checkbox + .mdl-mega-footer--heading:after, + .mdl-mega-footer--heading-checkbox + .mdl-mega-footer__heading:after, + .mdl-mega-footer__heading-checkbox + .mdl-mega-footer--heading:after, + .mdl-mega-footer__heading-checkbox + .mdl-mega-footer__heading:after { + content: ''; } + .mdl-mega-footer--heading-checkbox:checked ~ .mdl-mega-footer--link-list, + .mdl-mega-footer--heading-checkbox:checked ~ .mdl-mega-footer__link-list, + .mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer__heading + .mdl-mega-footer__link-list, + .mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer--heading + .mdl-mega-footer--link-list, + .mdl-mega-footer__heading-checkbox:checked ~ .mdl-mega-footer--link-list, + .mdl-mega-footer__heading-checkbox:checked ~ .mdl-mega-footer__link-list, + .mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer__heading + .mdl-mega-footer__link-list, + .mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer--heading + .mdl-mega-footer--link-list { + display: block; } + .mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer--heading:after, + .mdl-mega-footer--heading-checkbox:checked + .mdl-mega-footer__heading:after, + .mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer--heading:after, + .mdl-mega-footer__heading-checkbox:checked + .mdl-mega-footer__heading:after { + content: ''; } } + +.mdl-mega-footer--bottom-section, +.mdl-mega-footer__bottom-section { + padding-top: 16px; + margin-bottom: 16px; } + +.mdl-logo { + margin-bottom: 16px; + color: white; } + +.mdl-mega-footer--bottom-section .mdl-mega-footer--link-list li, +.mdl-mega-footer__bottom-section .mdl-mega-footer__link-list li { + float: left; + margin-bottom: 0; + margin-right: 16px; } + +@media screen and (min-width: 760px) { + .mdl-logo { + float: left; + margin-bottom: 0; + margin-right: 16px; } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-mini-footer { + display: flex; + flex-flow: row wrap; + justify-content: space-between; + padding: 32px 16px; + color: rgb(158,158,158); + background-color: rgb(66,66,66); } + .mdl-mini-footer:after { + content: ''; + display: block; } + .mdl-mini-footer .mdl-logo { + line-height: 36px; } + +.mdl-mini-footer--link-list, +.mdl-mini-footer__link-list { + display: flex; + flex-flow: row nowrap; + list-style: none; + margin: 0; + padding: 0; } + .mdl-mini-footer--link-list li, + .mdl-mini-footer__link-list li { + margin-bottom: 0; + margin-right: 16px; } + @media screen and (min-width: 760px) { + .mdl-mini-footer--link-list li, + .mdl-mini-footer__link-list li { + line-height: 36px; } } + .mdl-mini-footer--link-list a, + .mdl-mini-footer__link-list a { + color: inherit; + text-decoration: none; + white-space: nowrap; } + +.mdl-mini-footer--left-section, +.mdl-mini-footer__left-section { + display: inline-block; + order: 0; } + +.mdl-mini-footer--right-section, +.mdl-mini-footer__right-section { + display: inline-block; + order: 1; } + +.mdl-mini-footer--social-btn, +.mdl-mini-footer__social-btn { + width: 36px; + height: 36px; + padding: 0; + margin: 0; + background-color: rgb(158,158,158); + border: none; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-icon-toggle { + position: relative; + z-index: 1; + vertical-align: middle; + display: inline-block; + height: 32px; + margin: 0; + padding: 0; } + +.mdl-icon-toggle__input { + line-height: 32px; } + .mdl-icon-toggle.is-upgraded .mdl-icon-toggle__input { + position: absolute; + width: 0; + height: 0; + margin: 0; + padding: 0; + opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + border: none; } + +.mdl-icon-toggle__label { + display: inline-block; + position: relative; + cursor: pointer; + height: 32px; + width: 32px; + min-width: 32px; + color: rgb(97,97,97); + border-radius: 50%; + padding: 0; + margin-left: 0; + margin-right: 0; + text-align: center; + background-color: transparent; + will-change: background-color; + transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1); } + .mdl-icon-toggle__label.material-icons { + line-height: 32px; + font-size: 24px; } + .mdl-icon-toggle.is-checked .mdl-icon-toggle__label { + color: rgb(0, 188, 212); } + .mdl-icon-toggle.is-disabled .mdl-icon-toggle__label { + color: rgba(0,0,0, 0.26); + cursor: auto; + transition: none; } + .mdl-icon-toggle.is-focused .mdl-icon-toggle__label { + background-color: rgba(0,0,0, 0.12); } + .mdl-icon-toggle.is-focused.is-checked .mdl-icon-toggle__label { + background-color: rgba(0, 188, 212, 0.26); } + +.mdl-icon-toggle__ripple-container { + position: absolute; + z-index: 2; + top: -2px; + left: -2px; + box-sizing: border-box; + width: 36px; + height: 36px; + border-radius: 50%; + cursor: pointer; + overflow: hidden; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); } + .mdl-icon-toggle__ripple-container .mdl-ripple { + background: rgb(97,97,97); } + .mdl-icon-toggle.is-disabled .mdl-icon-toggle__ripple-container { + cursor: auto; } + .mdl-icon-toggle.is-disabled .mdl-icon-toggle__ripple-container .mdl-ripple { + background: transparent; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-list { + display: block; + padding: 0 0; + list-style: none; } + +.mdl-list__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.04em; + line-height: 1; + display: flex; + min-height: 48px; + box-sizing: border-box; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + padding: 16px; + cursor: default; + color: rgb(255, 255, 255); + overflow: hidden; } + .mdl-list__item .mdl-list__item-primary-content { + order: 0; + flex-grow: 2; + text-decoration: none; + box-sizing: border-box; + display: flex; + align-items: center; } + .mdl-list__item .mdl-list__item-primary-content .mdl-list__item-icon { + margin-right: 16px; } + .mdl-list__item .mdl-list__item-primary-content .mdl-list__item-avatar { + margin-right: 16px; } + .mdl-list__item .mdl-list__item-secondary-content { + display: flex; + flex-flow: column; + align-items: flex-end; + margin-left: 16px; } + .mdl-list__item .mdl-list__item-secondary-content .mdl-list__item-secondary-action label { + display: inline; } + .mdl-list__item .mdl-list__item-secondary-content .mdl-list__item-secondary-info { + font-size: 12px; + font-weight: 400; + line-height: 1; + letter-spacing: 0; + color: rgba(255, 255, 255, 0.54); } + .mdl-list__item .mdl-list__item-secondary-content .mdl-list__item-sub-header { + padding: 0 0 0 16px; } + +.mdl-list__item-icon, +.mdl-list__item-icon.material-icons { + height: 24px; + width: 24px; + font-size: 24px; + box-sizing: border-box; + color: rgba(255, 255, 255, 0.8); } + +.mdl-list__item-avatar, +.mdl-list__item-avatar.material-icons { + height: 32px; + width: 32px; + box-sizing: border-box; + border-radius: 50%; + background-color: rgba(255, 255, 255, 0.8); + font-size: 32px; + color: white; } + +.mdl-list__item--two-line { + height: 64px; } + .mdl-list__item--two-line .mdl-list__item-primary-content { + height: 32px; + line-height: 20px; + display: block; } + .mdl-list__item--two-line .mdl-list__item-primary-content .mdl-list__item-avatar { + float: left; } + .mdl-list__item--two-line .mdl-list__item-primary-content .mdl-list__item-icon { + float: left; + margin-top: 4px; } + .mdl-list__item--two-line .mdl-list__item-primary-content .mdl-list__item-secondary-content { + height: 32px; } + .mdl-list__item--two-line .mdl-list__item-primary-content .mdl-list__item-sub-title { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + line-height: 18px; + color: rgba(255, 255, 255, 0.54); + display: block; + padding: 0; } + +.mdl-list__item--three-line { + height: 88px; } + .mdl-list__item--three-line .mdl-list__item-primary-content { + height: 56px; + line-height: 20px; + display: block; } + .mdl-list__item--three-line .mdl-list__item-primary-content .mdl-list__item-avatar, + .mdl-list__item--three-line .mdl-list__item-primary-content .mdl-list__item-icon { + float: left; } + .mdl-list__item--three-line .mdl-list__item-secondary-content { + height: 56px; } + .mdl-list__item--three-line .mdl-list__item-text-body { + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + line-height: 18px; + height: 56px; + color: rgba(255, 255, 255, 0.54); + display: block; + padding: 0; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-menu__container { + display: block; + margin: 0; + padding: 0; + border: none; + position: absolute; + overflow: visible; + height: 0; + width: 0; + visibility: hidden; + z-index: -1; } + .mdl-menu__container.is-visible, .mdl-menu__container.is-animating { + z-index: 999; + visibility: visible; } + +.mdl-menu__outline { + display: block; + background: #4e4e4e; + margin: 0; + padding: 0; + border: none; + border-radius: 2px; + position: absolute; + top: 0; + left: 0; + overflow: hidden; + opacity: 0; + transform: scale(0); + transform-origin: 0 0; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + will-change: transform; + transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); + z-index: -1; } + .mdl-menu__container.is-visible .mdl-menu__outline { + opacity: 1; + transform: scale(1); + z-index: 999; } + .mdl-menu__outline.mdl-menu--bottom-right { + transform-origin: 100% 0; } + .mdl-menu__outline.mdl-menu--top-left { + transform-origin: 0 100%; } + .mdl-menu__outline.mdl-menu--top-right { + transform-origin: 100% 100%; } + +.mdl-menu { + position: absolute; + list-style: none; + top: 0; + left: 0; + height: auto; + width: auto; + min-width: 124px; + padding: 8px 0; + margin: 0; + opacity: 0; + clip: rect(0 0 0 0); + z-index: -1; } + .mdl-menu__container.is-visible .mdl-menu { + opacity: 1; + z-index: 999; } + .mdl-menu.is-animating { + transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1), clip 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + .mdl-menu.mdl-menu--bottom-right { + left: auto; + right: 0; } + .mdl-menu.mdl-menu--top-left { + top: auto; + bottom: 0; } + .mdl-menu.mdl-menu--top-right { + top: auto; + left: auto; + bottom: 0; + right: 0; } + .mdl-menu.mdl-menu--unaligned { + top: auto; + left: auto; } + +.mdl-menu__item { + display: block; + border: none; + color: rgba(0,0,0, 0.87); + background-color: transparent; + text-align: left; + margin: 0; + padding: 0 16px; + outline-color: rgb(189,189,189); + position: relative; + overflow: hidden; + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + text-decoration: none; + cursor: pointer; + height: 48px; + line-height: 48px; + white-space: nowrap; + opacity: 0; + transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); + user-select: none; } + .mdl-menu__container.is-visible .mdl-menu__item { + opacity: 1; } + .mdl-menu__item::-moz-focus-inner { + border: 0; } + .mdl-menu__item--full-bleed-divider { + border-bottom: 1px solid rgba(0,0,0, 0.12); } + .mdl-menu__item[disabled], .mdl-menu__item[data-mdl-disabled] { + color: rgb(189,189,189); + background-color: transparent; + cursor: auto; } + .mdl-menu__item[disabled]:hover, .mdl-menu__item[data-mdl-disabled]:hover { + background-color: transparent; } + .mdl-menu__item[disabled]:focus, .mdl-menu__item[data-mdl-disabled]:focus { + background-color: transparent; } + .mdl-menu__item[disabled] .mdl-ripple, .mdl-menu__item[data-mdl-disabled] .mdl-ripple { + background: transparent; } + .mdl-menu__item:hover { + background-color: rgba(0, 0, 0, 0.2); } + .mdl-menu__item:focus { + outline: none; + background-color: rgba(0, 0, 0, 0.15); } + .mdl-menu__item:active { + background-color: rgba(0, 0, 0, 0.15); } + +.mdl-menu__item--ripple-container { + display: block; + height: 100%; + left: 0px; + position: absolute; + top: 0px; + width: 100%; + z-index: 0; + overflow: hidden; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-progress { + display: block; + position: relative; + height: 4px; + width: 500px; + max-width: 100%; } + +.mdl-progress > .bar { + display: block; + position: absolute; + top: 0; + bottom: 0; + width: 0%; + transition: width 0.2s cubic-bezier(0.4, 0, 0.2, 1); } + +.mdl-progress > .progressbar { + background-color: rgb(255, 82, 82); + z-index: 1; + left: 0; } + +.mdl-progress > .bufferbar { + background-image: linear-gradient(to right, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4)), linear-gradient(to right, rgb(255, 82, 82), rgb(255, 82, 82)); + z-index: 0; + left: 0; } + +.mdl-progress > .auxbar { + right: 0; } + +@supports (-webkit-appearance: none) { + .mdl-progress:not(.mdl-progress--indeterminate):not(.mdl-progress--indeterminate) > .auxbar, + .mdl-progress:not(.mdl-progress__indeterminate):not(.mdl-progress__indeterminate) > .auxbar { + background-image: linear-gradient(to right, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4)), linear-gradient(to right, rgb(255, 82, 82), rgb(255, 82, 82)); + mask: url("../images/buffer.svg?embed"); } } + +.mdl-progress:not(.mdl-progress--indeterminate) > .auxbar, +.mdl-progress:not(.mdl-progress__indeterminate) > .auxbar { + background-image: linear-gradient(to right, rgba(255,255,255, 0.9), rgba(255,255,255, 0.9)), linear-gradient(to right, rgb(255, 82, 82), rgb(255, 82, 82)); } + +.mdl-progress.mdl-progress--indeterminate > .bar1, +.mdl-progress.mdl-progress__indeterminate > .bar1 { + background-color: rgb(255, 82, 82); + animation-name: indeterminate1; + animation-duration: 2s; + animation-iteration-count: infinite; + animation-timing-function: linear; } + +.mdl-progress.mdl-progress--indeterminate > .bar3, +.mdl-progress.mdl-progress__indeterminate > .bar3 { + background-image: none; + background-color: rgb(255, 82, 82); + animation-name: indeterminate2; + animation-duration: 2s; + animation-iteration-count: infinite; + animation-timing-function: linear; } + +@keyframes indeterminate1 { + 0% { + left: 0%; + width: 0%; } + 50% { + left: 25%; + width: 75%; } + 75% { + left: 100%; + width: 0%; } } + +@keyframes indeterminate2 { + 0% { + left: 0%; + width: 0%; } + 50% { + left: 0%; + width: 0%; } + 75% { + left: 0%; + width: 25%; } + 100% { + left: 100%; + width: 0%; } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-navigation { + display: flex; + flex-wrap: nowrap; + box-sizing: border-box; } + +.mdl-navigation__link { + color: rgb(66,66,66); + text-decoration: none; + margin: 0; + font-size: 14px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0; + opacity: 0.87; } + .mdl-navigation__link .material-icons { + vertical-align: middle; } + +.mdl-layout { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + overflow-y: auto; + overflow-x: hidden; + position: relative; + -webkit-overflow-scrolling: touch; } + +.mdl-layout.is-small-screen .mdl-layout--large-screen-only { + display: none; } + +.mdl-layout:not(.is-small-screen) .mdl-layout--small-screen-only { + display: none; } + +.mdl-layout__container { + position: absolute; + width: 100%; + height: 100%; } + +.mdl-layout__title, +.mdl-layout-title { + display: block; + position: relative; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 20px; + font-weight: 500; + line-height: 1; + letter-spacing: 0.02em; + font-weight: 400; + box-sizing: border-box; } + +.mdl-layout-spacer { + flex-grow: 1; } + +.mdl-layout__drawer { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + width: 236px; + height: 100%; + max-height: 100%; + position: absolute; + top: 0; + left: 0; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + box-sizing: border-box; + border-right: 1px solid rgb(224,224,224); + background: #202020; + transform: translateX(-246px); + transform-style: preserve-3d; + will-change: transform; + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: transform; + color: rgb(66,66,66); + overflow: visible; + overflow-y: auto; + z-index: 5; } + .mdl-layout__drawer.is-visible { + transform: translateX(0); } + .mdl-layout__drawer.is-visible ~ .mdl-layout__content.mdl-layout__content { + overflow: hidden; } + .mdl-layout__drawer > * { + flex-shrink: 0; } + .mdl-layout__drawer > .mdl-layout__title, + .mdl-layout__drawer > .mdl-layout-title { + line-height: 64px; + padding-left: 20px; } + @media screen and (max-width: 1440px) { + .mdl-layout__drawer > .mdl-layout__title, + .mdl-layout__drawer > .mdl-layout-title { + line-height: 56px; + padding-left: 8px; } } + .mdl-layout__drawer .mdl-navigation { + flex-direction: column; + align-items: stretch; + padding-top: 16px; } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link { + display: block; + flex-shrink: 0; + padding: 16px 20px; + margin: 0; + color: #757575; } + @media screen and (max-width: 1440px) { + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link { + padding: 16px 8px; } } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link:hover { + background-color: rgba(0, 0, 0, 0.25); } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link--current { + background-color: rgba(0, 0, 0, 0.25); + color: rgb(0, 188, 212); } + @media screen and (min-width: 1441px) { + .mdl-layout--fixed-drawer > .mdl-layout__drawer { + transform: translateX(0); } } + +.mdl-layout__drawer-button { + display: block; + position: absolute; + height: 48px; + width: 48px; + border: 0; + flex-shrink: 0; + overflow: hidden; + text-align: center; + cursor: pointer; + font-size: 26px; + line-height: 50px; + font-family: Helvetica, Arial, sans-serif; + margin: 10px 12px; + top: 0; + left: 0; + color: rgb(0, 188, 212); + z-index: 4; } + .mdl-layout__header .mdl-layout__drawer-button { + position: absolute; + color: rgb(0, 188, 212); + background-color: inherit; } + @media screen and (max-width: 1440px) { + .mdl-layout__header .mdl-layout__drawer-button { + margin: 4px; } } + @media screen and (max-width: 1440px) { + .mdl-layout__drawer-button { + margin: 4px; + color: rgba(0, 0, 0, 0.5); } } + @media screen and (min-width: 1441px) { + .mdl-layout--fixed-drawer > .mdl-layout__drawer-button { + display: none; } + .mdl-layout--no-desktop-drawer-button .mdl-layout__drawer-button { + display: none; } } + .mdl-layout--no-drawer-button .mdl-layout__drawer-button { + display: none; } + +.mdl-layout__header { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + justify-content: flex-start; + box-sizing: border-box; + flex-shrink: 0; + width: 100%; + margin: 0; + padding: 0; + border: none; + min-height: 64px; + max-height: 1000px; + z-index: 3; + background-color: #242424; + color: rgb(0, 188, 212); + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: max-height, box-shadow; } + @media screen and (max-width: 1440px) { + .mdl-layout__header { + min-height: 56px; } } + .mdl-layout--fixed-drawer.is-upgraded:not(.is-small-screen) > .mdl-layout__header { + margin-left: 236px; + width: calc(100% - 236px); } + @media screen and (min-width: 1441px) { + .mdl-layout--fixed-drawer > .mdl-layout__header .mdl-layout__header-row { + padding-left: 40px; } } + .mdl-layout__header > .mdl-layout-icon { + position: absolute; + left: 20px; + top: 16px; + height: 32px; + width: 32px; + overflow: hidden; + z-index: 3; + display: block; } + @media screen and (max-width: 1440px) { + .mdl-layout__header > .mdl-layout-icon { + left: 8px; + top: 12px; } } + .mdl-layout.has-drawer .mdl-layout__header > .mdl-layout-icon { + display: none; } + .mdl-layout__header.is-compact { + max-height: 64px; } + @media screen and (max-width: 1440px) { + .mdl-layout__header.is-compact { + max-height: 56px; } } + .mdl-layout__header.is-compact.has-tabs { + height: 112px; } + @media screen and (max-width: 1440px) { + .mdl-layout__header.is-compact.has-tabs { + min-height: 104px; } } + @media screen and (max-width: 1440px) { + .mdl-layout__header { + display: none; } + .mdl-layout--fixed-header > .mdl-layout__header { + display: flex; } } + +.mdl-layout__header--transparent.mdl-layout__header--transparent { + background-color: transparent; + box-shadow: none; } + +.mdl-layout__header--seamed { + box-shadow: none; } + +.mdl-layout__header--scroll { + box-shadow: none; } + +.mdl-layout__header--waterfall { + box-shadow: none; + overflow: hidden; } + .mdl-layout__header--waterfall.is-casting-shadow { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + .mdl-layout__header--waterfall.mdl-layout__header--waterfall-hide-top { + justify-content: flex-end; } + +.mdl-layout__header-row { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + flex-shrink: 0; + box-sizing: border-box; + align-self: stretch; + align-items: center; + height: 64px; + margin: 0; + padding: 0 20px 0 80px; } + .mdl-layout--no-drawer-button .mdl-layout__header-row { + padding-left: 20px; } + @media screen and (min-width: 1441px) { + .mdl-layout--no-desktop-drawer-button .mdl-layout__header-row { + padding-left: 20px; } } + @media screen and (max-width: 1440px) { + .mdl-layout__header-row { + height: 56px; + padding: 0 8px 0 72px; } + .mdl-layout--no-drawer-button .mdl-layout__header-row { + padding-left: 8px; } } + .mdl-layout__header-row > * { + flex-shrink: 0; } + .mdl-layout__header--scroll .mdl-layout__header-row { + width: 100%; } + .mdl-layout__header-row .mdl-navigation { + margin: 0; + padding: 0; + height: 64px; + flex-direction: row; + align-items: center; } + @media screen and (max-width: 1440px) { + .mdl-layout__header-row .mdl-navigation { + height: 56px; } } + .mdl-layout__header-row .mdl-navigation__link { + display: block; + color: rgb(0, 188, 212); + line-height: 64px; + padding: 0 24px; } + @media screen and (max-width: 1440px) { + .mdl-layout__header-row .mdl-navigation__link { + line-height: 56px; + padding: 0 8px; } } + +.mdl-layout__obfuscator { + background-color: transparent; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 4; + visibility: hidden; + transition-property: background-color; + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } + .mdl-layout__obfuscator.is-visible { + background-color: rgba(0, 0, 0, 0.5); + visibility: visible; } + @supports (pointer-events: auto) { + .mdl-layout__obfuscator { + background-color: rgba(0, 0, 0, 0.5); + opacity: 0; + transition-property: opacity; + visibility: visible; + pointer-events: none; } + .mdl-layout__obfuscator.is-visible { + pointer-events: auto; + opacity: 1; } } + +.mdl-layout__content { + -ms-flex: 0 1 auto; + position: relative; + display: inline-block; + overflow-y: auto; + overflow-x: hidden; + flex-grow: 1; + z-index: 1; + -webkit-overflow-scrolling: touch; } + .mdl-layout--fixed-drawer > .mdl-layout__content { + margin-left: 236px; } + .mdl-layout__container.has-scrolling-header .mdl-layout__content { + overflow: visible; } + @media screen and (max-width: 1440px) { + .mdl-layout--fixed-drawer > .mdl-layout__content { + margin-left: 0; } + .mdl-layout__container.has-scrolling-header .mdl-layout__content { + overflow-y: auto; + overflow-x: hidden; } } + +.mdl-layout__tab-bar { + height: 96px; + margin: 0; + width: calc(100% - 112px); + padding: 0 0 0 56px; + display: flex; + background-color: #242424; + overflow-y: hidden; + overflow-x: scroll; } + .mdl-layout__tab-bar::-webkit-scrollbar { + display: none; } + .mdl-layout--no-drawer-button .mdl-layout__tab-bar { + padding-left: -4px; + width: calc(100% - -8px); } + @media screen and (min-width: 1441px) { + .mdl-layout--no-desktop-drawer-button .mdl-layout__tab-bar { + padding-left: -4px; + width: calc(100% - -8px); } } + @media screen and (max-width: 1440px) { + .mdl-layout__tab-bar { + width: calc(100% - 60px); + padding: 0 0 0 60px; } + .mdl-layout--no-drawer-button .mdl-layout__tab-bar { + width: calc(100% - -8px); + padding-left: -4px; } } + .mdl-layout--fixed-tabs .mdl-layout__tab-bar { + padding: 0; + overflow: hidden; + width: 100%; } + +.mdl-layout__tab-bar-container { + position: relative; + height: 48px; + width: 100%; + border: none; + margin: 0; + z-index: 2; + flex-grow: 0; + flex-shrink: 0; + overflow: hidden; } + .mdl-layout__container > .mdl-layout__tab-bar-container { + position: absolute; + top: 0; + left: 0; } + +.mdl-layout__tab-bar-button { + display: inline-block; + position: absolute; + top: 0; + height: 48px; + width: 56px; + z-index: 4; + text-align: center; + background-color: #242424; + color: transparent; + cursor: pointer; + user-select: none; } + .mdl-layout--no-desktop-drawer-button .mdl-layout__tab-bar-button, + .mdl-layout--no-drawer-button .mdl-layout__tab-bar-button { + width: -4px; } + .mdl-layout--no-desktop-drawer-button .mdl-layout__tab-bar-button .material-icons, + .mdl-layout--no-drawer-button .mdl-layout__tab-bar-button .material-icons { + position: relative; + left: -14px; } + @media screen and (max-width: 1440px) { + .mdl-layout__tab-bar-button { + display: none; + width: 60px; } } + .mdl-layout--fixed-tabs .mdl-layout__tab-bar-button { + display: none; } + .mdl-layout__tab-bar-button .material-icons { + line-height: 48px; } + .mdl-layout__tab-bar-button.is-active { + color: rgb(0, 188, 212); } + +.mdl-layout__tab-bar-left-button { + left: 0; } + +.mdl-layout__tab-bar-right-button { + right: 0; } + +.mdl-layout__tab { + margin: 0; + border: none; + padding: 0 24px 0 24px; + float: left; + position: relative; + display: block; + flex-grow: 0; + flex-shrink: 0; + text-decoration: none; + height: 48px; + line-height: 48px; + text-align: center; + font-weight: 500; + font-size: 14px; + text-transform: uppercase; + color: rgba(255,255,255, 0.6); + overflow: hidden; } + @media screen and (max-width: 1440px) { + .mdl-layout__tab { + padding: 0 12px 0 12px; } } + .mdl-layout--fixed-tabs .mdl-layout__tab { + float: none; + flex-grow: 1; + padding: 0; } + .mdl-layout.is-upgraded .mdl-layout__tab.is-active { + color: rgb(0, 188, 212); } + .mdl-layout.is-upgraded .mdl-layout__tab.is-active::after { + height: 2px; + width: 100%; + display: block; + content: " "; + bottom: 0; + left: 0; + position: absolute; + background: rgb(255,64,129); + animation: border-expand 0.2s cubic-bezier(0.4, 0, 0.4, 1) 0.01s alternate forwards; + transition: all 1s cubic-bezier(0.4, 0, 1, 1); } + .mdl-layout__tab .mdl-layout__tab-ripple-container { + display: block; + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; + z-index: 1; + overflow: hidden; } + .mdl-layout__tab .mdl-layout__tab-ripple-container .mdl-ripple { + background-color: rgb(0, 188, 212); } + +.mdl-layout__tab-panel { + display: block; } + .mdl-layout.is-upgraded .mdl-layout__tab-panel { + display: none; } + .mdl-layout.is-upgraded .mdl-layout__tab-panel.is-active { + display: block; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-radio { + position: relative; + font-size: 16px; + line-height: 24px; + display: inline-block; + box-sizing: border-box; + margin: 0; + padding-left: 0; } + .mdl-radio.is-upgraded { + padding-left: 24px; } + +.mdl-radio__button { + line-height: 24px; } + .mdl-radio.is-upgraded .mdl-radio__button { + position: absolute; + width: 0; + height: 0; + margin: 0; + padding: 0; + opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + border: none; } + +.mdl-radio__outer-circle { + position: absolute; + top: 4px; + left: 0; + display: inline-block; + box-sizing: border-box; + width: 16px; + height: 16px; + margin: 0; + cursor: pointer; + border: 2px solid rgba(255, 255, 255, 0.8); + border-radius: 50%; + z-index: 2; } + .mdl-radio.is-checked .mdl-radio__outer-circle { + border: 2px solid rgba(0, 188, 212, 0.8); } + .mdl-radio__outer-circle fieldset[disabled] .mdl-radio, + .mdl-radio.is-disabled .mdl-radio__outer-circle { + border: 2px solid rgba(0,0,0, 0.26); + cursor: auto; } + +.mdl-radio__inner-circle { + position: absolute; + z-index: 1; + margin: 0; + top: 8px; + left: 4px; + box-sizing: border-box; + width: 8px; + height: 8px; + cursor: pointer; + transition-duration: 0.28s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: transform; + transform: scale3d(0, 0, 0); + border-radius: 50%; + background: rgba(0, 188, 212, 0.8); } + .mdl-radio.is-checked .mdl-radio__inner-circle { + transform: scale3d(1, 1, 1); } + fieldset[disabled] .mdl-radio .mdl-radio__inner-circle, + .mdl-radio.is-disabled .mdl-radio__inner-circle { + background: rgba(0,0,0, 0.26); + cursor: auto; } + .mdl-radio.is-focused .mdl-radio__inner-circle { + box-shadow: 0 0 0px 10px rgba(0, 0, 0, 0.1); } + +.mdl-radio__label { + cursor: pointer; } + fieldset[disabled] .mdl-radio .mdl-radio__label, + .mdl-radio.is-disabled .mdl-radio__label { + color: rgba(0,0,0, 0.26); + cursor: auto; } + +.mdl-radio__ripple-container { + position: absolute; + z-index: 2; + top: -9px; + left: -13px; + box-sizing: border-box; + width: 42px; + height: 42px; + border-radius: 50%; + cursor: pointer; + overflow: hidden; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); } + .mdl-radio__ripple-container .mdl-ripple { + background: rgba(0, 188, 212, 0.8); } + fieldset[disabled] .mdl-radio .mdl-radio__ripple-container, + .mdl-radio.is-disabled .mdl-radio__ripple-container { + cursor: auto; } + fieldset[disabled] .mdl-radio .mdl-radio__ripple-container .mdl-ripple, + .mdl-radio.is-disabled .mdl-radio__ripple-container .mdl-ripple { + background: transparent; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +_:-ms-input-placeholder, :root .mdl-slider.mdl-slider.is-upgraded { + -ms-appearance: none; + height: 32px; + margin: 0; } + +.mdl-slider { + width: calc(100% - 40px); + margin: 0 20px; } + .mdl-slider.is-upgraded { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 2px; + background: transparent; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + outline: 0; + padding: 0; + color: rgb(0, 188, 212); + align-self: center; + z-index: 1; + cursor: pointer; + /**************************** Tracks ****************************/ + /**************************** Thumbs ****************************/ + /**************************** 0-value ****************************/ + /**************************** Disabled ****************************/ } + .mdl-slider.is-upgraded::-moz-focus-outer { + border: 0; } + .mdl-slider.is-upgraded::-ms-tooltip { + display: none; } + .mdl-slider.is-upgraded::-webkit-slider-runnable-track { + background: transparent; } + .mdl-slider.is-upgraded::-moz-range-track { + background: transparent; + border: none; } + .mdl-slider.is-upgraded::-ms-track { + background: none; + color: transparent; + height: 2px; + width: 100%; + border: none; } + .mdl-slider.is-upgraded::-ms-fill-lower { + padding: 0; + background: linear-gradient(to right, transparent, transparent 16px, rgb(0, 188, 212) 16px, rgb(0, 188, 212) 0); } + .mdl-slider.is-upgraded::-ms-fill-upper { + padding: 0; + background: linear-gradient(to left, transparent, transparent 16px, rgba(0,0,0, 0.26) 16px, rgba(0,0,0, 0.26) 0); } + .mdl-slider.is-upgraded::-webkit-slider-thumb { + -webkit-appearance: none; + width: 12px; + height: 12px; + box-sizing: border-box; + border-radius: 50%; + background: rgb(0, 188, 212); + border: none; + transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), border 0.18s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1); } + .mdl-slider.is-upgraded::-moz-range-thumb { + -moz-appearance: none; + width: 12px; + height: 12px; + box-sizing: border-box; + border-radius: 50%; + background-image: none; + background: rgb(0, 188, 212); + border: none; } + .mdl-slider.is-upgraded:focus:not(:active)::-webkit-slider-thumb { + box-shadow: 0 0 0 10px rgba(0, 188, 212, 0.26); } + .mdl-slider.is-upgraded:focus:not(:active)::-moz-range-thumb { + box-shadow: 0 0 0 10px rgba(0, 188, 212, 0.26); } + .mdl-slider.is-upgraded:active::-webkit-slider-thumb { + background-image: none; + background: rgb(0, 188, 212); + transform: scale(1.5); } + .mdl-slider.is-upgraded:active::-moz-range-thumb { + background-image: none; + background: rgb(0, 188, 212); + transform: scale(1.5); } + .mdl-slider.is-upgraded::-ms-thumb { + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: rgb(0, 188, 212); + transform: scale(0.375); + transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1); } + .mdl-slider.is-upgraded:focus:not(:active)::-ms-thumb { + background: radial-gradient(circle closest-side, rgb(0, 188, 212) 0%, rgb(0, 188, 212) 37.5%, rgba(0, 188, 212, 0.26) 37.5%, rgba(0, 188, 212, 0.26) 100%); + transform: scale(1); } + .mdl-slider.is-upgraded:active::-ms-thumb { + background: rgb(0, 188, 212); + transform: scale(0.5625); } + .mdl-slider.is-upgraded.is-lowest-value::-webkit-slider-thumb { + border: 2px solid rgba(0,0,0, 0.26); + background: transparent; } + .mdl-slider.is-upgraded.is-lowest-value::-moz-range-thumb { + border: 2px solid rgba(0,0,0, 0.26); + background: transparent; } + .mdl-slider.is-upgraded.is-lowest-value + +.mdl-slider__background-flex > .mdl-slider__background-upper { + left: 6px; } + .mdl-slider.is-upgraded.is-lowest-value:focus:not(:active)::-webkit-slider-thumb { + box-shadow: 0 0 0 10px rgba(0,0,0, 0.12); + background: rgba(0,0,0, 0.12); } + .mdl-slider.is-upgraded.is-lowest-value:focus:not(:active)::-moz-range-thumb { + box-shadow: 0 0 0 10px rgba(0,0,0, 0.12); + background: rgba(0,0,0, 0.12); } + .mdl-slider.is-upgraded.is-lowest-value:active::-webkit-slider-thumb { + border: 1.6px solid rgba(0,0,0, 0.26); + transform: scale(1.5); } + .mdl-slider.is-upgraded.is-lowest-value:active + +.mdl-slider__background-flex > .mdl-slider__background-upper { + left: 9px; } + .mdl-slider.is-upgraded.is-lowest-value:active::-moz-range-thumb { + border: 1.5px solid rgba(0,0,0, 0.26); + transform: scale(1.5); } + .mdl-slider.is-upgraded.is-lowest-value::-ms-thumb { + background: radial-gradient(circle closest-side, transparent 0%, transparent 66.67%, rgba(0,0,0, 0.26) 66.67%, rgba(0,0,0, 0.26) 100%); } + .mdl-slider.is-upgraded.is-lowest-value:focus:not(:active)::-ms-thumb { + background: radial-gradient(circle closest-side, rgba(0,0,0, 0.12) 0%, rgba(0,0,0, 0.12) 25%, rgba(0,0,0, 0.26) 25%, rgba(0,0,0, 0.26) 37.5%, rgba(0,0,0, 0.12) 37.5%, rgba(0,0,0, 0.12) 100%); + transform: scale(1); } + .mdl-slider.is-upgraded.is-lowest-value:active::-ms-thumb { + transform: scale(0.5625); + background: radial-gradient(circle closest-side, transparent 0%, transparent 77.78%, rgba(0,0,0, 0.26) 77.78%, rgba(0,0,0, 0.26) 100%); } + .mdl-slider.is-upgraded.is-lowest-value::-ms-fill-lower { + background: transparent; } + .mdl-slider.is-upgraded.is-lowest-value::-ms-fill-upper { + margin-left: 6px; } + .mdl-slider.is-upgraded.is-lowest-value:active::-ms-fill-upper { + margin-left: 9px; } + .mdl-slider.is-upgraded:disabled:focus::-webkit-slider-thumb, .mdl-slider.is-upgraded:disabled:active::-webkit-slider-thumb, .mdl-slider.is-upgraded:disabled::-webkit-slider-thumb { + transform: scale(0.667); + background: rgba(0,0,0, 0.26); } + .mdl-slider.is-upgraded:disabled:focus::-moz-range-thumb, .mdl-slider.is-upgraded:disabled:active::-moz-range-thumb, .mdl-slider.is-upgraded:disabled::-moz-range-thumb { + transform: scale(0.667); + background: rgba(0,0,0, 0.26); } + .mdl-slider.is-upgraded:disabled + +.mdl-slider__background-flex > .mdl-slider__background-lower { + background-color: rgba(0,0,0, 0.26); + left: -6px; } + .mdl-slider.is-upgraded:disabled + +.mdl-slider__background-flex > .mdl-slider__background-upper { + left: 6px; } + .mdl-slider.is-upgraded.is-lowest-value:disabled:focus::-webkit-slider-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled:active::-webkit-slider-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled::-webkit-slider-thumb { + border: 3px solid rgba(0,0,0, 0.26); + background: transparent; + transform: scale(0.667); } + .mdl-slider.is-upgraded.is-lowest-value:disabled:focus::-moz-range-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled:active::-moz-range-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled::-moz-range-thumb { + border: 3px solid rgba(0,0,0, 0.26); + background: transparent; + transform: scale(0.667); } + .mdl-slider.is-upgraded.is-lowest-value:disabled:active + +.mdl-slider__background-flex > .mdl-slider__background-upper { + left: 6px; } + .mdl-slider.is-upgraded:disabled:focus::-ms-thumb, .mdl-slider.is-upgraded:disabled:active::-ms-thumb, .mdl-slider.is-upgraded:disabled::-ms-thumb { + transform: scale(0.25); + background: rgba(0,0,0, 0.26); } + .mdl-slider.is-upgraded.is-lowest-value:disabled:focus::-ms-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled:active::-ms-thumb, .mdl-slider.is-upgraded.is-lowest-value:disabled::-ms-thumb { + transform: scale(0.25); + background: radial-gradient(circle closest-side, transparent 0%, transparent 50%, rgba(0,0,0, 0.26) 50%, rgba(0,0,0, 0.26) 100%); } + .mdl-slider.is-upgraded:disabled::-ms-fill-lower { + margin-right: 6px; + background: linear-gradient(to right, transparent, transparent 25px, rgba(0,0,0, 0.26) 25px, rgba(0,0,0, 0.26) 0); } + .mdl-slider.is-upgraded:disabled::-ms-fill-upper { + margin-left: 6px; } + .mdl-slider.is-upgraded.is-lowest-value:disabled:active::-ms-fill-upper { + margin-left: 6px; } + +.mdl-slider__ie-container { + height: 18px; + overflow: visible; + border: none; + margin: none; + padding: none; } + +.mdl-slider__container { + height: 18px; + position: relative; + background: none; + display: flex; + flex-direction: row; } + +.mdl-slider__background-flex { + background: transparent; + position: absolute; + height: 2px; + width: calc(100% - 52px); + top: 50%; + left: 0; + margin: 0 26px; + display: flex; + overflow: hidden; + border: 0; + padding: 0; + transform: translate(0, -1px); } + +.mdl-slider__background-lower { + background: rgb(0, 188, 212); + flex: 0; + position: relative; + border: 0; + padding: 0; } + +.mdl-slider__background-upper { + background: rgba(0,0,0, 0.26); + flex: 0; + position: relative; + border: 0; + padding: 0; + transition: left 0.18s cubic-bezier(0.4, 0, 0.2, 1); } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-snackbar { + position: fixed; + bottom: 0; + left: 50%; + margin-right: -50%; + cursor: default; + background-color: #323232; + z-index: 10000; + display: flex; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + will-change: transform; + transform: translate(0, 80px); + transition: transform 0.25s cubic-bezier(0.4, 0, 1, 1); + pointer-events: none; } + @media (max-width: 1151px) { + .mdl-snackbar { + width: 100%; + left: 0; + min-height: 48px; + max-height: 80px; } } + @media (min-width: 1152px) { + .mdl-snackbar { + min-width: 288px; + max-width: 568px; + border-radius: 2px; } } + .mdl-snackbar--active { + transform: translate(0, 0); + pointer-events: auto; + transition: transform 0.25s cubic-bezier(0, 0, 0.2, 1); } + .mdl-snackbar__text { + padding: 14px 24px; + vertical-align: middle; + color: white; } + .mdl-snackbar__action { + background: transparent; + border: none; + color: rgb(255,64,129); + text-transform: uppercase; + padding: 14px 24px; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + line-height: 1; + letter-spacing: 0; + overflow: hidden; + outline: none; + opacity: 0; + pointer-events: none; + cursor: pointer; + text-decoration: none; + text-align: center; + vertical-align: middle; } + .mdl-snackbar__action::-moz-focus-inner { + border: 0; } + .mdl-snackbar__action:not([aria-hidden]) { + opacity: 1; + pointer-events: auto; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-spinner { + display: inline-block; + position: relative; + width: 28px; + height: 28px; } + .mdl-spinner:not(.is-upgraded).is-active:after { + content: "Loading..."; } + .mdl-spinner.is-upgraded.is-active { + animation: mdl-spinner__container-rotate 1568.23529ms linear infinite; } + +@keyframes mdl-spinner__container-rotate { + to { + transform: rotate(360deg); } } + +.mdl-spinner__layer { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; } + +.mdl-spinner__layer-1 { + border-color: rgb(66,165,245); } + .mdl-spinner--single-color .mdl-spinner__layer-1 { + border-color: rgb(0, 188, 212); } + .mdl-spinner.is-active .mdl-spinner__layer-1 { + animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.mdl-spinner__layer-2 { + border-color: rgb(244,67,54); } + .mdl-spinner--single-color .mdl-spinner__layer-2 { + border-color: rgb(0, 188, 212); } + .mdl-spinner.is-active .mdl-spinner__layer-2 { + animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.mdl-spinner__layer-3 { + border-color: rgb(253,216,53); } + .mdl-spinner--single-color .mdl-spinner__layer-3 { + border-color: rgb(0, 188, 212); } + .mdl-spinner.is-active .mdl-spinner__layer-3 { + animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.mdl-spinner__layer-4 { + border-color: rgb(76,175,80); } + .mdl-spinner--single-color .mdl-spinner__layer-4 { + border-color: rgb(0, 188, 212); } + .mdl-spinner.is-active .mdl-spinner__layer-4 { + animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +@keyframes mdl-spinner__fill-unfill-rotate { + 12.5% { + transform: rotate(135deg); } + 25% { + transform: rotate(270deg); } + 37.5% { + transform: rotate(405deg); } + 50% { + transform: rotate(540deg); } + 62.5% { + transform: rotate(675deg); } + 75% { + transform: rotate(810deg); } + 87.5% { + transform: rotate(945deg); } + to { + transform: rotate(1080deg); } } + +/** +* HACK: Even though the intention is to have the current .mdl-spinner__layer-N +* at `opacity: 1`, we set it to `opacity: 0.99` instead since this forces Chrome +* to do proper subpixel rendering for the elements being animated. This is +* especially visible in Chrome 39 on Ubuntu 14.04. See: +* +* - https://github.com/Polymer/paper-spinner/issues/9 +* - https://code.google.com/p/chromium/issues/detail?id=436255 +*/ +@keyframes mdl-spinner__layer-1-fade-in-out { + from { + opacity: 0.99; } + 25% { + opacity: 0.99; } + 26% { + opacity: 0; } + 89% { + opacity: 0; } + 90% { + opacity: 0.99; } + 100% { + opacity: 0.99; } } + +@keyframes mdl-spinner__layer-2-fade-in-out { + from { + opacity: 0; } + 15% { + opacity: 0; } + 25% { + opacity: 0.99; } + 50% { + opacity: 0.99; } + 51% { + opacity: 0; } } + +@keyframes mdl-spinner__layer-3-fade-in-out { + from { + opacity: 0; } + 40% { + opacity: 0; } + 50% { + opacity: 0.99; } + 75% { + opacity: 0.99; } + 76% { + opacity: 0; } } + +@keyframes mdl-spinner__layer-4-fade-in-out { + from { + opacity: 0; } + 65% { + opacity: 0; } + 75% { + opacity: 0.99; } + 90% { + opacity: 0.99; } + 100% { + opacity: 0; } } + +/** +* Patch the gap that appear between the two adjacent +* div.mdl-spinner__circle-clipper while the spinner is rotating +* (appears on Chrome 38, Safari 7.1, and IE 11). +* +* Update: the gap no longer appears on Chrome when .mdl-spinner__layer-N's +* opacity is 0.99, but still does on Safari and IE. +*/ +.mdl-spinner__gap-patch { + position: absolute; + box-sizing: border-box; + top: 0; + left: 45%; + width: 10%; + height: 100%; + overflow: hidden; + border-color: inherit; } + .mdl-spinner__gap-patch .mdl-spinner__circle { + width: 1000%; + left: -450%; } + +.mdl-spinner__circle-clipper { + display: inline-block; + position: relative; + width: 50%; + height: 100%; + overflow: hidden; + border-color: inherit; } + .mdl-spinner__circle-clipper .mdl-spinner__circle { + width: 200%; } + +.mdl-spinner__circle { + box-sizing: border-box; + height: 100%; + border-width: 3px; + border-style: solid; + border-color: inherit; + border-bottom-color: transparent !important; + border-radius: 50%; + animation: none; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; } + .mdl-spinner__left .mdl-spinner__circle { + border-right-color: transparent !important; + transform: rotate(129deg); } + .mdl-spinner.is-active .mdl-spinner__left .mdl-spinner__circle { + animation: mdl-spinner__left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + .mdl-spinner__right .mdl-spinner__circle { + left: -100%; + border-left-color: transparent !important; + transform: rotate(-129deg); } + .mdl-spinner.is-active .mdl-spinner__right .mdl-spinner__circle { + animation: mdl-spinner__right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +@keyframes mdl-spinner__left-spin { + from { + transform: rotate(130deg); } + 50% { + transform: rotate(-5deg); } + to { + transform: rotate(130deg); } } + +@keyframes mdl-spinner__right-spin { + from { + transform: rotate(-130deg); } + 50% { + transform: rotate(5deg); } + to { + transform: rotate(-130deg); } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-switch { + position: relative; + z-index: 1; + vertical-align: middle; + display: inline-block; + box-sizing: border-box; + width: 100%; + height: 24px; + margin: 0; + padding: 0; + overflow: visible; + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .mdl-switch.is-upgraded { + padding-left: 28px; } + +.mdl-switch__input { + line-height: 24px; } + .mdl-switch.is-upgraded .mdl-switch__input { + position: absolute; + width: 0; + height: 0; + margin: 0; + padding: 0; + opacity: 0; + -ms-appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + border: none; } + +.mdl-switch__track { + background: rgba(0,0,0, 0.26); + position: absolute; + left: 0; + top: 5px; + height: 14px; + width: 36px; + border-radius: 14px; + cursor: pointer; } + .mdl-switch.is-checked .mdl-switch__track { + background: rgba(0, 188, 212, 0.5); } + .mdl-switch__track fieldset[disabled] .mdl-switch, + .mdl-switch.is-disabled .mdl-switch__track { + background: rgba(0,0,0, 0.12); + cursor: auto; } + +.mdl-switch__thumb { + background: rgb(250,250,250); + position: absolute; + left: 0; + top: 2px; + height: 20px; + width: 20px; + border-radius: 50%; + cursor: pointer; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); + transition-duration: 0.28s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-property: left; } + .mdl-switch.is-checked .mdl-switch__thumb { + background: rgb(0, 188, 212); + left: 16px; + box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12); } + .mdl-switch__thumb fieldset[disabled] .mdl-switch, + .mdl-switch.is-disabled .mdl-switch__thumb { + background: rgb(189,189,189); + cursor: auto; } + +.mdl-switch__focus-helper { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-4px, -4px); + display: inline-block; + box-sizing: border-box; + width: 8px; + height: 8px; + border-radius: 50%; + background-color: transparent; } + .mdl-switch.is-focused .mdl-switch__focus-helper { + box-shadow: 0 0 0px 20px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); } + .mdl-switch.is-focused.is-checked .mdl-switch__focus-helper { + box-shadow: 0 0 0px 20px rgba(0, 188, 212, 0.26); + background-color: rgba(0, 188, 212, 0.26); } + +.mdl-switch__label { + position: relative; + cursor: pointer; + font-size: 16px; + line-height: 24px; + margin: 0; + left: 24px; } + .mdl-switch__label fieldset[disabled] .mdl-switch, + .mdl-switch.is-disabled .mdl-switch__label { + color: rgb(189,189,189); + cursor: auto; } + +.mdl-switch__ripple-container { + position: absolute; + z-index: 2; + top: -12px; + left: -14px; + box-sizing: border-box; + width: 48px; + height: 48px; + border-radius: 50%; + cursor: pointer; + overflow: hidden; + -webkit-mask-image: -webkit-radial-gradient(circle, white, black); + transition-duration: 0.40s; + transition-timing-function: step-end; + transition-property: left; } + .mdl-switch__ripple-container .mdl-ripple { + background: rgb(0, 188, 212); } + .mdl-switch__ripple-container fieldset[disabled] .mdl-switch, + .mdl-switch.is-disabled .mdl-switch__ripple-container { + cursor: auto; } + fieldset[disabled] .mdl-switch .mdl-switch__ripple-container .mdl-ripple, + .mdl-switch.is-disabled .mdl-switch__ripple-container .mdl-ripple { + background: transparent; } + .mdl-switch.is-checked .mdl-switch__ripple-container { + left: 2px; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-tabs { + display: block; + width: 100%; } + +.mdl-tabs__tab-bar { + display: flex; + flex-direction: row; + justify-content: center; + align-content: space-between; + align-items: flex-start; + height: 48px; + padding: 0 0 0 0; + margin: 0; + border-bottom: 1px solid rgb(224,224,224); } + +.mdl-tabs__tab { + margin: 0; + border: none; + padding: 0 24px 0 24px; + float: left; + position: relative; + display: block; + text-decoration: none; + height: 48px; + line-height: 48px; + text-align: center; + font-weight: 500; + font-size: 14px; + text-transform: uppercase; + color: rgba(0,0,0, 0.54); + overflow: hidden; } + .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active { + color: rgba(0,0,0, 0.87); } + .mdl-tabs.is-upgraded .mdl-tabs__tab.is-active:after { + height: 2px; + width: 100%; + display: block; + content: " "; + bottom: 0px; + left: 0px; + position: absolute; + background: rgb(0, 188, 212); + animation: border-expand 0.2s cubic-bezier(0.4, 0, 0.4, 1) 0.01s alternate forwards; + transition: all 1s cubic-bezier(0.4, 0, 1, 1); } + .mdl-tabs__tab .mdl-tabs__ripple-container { + display: block; + position: absolute; + height: 100%; + width: 100%; + left: 0px; + top: 0px; + z-index: 1; + overflow: hidden; } + .mdl-tabs__tab .mdl-tabs__ripple-container .mdl-ripple { + background: rgb(0, 188, 212); } + +.mdl-tabs__panel { + display: block; } + .mdl-tabs.is-upgraded .mdl-tabs__panel { + display: none; } + .mdl-tabs.is-upgraded .mdl-tabs__panel.is-active { + display: block; } + +@keyframes border-expand { + 0% { + opacity: 0; + width: 0; } + 100% { + opacity: 1; + width: 100%; } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-textfield { + position: relative; + font-size: 16px; + display: inline-block; + box-sizing: border-box; + width: 300px; + max-width: 100%; + margin: 0; + padding: 20px 0; } + .mdl-textfield .mdl-button { + position: absolute; + bottom: 20px; } + +.mdl-textfield--align-right { + text-align: right; } + +.mdl-textfield--full-width { + width: 100%; } + +.mdl-textfield--expandable { + min-width: 32px; + width: auto; + min-height: 32px; } + +.mdl-textfield__input { + border: none; + border-bottom: 1px solid rgba(255, 255, 255, 0.2); + display: block; + font-size: 16px; + font-family: "Helvetica", "Arial", sans-serif; + margin: 0; + padding: 4px 0; + width: 100%; + background: none; + text-align: left; + color: inherit; } + .mdl-textfield__input[type="number"] { + -moz-appearance: textfield; } + .mdl-textfield__input[type="number"]::-webkit-inner-spin-button, .mdl-textfield__input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; } + .mdl-textfield.is-focused .mdl-textfield__input { + outline: none; } + .mdl-textfield.is-invalid .mdl-textfield__input { + border-color: rgb(213,0,0); + box-shadow: none; } + fieldset[disabled] .mdl-textfield .mdl-textfield__input, + .mdl-textfield.is-disabled .mdl-textfield__input { + background-color: transparent; + border-bottom: 1px dotted rgba(255, 255, 255, 0.2); + color: rgba(255, 255, 255, 0.6); } + +.mdl-textfield textarea.mdl-textfield__input { + display: block; } + +.mdl-textfield__label { + bottom: 0; + color: rgba(0,0,0, 0.26); + font-size: 16px; + left: 0; + right: 0; + pointer-events: none; + position: absolute; + display: block; + top: 24px; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-align: left; } + .mdl-textfield.is-dirty .mdl-textfield__label { + visibility: hidden; } + .mdl-textfield--floating-label .mdl-textfield__label { + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } + fieldset[disabled] .mdl-textfield .mdl-textfield__label, + .mdl-textfield.is-disabled.is-disabled .mdl-textfield__label { + color: rgba(255, 255, 255, 0.6); } + .mdl-textfield--floating-label.is-focused .mdl-textfield__label, + .mdl-textfield--floating-label.is-dirty .mdl-textfield__label { + color: rgb(0, 188, 212); + font-size: 12px; + top: 4px; + visibility: visible; } + .mdl-textfield--floating-label.is-focused .mdl-textfield__expandable-holder .mdl-textfield__label, + .mdl-textfield--floating-label.is-dirty .mdl-textfield__expandable-holder .mdl-textfield__label { + top: -16px; } + .mdl-textfield--floating-label.is-invalid .mdl-textfield__label { + color: rgb(213,0,0); + font-size: 12px; } + .mdl-textfield__label:after { + background-color: rgb(0, 188, 212); + bottom: 20px; + content: ''; + height: 2px; + left: 45%; + position: absolute; + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + visibility: hidden; + width: 10px; } + .mdl-textfield.is-focused .mdl-textfield__label:after { + left: 0; + visibility: visible; + width: 100%; } + .mdl-textfield.is-invalid .mdl-textfield__label:after { + background-color: rgb(213,0,0); } + +.mdl-textfield__error { + color: rgb(213,0,0); + position: absolute; + font-size: 12px; + margin-top: 3px; + visibility: hidden; + display: block; } + .mdl-textfield.is-invalid .mdl-textfield__error { + visibility: visible; } + +.mdl-textfield__expandable-holder { + display: inline-block; + position: relative; + margin-left: 32px; + transition-duration: 0.2s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + display: inline-block; + max-width: 0.1px; } + .mdl-textfield.is-focused .mdl-textfield__expandable-holder, .mdl-textfield.is-dirty .mdl-textfield__expandable-holder { + max-width: 600px; } + .mdl-textfield__expandable-holder .mdl-textfield__label:after { + bottom: 0; } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-tooltip { + transform: scale(0); + transform-origin: top center; + will-change: transform; + z-index: 999; + background: #353535; + border-radius: 2px; + color: rgb(255,255,255); + display: inline-block; + font-size: 12px; + font-weight: 500; + line-height: 14px; + max-width: 170px; + position: fixed; + top: -500px; + left: -500px; + padding: 8px; + text-align: center; } + +.mdl-tooltip.is-active { + animation: pulse 200ms cubic-bezier(0, 0, 0.2, 1) forwards; } + +.mdl-tooltip--large { + line-height: 14px; + font-size: 14px; + padding: 16px; } + +@keyframes pulse { + 0% { + transform: scale(0); + opacity: 0; } + 50% { + transform: scale(0.99); } + 100% { + transform: scale(1); + opacity: 1; + visibility: visible; } } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Typography */ +/* Shadows */ +/* Animations */ +/* Dialog */ +.mdl-shadow--2dp { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + +.mdl-shadow--3dp { + box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12); } + +.mdl-shadow--4dp { + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2); } + +.mdl-shadow--6dp { + box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1px rgba(0, 0, 0, 0.2); } + +.mdl-shadow--8dp { + box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); } + +.mdl-shadow--16dp { + box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); } + +.mdl-shadow--24dp { + box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2); } + +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* +* NOTE: Some rules here are applied using duplicate selectors. +* This is on purpose to increase their specificity when applied. +* For example: `.mdl-cell--1-col-phone.mdl-cell--1-col-phone` +*/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*------------------------------------* $CONTENTS +\*------------------------------------*/ +/** + * STYLE GUIDE VARIABLES------------------Declarations of Sass variables + * -----Typography + * -----Colors + * -----Textfield + * -----Switch + * -----Spinner + * -----Radio + * -----Menu + * -----List + * -----Layout + * -----Icon toggles + * -----Footer + * -----Column + * -----Checkbox + * -----Card + * -----Button + * -----Animation + * -----Progress + * -----Badge + * -----Shadows + * -----Grid + * -----Data table + * -----Dialog + * -----Snackbar + * + * Even though all variables have the `!default` directive, most of them + * should not be changed as they are dependent one another. This can cause + * visual distortions (like alignment issues) that are hard to track down + * and fix. + */ +/* ========== TYPOGRAPHY ========== */ +/* We're splitting fonts into "preferred" and "performance" in order to optimize + page loading. For important text, such as the body, we want it to load + immediately and not wait for the web font load, whereas for other sections, + such as headers and titles, we're OK with things taking a bit longer to load. + We do have some optional classes and parameters in the mixins, in case you + definitely want to make sure you're using the preferred font and don't mind + the performance hit. + We should be able to improve on this once CSS Font Loading L3 becomes more + widely available. +*/ +/* ========== COLORS ========== */ +/** +* +* Material design color palettes. +* @see http://www.google.com/design/spec/style/color.html +* +**/ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== Color Palettes ========== */ +/* colors.scss */ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* ========== IMAGES ========== */ +/* ========== Color & Themes ========== */ +/* ========== Typography ========== */ +/* ========== Components ========== */ +/* ========== Standard Buttons ========== */ +/* ========== Icon Toggles ========== */ +/* ========== Radio Buttons ========== */ +/* ========== Ripple effect ========== */ +/* ========== Layout ========== */ +/* ========== Content Tabs ========== */ +/* ========== Checkboxes ========== */ +/* ========== Switches ========== */ +/* ========== Spinner ========== */ +/* ========== Text fields ========== */ +/* ========== Card ========== */ +/* ========== Sliders ========== */ +/* ========== Progress ========== */ +/* ========== List ========== */ +/* ========== Item ========== */ +/* ========== Dropdown menu ========== */ +/* ========== Tooltips ========== */ +/* ========== Footer ========== */ +/* TEXTFIELD */ +/* SWITCH */ +/* SPINNER */ +/* RADIO */ +/* MENU */ +/* LIST */ +/* LAYOUT */ +/* ICON TOGGLE */ +/* FOOTER */ +/*mega-footer*/ +/*mini-footer*/ +/* CHECKBOX */ +/* CARD */ +/* Card dimensions */ +/* Cover image */ +/* BUTTON */ +/** + * + * Dimensions + * + */ +/* ANIMATION */ +/* PROGRESS */ +/* BADGE */ +/* SHADOWS */ +/* GRID */ +/* DATA TABLE */ +/* DIALOG */ +/* SNACKBAR */ +/* TOOLTIP */ +.mdl-grid { + display: flex; + flex-flow: row wrap; + margin: 0 auto 0 auto; + align-items: stretch; } + .mdl-grid.mdl-grid--no-spacing { + padding: 0; } + +.mdl-cell { + box-sizing: border-box; } + +.mdl-cell--top { + align-self: flex-start; } + +.mdl-cell--middle { + align-self: center; } + +.mdl-cell--bottom { + align-self: flex-end; } + +.mdl-cell--stretch { + align-self: stretch; } + +.mdl-grid.mdl-grid--no-spacing > .mdl-cell { + margin: 0; } + +.mdl-cell--order-1 { + order: 1; } + +.mdl-cell--order-2 { + order: 2; } + +.mdl-cell--order-3 { + order: 3; } + +.mdl-cell--order-4 { + order: 4; } + +.mdl-cell--order-5 { + order: 5; } + +.mdl-cell--order-6 { + order: 6; } + +.mdl-cell--order-7 { + order: 7; } + +.mdl-cell--order-8 { + order: 8; } + +.mdl-cell--order-9 { + order: 9; } + +.mdl-cell--order-10 { + order: 10; } + +.mdl-cell--order-11 { + order: 11; } + +.mdl-cell--order-12 { + order: 12; } + +@media (max-width: 1151px) { + .mdl-grid { + padding: 0px; } + .mdl-cell { + margin: 16px; + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell { + width: 100%; } + .mdl-cell--hide-phone { + display: none !important; } + .mdl-cell--order-1-phone.mdl-cell--order-1-phone { + order: 1; } + .mdl-cell--order-2-phone.mdl-cell--order-2-phone { + order: 2; } + .mdl-cell--order-3-phone.mdl-cell--order-3-phone { + order: 3; } + .mdl-cell--order-4-phone.mdl-cell--order-4-phone { + order: 4; } + .mdl-cell--order-5-phone.mdl-cell--order-5-phone { + order: 5; } + .mdl-cell--order-6-phone.mdl-cell--order-6-phone { + order: 6; } + .mdl-cell--order-7-phone.mdl-cell--order-7-phone { + order: 7; } + .mdl-cell--order-8-phone.mdl-cell--order-8-phone { + order: 8; } + .mdl-cell--order-9-phone.mdl-cell--order-9-phone { + order: 9; } + .mdl-cell--order-10-phone.mdl-cell--order-10-phone { + order: 10; } + .mdl-cell--order-11-phone.mdl-cell--order-11-phone { + order: 11; } + .mdl-cell--order-12-phone.mdl-cell--order-12-phone { + order: 12; } + .mdl-cell--1-col, + .mdl-cell--1-col-phone.mdl-cell--1-col-phone { + width: calc(25% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--1-col, .mdl-grid--no-spacing > + .mdl-cell--1-col-phone.mdl-cell--1-col-phone { + width: 25%; } + .mdl-cell--2-col, + .mdl-cell--2-col-phone.mdl-cell--2-col-phone { + width: calc(50% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--2-col, .mdl-grid--no-spacing > + .mdl-cell--2-col-phone.mdl-cell--2-col-phone { + width: 50%; } + .mdl-cell--3-col, + .mdl-cell--3-col-phone.mdl-cell--3-col-phone { + width: calc(75% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--3-col, .mdl-grid--no-spacing > + .mdl-cell--3-col-phone.mdl-cell--3-col-phone { + width: 75%; } + .mdl-cell--4-col, + .mdl-cell--4-col-phone.mdl-cell--4-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--4-col, .mdl-grid--no-spacing > + .mdl-cell--4-col-phone.mdl-cell--4-col-phone { + width: 100%; } + .mdl-cell--5-col, + .mdl-cell--5-col-phone.mdl-cell--5-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--5-col, .mdl-grid--no-spacing > + .mdl-cell--5-col-phone.mdl-cell--5-col-phone { + width: 100%; } + .mdl-cell--6-col, + .mdl-cell--6-col-phone.mdl-cell--6-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--6-col, .mdl-grid--no-spacing > + .mdl-cell--6-col-phone.mdl-cell--6-col-phone { + width: 100%; } + .mdl-cell--7-col, + .mdl-cell--7-col-phone.mdl-cell--7-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--7-col, .mdl-grid--no-spacing > + .mdl-cell--7-col-phone.mdl-cell--7-col-phone { + width: 100%; } + .mdl-cell--8-col, + .mdl-cell--8-col-phone.mdl-cell--8-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--8-col, .mdl-grid--no-spacing > + .mdl-cell--8-col-phone.mdl-cell--8-col-phone { + width: 100%; } + .mdl-cell--9-col, + .mdl-cell--9-col-phone.mdl-cell--9-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--9-col, .mdl-grid--no-spacing > + .mdl-cell--9-col-phone.mdl-cell--9-col-phone { + width: 100%; } + .mdl-cell--10-col, + .mdl-cell--10-col-phone.mdl-cell--10-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--10-col, .mdl-grid--no-spacing > + .mdl-cell--10-col-phone.mdl-cell--10-col-phone { + width: 100%; } + .mdl-cell--11-col, + .mdl-cell--11-col-phone.mdl-cell--11-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--11-col, .mdl-grid--no-spacing > + .mdl-cell--11-col-phone.mdl-cell--11-col-phone { + width: 100%; } + .mdl-cell--12-col, + .mdl-cell--12-col-phone.mdl-cell--12-col-phone { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--12-col, .mdl-grid--no-spacing > + .mdl-cell--12-col-phone.mdl-cell--12-col-phone { + width: 100%; } + .mdl-cell--1-offset, + .mdl-cell--1-offset-phone.mdl-cell--1-offset-phone { + margin-left: calc(25% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--1-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--1-offset-phone.mdl-cell--1-offset-phone { + margin-left: 25%; } + .mdl-cell--2-offset, + .mdl-cell--2-offset-phone.mdl-cell--2-offset-phone { + margin-left: calc(50% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--2-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--2-offset-phone.mdl-cell--2-offset-phone { + margin-left: 50%; } + .mdl-cell--3-offset, + .mdl-cell--3-offset-phone.mdl-cell--3-offset-phone { + margin-left: calc(75% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--3-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--3-offset-phone.mdl-cell--3-offset-phone { + margin-left: 75%; } } + +@media (min-width: 1152px) and (max-width: 1919px) { + .mdl-grid { + padding: 0px; } + .mdl-cell { + margin: 16px; + width: calc(33.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell { + width: 33.33333%; } + .mdl-cell--hide-tablet { + display: none !important; } + .mdl-cell--order-1-tablet.mdl-cell--order-1-tablet { + order: 1; } + .mdl-cell--order-2-tablet.mdl-cell--order-2-tablet { + order: 2; } + .mdl-cell--order-3-tablet.mdl-cell--order-3-tablet { + order: 3; } + .mdl-cell--order-4-tablet.mdl-cell--order-4-tablet { + order: 4; } + .mdl-cell--order-5-tablet.mdl-cell--order-5-tablet { + order: 5; } + .mdl-cell--order-6-tablet.mdl-cell--order-6-tablet { + order: 6; } + .mdl-cell--order-7-tablet.mdl-cell--order-7-tablet { + order: 7; } + .mdl-cell--order-8-tablet.mdl-cell--order-8-tablet { + order: 8; } + .mdl-cell--order-9-tablet.mdl-cell--order-9-tablet { + order: 9; } + .mdl-cell--order-10-tablet.mdl-cell--order-10-tablet { + order: 10; } + .mdl-cell--order-11-tablet.mdl-cell--order-11-tablet { + order: 11; } + .mdl-cell--order-12-tablet.mdl-cell--order-12-tablet { + order: 12; } + .mdl-cell--1-col, + .mdl-cell--1-col-tablet.mdl-cell--1-col-tablet { + width: calc(8.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--1-col, .mdl-grid--no-spacing > + .mdl-cell--1-col-tablet.mdl-cell--1-col-tablet { + width: 8.33333%; } + .mdl-cell--2-col, + .mdl-cell--2-col-tablet.mdl-cell--2-col-tablet { + width: calc(16.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--2-col, .mdl-grid--no-spacing > + .mdl-cell--2-col-tablet.mdl-cell--2-col-tablet { + width: 16.66667%; } + .mdl-cell--3-col, + .mdl-cell--3-col-tablet.mdl-cell--3-col-tablet { + width: calc(25% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--3-col, .mdl-grid--no-spacing > + .mdl-cell--3-col-tablet.mdl-cell--3-col-tablet { + width: 25%; } + .mdl-cell--4-col, + .mdl-cell--4-col-tablet.mdl-cell--4-col-tablet { + width: calc(33.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--4-col, .mdl-grid--no-spacing > + .mdl-cell--4-col-tablet.mdl-cell--4-col-tablet { + width: 33.33333%; } + .mdl-cell--5-col, + .mdl-cell--5-col-tablet.mdl-cell--5-col-tablet { + width: calc(41.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--5-col, .mdl-grid--no-spacing > + .mdl-cell--5-col-tablet.mdl-cell--5-col-tablet { + width: 41.66667%; } + .mdl-cell--6-col, + .mdl-cell--6-col-tablet.mdl-cell--6-col-tablet { + width: calc(50% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--6-col, .mdl-grid--no-spacing > + .mdl-cell--6-col-tablet.mdl-cell--6-col-tablet { + width: 50%; } + .mdl-cell--7-col, + .mdl-cell--7-col-tablet.mdl-cell--7-col-tablet { + width: calc(58.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--7-col, .mdl-grid--no-spacing > + .mdl-cell--7-col-tablet.mdl-cell--7-col-tablet { + width: 58.33333%; } + .mdl-cell--8-col, + .mdl-cell--8-col-tablet.mdl-cell--8-col-tablet { + width: calc(66.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--8-col, .mdl-grid--no-spacing > + .mdl-cell--8-col-tablet.mdl-cell--8-col-tablet { + width: 66.66667%; } + .mdl-cell--9-col, + .mdl-cell--9-col-tablet.mdl-cell--9-col-tablet { + width: calc(75% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--9-col, .mdl-grid--no-spacing > + .mdl-cell--9-col-tablet.mdl-cell--9-col-tablet { + width: 75%; } + .mdl-cell--10-col, + .mdl-cell--10-col-tablet.mdl-cell--10-col-tablet { + width: calc(83.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--10-col, .mdl-grid--no-spacing > + .mdl-cell--10-col-tablet.mdl-cell--10-col-tablet { + width: 83.33333%; } + .mdl-cell--11-col, + .mdl-cell--11-col-tablet.mdl-cell--11-col-tablet { + width: calc(91.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--11-col, .mdl-grid--no-spacing > + .mdl-cell--11-col-tablet.mdl-cell--11-col-tablet { + width: 91.66667%; } + .mdl-cell--12-col, + .mdl-cell--12-col-tablet.mdl-cell--12-col-tablet { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--12-col, .mdl-grid--no-spacing > + .mdl-cell--12-col-tablet.mdl-cell--12-col-tablet { + width: 100%; } + .mdl-cell--1-offset, + .mdl-cell--1-offset-tablet.mdl-cell--1-offset-tablet { + margin-left: calc(8.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--1-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--1-offset-tablet.mdl-cell--1-offset-tablet { + margin-left: 8.33333%; } + .mdl-cell--2-offset, + .mdl-cell--2-offset-tablet.mdl-cell--2-offset-tablet { + margin-left: calc(16.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--2-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--2-offset-tablet.mdl-cell--2-offset-tablet { + margin-left: 16.66667%; } + .mdl-cell--3-offset, + .mdl-cell--3-offset-tablet.mdl-cell--3-offset-tablet { + margin-left: calc(25% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--3-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--3-offset-tablet.mdl-cell--3-offset-tablet { + margin-left: 25%; } + .mdl-cell--4-offset, + .mdl-cell--4-offset-tablet.mdl-cell--4-offset-tablet { + margin-left: calc(33.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--4-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--4-offset-tablet.mdl-cell--4-offset-tablet { + margin-left: 33.33333%; } + .mdl-cell--5-offset, + .mdl-cell--5-offset-tablet.mdl-cell--5-offset-tablet { + margin-left: calc(41.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--5-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--5-offset-tablet.mdl-cell--5-offset-tablet { + margin-left: 41.66667%; } + .mdl-cell--6-offset, + .mdl-cell--6-offset-tablet.mdl-cell--6-offset-tablet { + margin-left: calc(50% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--6-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--6-offset-tablet.mdl-cell--6-offset-tablet { + margin-left: 50%; } + .mdl-cell--7-offset, + .mdl-cell--7-offset-tablet.mdl-cell--7-offset-tablet { + margin-left: calc(58.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--7-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--7-offset-tablet.mdl-cell--7-offset-tablet { + margin-left: 58.33333%; } + .mdl-cell--8-offset, + .mdl-cell--8-offset-tablet.mdl-cell--8-offset-tablet { + margin-left: calc(66.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--8-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--8-offset-tablet.mdl-cell--8-offset-tablet { + margin-left: 66.66667%; } + .mdl-cell--9-offset, + .mdl-cell--9-offset-tablet.mdl-cell--9-offset-tablet { + margin-left: calc(75% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--9-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--9-offset-tablet.mdl-cell--9-offset-tablet { + margin-left: 75%; } + .mdl-cell--10-offset, + .mdl-cell--10-offset-tablet.mdl-cell--10-offset-tablet { + margin-left: calc(83.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--10-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--10-offset-tablet.mdl-cell--10-offset-tablet { + margin-left: 83.33333%; } + .mdl-cell--11-offset, + .mdl-cell--11-offset-tablet.mdl-cell--11-offset-tablet { + margin-left: calc(91.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--11-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--11-offset-tablet.mdl-cell--11-offset-tablet { + margin-left: 91.66667%; } } + +@media (min-width: 1920px) { + .mdl-grid { + padding: 0px; } + .mdl-cell { + margin: 16px; + width: calc(33.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell { + width: 33.33333%; } + .mdl-cell--hide-desktop { + display: none !important; } + .mdl-cell--order-1-desktop.mdl-cell--order-1-desktop { + order: 1; } + .mdl-cell--order-2-desktop.mdl-cell--order-2-desktop { + order: 2; } + .mdl-cell--order-3-desktop.mdl-cell--order-3-desktop { + order: 3; } + .mdl-cell--order-4-desktop.mdl-cell--order-4-desktop { + order: 4; } + .mdl-cell--order-5-desktop.mdl-cell--order-5-desktop { + order: 5; } + .mdl-cell--order-6-desktop.mdl-cell--order-6-desktop { + order: 6; } + .mdl-cell--order-7-desktop.mdl-cell--order-7-desktop { + order: 7; } + .mdl-cell--order-8-desktop.mdl-cell--order-8-desktop { + order: 8; } + .mdl-cell--order-9-desktop.mdl-cell--order-9-desktop { + order: 9; } + .mdl-cell--order-10-desktop.mdl-cell--order-10-desktop { + order: 10; } + .mdl-cell--order-11-desktop.mdl-cell--order-11-desktop { + order: 11; } + .mdl-cell--order-12-desktop.mdl-cell--order-12-desktop { + order: 12; } + .mdl-cell--1-col, + .mdl-cell--1-col-desktop.mdl-cell--1-col-desktop { + width: calc(8.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--1-col, .mdl-grid--no-spacing > + .mdl-cell--1-col-desktop.mdl-cell--1-col-desktop { + width: 8.33333%; } + .mdl-cell--2-col, + .mdl-cell--2-col-desktop.mdl-cell--2-col-desktop { + width: calc(16.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--2-col, .mdl-grid--no-spacing > + .mdl-cell--2-col-desktop.mdl-cell--2-col-desktop { + width: 16.66667%; } + .mdl-cell--3-col, + .mdl-cell--3-col-desktop.mdl-cell--3-col-desktop { + width: calc(25% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--3-col, .mdl-grid--no-spacing > + .mdl-cell--3-col-desktop.mdl-cell--3-col-desktop { + width: 25%; } + .mdl-cell--4-col, + .mdl-cell--4-col-desktop.mdl-cell--4-col-desktop { + width: calc(33.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--4-col, .mdl-grid--no-spacing > + .mdl-cell--4-col-desktop.mdl-cell--4-col-desktop { + width: 33.33333%; } + .mdl-cell--5-col, + .mdl-cell--5-col-desktop.mdl-cell--5-col-desktop { + width: calc(41.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--5-col, .mdl-grid--no-spacing > + .mdl-cell--5-col-desktop.mdl-cell--5-col-desktop { + width: 41.66667%; } + .mdl-cell--6-col, + .mdl-cell--6-col-desktop.mdl-cell--6-col-desktop { + width: calc(50% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--6-col, .mdl-grid--no-spacing > + .mdl-cell--6-col-desktop.mdl-cell--6-col-desktop { + width: 50%; } + .mdl-cell--7-col, + .mdl-cell--7-col-desktop.mdl-cell--7-col-desktop { + width: calc(58.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--7-col, .mdl-grid--no-spacing > + .mdl-cell--7-col-desktop.mdl-cell--7-col-desktop { + width: 58.33333%; } + .mdl-cell--8-col, + .mdl-cell--8-col-desktop.mdl-cell--8-col-desktop { + width: calc(66.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--8-col, .mdl-grid--no-spacing > + .mdl-cell--8-col-desktop.mdl-cell--8-col-desktop { + width: 66.66667%; } + .mdl-cell--9-col, + .mdl-cell--9-col-desktop.mdl-cell--9-col-desktop { + width: calc(75% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--9-col, .mdl-grid--no-spacing > + .mdl-cell--9-col-desktop.mdl-cell--9-col-desktop { + width: 75%; } + .mdl-cell--10-col, + .mdl-cell--10-col-desktop.mdl-cell--10-col-desktop { + width: calc(83.33333% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--10-col, .mdl-grid--no-spacing > + .mdl-cell--10-col-desktop.mdl-cell--10-col-desktop { + width: 83.33333%; } + .mdl-cell--11-col, + .mdl-cell--11-col-desktop.mdl-cell--11-col-desktop { + width: calc(91.66667% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--11-col, .mdl-grid--no-spacing > + .mdl-cell--11-col-desktop.mdl-cell--11-col-desktop { + width: 91.66667%; } + .mdl-cell--12-col, + .mdl-cell--12-col-desktop.mdl-cell--12-col-desktop { + width: calc(100% - 32px); } + .mdl-grid--no-spacing > .mdl-cell--12-col, .mdl-grid--no-spacing > + .mdl-cell--12-col-desktop.mdl-cell--12-col-desktop { + width: 100%; } + .mdl-cell--1-offset, + .mdl-cell--1-offset-desktop.mdl-cell--1-offset-desktop { + margin-left: calc(8.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--1-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--1-offset-desktop.mdl-cell--1-offset-desktop { + margin-left: 8.33333%; } + .mdl-cell--2-offset, + .mdl-cell--2-offset-desktop.mdl-cell--2-offset-desktop { + margin-left: calc(16.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--2-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--2-offset-desktop.mdl-cell--2-offset-desktop { + margin-left: 16.66667%; } + .mdl-cell--3-offset, + .mdl-cell--3-offset-desktop.mdl-cell--3-offset-desktop { + margin-left: calc(25% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--3-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--3-offset-desktop.mdl-cell--3-offset-desktop { + margin-left: 25%; } + .mdl-cell--4-offset, + .mdl-cell--4-offset-desktop.mdl-cell--4-offset-desktop { + margin-left: calc(33.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--4-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--4-offset-desktop.mdl-cell--4-offset-desktop { + margin-left: 33.33333%; } + .mdl-cell--5-offset, + .mdl-cell--5-offset-desktop.mdl-cell--5-offset-desktop { + margin-left: calc(41.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--5-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--5-offset-desktop.mdl-cell--5-offset-desktop { + margin-left: 41.66667%; } + .mdl-cell--6-offset, + .mdl-cell--6-offset-desktop.mdl-cell--6-offset-desktop { + margin-left: calc(50% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--6-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--6-offset-desktop.mdl-cell--6-offset-desktop { + margin-left: 50%; } + .mdl-cell--7-offset, + .mdl-cell--7-offset-desktop.mdl-cell--7-offset-desktop { + margin-left: calc(58.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--7-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--7-offset-desktop.mdl-cell--7-offset-desktop { + margin-left: 58.33333%; } + .mdl-cell--8-offset, + .mdl-cell--8-offset-desktop.mdl-cell--8-offset-desktop { + margin-left: calc(66.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--8-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--8-offset-desktop.mdl-cell--8-offset-desktop { + margin-left: 66.66667%; } + .mdl-cell--9-offset, + .mdl-cell--9-offset-desktop.mdl-cell--9-offset-desktop { + margin-left: calc(75% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--9-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--9-offset-desktop.mdl-cell--9-offset-desktop { + margin-left: 75%; } + .mdl-cell--10-offset, + .mdl-cell--10-offset-desktop.mdl-cell--10-offset-desktop { + margin-left: calc(83.33333% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--10-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--10-offset-desktop.mdl-cell--10-offset-desktop { + margin-left: 83.33333%; } + .mdl-cell--11-offset, + .mdl-cell--11-offset-desktop.mdl-cell--11-offset-desktop { + margin-left: calc(91.66667% + 16px); } + .mdl-grid.mdl-grid--no-spacing > .mdl-cell--11-offset, .mdl-grid.mdl-grid--no-spacing > + .mdl-cell--11-offset-desktop.mdl-cell--11-offset-desktop { + margin-left: 91.66667%; } } + +.mdl-layout { + background: #202020; } + +main { + background: url("../images/Dark_background_1920x1080.png") center top no-repeat; + background-size: cover; + margin-right: -18px; } + +.mdl-layout__header { + width: 100% !important; + margin-left: 0 !important; } + +.mdl-layout__drawer { + border: none; } + .mdl-layout__drawer header { + text-align: center; + text-transform: uppercase; + color: rgb(255, 255, 255); + height: 64px; + line-height: 64px; + background: rgba(0, 0, 0,0.85); + font-size: 25px; + font-weight: 500; + letter-spacing: 1px; } + .mdl-layout__drawer .mdl-navigation { + flex-grow: 1; + padding-top: 48px; + padding-bottom: 8px; } + .mdl-layout__drawer .mdl-navigation .mdl-layout-spacer { + border-bottom: 1px solid rgba(255,255,255, 0.1); + margin-bottom: 8px; } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 13px; + font-weight: 500; + padding: 12px 0; + position: relative; } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link .material-icons { + font-size: 22px; + width: 22px; } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link .material-icons { + margin: -3px 25px 0 23px; + color: rgba(255, 255, 255, 0.56); } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link--current { + border-left: 2px solid rgb(0, 188, 212); } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link--current .material-icons { + color: rgb(0, 188, 212); } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link:hover { + color: rgb(0, 188, 212); } + .mdl-layout__drawer .mdl-navigation .mdl-navigation__link:hover .material-icons { + color: rgb(0, 188, 212); } + +.mdl-layout__header-row { + color: rgba(255, 255, 255, 0.8); } + .mdl-layout__header-row .avatar-dropdown { + cursor: pointer; + margin: 0 10px; + padding: 0 20px; + line-height: 64px; } + .mdl-layout__header-row .avatar-dropdown:hover { + background: rgba(0, 0, 0, 0.3); } + .mdl-layout__header-row .avatar-dropdown > img { + width: 32px; + height: 32px; } + .mdl-layout__header-row .avatar-dropdown > span { + color: rgba(255, 255, 255, 0.5); + padding-right: 16px; } + .mdl-layout__header-row .mdl-textfield { + padding: 23px 0; } + .mdl-layout__header-row .mdl-button--icon:hover { + background: rgba(0, 0, 0, 0.3); } + .mdl-layout__header-row .material-icons.mdl-badge { + margin: 10px; + cursor: pointer; + overflow: visible; + text-align: center; + height: 24px; + width: 24px; + min-width: 0; + padding: 4px 4px; } + .mdl-layout__header-row .material-icons.mdl-badge:hover { + background: rgba(0, 0, 0, 0.3); } + .mdl-layout__header-row .material-icons.mdl-badge.mdl-badge--overlap:after { + top: -3px; + right: -8px; } + +@media screen and (max-width: 1440px) { + .mdl-layout--fixed-drawer > .mdl-layout__content { + margin-left: 0; } + .mdl-layout--fixed-drawer > .mdl-layout__drawer { + transform: translateX(-246px); } + .mdl-layout--fixed-drawer > .mdl-layout__drawer.is-visible { + transform: translateX(0) !important; } + .mdl-layout--fixed-drawer > .mdl-layout__drawer header { + height: 56px; + line-height: 56px; } + .mdl-layout__header-row .avatar-dropdown { + line-height: 56px; } } + +@media screen and (max-width: 799px) { + .mdl-grid > .mdl-grid .mdl-cell { + width: 100% !important; } + .mdl-layout__header-row .message, .mdl-layout__header-row .notification { + display: none; } } + +.mdl-card__title { + background-color: rgba(0, 0, 0, 0.3); } + +.mdl-card__supporting-text { + width: calc(100% - 32px); } + +.mdl-card__actions { + background-color: rgba(255, 255, 255,0.05); } + +.mdl-menu { + width: 310px; } + .mdl-menu .mdl-menu__item.mdl-list__item { + display: flex; } + +.mdl-menu__outline { + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2); } + +.mdl-checkbox__tick-outline { + -webkit-mask: url("../images/tick-mask.svg"); } + +.mdl-button { + font-weight: 400; + padding-top: 1px; } + .mdl-button.mdl-button--mini-icon .mdl-button--colored { + color: rgb(255, 82, 82); } + .mdl-button.mdl-button--mini-icon .material-icons { + top: 50% !important; + left: 50% !important; + font-size: 20px; } + +.mdl-card__actions .mdl-button--fab { + position: absolute; + right: 24px; + bottom: 24px; + z-index: 99; } + +a { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 300; + color: rgb(0, 188, 212); + text-decoration: none; } + +.mdl-textfield { + width: auto; } + .mdl-textfield .mdl-textfield__input { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; } + +.mdl-progress { + min-width: 100px; + width: auto; } + .mdl-progress > .bufferbar { + background-image: none; + background-color: rgba(255, 255, 255, 0.4); } + .mdl-progress:focus { + outline: none; } + +.mdl-data-table { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-weight: 300; + background-color: #4e4e4e; + color: rgb(255, 255, 255); + border: none; } + .mdl-data-table tr:last-child td { + border: none; } + .mdl-data-table td:first-of-type, .mdl-data-table th:first-of-type { + padding-left: 16px; } + .mdl-data-table td:last-of-type, .mdl-data-table th:last-of-type { + padding-right: 16px; } + .mdl-data-table tr:hover { + background-clip: padding-box; } + +.label { + background-color: rgba(255, 255, 255, 0.1); + color: white; + border-radius: 2px; + height: 12px; + padding: 5px 8px 5px 8px; + margin: 0; + margin-left: auto; + font-size: 12px; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-weight: 300; + line-height: 1em; } + .label--mini { + padding: 3px 8px 2px; + cursor: pointer; + vertical-align: middle; } + .label--transparent { + background-color: transparent; + padding: 0; } + +.projects-table { + width: 100%; } + .projects-table tbody td:nth-child(1) { + width: 1px; } + .projects-table tbody td:nth-child(2) { + width: 300px; } + .projects-table tbody td:nth-child(3) { + width: 240px; } + .projects-table tbody td:nth-child(4) { + width: 300px; } + .projects-table tbody td:nth-child(5) { + width: 200px; } + .projects-table tbody td:nth-child(6) { + width: 300px; } + .projects-table tbody td:nth-child(6) .mdl-progress { + cursor: pointer; + min-width: 80px; + max-width: 200px; } + .projects-table tbody .task-done { + padding-top: 6px !important; + padding-bottom: 0 !important; + color: rgb(255, 82, 82); } + .projects-table tbody .task-done .material-icons { + cursor: pointer; } + +@media screen and (max-width: 848px) { + .projects-table { + display: none; } } + +.mdl-tooltip { + padding: 5px 8px; + border: none; } + +.notifications-dropdown.mdl-list .mdl-list__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 100; + color: white; } + .notifications-dropdown.mdl-list .mdl-list__item:first-child { + color: rgba(255, 255, 255, 0.8); } + .notifications-dropdown.mdl-list .mdl-list__item .mdl-list__item-avatar { + padding: 4px; + text-align: center; } + .notifications-dropdown.mdl-list .mdl-list__item .mdl-list__item-avatar .material-icons { + vertical-align: top; } + .notifications-dropdown.mdl-list .mdl-list__item:last-child { + padding-top: 8px; + padding-bottom: 0; } + +.trending .mdl-card__supporting-text { + width: 100%; + padding: 8px 0; } + +.trending .mdl-list__item:hover { + background-color: rgba(0, 0, 0, 0.2); } + +.trending .mdl-list__item .mdl-list__item-secondary-content { + margin: 0; } + +.trending .material-icons { + line-height: 0.33333; + font-size: 48px; } + +.trending__arrow-up { + color: rgb(0, 188, 212); } + +.trending__arrow-down { + color: rgb(255, 82, 82); } + +.trending__percent { + text-align: right; + width: 40px; } + +.messages-dropdown .label { + color: rgba(255, 255, 255, 0.5); } + +.messages-dropdown .mdl-list__item-primary-content { + font-weight: 400; + line-height: 18px; } + .messages-dropdown .mdl-list__item-primary-content .mdl-list__item-avatar { + padding: 4px; + text-align: center; } + .messages-dropdown .mdl-list__item-primary-content .mdl-list__item-avatar .material-icons { + vertical-align: top; } + .messages-dropdown .mdl-list__item-primary-content .mdl-list__item-avatar text { + font-size: 19px; + vertical-align: middle; } + .messages-dropdown .mdl-list__item-primary-content .mdl-list__item-sub-title { + font-weight: 100; + font-size: 12px; } + +.messages-dropdown.mdl-list .mdl-list__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 100; + color: white; } + .messages-dropdown.mdl-list .mdl-list__item:first-child { + color: rgba(255, 255, 255, 0.8); } + .messages-dropdown.mdl-list .mdl-list__item:last-child { + padding-top: 8px; + padding-bottom: 0; } + +.mdl-list { + margin: 0; } + .mdl-list .mdl-list__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 300; + color: white; + letter-spacing: 0; } + .mdl-list .list__item--border-top { + background-clip: padding-box; + border-top: 1px solid rgba(255, 255, 255,0.1); } + +.todo .mdl-card__supporting-text { + width: 100%; + padding: 0; + min-height: 70px; } + .todo .mdl-card__supporting-text .mdl-list__item { + align-items: flex-start; + padding-bottom: 0; } + .todo .mdl-card__supporting-text .mdl-list__item .mdl-list__item-primary-content { + max-width: 100%; + word-wrap: break-word; } + .todo .mdl-card__supporting-text .mdl-list__item .material-icons { + visibility: hidden; } + .todo .mdl-card__supporting-text .mdl-list__item:hover .material-icons { + visibility: visible; } + .todo .mdl-card__supporting-text .mdl-checkbox { + height: auto; + padding-left: 36px; } + .todo .mdl-card__supporting-text .mdl-textfield { + width: 100%; + padding: 0; } + .todo .mdl-card__supporting-text .mdl-textfield__input { + padding: 2px 0; } + .todo .mdl-card__supporting-text .mdl-textfield__label { + color: rgba(255, 255, 255, 0.2); + top: 0; } + .todo .mdl-card__supporting-text .mdl-textfield__label:after { + background-color: rgba(255, 255, 255, 0.7); + bottom: 0; } + +.todo .mdl-card__actions { + margin-top: 20px; } + +.pie-chart__container { + display: flex; + flex-wrap: wrap; + justify-content: space-around; + align-items: center; + min-height: 228px; } + .pie-chart__container svg { + min-height: 200px; + max-width: 180px; } + .pie-chart__container svg .nvd3.nv-pie path { + fill-opacity: 1; + stroke-width: 0; } + .pie-chart__container svg .nvd3.nv-pie .nv-pie-title { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + fill: rgb(255,255,255); + font-weight: 300; + font-size: 22px !important; } + .pie-chart__container .legend { + max-width: 140px; } + +.line-chart__container { + min-height: 280px; } + .line-chart__container svg { + height: 280px; + width: 100%; } + .line-chart__container svg .y-axis-label, .line-chart__container svg .x-axis-label { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 12px; + font-weight: 300; + fill: rgba(255, 255, 255,0.5); } + .line-chart__container svg .nv-lineChart .nv-guideline { + stroke: rgba(255, 255, 255,0.5); + stroke-width: 0.5px; } + .line-chart__container svg .nv-lineChart .tick { + opacity: 0.1 !important; } + .line-chart__container svg .nv-lineChart .tick.zero { + opacity: 0.5 !important; } + .line-chart__container svg .nv-lineChart .tick.zero line { + stroke-opacity: 1 !important; } + .line-chart__container svg .nv-lineChart .nv-y .domain { + stroke-opacity: 0 !important; } + .line-chart__container svg .nv-lineChart .nvd3.nv-scatter .nv-groups .nv-point.hover { + stroke-width: 5px; } + .line-chart__container .legend { + margin: auto; + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-top: 16px; } + +.legend .legend__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-weight: 300; + font-size: 16px; + color: rgb(255,255,255); + margin: 8px 18px; + display: inline-block; } + .legend .legend__item .legend__text { + margin-left: 24px; } + .legend .legend__item .legend__mark { + width: 8px; + height: 8px; + margin-top: 4px; } + +.account-dropdown .mdl-list__item { + font-size: 14px; } + .account-dropdown .mdl-list__item:first-child { + font-size: 16px; + padding-top: 8px; + padding-bottom: 8px; + height: 64px; } + .account-dropdown .mdl-list__item:first-child .mdl-list__item-primary-content { + height: 48px; + line-height: 28px; } + .account-dropdown .mdl-list__item:first-child .mdl-list__item-primary-content .mdl-list__item-avatar { + height: 48px; + width: 48px; + background: url("../images/Icon.png"); + background-size: cover; } + .account-dropdown .mdl-list__item:first-child .mdl-list__item-primary-content .mdl-list__item-sub-title { + font-weight: 300; } + .account-dropdown .mdl-list__item:hover .mdl-list__item-icon { + color: rgb(0, 188, 212); } + +.account-dropdown .list__item--border-top { + margin-top: 8px; + padding-top: 8px; } + +.settings-dropdown { + width: 135px; } + .settings-dropdown .mdl-menu__item, .settings-dropdown a { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 100; + color: white; } + +.robot { + height: 450px; } + .robot .mdl-card__supporting-text { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 300; + padding-bottom: 26px; } + .robot .mdl-card__title { + background: url("../images/robot.png") center center no-repeat; + background-size: cover; } + .robot .mdl-card__title .mdl-card__title-text { + color: rgb(255, 255, 255); } + +.cotoneaster { + height: 430px; } + .cotoneaster .mdl-card__supporting-text { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 300; + padding-bottom: 26px; } + .cotoneaster .mdl-card__title { + background: url("../images/cotoneaster.jpg") center center no-repeat; + background-size: cover; } + .cotoneaster .mdl-card__title .mdl-card__title-text { + color: rgb(255, 255, 255); } + +@media screen and (max-width: 1151px) { + .cotoneaster { + height: 329px; } } + +.weather { + height: 329px; } + .weather .mdl-card__supporting-text { + color: rgba(255, 255, 255, 0.8); + background: url("../images/weather_bck.png") center center no-repeat; + background-size: cover; + text-align: right; + padding-top: 38px; + text-shadow: 4px 4px 4px rgba(0, 0, 0, 0.4); } + .weather .mdl-card__supporting-text .weather-temperature { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 100px; + line-height: 1; + color: rgba(255, 255, 255, 0.9); } + .weather .mdl-card__supporting-text .weather-temperature sup { + position: relative; + top: 13px; } + .weather .mdl-card__supporting-text .weather-description { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 18px; + font-weight: 300; + position: relative; } + .weather .mdl-card__supporting-text .weather-description:before { + width: 35px; + position: absolute; + right: 150px; + content: url(../images/cloudy_and_snow.svg); } + .weather .mdl-card__title .mdl-card__subtitle-text { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 16px; + font-weight: 300; } + .weather .mdl-card__title .mdl-card__subtitle-text .material-icons { + font-size: 16px; + top: 2px; + position: relative; } + +.employer-form { + padding: 0; + width: 670px; + background-color: #4e4e4e; + margin: 16px auto; } + .employer-form .mdl-radio { + width: 20%; + margin-top: 22px; + margin-bottom: 22px; + color: white; } + .employer-form .mdl-radio span:first-of-type { + margin-left: 10px; } + .employer-form .form__article > span { + float: left; + width: 100%; + color: rgba(255, 255, 255, 0.6); + font-weight: 200; } + .employer-form .mdl-card__title { + background-color: "255,64,129"; + height: 66px; + width: 100%; + padding-top: 16px; + padding-left: 15px; + padding-right: 15px; + padding-bottom: 0; + display: block; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; } + .employer-form .mdl-card__title h2:first-of-type { + font-size: 24px; + font-weight: 400; + color: rgba(255, 255, 255, 0.8); + line-height: 1.2em; + margin-top: 0; + margin-bottom: 0; } + .employer-form .mdl-card__title .mdl-card__subtitle { + font-size: 13px; + font-weight: 300; + color: rgba(255, 255, 255, 0.2); + line-height: 1.2em; } + .employer-form button.mdl-button.mdl-button--colored { + width: 68px; + height: 32px; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 13px; + line-height: 13px; + font-weight: 400; + color: white; + background-color: rgb(0, 188, 212); } + .employer-form button.mdl-button.mdl-button--colored:disabled { + background-color: gray; + color: rgba(255, 255, 255, 0.6); } + .employer-form label { + font-size: 15px; + color: rgba(255, 255, 255, 0.6); } + .employer-form .form__action .mdl-checkbox .mdl-ripple { + background: rgb(0, 188, 212); } + .employer-form .form__action .mdl-checkbox.is-checked .mdl-checkbox__box-outline { + border-color: rgb(0, 188, 212); } + .employer-form .form__action .mdl-checkbox.is-checked .mdl-checkbox__box-outline .mdl-checkbox__tick-outline { + background-color: rgb(0, 188, 212); + background-image: url("../images/tick_dark.svg?embed"); } + +.employer-form__general_skills { + margin-top: 24px; } + .employer-form__general_skills div { + width: 100%; } + .employer-form__general_skills h3 { + margin-bottom: 0; + margin-top: 0; } + .employer-form__general_skills .mdl-textfield label { + color: rgba(255, 255, 255, 0.6); } + .employer-form__general_skills .mdl-textfield--floating-label.is-focused .mdl-textfield__label { + color: rgb(0, 188, 212); } + .employer-form__general_skills textarea { + height: 90px; } + +.employer-form__contacts h3 { + margin-bottom: 40px; } + +.employer-form__contacts div .mdl-textfield.getmdl-select .mdl-textfield__input { + color: rgba(255, 255, 255, 0.6); } + +.employer-form__contacts div .mdl-textfield { + padding-top: 0; } + .employer-form__contacts div .mdl-textfield label { + top: 4px; + font-weight: 300; } + +.employer-form__contacts div i { + color: white; } + +.form .mdl-grid { + padding: 0; } + +.form .mdl-cell { + margin: 0; + padding-right: 30px; } + .form .mdl-cell.mdl-textfield.is-focused .mdl-textfield__label:after { + width: calc(100% - 30px); } + .form .mdl-cell:last-of-type { + padding-right: 0; } + .form .mdl-cell:last-of-type.mdl-textfield.is-focused .mdl-textfield__label:after { + width: 100%; } + +.form .mdl-cell--1-col { + width: calc(100% * 1 / 12); } + +.form .mdl-cell--2-col { + width: calc(100% * 2 / 12); } + +.form .mdl-cell--3-col { + width: calc(100% * 3 / 12); } + +.form .mdl-cell--4-col { + width: calc(100% * 4 / 12); } + +.form .mdl-cell--5-col { + width: calc(100% * 5 / 12); } + +.form .mdl-cell--6-col { + width: calc(100% * 6 / 12); } + +.form .mdl-cell--7-col { + width: calc(100% * 7 / 12); } + +.form .mdl-cell--8-col { + width: calc(100% * 8 / 12); } + +.form .mdl-cell--9-col { + width: calc(100% * 9 / 12); } + +.form .mdl-cell--10-col { + width: calc(100% * 10 / 12); } + +.form .mdl-cell--11-col { + width: calc(100% * 11 / 12); } + +.form .mdl-cell--12-col { + width: 100%; } + +.form__article h3 { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 20px; + font-weight: 300; + color: rgba(255, 255, 255, 0.6); + margin-top: 4px; + margin-bottom: 20px; } + +.form__action { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 60px; } + .form__action .mdl-checkbox { + width: auto; } + .form__action .mdl-checkbox .mdl-checkbox__label { + margin-left: 10px; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + color: white; + font-size: 16px; + font-weight: 300; } + .form__action .mdl-button { + padding: 0; } + +.input-group > i { + margin-right: 15px; + margin-top: 4px; + margin-left: 5px; + font-size: 20px; } + +.input-group img { + margin-top: 4px; + margin-left: 5px; + margin-right: 16px; + height: 18px; + width: 18px; + float: left; } + +.input-group label { + margin-top: 4px; } + +.input-group .mdl-textfield { + width: calc(100% - 40.5px); } + +.pull-right { + float: right; } + +.pull-left { + float: left; } + +.background-color--primary { + background-color: rgba(0, 188, 212, 0.9); } + +.background-color--secondary { + background-color: rgba(255, 82, 82, 0.9); } + +.background-color--baby-blue { + background-color: rgba(116, 199, 209, 0.9); } + +.background-color--cerulean { + background-color: rgba(80, 150, 215, 0.9); } + +.background-color--mint { + background-color: rgba(96, 196, 150, 0.9); } + +.text-color--primary { + color: rgba(0, 188, 212, 0.8) !important; } + +.text-color--secondary { + color: rgba(255, 82, 82, 0.8) !important; } + +.text-color--baby-blue { + color: rgba(116, 199, 209, 0.8) !important; } + +.text-color--cerulean { + color: rgba(80, 150, 215, 0.8) !important; } + +.text-color--mint { + color: rgba(96, 196, 150, 0.8) !important; } + +.getmdl-select .mdl-icon-toggle__label { + color: white; } + +.getmdl-select.is-focused i.material-icons { + color: rgb(0, 188, 212); } + +.getmdl-select .mdl-menu__container { + margin-top: -45px !important; } + .getmdl-select .mdl-menu__container .mdl-menu__outline { + box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); } + +.getmdl-select .mdl-menu .mdl-menu__item { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + color: white; + font-size: 16px; + font-weight: 300; } + +.mdl-textfield input, .mdl-textfield textarea { + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + color: white; + font-size: 16px; + font-weight: 300; } + +.mdl-textfield.is-focused.getmdl-select input, .mdl-textfield.is-focused.getmdl-select textarea { + font-weight: 300; } + +.mdl-textfield.is-focused input, .mdl-textfield.is-focused textarea { + font-weight: 400; } + +.mdl-textfield.is-disabled input { + border-bottom-width: 2px !important; } diff --git a/dist/css/lib/getmdl-select.min.css b/dist/css/lib/getmdl-select.min.css new file mode 100644 index 0000000..b1c2409 --- /dev/null +++ b/dist/css/lib/getmdl-select.min.css @@ -0,0 +1,3 @@ +.getmdl-select .mdl-icon-toggle__label{float:right;margin-top:-30px;color:rgba(0,0,0,0.4)}.getmdl-select.is-focused .mdl-icon-toggle__label{color:#3f51b5}.getmdl-select .mdl-menu__container{width:100% !important}.getmdl-select .mdl-menu__container .mdl-menu{width:100%} + +/*# sourceMappingURL=getmdl-select.min.css.map */ diff --git a/dist/css/lib/nv.d3.css b/dist/css/lib/nv.d3.css new file mode 100644 index 0000000..21ce216 --- /dev/null +++ b/dist/css/lib/nv.d3.css @@ -0,0 +1,647 @@ +/* nvd3 version 1.8.2 (https://github.com/novus/nvd3) 2016-01-24 */ +.nvd3 .nv-axis { + pointer-events:none; + opacity: 1; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 0; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, + /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + +.nvd3 .nv-axis.nv-disabled { + opacity: 0; +} + +.nvd3 .nv-bars rect { + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-candlestickBar .nv-ticks rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} + +/* boxplot CSS */ +.nvd3 .nv-boxplot circle { + fill-opacity: 0.5; +} + +.nvd3 .nv-boxplot circle:hover { + fill-opacity: 1; +} + +.nvd3 .nv-boxplot rect:hover { + fill-opacity: 1; +} + +.nvd3 line.nv-boxplot-median { + stroke: black; +} + +.nv-boxplot-tick:hover { + stroke-width: 2.5px; +} +/* bullet */ +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { + stroke: #d62728; + fill: #d62728; +} + +.with-transitions .nv-candlestickBar .nv-ticks .nv-tick { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-candlestickBar .nv-ticks line { + stroke: #333; +} + + +.nvd3 .nv-legend .nv-disabled rect { + /*fill-opacity: 0;*/ +} + +.nvd3 .nv-check-box .nv-box { + fill-opacity:0; + stroke-width:2; +} + +.nvd3 .nv-check-box .nv-check { + fill-opacity:0; + stroke-width:4; +} + +.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check { + fill-opacity:0; + stroke-opacity:0; +} + +.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check { + opacity: 0; +} + +/* line plus bar */ +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} +.nvd3 .nv-groups path.nv-line { + fill: none; +} + +.nvd3 .nv-groups path.nv-area { + stroke: none; +} + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} + +/******************** + * SVG CSS + */ + +/******************** + Default CSS for an svg element nvd3 used +*/ +svg.nvd3-svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + user-select: none; + display: block; + width:100%; + height:100%; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + + +.nvd3 text { + font: normal 12px Arial; +} + +.nvd3 .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .nv-disabled circle { + fill-opacity: 0; +} + +/* focus */ +.nvd3 .nv-brush .extent { + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + + +.nvd3 .background path { + fill: none; + stroke: #EEE; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke-opacity: .7; +} + +.nvd3 .nv-parallelCoordinates-brush .extent +{ + fill: #fff; + fill-opacity: .6; + stroke: gray; + shape-rendering: crispEdges; +} + +.nvd3 .nv-parallelCoordinates .hover { + fill-opacity: 1; + stroke-width: 3px; +} + + +.nvd3 .missingValuesline line { + fill: none; + stroke: black; + stroke-width: 1; + stroke-opacity: 1; + stroke-dasharray: 5, 5; +} +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-pie-title { + font-size: 24px; + fill: rgba(19, 196, 249, 0.59); +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie path { + fill-opacity: .7; +} +.nvd3.nv-pie .hover path { + fill-opacity: 1; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} + +/* scatter */ +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} +.nv-noninteractive { + pointer-events: none; +} + +.nv-distx, .nv-disty { + pointer-events: none; +} + +/* sparkline */ +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; +} + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + font-weight: bold; + font-size: 1.1em; +} +/* stacked area */ +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; +} + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} + + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + color: rgba(0,0,0,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + display: block; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.nvtooltip { + background: rgba(255,255,255, 0.8); + border: 1px solid rgba(0,0,0,0.5); + border-radius: 4px; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 50ms linear; + -moz-transition: opacity 50ms linear; + -webkit-transition: opacity 50ms linear; + + transition-delay: 200ms; + -moz-transition-delay: 200ms; + -webkit-transition-delay: 200ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + color: rgba(0,0,0,1.0); + text-align: center; + + border-bottom: 1px solid #ebebeb; + + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight: normal; +} +.nvtooltip table td.key.total { + font-weight: bold; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip table td.legend-color-guide div { + width: 12px; + height: 12px; + border: 1px solid #999; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + +.nvtooltip-pending-removal { + pointer-events: none; + display: none; +} + + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; +} diff --git a/dist/forms.html b/dist/forms.html new file mode 100644 index 0000000..d5abb9d --- /dev/null +++ b/dist/forms.html @@ -0,0 +1,515 @@ + + + + + + + + + + Material Dashboard Lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+ + +
+ + +
+
+ +
+ notifications_none +
+ +
    +
  • + You have 23 new notifications! +
  • +
  • + + + plus_one + + You have 3 new orders. + + + just now + +
  • +
  • + + + error_outline + + Database error + + + 1 min + +
  • +
  • + + + new_releases + + The Death Star is built! + + + 2 hours + +
  • +
  • + + + mail_outline + + You have 4 new mails. + + + 5 days + +
  • +
  • + +
  • +
+ +
+ mail_outline +
+ +
    +
  • + You have 4 new messages! +
  • +
  • + + + A + + Alice + Birthday Party + + + just now + +
  • +
  • + + + M + + Mike + No theme + + + 5 min + +
  • +
  • + + + D + + Darth + Suggestion + + + 23 hours + +
  • +
  • + + + D + + Don McDuket + NEWS + + + 30 Nov + +
  • +
  • + +
  • +
+ +
+ Luke + +
+ + + + + + +
+
+ + + +
+
+
+

Form

+
Please complete the form
+
+ +
+
+
+

Personal data

+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + + + +
    +
  • Male
  • +
  • Female
  • +
+ + +
+
+
+ +
+

Employment

+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
    +
  • Young Padawan
  • +
  • Junior
  • +
  • Middle
  • +
  • Senior
  • +
+ +
+
+ + Type of employment: + + + + +
+ +
+

Contacts

+ +
+
+ call + +
+ + +
+
+ +
+ +
    +
  • Mobile
  • +
  • Home
  • +
  • Work
  • +
+ +
+
+ +
+
+ + +
+ + +
+
+ +
+ +
    +
  • Personal
  • +
  • Work
  • +
+ +
+
+ +
+
+ mail_outline + +
+ + +
+
+ +
+ +
    +
  • Personal
  • +
  • Work
  • +
+ +
+
+ +
+
+ place + +
+ + +
+
+ +
+ +
    +
  • Home
  • +
  • Work
  • +
+ +
+
+
+ +
+

General skills

+ +
+ + +
+
+ +
+ + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + diff --git "a/dist/images/DB_16\321\20516.png" "b/dist/images/DB_16\321\20516.png" new file mode 100644 index 0000000000000000000000000000000000000000..928a0f9f06ba8535ab8adc07908428b8978f409d GIT binary patch literal 20532 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%0AxO7W20_)$WlvP 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 literal 0 HcmV?d00001 diff --git a/dist/images/Icon.png b/dist/images/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a096ddebbba173108d9d8af2b4fbd70738e208 GIT binary patch literal 36988 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 N002ovPDHLkV1i?7pK$;H literal 0 HcmV?d00001 diff --git a/dist/images/Icon_header.png b/dist/images/Icon_header.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3f28212f3134c364d3f9b6a38c83133a09911e GIT binary patch literal 35130 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 Qc>n+a07*qoM6N<$f&t12o&W#< literal 0 HcmV?d00001 diff --git a/dist/images/card.jpg b/dist/images/card.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6362318436266d376070a6178294572c000f22a6 GIT binary patch literal 1799 zcmbV}e>~H99LK-=%@D%~cgfEqxs+dtNQIW0YK5tgrr36Jl!n`^T%nNjD;LKkS4qq7 zWVzwY6r~u-GHrI{M`%kS!)~j4+&v!m*WJB8kN4~Gc|Shy_vi6?KHl=@av`9#+Z*Ez zfIuMNh~fb97r+hxtSCVsrGk|Kg(wvUg+ick7##j75vnS1gen3KS5Z?@MJhvaQ&&T( zD+}c(pGUzk2n2>iz!9HX{*%aC0h9`01z15qrT`cPf}lWh4qyxbAlN5+AmGmcfgw;B z9HFqGrf6u;QrL$;6sBPc$BJ&6;vImZVA>`dJ>fe0!Vso0x|_~sUsW;NUekug^-9d` zkH#jeBK7oF8yH$xer097&cV^id9%xw9Xq|eeRg4X??2!l5Qq;tNC-c6JR*`vI(aJY zG$lSE@rQHgQ&Q6|T+GSM%fDRk)0M)qYvsROzj3qTR&8BM!|&z=wQMWf>1U%eh1pO}=sn|=RbZhqn8qLK>)Kt5wB^fTB$xKIi%uyO|oB^L-x zQ6vNfg_&%GYkTfPgvIEXZaS-?yFL4AO`EEjJx+o?8rzH1Gj|YKNR?=x$o?Hz^8X_H z3+!($KA;W(DV7I80Up5eLdi)3{55Q!v*7T`4So|njiK#kEt%xQr4F^hheJFH$PwCE zBX{jH%g;mDetxb$2VzKVSIJ8!?5W+2EIFWJoa%ui&!*3{FW0WWljI_Z)HlpfvrO0P zHacD~PoT25*KGBmZFw~Ha+cfU_=SB$XHOmSp8AFvwoBxlsyA`~@@S@8QqvJIzk+TV zrxiy?C+7n)+3k`ZV@tQB8LTJ8X>SYC%xnfMNDL&4TJ&GML3I{+^Im6r`X+>H8fk9x z@!JY4uF3z{LXc78%|xr}M9~_P{Hc?q!c~lDu`#+1%ktvAjf3(EefCn!$;2xuKFCsu zOBJixOsuJ4SwRy8Q~ZN0YX!8BWy(T+Pz09aJ@G z;EF0QT9PYbH%K}~Z##?ian1dXo)vN+>?Ls{e>mk`fW;-0QT19=brZESt27;FgXZ*g zaLwzu&dCQS>+4zqpFIr4?x9;S&u32bpN^WiE(cQgI1@%0L#b_R)<}QN%5*oQVix>I zr+qobNWOn6zVFnP(O;#fG){2I@wsD$=kIfz>aA95b?G8L`V2GF+zpp}7h)vjRyt~b zr{U{5VK+nL5HV@3BrBsHeNpDsJErNNjoFkPQ$+m6Dqv5^Y8EWqlpVZaE0N7rho(y- zL*P~`&ZSf?NcG<<%+ z&&Io(b%(KB5oS?1g8jD7O zrK0o)$h`O-_qe=k8?`Nig7=+;g1peh0V4x8@ z$Bfv^&Lxp_?%Jc7SJ&IxYK3V#xmGttJqjK!YaZ4MN@*Rez!gP3{18=M-)B>{M4cv7 oqS7nVZmjO&e|^E`BYSFb)yRkq{+wM_UgFQWUb=zhu?+dpAM)rX + + + + + + + + + + + + + + + + + + + + diff --git a/dist/images/cotoneaster.jpg b/dist/images/cotoneaster.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec32d6a2b0caf67af326dbbbe0308df42a79a0da GIT binary patch literal 87201 zcmb4}Wm6nH-0l~5cPMVfWr5=E?kw(5Slqoui~HhI+--4pSfDs84ma+lMOviL)90Ld zKESz>SNTtpNoI1zet*~h{s+KURa8*~ARr(Dl>a5b-z|U~00|NCfAT*e|H~-oC@9Ft zD41wysOZ?3*w|Q@SXel?g!nkP1h`mO_@wv*M8qT{B-nUlSUx7{oYOIK=Ki>LylO5$-076tt#>YPHT8Lg&@}2Tsr5z@9FvtN+&ASX!nkR~PD`HDjSPgzWDJ2yzs0 zWvs~1#Z*x5(-_n0zBIc&?RG_I4$`pfO3!EL_w<3=6qoQ*vgJ~j{Wl;8@1GV-`~=11lRNrN&7e zVS{S{w0e?tyQcF`-;0#y#0G((6rX)ZIF+gBnY0ZfBq(9dF{N2XY#$}UD~!|`Uf8Si zrj9I|j2gZ|u@zD5`Mz`SGb+1CdM?~1>Wq;(wCzV3Q}{>{4NX(y0k=c3(!M8dz}A;M z#6sS%YW6cpFftZ2X;crRAHCARhAo*NN4hRKg6>UXNiyTVF=9@?suq%zT&(w% zq_v$_l$jZ7u8nmBUTpEYOAE2ebWjWhxMKUnr&X2T;dLN6BApk|meRMPeGBD*ff(Du zJ1Y#FnI^m?QXbveLEY*TEUf8g8ZEc?3L+vy9w@-mfD=? zeNStB@N(*|H7DpvyfG7;z2xZYmF9GS;HTlpvo#?UTz2FusH3oMV6Ni4qAW0!o|R z`$l<8#-E%vt88`&f=i?&v#BdBrpP2~wKHI=+4P5Bi#ilw=Q%Tqhz)m>Z_N#;JsK?V zmnNx);)Yevrebb~;F41@2W#m4%Ema67Ldszn6W{Dzn<_42_> zIjj}piJ_*>$1lI0g7ub1jaP56_VUexSrZm->hCUYV2iG!TlrGi=Q`^%nhsjgEK`Ls3AJgk}y)Q+sA33|b2P;gLO45w!VKz42_g+aB=xU7r9 zh2Ysw5?6O1ki2mLx~sW9{H~0>kDAL!(l*lNFF<>Kp-w?mFziQIL2}XLOepOH1;PVo zCtj$rNRx)aM$-0Y&iVlT`nABnfF^g|UxGnh5zK!9NEd;GK7rBx)`$z;+0Dv|AGf%} z^8I}(??axw_uwuZ{N5!FSRIC(j`VRQ9NJycESTEQ*B?tBjLiPq0P1*WEoeYLTfO^X zm=}^fo#c8p$T65Dmawwj>x!h5=~UB!RMC0*!bsVcbqke9d1rG*mT|La9zVNFb|$!~ z7G+OLUns=5TwrQoODBK!I0*9A+`8N#=|$LnGS3(P-YR&(*~DQ_oVFoBd)7Dm{;Gr0 zn}mJe+2&phWh14RpoTm`2Luan%9-mm=$>h3->p=mS@S8-N2q;6Bk*%q9@Y$Z+g@9k z*UM2d`xRZ7{W158?!K>$QQk9T*&}QQ=iP6}*|rc*;>IMcQJ!nc%E#M>)~&utQ41@t z7$)pQ-#S(TIs~#@fisVaxQb+V>0#+sdpZ zqXU?o`}{1jG%wm$$OOBOaM+4weXU0REPc9{9yWX7Fy)Zfz+&JC3liUnQ7f2mfqxXq zU&tRF#Lv&xPEC*CuZ*PYybSncHRksQ{y2DMhF5Oi{)6vTi{xGtZ~3kHkL~xF+e={0 z`JcZ4(T5|qaz!9&X&)n0QH^v@Ze180mIX?zxZJWmJ8Zu@DGw&q<@K`ip$9lmtJN~_ znXYz?FPj|G-=_^k8@SaQ{s9b9PWtZ&qp9(Z@k(C@7J^{ZmGKe zv}U)Tvl+KI7UyPt`n>C3xg2TFsLVqsqEY)T3wkA4rFy?DffsbXl9jLEu|YdJNDXWD zW1Kl`oCdf50+ci;iEr*isf}^`0MTilDbjLk*t_v7aOS>>phr~0&0YTm?y0j<-Pt0K zt7pF8Kdv)H6Z%1|x>F#zF_C4=wliKRp*SK|b6A+3LSKQsZmrgUkH4I`*^>zv+lijju&AIO3D^1HMGiCL%W`2X@ z4tqdP^t>v8t>)7CVoMbx33lF;!VO;z%as=2H*cq%f9BABk)M)s^C#k^P7xj2PvV}| zf+`nE6M1H4Sq;WjB@fZ-zTLs;TP0Y+e0UVh>)`8$TmJ?%-pnhx+*5w9-K5M~Ilt1P zd{1YXP!DQuQJZ#~-;?XvD@mBzl^dMfU@kdCFb<`u%e}{_TwS{(bp5$9p!oP|Kx$oa z>oq4Qx|xm;^x`gM&*`@cp(Gc3s;s1XbTc?>fF>1+tv1arA|^v}!xB{uXa-@ z?Nm@cS}66sFPPB@A# zUrAsXLU4=%ZJaaIh%g-|a_o#o=P7b4+Ekdj8fmTFnF3kAEvi1eoA3K~M`Eh7bp#OeL7W@@P-+xP>`@r$=>De_xr$Y3Oh3kHE&ac+Jt+w=P;DYVD^EQ_CbokrLOWL4Uegz zlo9VnQPq5*@hF`1oQ<&k3TbG>Tfet*<=AYh-{iA?q4L>y_^;#)Dt z`Aa;fMIK*oU|?A1?Dr58PArA?6F&#AX~jSfg%dxo2NB!(c-=p1i(0cVZMggA`7QM< zALcHWWWknYag}vnDPXSxF7L0c?md^y=e;xzNEEu&2+Jh%I{Yw@Z1Qy(>i_IH%TzyW zVog9hi1A&8HQGX%1<1!;K#W)%H2e$BW$h221b^X`xZNR3NQuszOR8)=rMnh=f_AQ& zHuL_%ma~WYCme-JMSR=+3*eF%;9zWx2?Zt=M&}9nD`=;uGuX#lnOxlaQSR~Kxe`GMo*YM#CrI>GP?kHc?m)6+V#OPzf@VYh&+rsmn z5(sDdvQC0J1Q7!fHFCz+uz|1_yz|e*RUG!-^(s+M;F+}=0jM6!jjE~NmCATTM+i%6 zh<4x>uZH{uEDks=?mKtCg*RkY4$=Ut?rvz%jSO@^ZRgC2M;!5H6x9)FR=B#q8t4K4 z6<~I4B)+8$XvuQrqIDvgzsV{%Qt4^#SFmh#vI#q^x{V}kt?X!%Op`o>+t|=__{x@< zYbk;|rRq}DSmT?smI*x?1w1A;BoNd}nFEru9Si-P*;#pM1HM^g{)w0zy{d(_H zVUA!!uKjg^-wJK@F~+b zEU@tG$z;Qp`9GLq?X)>FHh=~HTcTtnl)pZCTE_mw)3x2L=I$3+-(P@(uLQ)TuV=@? zi>1~$5YOt9K|^XY6RI|hSTa3p-c(1mLJi?#3k2Ml!Tnw5e7dT&`23M2Q0&YYkmlbmnci^*{9LMU2_t{)oC`M%|h35glTHEt}nz>N7in@>R@x*k#4D#Vz%y(pwh|hN z`x>Ug!luABIA+pZ(_#@Mc{)o7pF6$((_0E6&3)*1?sqd(4e zOv~3fU*DT9wy1a7a64R=$oX+$O|tLTuKk1yxZAcWQE=$YtAZnZ)`chr(lWgvcG-qQ z+$qMspwo0o1HLB3THY~Kvg9Dxej*7^)TUaa1KY~yIq!O4F~E&S8~0yL&;JxFKzB|_ zzdZ7oP8^C_m@b(cP9-4s7H^2K%8_Ya;~*yG>JlFjqyui1A-4J550=1Rp|9JPq9M^Y zBfsA`^lDOzO&#k^U_D9{?UtH}-{0J(>zu3toD0d~a_qwKYQ2ULvSlk_Df7EG*6P?KEsN58J*e;Dw-&Yxymz1ok-3k&iK zv0V<)EHhL8AV+UA^qSCoJDY=M0+i`R`F%@9v#`46%B>U0 zloaC>d29KVQk3$+Q*dE3Wz29MqYaW;c7^XG@bZ56sd#NkpklaHPqbRY&5N z?P=h+x3_A}K#Is&$xt(z!qRJ+_xbkkp77PILC=8KhV#m)COF}1NQ2Ne=58$|_u7f#uGJwRf-6wCshuQ~?1`V5gs1Dyogn$GrJR=rTyzhV9S1#O3Yu{F~)|na$m1 z(Ksa8P)s9*qOF`wPS~D7`=+d^+^R!%*-B75kigW%@TiqY!_hrpKT7!Z!Miy(%Z<`_bDOpqc;KXxkr zP*_#IVboq;Pl4$1vYyLThzK`dP?Dde1!enX72m=ShU?o*UO`MOk{!*wm3Jc~MP+Cq{<6eC48kpz z=vPvy&B^?Xcl@Pfrbk=4L4r}WsI-l@hqm5s<16%=t8ZDSP*Lx2w`oNd8(~uQk5{sp zm3f~xk7cb~lC=?sqR!m!M!pObNFvM!;zm~Q_|sY_m98M1AQEe&VJjeEgvs$`nmfZN z8m~v4i-14@sjNzPIJuQfbufyetTKi1m(xqqEbis;I2?mQvKp%s{W1v~`H_Wn6m=Ce zJ@ZCLnJGs{FQqb6@xyAVQ=jMq76tbnSGlaZAbt^Bgcq%X>OmHDx~@t2XJ>m`@&!9| zK0|^v9m1Uv)>mk<#|C0zOpL zjC0|S$rYBjx-Uu}W@JrFO!W3c8ccfcP7sl*-h)IhqEXY>otx1t?YP@dBn$wQRA`<^ z=JlrT8R}fBPam75Zd|evHzD5_rEP*1sHSSs$X~;-j0#b|yTFj zm%s*RoHza<8>JGraKXqW5Oe7VJY!4-Ldvu{rP<#djjN)6zQXT5hS+YTYv0ol7+b2) z`E>cD>CE0kCn(9)B`*ELx&GOANf~FZIHr<*mLq2>BWczRLFEPhH@ZEfWhx;5CDSMwLb4-$aX1ii49GZE6)A{-?aGLC4H z3a)Pp)y3`oDiFNyzKrM5;lneUHvx7Sj7l&;rq#}!eR4t>^ZVZ1E^r!hzl@&MmPsId z9l@zyMlh+a&FXCPi87}O;>9Xg*_vZQq~e%sw@I^$=1{F;_uw!%04>*m4VfVs7PDGB zJFk{07x$#r?>b?k1A3=BpAeA5@yhpU(tjw&;QLzDi)-w!C#)y9sBda&DOg;|ek`rP z1$SW?@!5lO-3gf#Rahzo9uRtSCV7HoOz$jnF9^==MY!H9TDg#8O^n=1lJIRSLluK{ z)-{b7VyqmgNzNN_5%4`YfJ;O;9_ETYG(CAa3DqBgi_Vr0T7185s#t`6|93?(w()eh z6q4rK%@Jecrzr>HOh0CRPq9(6flf~>W4bv*2xIH-a7(_y5q4d_3+3cbKPMZ{%^XHv z_1aPB;%agdyhMF7uknPOQ+~HP5~v>8Fyl;`t@{jz7%ehC?VBWF9nwGv+VDSK1&=bw z8*tdZ>v(SykqoL%RmE;Q?{WG%OGbP4()g()!j#b@A8+oJY(jc*68Q^cb3EF?5pxyU zsz8E}#S53hD_a>Zz@Bt>`ZAW^XL4<(WYGJ5ScVu0f8dzBQzlIoqr&Asar$v*vGCv1)f6yc)64aXDotjNu64Ol%=DaL!c%bRFzvQO45C>)M2#2k&a6|Y%>xL`q|(? zCJ4FD--bI}%apYsdhwHfWKI&XST>#hWsGC?7myl+mxJan{&`{sC+*dcvzzk^Jy24O zT-bnwz;LDc8ynZhmQBdDGK**>Ysc^gI>A!pp)pPa1M@u#9kH=thcSyd^2f5A>e91Ffl{i^nbwp+S~7OjM4uE&frsB~>HXSGIB@X0CoI;M zyDc^s2Kme_8SgC_8>iQSIau}rBmHZ1?=yLpCb)^Ue@CN^EiVVnpydMMFa!i8bx)XS za59aM6`dP=I1Zi><(PaazR3S9B%GpiSR*;(smTnYs~lf+Y(EG8`@liQLJfgqt^=E! z)Rm8@38%Qy83Y=q3+kOq9g6aIM?*M)ew}|T%e!21>tEfIeoK0X4f0Y$q+{sU(JB=b zn{Dds0~$76EbUEIo37rwRH91)02$gdd8x_Y zXA?CIw@OqohC2jJPg+Sc8!B<=kt?6$XmeS64j{&+0+p4|O=pP}_)M~B(x14a{`8v@ zQnkFG283qCmlV3vieLX3R=lBGv_M`dltreH?%r(`b_yq(Z z8!Ii`U8Lh>Jct~mvQI118-vTOtCLmEso`*CY~8x{`$T7sUE6yD4^C}W3M5oS@p^=B zZplO((JeKtlJ_hLuBJVlrQ1RzU9vD-%&|(o{moo!WVux~Og6e7CrYSXi2AxHuBrRZ zWm>V`1}Tto%@{KX+pwj+x&YAG2kazP%k%WTAl6msq3gG7lr|BgD?{5=Mxv|V4#z>U zLP)!w(?+U;Y3YK!8F>gilP*z=ul0$WI59VImb^=9T?N8KD0|6A(}k>#gWF z#n&Lhzm)Alrv(3-7&peQF*I>Kl&r5*n}wZ*T>ty54FnD_ggJ9lL4>Wv9T6qme@5lx zS(qi`CrH`T2QJ||ZWvYzzB`J3GA+kLpd_vaLW;ZV%I-tp40G(v(XzR7~1I>{m54xbnQvP=b z-eO?1of0i9ge14%PE*dGMjg$jIMRk+6_47GmC6#NHrE3a8QDG>JI247b|tQH`%>Iu z{6$P!AN}nzcDr~~Zh$)Eyq?r2BJ3`B){fheS+5XiG73wYmgJw1-dCzE;E0jb#F7iQ zXj1%Xko*4dz_5{*uA7@CC^$n6@hG8IUd;N6!PK85{bE}%7q2Uowhg~rp_21IHw zw??AI<2$jo_%$^`rT2Mn%N z!tY~|f7)Kj)midhAZOr0c(2AEna! zJaUw8ZvGCzJZ=iqRbY`B?<+C02%8apR#zlD?NG6r^BZz3bDpd6ut%4J(tPX1 zXV0r^KF0Bhy20r4PV$Ie#kWBXEgc& zZRUqb(iX#Z$WEV2!Eu@0B*i#YPKjmmthQO@f2gK?g(e6>geUwq-ho?a-UYrY%_08S z1NHx<+Rpr-!KfQ2IKA?OuMr%k*VX@e5%pauX=i^=@)yA1)DZD3DGs@i;fJ|0E?a$u z*w!z1kt%Js%L|PUHO5S;2V2`cRnmut((JU?QCDieidTPr6;JN$5=1raWuM|+UK9LW zw7z;tWXe*HKkHp&wj=zy+Iam z9*$`lbl;at62%Nj$IN%eb`*+E8t|T?@nTc5op-geLEUX(tx^HL12U1`Q9 z`hHyMAgoi1>aFj=5~;p*BmwF6wA^Zbo>RS%J(jmTlVXg}TlJ=BY{4styw3m8Fg*@@V&%D{_hJ!+3C{G+Kzi4rDY??2vI%SNV_5$=gIGn?k#(F=_`?EJr$?c??rY7t@G$SjXjPkleUw>K?JkhPHN%Jfye^q=`^3;|`)_T< z8V4y?uJ;?&C0R%jy?(kFQl)3)#k8r|rAOpV%9&)JM^dFKPAA@AERnI_34x`3xVKWgo7Q@1d{`(Id`P&i1h1%0S~m>b1mCL9{Pay-dM_I ze2ampO~JAY{rF46y2@j|c9&TGFdHXsNs-0f@CCzTdQtk9GDyRbL62rb#$DdcKppCY>1a1cL*H#j4Mq>A2TJ3W4-J<=F==HdVe|!P975vMq8-W%lZa?c@6Ygq$!|fX?8W)a-BSE0YaezEe!fc*Hip>5rRLmQK3n-0dR-nJ zK;oG6t=m>0=)>IBS)wE}i9UR%-$hKHg6td*41LfSZ=9*6Ht+RYlupGs{&c>h4=dug`Y3d12xo!FV zfDa*j!D+YHwaVuU_E~F(@Mw^6OKW*iDps>yW~PWsTz{CD@psl5-pY`~*rq9A{&7!e z$8i1EfsjFxQ-}Q*&u|o>MDQ1iI@CrHw4_%F{o7L#!86YcNv!0bja`M&>oGMu*#t85 z7QM8Tp^b|;bh#0BzH#7E;Aqljb$Gm3#g;KD(#S6 z?b`EOJ>b9skI7i`LXB+Z(PGBpdQsnV+ec8N9?XZHh!Hm}E@K>8M1T}MbhanI00iZ! z?jN821&r*1@s^B;U0%7L4C3Jd@F$7QfOZtmmbnM^kek%L3$N};YBAzKpF^&(0pazd zlX>JZkx&~a zafD+a#LY4KaniQl^8KHV@g67aV1PWgd%J6|W0r4$PxdFyVgCeaFKJ5&ja!f~Yo8he z)((td`}P=I1RQAQhZWis5^zMf633j<%oE&ZrgEr zR1iJVV$;9dRbrY{Tia*f#dg%-Kdl}+2TVm_4-|i$v*QBs1WfT2p8Wm`I7>voW}zkE zC$fO`(V7_gCW1(uF=ifbN|0}mkLYJ9P#vXrU$F^ACIIo z2V#`iAJW~X9I0py=^pT}`i5-+#|wk!95a8Qwz6~S61EUR4AzxsPEaayDkmL{4wB_< zPIanmTgXxy!nSYTV_`ht*E0BdHe9DXnd&R>>eiS}GnnZmhD51P**iRb+eJ$AmiP`O z5YKmg%X}`T_)qxINJJb+X986Lvq%W$!Tww}`fr0f0;as`LWh!N3PR^LPG}LIr))k` zFb(8NiKs{l|Uh-T=AK#ikkyBpj5EXhGH`UO{fZ5wjNi*22UX!p;juQw;7WNujjV0O% zGRqF~4qbW=M*kgbE$-Me-f(YpKB%Yz$ziBCiN6EM2<-d}vZmXw8n#1t1N;n|65HYz zgCQK64U)Q0y0C1tvjM3J}j>#9ROwlOy6?}C!hyi^L?S7#0IpELJEAT zJc}Hg;_Tp6dWKv^pFLJ@vSN%R6Sym^`p*B@aDJkyS7XRiE`1kxBB4xXIYGa}OnSn* z)n^M`erq>h{ztsgoU%-?NQ_q2GhMSANZ>Vq;d%lMaH#5l+OV$0=9{Sfv>~xj_&$84 zGg%=^D#qF3!nHx1ho3!Rg2rxe|Cg9ikrG%AP8#@udA4e_=)k#&vW2guVxEKm9-S)x zA%n9Q_QZF*k;#3iSCB#`o;nRG!0P9(D}!q7o-$5Mdtrfiwpmkr3uq8m_BqD&CRxD+ zbxR`#{79yALSPb`lma-Ef|r7*-t4vXzZ$Q>T1_-^zHaKH>R&v9>K3~ih5K4gv4!w* z&1B7HgK7SOq-F_DK5xM%W9`9ovF^u6Yx>y!ipn#%i|O_bVSqvPg8P^duEO^^p>+D2 zMc5C?IXm^aP7H8En`jYL8Ploo4S6?)Zv{kli_`}1?SV7kK!gpWNK0bU1sXiJMBb=T zQrx|6M?A2+_Uzday;sR?I6bsBKaf7BSlsE3H=cM*T>V);ZB*7Y8_b?m*CKSW7-z=u zsP%vl9J^+m_E@l2t{LcsCCU1M58*EM%s8xRvebxMa7`C&=kaIMjDsmc7BAEas>A^7 zh+X||WS|*mB9%w}o?B*Qx}AD8(iyvaFq899pUjv%B)9pK23+p+F-9c*-1XBYtg$N2 z(zL*;1ah_WwP}xvT)fv6^7UeYV&rLR&7HffbME)0L33==yoQ6$QTE3`1)PwVA~%}6 zEIQO|21dT=Nt>hRNh#Pb8p+A7!wXJSW=nAVZ?2Y+IQ|FzszgJu;AM5eC13t7#wEKb z@^!O@MiQy#Pv&Tl?{yYM3+QnsY&(S<-OM-Z+foZ}ts@b)@`woKIA|_+A0Em7RUxTV zdHVB4F_NabRv2LE!f2Jld(!&$d8QzfoKaU*1<}%MBjr(S^iP5Mrzfhj8}D`H(YpJI zwHzar_vd_hFnEad{Gx^sErHWC%iayP|84#2Na|O*$R zxY((WhO)R@$P@ofq4t2V8ne#$9zZUcJH-If*~AP+^%S?>VHX!RLj75)cKX=lw(kqjk@U*Gj!x=KBxEd5ri~5?Qz+1bsjfhpQB5j`BbxLFLdK; zRP85qq32vF=u-n!Z3oxa7TUI&Z66@v%q^W)x`hhCw4*$`-hNw!&N>oV@Q+6{Uo2J>ToV1{qoPnBJ9<|BhWn6uJ}%WQE6f zakJJsM{1RLd3)W3@IQ?!W0t~XjSIeYFb&%d_T!5j7^#=|zrD(lbjIB>vrJRl6kRX>^;3RF~K9*ELk`c?i;nU00{djR@QX+H?*ZLYXVD47*GiC88%F_1$6r5^6x0$2 z!#-mz?tGm7HrDC67G@~z$3OQ2k$Qs>k#L4~oF`xFuvU)m9+Q40V&uYO_1~IKsY&eX zMmSPIdAa=WH0{f%ru?P@h%pW?A~~0FQ(WHIu!(i`=NglEf(8L_UpRUVsjtD{Wc=s6 z=kyVnSUI~q%&uS57aJA-Xr1kIF2h4UkUe%6Z|q2uxzK_0hSvS-n$J|EKVUb){{>|N zaMB*3%U@&}h@p^^_q{2uYZ%g}M*o~oQZnh(vPytYT;+Kh8(p9HRfq>#>#=njrX9w4 z*d+V2AV>DQSO2#?u4?t%aS((|`um$Gbre6L_oiL%NG*Yt-Wkc`lSh2*vaxqF!%Jd& z>c%_7J2ccn)nw8li~rbs@!=hr0T*5dU$!aBS(m8NN@r>=3xQQ@mCV5z$yMj|^-b?( zU*=m!F?8gBv%(6j3_+QoUA6Y4mUIhQhKIPc>5wEy&TV`PP+gq`Lx&WGVWiG!Sxdw} zAB`J)%#N4l+S>66)(Xj$hRUSZi`m0RSyX~CmjbIf%eBGvv-6zAR4u;aR(NJJ++%S& zkKl^dEf)X0`3cX4v(Fu-?6rLgLrq+!#EsXnEPsIHjYSa@+E!QF=$t<%IKy_)VHTxp zqoK$wp4_6>UgKq4*HPwWjjf=lz~n08elq-i%L6;cw?z4)S}y~>BDSd{$3IU64G!RA zFcIvy(x^^=g6k;GKIxEH@WpQmTaM0iu%OmF>+#~fkA0l+sLL+dkqaW^&9oHfl0T3;u&dhO%zW3~)|tLWebsAcLL|$z#k>B{w?7@JljX zdx038b)|-_Q^4fpt=htm%;-RM8?B*2(*uqz%L`o8fYzyTpziYHUjRy0<)IOr^n$+2x=wd z1gSdqKl7+&9O+jDFtQ2wt*$=S*SBacY~p|jFCkawA95Bg3yNgFZ01zfu3IT3KjqSN z57H12sf~alNm_qnK74+1fI4i>h&OMPnB%2u2f5x`P$* zI?-#FjJ)}Yq$mB|@dZ*Pw;!{`O@hQILu?g(xP?js!$bfS=kd!b-%LYBGPFTul_MM6Vzm@6q>LmBRjTnM(lLP}EGu z7svDrU>?&a)?wif~lm z>b;JcM%GI&*y2am5)%yHX3^@Ow^bD8^HIX$(2a+Wq6EF0nMHx4BERPDD6q#<_b2>+ zL_r;i_pxnb_cQtmo?zB?qTZeB)X12494_i|%7;kT1yP^QcAN8oRIsrR<-%5)^?v~z zdJk6jZ1dmjwGvT2I-ckk{nsni))GaM zhpaILordMIqNLsN8AoS;npfA*ecuRx5Q-ziL!FueQfGHytN);8h6vo2_2(0Q5!9Yq zlR?pTVUR8qU78lP{Hy))k!|piO9gv0%0C?OKowh3f?W}p4`{ax?T7cpSuXrp|& z)IFapn!JeJKB2Z|3IKr!q|X1~H_qn#bk3V}KlCU@)Qc>+mGsk(h=Sr?FG;uVM<69% z>M+9ikR8vIBqE(N3qR4Wx~NSWS5{Lc?jb2Be)=_45^1TJt)qQf{!09x9M6T)P~yGH zQ>;@4U*O|7>IZ2QJ`sZM#(|tZGURRcT`Kh^5vc;1GsnZ_&b7EU8h(0fshgzZ&e)*Z zy5EYb@po>68&mllqOpS+94vlSHDpd@HssKhw!Z*kUCW}`N|G%269vv8Qi;PWN_pRJ z$MBC|B;Jk!Q7!^O%RIT(&B@x`-X@Yej+?`cRfb6_1^xOp0$RpW!j@)x4ZgN!D2YYm zmqddq4-F|i95V;{5*}W&Bf7!!zUHV&-=(q5S`iEIzC9ZmW#Hi7-PqJq#f>kfvQ3R%Vel~#ceWWfIvX`Ptp&oNwo){`e*ws?hk+FRuofo_ zJ_m)IcczG5oXI)u=3^`MOlJIQ6hlQD8nreRB>FSUg&1iT-Rq(-lthyT4L_0fcdgSM zbLbSQtM568B{5rY!GDAwucHQ!3`#BwQ1zKA4OeMk<<%0-tL$ah#%?KV%4iv&px&yLd zmF*d|ayCq+SgoX8++B_wbe)Iu+dI)tRr$M08UTcJLJrl{1=m@A4BYl9Z5VHAu`26o zlGMAjDJyxXNh`7!!5_~z94@?Sv_Q&YDhO)pBp@0%;oKVShDPD1M&G(opEc(*3ufxP zM9N$xFq+)A49|#)OngctD%iG`&l0WD(>h;{_zO6MP4`jziO!#Q=lJ7pj-vEkv482y zedoH=xCWBAY7#iGeK?@h&+ zy;3+&VI^IC0SldMxzk#w{0J_|t&guy`*jCdl@$5Y6*cR83*EB*65&m;7x*+v0ZUP! zsc5c=qju;_i|ni1t(X!WrQ*yTmh759m`p(SEn52v(D)#8dpOm|(*7*Z)1);aC|Im1 zEfQZfx@q3b$;55Dp>iN%7(@02k^&`1TbF+jZ?MD(-;Gg2GuQ9Rb!UiD3smf}*}U6k z@NliteXzCU{0qPo3Q>T`R$<&N6xZMSr|9UAGSsX?;L+CD=OI9K@J~-O#}tgngQaiI z)1RNEZy5NMboK5VyE2Jw4jq@oJqUHAiiuC7%E%~lYVF!RldW55SndHMQ2WD{kO`7`etTtm^!!!rHezSQ+%%Nw08JFGHV&@53bVsDnhrH zc;YPQ*aB3HM{B`?Zl>qYb!$5kd>GL;*z|(!tJGWHnutnb zzM2qBn9c~~iPXat-+lT#Km5sZLjB~`w;(hiG`b=1>Nr*KKhVCVH{X>q{KZ_O*>JA&*`cLQl0(Fz~gjpKV56leCLJDzIWU&=|MX|`a z;~(6j3dP()Oy+zwR(#Z)T6;{j+Im3dw}d*tj7jvz7ip?rTKtsO$STY^HG#SQQIXfD zTqSkR9bi^WwIg9^xw zP4-L+8ulb601hV}qW6?)FUmnykn+6LTUsMWXggxl)qQ?TSvWJ2ddbAItgy0YM~pOSWD4uzw@0 zr!m*J$?^W;7`asMH=U<9yzS`)sara;%OEAO#Mv1p&Rb#32z=LHm5!pp!Jv8U;0d)l zhvGMz&yvVipuQ(@t>P8cO&v@RW2PPR#kQRG%G|j&vD^g2)VIhi_^V-vwAySkUBO+F zL_T6$kVH8aPB1L9J?pY>w+h=QD=s`uSnL89Do>X+0L4tqm0jh|Jc>%Y)U?{lfP z1$Hp+XS?1ucZ5UWp#|l(ziQN2hXQSy3G0ghV<1>D+au#XCnR<0_{eO?`KEBpCl>gK zDcrIDObXLCP3fgOxCB424(?kH>>bLlkr*wJ+A9BoxG z?qrc!a7K7i(-`(FyrtQJR?!4fAqJTj+_Sqrj ze@+WV)mBt*&L$#C^8LFwZ8MVQII$zH1UYbE>VeA1FBibhUsm!Xw356a3-U`6N;Cl( zl~G(ugs_4~I_eyf0^HyiNv|qqMNZijNOAzj4$!WB!rzXmjNgCpPy0+}MV}KNid|uc z{I>fznUF+4I)9Riy!LKK^Xg+2X^X}3#~J&sv7CpH`ylXH4xAW^6`N@r7 z{{SUsMu=DN;^?yP(uX1-17S_V0numt7WFI5i7~hFFcUqeKRK^R9pNvmd}^igtS#gk z>CI&eGJtCP#d-Lju2eqCgZSiG6BlM_-IGnoB+93(Vn!qhUQqqEWLTv{*r*|ZQj=AU z!Oyl)vQIdAilvQuO|~KfH$6#lsovef=pzijcaDjNmdPWDW1SSAuKfO z2zvTfR$9=Gw;nB5)@wX_!i^?{!U!87*sQ_LZcLLA%0VjC-zIWR?CCjKrvBhU4=LA) zZy-{$j!BAxvjq;aPJPE_s8uE&Uc?=jIODC7pqw@S-i&8^#Bca0i2nZ-3=xQ(FxvkH_T_5@9E33%Ct*N#;#g{@` zHw4{hz1Du^tSkG&6LEV}!dVVfY=MM1hDvc{BRo+V*LcNDO>Se@t@q0QCF`p$8;KNcG9|jc$2xBu>NKWNsM>%kv+Y%4afFY_g%& zxV8`KNP(JFCiX{{SN{{{VT<`$y)fe|oVJu4e-$@q_tS^`HK~ z{{Y*6u>SyQ#s2_oJe&{iF{S0N_DAIZ03nC{+4!;jV<+<;+JCJ-mE4c2bN-fp|HJ?` z5dZ-M0RsaA0|NsC1Oov8009630}%ugAu$CI6Cff%6f#jGFkuElaTS4)7Biu-LsHQ| z|Jncu0RsU6KLNJsptD)-*<`{|1-*hTOlqKuQT4Ra#*O(7($x=3juzaB_;}LnvwB;h z8l&7I)uDLNXj)ZwuJnji-XXfg(WiBoS@5Lg0cMsLN%DM0!tgmX z8X&B}reX(sMatEt_qBbg9?dkHJBJDK7b3cDKbApiI71o&(?J<`T~igZ!>lT!U9Yt& z{hI95{{T*;N^6S>FV)In0NNT{(3u=XO@PT;Y~?+sH)(PkBRc^ni-1L5okMA>XFR*v{+gT2me*V)}KRrI_R?8}HdVH#e1iue)1l zkShJX%ojI2u z+Oe^ul3h+wFcynlSh1L-Bg!#2a)OJq7m5lN{Y>FtJ;?uWU zc10fHT6&E9Ckj@JjVeJM)|JAwYgc_#u`{%6Q0j5T%KrdW4*N>#InSB86C?iOi>**i zG`yjsboz0yi0x}p?b7;r%zpeY1URCAUP#@sYR~Cxk-k_~A5C+<;D=3$mPbkr-Ko%N z*?2WNmK<34%(Aj_apY|^J-+Re;c?wLq;uFJ6_nW(hbtiiVRTFe$@;HdVgg~NA_z27 zH*f`I<+{H;1lB+@Qg!q&AFWT3RI2(b{FEUt+YV~1ss()S^b zp^KM9V$r}TS?5_22whZD%E!9V4O6a(SPALbSa~B_g`*Sf|}Jz z)}?DrrnZf)nV8tyMLVcK-O9=9%weVlo1FZ&Zi7is z0+}AB+HhE~x@QJ8VszN?*>$>=w$cbsIvqt#C%S@?T}-6UxF=-m&=11JlsYh+0p)vI zr(2h z;716%PYe8@EeZ=wuMXA2)UXxm`WxY*5)Z94!8fS`4so zh(V;OAq{G!0r*aY)vvJZogiI3D$jHG9J;gE!2w$G^?@iBd&sv?W74SZTGPkL`| zk%?H1C*?}kM-#0|KTx2Y;_ledgSwg25%hF8TNW@=@QyyM);>88wf#r~XAf#?#KTLI zo21fkuSnfCHaKpi#`$V+rL}h98YsGj1UtXoL@FwZ)7YRlMuy4N@T%32k8tE&+f#s1 zWVyRJO%q-M+Q=5UOze=4^{QsAzYl+OSPOz1+*5N)+Z?zd+RcIf|@sq$>NaYI%7RWTUyRF&CR(YkV zS`VeJ*0ePIsRVbj(?hnT!VfE56?U|(7s4Qp@v_~zd)R%TBM9UxEeJPXC}Qg296#kp zj#_Th;tx+_<3O1`s}C8tSgnPr{YC}~aQURu1mNgiDI=jV{oEV+;v)X#pth;)2+MmoLthJ zcCv}S;c7+K%4?{nQQUe!Dl??+r44x5R`i86YfT}_BSC(hZq)w(ANWm_wK`Wjg{|L} zto~7RtCfUxWHV6tPCA+wSA<0UOgoj)<&CZndEIFb-G5Ml^d|la>6o5pSy=Hi9h9VZ_l001C*!z8_Xd``1&8hpYojl0RF3ix*+nI#_EEN{{RW9Xrl(n zKoj<&D`J3UZmkz4$XM|I0K&!UEqg-xc(Nbla{4S-{n|n~Y-;PhN6Z8bT^}Khc9NXm zFbHD=aoRUsQg;d351JCH`ZxLXtdefBrQl7B*o0EsDy)d=8?z77w0s`3B8X)GhX+ z+cu1A8HKN~y8b88_x)la{fZ0DXSA40m-oTvV<7GzT*H~CROwbNPJ*oXkyeTn0ws2+p zRNvFs(l_*7MPzj6;=e?T>6`xm*&J65!XUR}`&)$^z_&?H*~k-lhf;5aU;)gbC|F||dj$kXj3W#Vx(0(5)?*Ld~`)K=|Rx_1f= zRLlTaLvu@`^j5~fJmYmEykeTVmr!;$v4`G&@SI6DdF^V@Z^|H6$*t6AEDnd{Zn;x> z6hA8~qrxH~oT4{OI!%;i(soSEKP&2;%KrdSlEGrd$QdlvA3ufEv3{ouTfX46xu{M; z6Gr`>6p(GHn~uQ|+#}hh_C#qblr~LWGH}?tUw(iFf>*+8eo6tMWlI|%fB0Q9C`kxf zfZaN8!gQ85QqCZj!jCvoIgz|+a?ikxCiYuezd8GwE^w_?j)hP8n z+pedN^!Y9y1ycKfYN7I&MN$yz-HI8Vj_)LVtZuI!WF|Q_cmC9bYbbzLg&W-w*+_Ld z(1+QnGyrI)3M);cx1gIHtp_Yjp%~ov(rVBIuA7te=SfiHhoc|?PnHMTx|VZ`Ja)Qn zVT;Ck&r@cb@w9n4Vn?( zxAfy15ML>8zhb{K=yd@@A8^m9?o7+7SeF3!0eve_XTJ@WAx0do#ST9 z{+`SEr9Vu`g}-W}sZ81^1O=ii(@K+e2%u>+vQAfy$F({cLA4%i_{VhKu;=ofoqMUI zGCIm>(oo3Tbu60-3sIz9*h&ber%QV`WZ!V5E5Ejt{#P6=N=&nrh{#{dc>e$hFoK=8 zYSa~9Da@`EEtXdXMl7rjn>1~?pGzyviyp2*ozNE&)~8GG)Xld+u6F9X71J}_jMC7* z*Na`o%l@EcA=G?=*HE8Vw05;*sGy%NK*+_FAN0%1L7GY`U+LM{E(eEy;Rt0Uwc?x; z?Wc6%MRZP$8(1K58?S^Q2tXHJkVA{(A1F#pdQk0Y%>?Y6H21GoG_(s=EWxLBGr?k+ zwDZ^l@U*H|TXv;EQls0*M#zxv7Rs-L*d%}25yzSzbKA1=dEnBFPag`AnnKXR?U1fY z!|JWY8VrB%q3Sq~7ELT^VUyh%O&7X*+UIE~>EUIybyfi`pt1h|?u$|na?*%IZGMfD zD^i)?rYNYTk?$4C=}(!=se)@-6!Lznhw`;*ZKgP|>T1I3&J-R~Gg$Fpr{#NXb&Rts zv?c?iQq^e7wFE4p-;#}KuED6Zj^Us!zY9n}G;R|fLXRTGlCwbNG-@=Q?|_)<3sFwo zTGUqVT2K|;!{@NuaJpwjc1uP^M$P zRiy5Pa<2Ib49Ria9Ns?*3o)5d2^fqv>rQ1Xz7}`tNlIbimv4n^-N?y%1b0BtuShhS zM6A+=GyWDHUxlHiWc7g*M!83GYBNTVK+=yT&G}BxHOi7hBdn=^N(Qs!p%e7lhaN|t zwKJql=G*3kQfLmFLR9UQb=TRavXLZuC3WrksAaz`%>?^E zANo~GQCgL&{3za9_PBBiGHDj#qsa2KNfEHK@Z;(**A5Fg-XY=nShzFgpVDgo0H>#| z+!jYh%7ALC{{RZBWZzH6r}<4gubq{CRelzm7Mj;pr*MMl?xDJhP0)~5>#DJ=%XnfA z_)L>e+Ec)gSnm112sqWbTGX$(*)iKuP5YDGdoERguKR;Z%$qfM-N{7$77X4Q!;><# zN9|eD&l%Gv3mY-edt+GHPchtubxfUJ)d3&eiG=?EYIem7Ru;t;kZd8JJd7=Kw_P71 zOVO&SFw>OX7Adp*@B2vO`Avc>aj>LhV~We4>DlD?T}nu@->N42hbU|>(MW$PuY^YG zzbGdr>{r{~%B0qp>=q|N$dqb!$-Np#hR(Gsq{i9dP1Q>qvU{B)i;B>GP+@k#G6@>I zO>@wS5IZ(P5PWBlzfAnE7(5hWaN!n_&wEV;#(+`u?759HGLJ**1OEVz{{SIN6u9ou zD`@`!E67lG`=Vn^c86F}Na;E6jno{`q^TP0vwD!}zxWORI2I0u!05 zcCHYwKndN)r|w-J6l&B}h}xMuT(To%qeI1om(xZw@8LP|#*EFYUr}Fb`nM-btr-eC zYLbbZVHNr~N7FtWPF+bO1W(isYlQqy4;2?n-*!Xmo_ zM}B)BKo+=1wRY(;c(WsNmB&Z5HhCJNo5`~Nr0L=({ZxNErq%nDgjchVLu=)2Xo1Qn z0gB(cRM5o4L77BCR z?tKxr;Tvw>vxCy|dV&2Rx98zO{V$Cex!hcT;XC?&0mt;sAM&$$WY}|wm~1C!YT4YQ zllUm)Cp^2J@yJ?rH9jFDe6jxkxJP6cKe7=Q>Bc%`Y5q|zcx@pAepBBTIJXtmCXQT3 zAT=67!KC)-J+@pRX#%-KS881YrZXBZGl#safQ2Z#Gt8C z(p4?gQo1*4YMG3YzF5E9c4<_b*!K#T2!2z!L-|&ZDTbUD7E4SGB(AZSkpx~yle4AB zaMpNIWX+I0+XZpQ_64l+oZ{nWu=EE2wJQr4HPQ=M)u08Hu(SeXI@7V@k|#j^9Gu-Q zE&P7KD(wV)U(+!LV;MeNQ_r<%bDV@_tEoRuGp#sp-Ggp{dKZ?>ZDR+f*sex3VKBGX>M@V=_P(4CPZ`97G!cPi~X{2~)rIZYl%C^7W}{+LTO zH99FHQ9+pTakkU*Wr4;w@)WYVXKHs~zsI1DK(CZSzQC*RsHV>L{GpU>{#UFD4-13FX}vT9#do=+&}cIvsVRwDE0=HrB)h51LZSV-{Co+ zoscxGa*I3PYFi;o;Q?Oc?Hq;i=?M4fy+T%gllNV6Khk6VeJ9gO>$QBWd5kZ$iPVK| zrRuDVU966^B%1`>sR`8LvL|%zv)f9lSLk5&qBQU54ptL^JB0SrwEVB7b4@)MTlqpD zN-+Kxi<>>|H*{LK?P!ZfwG~BZDv8)9U(aey@=fhu@KM7 z)BL8>wkk&W%^*k0A#d=5!^Zrg0rVfr7s>>nMQ)nb^5a1}CMJK|Qcmf97RaAN zN_Bi7NJlWWsLiY$UY11X@U&@P9IYq{T2__z`pEY73*iEe`}U<@3qkuz3@3y|8a=6U zi9pd`e&b|cD_gqNtL|62Yk=e@Iyp8@$1O%N@V?W!AQiY=t~&$q+9m>bPr)v3rXnkp zNA3<(l}MjPptR`}6WLp$RjWnH{{Ui0y|&)Nu+v7+?Z0hDXpC+kpqkxIq+%h|ioVy{ zw6qS++q6;er)3qw)U}eWYg)eu@95Qg6{hRKr8dP)u^@*dJ0n(*3GQBZFX_ znfOi0y`94AeJ(E_)nkwI`;@d4ASDP<+hyibKFTElYfTGUktfp_P`EK;Q^qJFjTv835sViqz*6N6Lmz8^egT zB!5$oL<5!nk1S(T*Nw66rI_XD1Y_>r63Md5IS~wbcau7hzxz@TKSe_jpgmKzU zp%Xx*;%%#AS5_eAJdaIZp!UA@xb1_L^s|W+(}`QCE}#wS9fs>kR8@Xa9f3|a-&y%q z)vM#s1@|(SwKRdbP6Uf6YxrJ6@|U4qFAfGO%-G zz?V>1-F68^<;d`&M`Ep694qcO9kwX6j`#4nRI&4PN8@tH zn8%07$rvtpcpO?_;5RU3CsadEX|EB&xG>|0#-9lxii&|JiF+iNGM;q@Uz zQ@<-a25z4(jzwiP%0pZzcY2keosdu5D?_pDc0+VQ29pW2??#6$$6%>arE6tgu#a}5 z%H>j}OG#9#)qaMiHr$`e3Xnl`m+8o_$}p4xY1w9D4yTKy-*8ey=-gU+Y)0!-p8+LcJD^Y;cZbi+#(c94G*2tzK$_l+S ze_}JKntgUqJ%A-0kQRw86j48qKu6aEVrJ6%IWB_fSYsdF?pLx!;2M_Eh1cf~$=NvW zwIG@|PT2>LtrLBj3!TE6C$sJdCewFvG=9|9@4C|Bw3WvyV{Wn8sHUwuAQ1_pQKaS= z&gr|YDa<3(4R$BE?$+7?I=&DDqqhk9LOqXQEont#OXG5aX1H2@SYSh~1{MDRPynUt zh2v$BBc^$ARoE0cTdMR&mE&yypCFs>T4QQ1Z_3uxBxpuJQ)Q&$9(%X5Td2|_K%{m= z_Km_;Xm=`$3LfByP859(VQ)UGM~=jbptUObT9Ncu%5n(v*!E{B$o7vQwLc-mB5hjK zuh0>3T9t*YBJ1ooR95R`O0{aMyHzd`CCT0Y0Fa_O_AA`OMK!@nn%m`DM+(t*cuR)0^vOD58Rsp6%f`?ox1?rBCCx z$78}h+xDmZqqLv)+vs<3$6@fF=m@Wm*&WYtzEk~8;W-Zf0RO}QE)f6%0s#a81Oos9 z0s;d8000010ucic5+N}l1QQ}bFfvgTVM1{uKr=&9f&bb72mt~C0Y3q!W-dhN?@IiP zl(urodZze@v&|U2LZ5y%UxU?nNS%WS-VZ86jrsZ_&A{|(=@3Pm9d*l85)&qT5d1K%P&QvBjdML zOM`zV=@87*Z7>W?vL^0m5m;sKRX#kek&93Y_T&cZ1#!9nYoyg-DF<{ z*v3|iO~ZOER*a91^llq}LQRe*w2y4b58;VaMklT5dd@qDt+V8m(ne3)gVRO(m!{>W z;_t!fMI0{0CE-G$#WGPylvIyohB_Za6GiDoGp!nWEQ!6Sp`k5UhREwnR7nV;M&q)J z(uycdqiH-upxCh(v8eJnA&O%nylYQUo7+bDWMxTxnEgYK5+~|Ehrc2opji#{jI*4d z20iPt_%}30X_hu_7bOnRhI*WiJR{Oe=g5cAj$4eG7A0)S>nAtCc^}yfvw;P5V{{RHqI~o+JmPmXHD!Ma6d5aT^F}vVq2U3yhayiILlIX&>vme3j^1W z=;kc%S~irA0`J!<*! zPnu^;Ok&_{Zp4&2@WjL>pN zvh0o-5Q|-iw7VWye?`fY5$(~i_RJWz^R8L7r4)+Ql9h0XOL5!Ly(-5Rh@r;FsuyIW zI~JFw<8vC_**HrZH|{XXogM1SrbkB-k~@5vG41(8hK$Mo0FHKyeyKhrSlJA=%S4Up z=NYLA9_l3 zMXM7pUsBwpMRIPUbF_Lj@uo@+9K=(!E_{DZQ3)xl(#z*g&9rUjoh-8Gvdhtpi;;h^ zm1ITZQDm@3=!QoJOpCoJVlpy3^k&QLRg%w>Cl)7`Ju@D8DSzY>8!}?QkqmqhM{f0e zl|s4_*EAiA3m!H{A19}cEhM&)W%zrFTr&!BlZfBfg^wzaV@gKSv~eh-pQ0_$rDYpN zni?vLH_)V+Wt)jF;qKF>Qhkx*qV(*c#XiWzN0T(3T$V@EvBq%hZY>_0=kaf%QI}7X zI{1*yH_;DM^)fwbqS&C8w8+^wSr{UC(6EtIv~Ku6QL--3w3nw{#Kxr_$5+X}`J+j` zMMmB!koY~if1xVyqKQVx@x#@jwvTZWsdPq8EVWijO|e;Z*_)Z!9pBM8#EwoZc?C9E zxXD{x9Z10~%ahbawMc4@NWNxCZANLi@M2p~+I^m$Qc|VSLWlHTbWvJJfhgH1KcXBW z`7G;471>%ze+cw4Jd~5BJbPa26pJkP2DPvM6fv$+d`dJEN zT4jauKZvrnsUcGAQvU!#vuL6y@kH?()(F6>^d{g~$&tBLBftZKf<&n8c@IVBI+hE2%z8EQ2Ve4izo zjE>Rh@_V@H{Rvi$$vz9QvB=)KM$|`*87_>Hg6*H=M{Oc8xTcD4vuQpMIn5VUwmGV1G#giZKc;O|{KSz#TaC&@Gz}T$Zhdy{O zb2$_vAweOM=*25^$sVKBH}Q!TxtOr25L^|dmwI%JzNVcc{GuMB@S zHacbrZOcoe+Dv#8J)D^NgCUmqmW)N}iX^L)MebTYbjcokeMe&%wX+^Jq-KDiD5OxM zxepob806qukd~56Y=kS9r&?~ZOMyMIvoyXO5{ZktAsSS4a>km`NBT=2+A_;*NAi*F zqoW+RM_zg|LP^;S?)J!%-|>*}ds5(!TFwe;h(~N_d82ere;Y(4XmX-F>d2~kG*OfN zc;$}nNkB-93{d9Gu)akD+dZ2fNUD3ajyKAuxsqIz83>^b@oE?LSq z7MVDGqMPiL3~;HYU2r=@VYie#x6x8(L{C@Q9tS4K!M@CVE;Q_nlz3xGM6ll|lbkFYfB@&3$yyAZO)$WP*8cM*-#;EcCxTC;0xv7Dm+0H)+TahdE&v_#F1b3ezk{A1gr6n@UlqlK3YF(vELbr_4*>Ovck(bVZ)8)W6aM zBfGIeC~%80%1P`oaE7dLvl`pyTD4;xn5Ry)ZiK(OGQ5+bO%3oyPPsc8Av=`}s~hJ` z>ABN<8)Aw4en|fSDJ)yQ&+;cH*^fM*5;x`UqS?-aQid@%= zBDow=N2rW{;xyR^{7}_1YL{g2S3|}q7$IDf?uw&l+tSayEKgopxBAEakC^3Mm3*TR z-76B`@{uT8OlZXZY9`Z!c2UQtViKaRR&L~!*Ytj( zDVV0RD>%{V$xNms{?CbM;Bw@GA1KHA(8+LMk2~1jwqBgGXY|U}I9y3CNI!{Z{LFH= zi)&mQ50P+oJ`Bk=-V{y zj&k}IM))F@yX7K{sM?LCG$~$>iIV8-QKdwSvWh6-7pJLT0#W2jPoh}o5hmT3J27JR z@4>I(b=f4GSsZ(rJX;+z4p)Xo1-s@?EOGXKksBeN5*rx0{7oHlUFm;E2vWDER5Umk z8*o-QeUgC*ZFKce;)%*I3^i+k=#+hZRBN*A9G3}y8KTy^ksGdnl(H+ScqwYE*jpJOhtN0)hBD-So&7V}$cvnNLe2daNWExsq36cCV)a;m zq+DjLGioTW8R8Szd*4K0*p&}N^=iiwUmi*Nhc&gEY>qmB*4JZ^>1PAq;h~XQNdNuYTSCfoo+BUfKZYP&ycN57kQ7e55 zo{=n5hbA1p)a`U9e6PUbn6aheqfbYpCmTJwG2-0l$qp$FBaN|RX_&W5y&6pRtMx6e z&Bf}Tud>ec>}zi(NbV&KtW1UrBY5%@I9Q9V5mZ@cJ}qr_dg=cF!4csem2M}|lZNRY znB8@rxVg;+_tfsdE{EX8=);6uY@dYj8;BLddxBV z7p=m`WQ_TX7L8ctwTbQ$uL+pl{v5gChxRAy=KlaxFIkm#Lo&$<7C+&z*d3aIi&U`L~*|H*r*Ku@uZ&2p;PrYWW zgnVR-Hm?5w27JEMFYKFb@?zl0E-1w!AFj7v86c#onB1{FvL7SS_`b{1U&1ee>n>4~ zAIQN7$oG1! zK0GHTh)VU8RFyLu`eWct9r(3+CNm$}@SZpF@nF+3a6zju=Piehu~*s-Z{h@~DDpXlqoSf7K^v}msf6l@elqShUFuUW{)%fH1h2C0&N!7t#W{W?238BgexHxa@mTn$jPmsBNO56Y2R z+0K+n(i1L>xhWpuihI|ae?(O-e-=X;+Yi8=kHIhK;Es*Sj&VYnxJX~@GrPpvWJQc&OSVwf4WgA>_Tnwa&DnJ*2Xxu$?e+|O45bo z#iKIi+rlwRbbMEzw;QvgJb5JnMUiq{5_6YlrHwcEB_$D0@T>dsX*EPHJUwXK%Ce26 zcvWbx?ECSMhsK#9ZqH8sPx02Bx+fjTmN8DxP#(X(GkMb{} zWRo1EER70#wMdft6YyMkS-BR4rJI$MEm|YT8Z}It;*o(<@mhP4=->Pnw?tKF<7IfX zEBo=DH8U1C<5avaMK6n!B^9wmQLb#JCnEm<(fXTIxi&S{oQ^w%$AZzL?3BKeBZ_kU zh{JDM)|KHTF1aZ7`8L;uqInbtHz5g}vy$3BZ#h4eYkZfc<8l)>C-Ow{#vO^;yimlaEEZ84IDdgyj1Z8nL65;E6NbrYe7#c*)=Qpn{p!NzJ-~8$qGsJqe3o(uSpW* z$CX2gGyJ?i(mAou^?nQTPFqoI-$pN&BJi>?@Mhx7osgA`lci){|iGPm(FJq%3T~`Ym62b@*PnVZJm)QHC)^jnJiIk-3W} z)AFq-u@8byi{nP*n4`OvaTA7ZPs+8e8|1UGx;t8SDaJps9GKtPlN!j0dUl0{ivjGB zRJ?oee0koI$8N}~)3G7O$|nmT{NGx)$u(pPa_CBnJJP=&-iT|%*23wY+>BnMCLa1R zWsX&ATGMwTA9}5B#^_G@8OeHBq_pqOh2<`UEhHsT6p>|@rI+BmzVt)z&b|iYvld5& zdYaFXrdfRvBqijLJ`oPIqK-|cIxjo=7K^yF*^vls6wNFZvkw~O)IZ+uK zlG52_>E6G7IW9b-+%nC~aDPR1|xkNH4aQvkm%7ws{>mhNYl?#*p$0{PZwm%iB(!?@q(I|=svd{5_fQs6S z(fP{`=WL8NbW>*2X|$ols@8hHiZ1oZjmBHxZrp~py&)~gXF4hKUQbTS=FW*pw?tz? zM76)7Ix!VmF&CqNpuY;%iq^jj#8~Dp3CH*6EMGVdT0I=Fl}k#%Ke&`Pk^u zE>RE^42@~dZ{gUgoPd;61vJ@RSzLYxNLqO{^6Qk9ZzQ=Ezy)+&s+R?2Q>@hrrjIC6 zt)Ekg@G3a(eAD_En4$Ck=my)dL*3*{MTrWGYwNNG_@>TD=eoM;dgAV_PJ zOa%h!mWW!b`NmqS<)yN$=$z~#EwNNSLE%nTDjub!blnwJhbcNJ7woDM(zTRpRWnSO zT8BAmq={*8?+omkd`T%zk_?aG%GbxcYI%tiQ4kcK9!x^uIz%HddLq=joeLxL`9 zq=jX3b?R0(Q#s!#3HVMri!bn*?2HH_LVCLDR}1hq3O9Mv4_7 zT>t{ndRL)SLhDvR_+?V-Jx0p5YQIw7&Kfl-us&w)OrK=O4er12p?FxrX)q6D=Q8Zd z6@;%!rB$F)ImYTflmKX+Rlr5f5PKrZ;mRH71-_Hy5t|u3E!h@vaEbo_C_54!8~uPU>P&$T_BLv|f_5%IF~12^^tDh=LQDO_Zyxe4C&gWFY)AbqCGXz^lU$ z)YiR&5#OnQ`1ohoBZGw70bo%#2B=QIT6QDPQMwJpX>8n1;Q<#-KT*mXl(;}gjN(vK zp>?iOSB8HuXr$S}Y2>R9-Ver{VlR!;cm#m~+z?P}eNy}B-Cbga(11YDVE4;l2G{Hgd^@|?r(@Lqr z$_Gnx{{VIBQtP=@5;sQ^3A7KlKA^f?3zgQ?T+do8K)h7-WH~d6+bVo{?gp#oV&YHzN}vFkKxe=AKY(t7aWH%`cZg4KDp`nXCq&ni*Ef|B z{izD*7?r_YVnP9RGN?FgKeDgk=8v?X z*D$t6lEreP7Z3MeD@9aXtEYIEMjS$*Cv1tv#qjXLZ-G-xYN$UD1CGsfp(XGT=?_1u z>!#g;@g8NtNGi8J`vR(KM5#f8DBWrkw+MVjAn@?|o38M>zYY;nsD7%#%9m@DfTA*$ z-A?&S{{V#)BKG0kIAZFmmGM2BhFOh!ViGTcwR6nbaA zUX`~#G#T&#jFJSQGC4cAmU+DhmVVZ@352(DDfN2EHL*_&}GN6@SBGW8XeJY8yxT1HnK3l{!?2_ zwDP1|*+#5Fqi!-Sw6UIEIhV z-Bz(16@I4;f+4*v?5V_W?tx~DMJeO5EjFDMbdm<82De$X=&Nw1@d#mJity3+zk$VT zoAqH7aj@iKjpx(ukBhH7qbk`458*lV(>o!F8m6`S5}Xy3c_)0J>J%cm%A#i|LJE?s zp+}GdV2Ce~vW*dO(R3KY`%a1@{Wc-`zL`f07o)fS7v+x&OWiyiHoFbqR_y-((y6)? zNL-3$6NMm1)!QS7hHLD;V`(eF#nY5aG&wkIfM$u0ap?w6b@JR^Nw;8zCL_Ey@D(k? zsy8ZP7jz2MYKRI?y71gpjHcq@TOUH*pZ@^0)Y8{*q1Ot$2U7kH=(U2JM(c!k_FgU@ zQ%%T?GKJ8>P?iK4PKmVaRa~N+(z=FmlbCf-TmJyG8;Cq?Ex8G_VmA?oos=v(90X_&3S*<0PHfDy zLL8}SoJQW-g-$RIixeEgQ&7WTB&l_~F1Fcel}@?TFA4qOK;JEYmFv+| zNqf*W0DYBAH6u_g#>4uR7{Z)Q97oipzJsJ8iHaofhRaD_lusx=)XgZuswc8xrX7_2 z1Zp#pogrUU*#ZQBEQ^Dh?_#%C&QLROy)wh97qYXf9?Fn!RHl2NI4O~`A&)h=bUrUI zfOITJ(+>vgL~W`p`Z-j$2rCL5$W&ptIjg8N72uHAa&nQBjXSF;@~{Ykt`;sf8#;?r zz4Y+BCwiNeB|_B#F0S8A&~vP(WY>CFEWTbKKIk#mjl!S71gXr1gFThWaXr)=IdUvx zHPkOnD%Ni|}&i#?i9 zclM-2a!errJ`B$8 zHdnV~9yD5cY;K1us=+}{_d)ITGR{HJgT8{MRm!CUFv+@W8}zRYpf*3WHU#dDBitjE z;RrALlVM0I2+TVctZCxGQqP2B4pV$g2DWC+YN@U`ZsAS~gZ}_Y)p&TVEq8PiTgim% zEHO-4$>6XWw>vLQwokWMn71A*Cig5K-XP*NI4x)_*~hThw* zj4;%6Ma&V{A+eMJbc6J|>K*?84(?lUtHt@a5$a{raTr4}C+<^-&aF$TC}LsKLk6r+ z>k+B~Zk&lxx@=j@f}e`+tY>{AWkX{OWcGb7KzU;*ly7{CPLB|aI8UE(oTgxlINYkx zelrdy=~07*%n#J!jsu@q94pRH3NLceXqi|vkFhl2$&M_p2*WmkvTsFH+Fq<#1ZX$x zjDR<~gvW4YVd4w38MR6+Jtad$Q~Z^M@PqSDULp({pwWI-!8c!Y8-nIy1NN_&{{RiX z>Tw=%UBdYo4PgC3Q${nS3&Moloo$q(Eg-K-oFZC#=)Pd^J|cGX6dQ~nZ0=W0M4gMF zFpXSkAabrDdSzb8{{R_?I$5H7&(vj4IZ0iWlpN>Ds_6=%-$}VuH%BK`phqFXn-%jL zP~mjo0sEmZpms&>4aOhZ@Y{&&5Bh|ztaiDF`A)^c#V>Bi;U17P`Iw*f%7)-IS*?|J zG>>H=l+O$Ev6}CB3#+M{JZX~+Qv5eU!)e;rPWa4Ia27YkVqMN&B{K*Y;}2%3ekg?v zZD{yR7-1QA@sy%aJT8{NS|**;gbaYzfp6ItHJ1HBK@9dH7h4V&bZZso}h~jYc z4drY6uTIKBx-5O#bp>?a4cZj!HyFdjRiS}~ep7WLbQ%B(0CTZ7;Z)`|p;!fIkJ6;v z_f)hgErH6l^M~k*S^TMSP_LG&rPkqfj|tq36qv+k{{SFUhlpO(=7*c=(x|F}+W?x< z={?bL(CmdGN|zW4(MqMD7XfnA=PJuenY{XPw1islx^9T!ORTz(U`G(_5yyS;9ik-^ zS`0IFGB`)>cFTpz>KPLRtAeRxNhoxF%CTmY1HEcW02-UYK;wKj{{T{<%zhVj)A4MM z92DSVGZV0MubqZk?s-LyI;h+fd!o?OeiY&1Im5V9;2+sWBS?1#AWg!sfAXqfLbGAE zaIWPg`Clkg^$hx51TMBxe&!}OU(|*zU$D_ejb6)Ds_Fcrshts|*3vaWpuh^2zMMgz zP~j`8#aPJ7;ysajdihvv8fv|fD-Q^7cP4NRYHJrKjU0xgUbtekSC9O4jiWqf@imm~6 z<#e?r1IaNDFVyE*Qiw{WPE3V3QP9n*|tHwi) z5H0k%ODuR%p&4IQCBdV*pA!9|AxyT9xy5|Su^v8_Kp(k43?_JEVHF`H+mftr%B1Qv zUL)>w9hHsYKjn~4gdpN=>ZuV0&O4`Cl2!BS6)Q?)Y&@iS90#jaZ{b|1Io#wfwOXn2 zN^Cs1a8zUAHJ_=dzXjeaJ1uJLtmq?TI#}RM+UDx4APs^nZ%aa#8b@`~D|dAo1WOG#6?QOtpc_|ClBL9#bLD81FDj>UGNYJQZQ&wa{?XFZCE-_cw(qGlV)7*c9O(+b$Kl zy_LpS&RXgo6h81a2QIro}-PhW9RWv}# za(6JBB3BEQ;sNf3avRw-xGf#ZobJ0SV_nd}!?SCO$fx)6QkJB+4b6ct+)QUqBS0oL2D*)(v7;Sz(La;#O#{{UpxjY`t!Uh9N! zbU8UbgtBM)jHj&gfC>mj-Wi}ql`Eph4wIRF0`AxqH?QC%hLn&A0 z!37z=3lr0#jz0&BdQdTS3j^`HWDTV6FTv4PzRH76*?Oih~sagr)UdKCVxI7i&GW?+L)UJmIB4WeI z(&ECe@l_rnde>8l%f!WLEE<5YaD!iONGrn@4-=v#?r5hb0JRO1@02Za zoq{iLH615CF0SRQtvtFy={Z%3=M3TSuJVeF3?YPHB7>SY(50tyuA z?!EGjv!&W128brOI2yGaXBlH1=(4LPJB3yuhVja$1+)cobX=b8i;t21`EoMAYaK(j zCdiM5VSDtc+wz@;?OC)YwCs3YVWJL)Rp8-8ZnDuCRGm?gbx2Jk>Ix$#VVxWy9?Gr} zBQBDo5wYAZlPWX1=@PvmT!pWflm?4%6OP>Z@0cM}G(KM2q2c1Nx4%gXuM}dRwV(M_ ze@b`VK-GS&)iW+Pu}&UG`7khph{R_j)!9xaFw={K`9Cud`gGO%0}V8^;H z*>l}-?zK}E=PN3*fu}iZc$N|*n-5VyiK@f{}D9`hofbw`wFm)2BuFVo$ zyibb6Y3?;%7s4=8_Y~t@SdaA-Up^iSb#Yw;;NZ`!?4iFAh~P|JzxziNVt@yFT!WuX zfgK_xNYP1N8@)qJswYKLg@;i^+XUw9p!sZb^nvWXC;3n?*59(16dI`l8aYu4jmN2W zU!m6?aft6st26-J(LaQE&?5@1*1D#$ZUu)5tE@BKV?uAy|~ zYHX`C1kvB{AS+++dTr$4J9kG&c9N@b=~dy|5NxS^*n^s(!cl${o#7VLj5cSL(nEcf z-mdj`{{Tn;TtaaKG`B(bFC2>7!mkXLyzK3h9BKFWS5f4>yC!USTovMC86`K%1+m|s zBqB@#2IU$|Wm~mApDo=hwp=cJweCuGAsT;`>Hb!pTs$Vp#UK;=sKt_LlL&!`((s}0 zrM;7!z~;dNMDp_if};X*1^)oT26|8dR>6J3ga{}ji-sc*YB|qEp;|(WHvZ|O5Yk6w z4ta!2aRZz_gSx500NHvQAEg~_q~;u(j^Aofr59p}KXFoeaE6Uh<$;w{*<7ON>77?j zh{c*VL7-}(zJ^$NbhdCsLxs@j?0mP|WFGNLK9Jo8ew8~dSHs|g`H);zFU5Fa_(9)R zkf}ItbDO&j!+1bH4VXdJhYb^cZXO-urt*#(ektPw-JkeaxG!_OM*;)zkMviCSBr*3 zvBj|~=HZ1?4OoBJRbh$tK)eBp&33FR@cJI1!U`9@PJ2hoDrI(82i;C1#v4Dh&j#dh zy862-;eQLzq1BPMR*R)Z-b!8RK;W5b4BI0ssgyB+OC5m z@Z)bd0f;mRT1u_j>=fk#sY6=`)@2c$)a3RzT~@c@JK04404ox@n(d=Pf`WSraGJ(n!<2p|YABg9U=yk^l z&a>L<)Cx4T)uuU*-=K`~Lv^7ai3DR|}v8?uWv& zZ&^(T(iczkq=ZFQP+e|RZQT;kq~)Tsh*18a%C@0Zx|f?FZj)s3-#K@sbhJXzTqBCX z9FM|}CD*!$(#!2n`vYPpzNRZ%P#v37witoA@ zxcxYP<#>mwymnqU!(R_^!lMv-IY8HJqO(d8wm<+S5(2nafEC>+($&UOwox#9sXr3W zV6TW??gHWz5~iiQ-8yPKb?_IR{~W;eJ{7%ha`6=F4?Sl8iO9?&mgR*;j|?cl4st zjXg52>QHh%XgVu^tWXX%<#HDY7L+8R^tl$6Im@pIi*BW-_8v}=8HG6**M!nEl;OMG zC_fwj0IDoFP4LdjvR{feW{P$?4i~6|d{$N6Lk#d$IGQUfqtOw*Lh9KBGP%DBC&*Y< zh`2VFa;bRA9GV-UYWQ&L;m=S!FB9Q^Ex$sOe#2z(Yh6fJ_2pRo)F3xdsUZfbBI?;{ zyA=xSsdSajK)GyG;d;16Y<$i4Km{2BY#Vu1=*dEWT&}%9EtjRFd!zEom@u!M15Y(O zgeOf?&vX!Q*EXG%mC>^4>h{QZjv?*P_Czw%tGCORJNicY@s*c!M=8%bH4?gYMUP;1 zFW!TS!TYoHDJ9i@f!A&YnshnBh|XmvW}Cq&=(i8ow|j^8&M^ z_EfkBglV6^bSs>}K9Z|unKd^uSZr>i(~HPgR{j?qk(&g1Y6>YtX`4pwx+r3NNHq~4 zCx?j}6boM~saqo1>P1fhIQLHn%VnbP=f%J}ut-DS$)Hl_QNUMmr5>W75=xEz*Q!@d z(P==5g=3zdx`D1uJozD0vY1yuO7ESDrS}V@*#JmXpXnBdS!vXOBSoSOXe985jKb6g z!s@JNS}YK6!vbShIdvc1No|*Y5UICDms=;E$ii?dlQ;+Idn$17#eZ>M@eh?OQ-~#6!-cFU+bgT&^jw$+)Q%P|7&YkReUZrEWB&l! zPSR+k>i1`(fiF2Zv?{KO5=Xw<6QJ&|j1 ze|IlrWp~QDO#tec=BOyB*d~b3WjrF`WzUEqIi6Ii z==PQ3I%7Df!kx+su|doV$l(6~`qOeJIh0C!T&xkutNA}lrkNg2>I${jW1WolD_Tzn zE30L$VLc9)cX58=0L$EJi~T^D0|s0zZj&D(8JndCcog%+&D^sdUS@ zvg5+gtR)~ysH2od6`8=8>SsJdv&OFF(+d?C<_01;_~sR;Yf_nbIYuKr!ZSG6#Kj65 znugKU2=0aN0vO9mGdZEk3zPL_m}o8eX42-*|yiNv;|uMvkrS^;3pa!m^L0916TmQ)Hp z0!lfL68``V;)_^f9m3TH0Seqg%}22<5i!50)vU^JAnCSo7T%$yJ|u{`k=b9UOw~(i z4YpW;dw^aTi>jAnxj=w83KAVqfgUF1Rliwk6=_&Ng4pXakQRl+*Gq|ZV<3xj44x{p z0-RhXZO6<)HjoGe$w;K6Ro15f!mLe82=AHAfQOek!1V|=FB1GJW##AUC6+3ykCHNn zFh*6(S<)YDf~laD_c9B7tEg4X>f+lkfwNoh`rXAH}!NV9o-?3j77 zp{^+im|(LfI8};Z=I>FaCp)tqf%!)+p(`gc@Prq1r&tvaq*$-aa*B5^Y0Nh(foPE| zE4iM*+!jW0m|3w03e-24vG%juFEt4UTHqzzJ0O~ZiL)wUDhExx%l-qF@?sqYuMjL5 zVWgR~v~|-J3?ib7Sf~fbT%n?)zLoF|rOV}oRMa4@Ab!XS)3g%yxbqGcE0jcoUCiSNmXftx234j}H!Ulk=6OnB z#>P{GdB@WQ?pIaZ`;=g;LJ=0R+L%j8=@uQH5IIbw_X`}Uf;vOsKOP5>MO!I3$VWW< zT3EOv4!MuAqD0QFQ(H_gBQyX)FUt^9o~Cphg9pn!Ab%m!@t$Q0wF6R)q7!XYt9QEU z3@jUz*~D7kQH8KxAajvgOh79PJ1S*Hm@Q~SH#(&~>EllkQi4FnlK4194+yh^+5xpH zrs8VH%T35~YnukRJjR9HHoQhm=kWLf4A?n4K^*(|H-cp}%&JusPcRhZg4~o_Afz*{ z;2==(1qsu2D3U&6;Ij;FR!}5+7)SV)XAJ1r4=5LDdn@x284xP<87_*3R53DmPNB4- zDbRu$^S#9gH#;#wYVyQOEoBC&d2TVG`XN>qDBtxjt{6FMH^7<;%55eE#w}iIXNG5!pdZMZWkN3d@Yt}tMx?xc6QWg`RIwuWI98d1+MNx^u7 zdhfWb=|531hfJExHaTV$>ZWOR6#f#F6qZ&~u*~&i6aeXLv0po;Rz9K4?u@>h&oeW; zJsN=Ma$3k7FWa6@OgMoz9EKslZopDDCS^-NS-+yL4>pd5M=>xCHxmqw%L z>N8h~olaJu9ZTt%>zE6?%~BCcNh#I>W)Hcw@Y!5)qUxCZ2A0ZD$3(SXGZIL|24CqH zFd?jk*qG!L%G4dqfvZUKGx8GefGajM{$fGrZoEd%muskMxJcAkxQ?pwzyYH-IKAo$ zuKJa*1x2ApZxaJ%Wtg<2%3fvS)ea*lmTFbbJV8U&b)~DrJc%z8a+HAW0u?0<%55bg z9iAF;ORGE-V#;*i0b9$0bqp$zMw}1 z@h<1iWSQ87e2hGBxy`FE;_zhg1E&dYU4W`>Al zsI3ygFcHC9j)kqoR_`U8e<8UN%_3{>M6{7+_jsQ7r!Qm!$P!Sgc}$m0A*E2;tCirkm=JN4+y2xSmG&`;q4qmOz>tV%TO!<$>vj;=H_4` zaY$|PQI!JS5mLbNV<~C}`x4PS7mAfmR;w*y=f&!A05(|=%u9&qXDv@Mkt@P=7?G4F#hD2P7M73|w}s?sVMc@I}>MhQ8R?iM-F?gVQc^m+DhQ6>=SMoDeIMjOdEF zQL(LoT|t&D&Y~O%O_!Tv0L@H!OM-yrB`{ofF}-Tr5vjN{rtaYCE&}CI66I7MF`P~6 zQu3DgAOX2l2ZF|!BAH{RA8}-@8xhYkO?ZUI5}?tV^>UZK;@09Gl|IRe%3-Zdv43!; zFCOK5T!Ex|wAcW$`jAUE(Vn_2wJpl+T7HDE1vSqQ1a}XK$SB- z1{B1UQ_QZoW*cM`Jod|rtirLvOFiN)>W&=BqIr-ktIn8SQMh7Z9LC(~Y^zlmfVPaF zvWY^i0k}k-lAzm?Dm#J-(TMciDihZbPawa3FZn8im;MtI={fp9fno`dn}!vH?E4y)u@5CQOX=FC-4S?cZg@YujL54#EXEoFxWT+ZiwEqBbt{jB!5C&1AZ;HEM zFR_=XT}8QluokM=eepU<9KTS!=x(LF&)!8y3B+EH9n2Ci7B;Ksj^jOwv(xS}5@+Md z;wE6oRB4Dg1bjl5cyyS7`NXw{XA;4}3o8qjxC%d6(Je|`Tg*jTjNm4-P|o{-W;}d6r`F@VC?W zo?JVBs#T5l+JaXD&)W|B6SyKqmwcBxi8m^W#K>6_5na-aQRkb|Ue_bojH}?P+%@sz zZ{Jg7a%_N_WgEWW;P9AYVJUnF?E}x4I}BJLgClWJ!PXgw!bPYM5VWTfy7#u_J83N3AU!htCsny-r2A51yoEq ze3#4swlR@@2>ebvC5@$m0bZoQ%uLRgP@GuByFE)un4S0$hK16elhxt6^rgR9Zm=!*cnw!8)XA+GN9X5ET^S9_!}RL9L@~bS-T4= z3C?5fhj3%ieh)AYxrZ@46v)hWS>9g|W8k@ql&Y`t2NR_;E~|-EmRNnUg}AuncAy*s zNl*9Y7m3!(g{u{lq+74qe+xKPwddRY%|I^inMfM6{g0?g+&TtYjEb7uh;EhyE+->5 zYUULwOV*Q^)+e7N;^4@-1c1%tORW<6its&5b4f=LkSt(oWvf#%fw+}&jN^%$n|YR- zT*qrRZ0!dbaXVXHa45vct|3hgY`$l(v;wty!wfhvv)sX=j|6#$;dyu`bWpgOpqvEb z&=Meqf>a6*&NBk^iFY++UR3w;qASS}FwzlsE12x~?{4SZpHYCOiC&X1F{v{bIfFY> z2?+OzSx%J|O(NievISMm%=LZa{{Y%6%;|o}?iHGpcwR}3amAWy+Xdw#N+Ww^oH#d-jwVPjuGZsT_UB|fEA%F>Sn-Z77ZG;r@y0%#my)vS0stfv58}CrIO5Rc}eDXO|qEZf@hAbHDPw2!e^yGQ! zULBDo8+Q}Wd||{3wf&PjT0S9YI_^6JD9R=-9LtMDU;!l- zz;*VpUsX!CrK%=4wi~HS4mg14%ha}oUgiG)M4&p{L?HVhP&B5sFxEZPCkAr#hg-$d znMVZM4aiIpxTjhIF<$0=e$Tq)jOI;@{$qs|TKb7iRNTI+GbMr8QZYK>0chM~_E4Nl zn?;v#1N=zOd?r*8s)|!v^%1E3Fn66=AiKKvDuTIXnV9f*L~>J37ai~H!U|4D1b8Mo zj&|reVu)*-<$#o)stwaKsD}pv?@?gsC2Q^&wOob1$WR4f^f8CIixQWCSuq=@D|I>A zK^lM!0C7=klu(sM15$y+2av_7wkx=}+h@2Myh9M2{2j!uv2wNuejz1w8@q(Lm((c2 zyw_6-v^%)uw8hQ{MG#qcaQPpSMqPqu%7N4ZEIr3pA$Gt}wBeAnfY|UnZYH%hFmLw&H=R%XzcU|Xp@0qQZeR?!_J!*W z?RV{#2FS+YJiW(w6fI}|$3Pp0Bqxbpcz=Y+eK|GJHd2TH_nzUm^mXEO;^vx^VpVNd z*y?XuFEqp~(U9tR$D0q-P~ISZA(5d-&pH)8!#D5%j7oLGNi;~8Ox*JOmo+?-f9aNX z#ay_|p;Zka#W#QY1NSq+e7TJi=wgPdIA(lYj}LAo0_dp82Cggnk6~od)Xa9nyY(^*Y^=-x1s5(AS`8A-)h(t7 zFUC|#%2h*0cWF!W7xRY5PXV(eGQ2Kjtv4f>b1hbh zq15lvk_JBCmF<|)$! zxri_t(`6`FB;S@%I;=a)ppe_ROpk(n5D8lDSZ&nI0Wt;weHLQk;YTJnIi`zW=4bcC z%T+(jyI&1NU-?Ve zjUrk?r!##_(;33k(*Pz@C~e8q{{UMH)U=0_2m-J6OgXa_FKr*F$p>7JDrGFB%IO1% z{{T@E6Rsf2R+Qv;iv!M-K~7c8)V>3jS(i39M6kho63>{1cxR$+5RFa}ZRIW_7hTKu z3=Mmp5b+QTa`BX^saF#nlA=F|&gBp);-GUb;J}fhuAU<*Dj8R)11TRDnB>}ES| z?cC^Lh_3|4-bUqz4^pRyLTrEGDqpKa(=ZQZK3Rw#R&F;B=}p3d{gn=c8Je{_xZ{fI?@`YWtb04MkG%tCn(4ckWWz2gP*-S+Arozr${&ilHgo zJ5TaKO~C9kXKaTll;Ia+kr^c1+NgE6|09`IHo+q^hJl4 zv)t6iA~BUT)Lm25Up?0w+a8wru3*_9vJm6QMxf64gJ!%BECB3oF|M4p=<>Nyo?~>r zsHg>MHupH>`h*b8Qon0o;%i$+WXk^lPFlTWQB|$m1<|w+y$NTy!2~%m6@fObFjlO) zl&(5uer0N6p#G(x$oQ2{1bj+XZth;yyMx||L%QrEc_?R@;sG@uN8mio8lGb5KsX6&U*<&$ZzdW9ln?w$i7wp} zNTc@}&)JM>sJYbiK)n7SB4(hMd?H%J1uE(XB&8B|_b;1fr-e67%S}m{J0`G7)1v+v zQ-l6(n8kzO4*>!RJAcFf0Fx#wcuz#P?Ugag`JD=xb2FIcR2fWxWd>BGTUXp#dM8;- zBt7;CoRs?|h{!fnWQk>tRU9>FX~KrPCMsRDL8aa2ApmIj2w$9n%y9;80jla^OJMUp z#`C`YM_d@}v*t8v7)s6@%%ET961iR@CJE1&h=*r$X_s>OPiWweY_!Ebn5wpe+wm)s z?pGf!A+;?*s!dbMQ<%9a!gMV zha`-G#}8?HBiYk5?xL^^mU*7i^wSx2RNX`HQoj(5Fk@;?k!L&xVhNwM_bilE%-xJz z+|JX?KuvQFoc7R|fj6ATMrPLiJNtpJ`;Yn|@`D-Y{b8y;N-l?v6Tp|MVGo5pt!Wne z1>hrO=;FNMsnM8za;O=HyB7U(q0=vEoMPgwOGH7hL4RGwxt2B_5D zlywIgbgoWf8Rcx7d`#V{XUy-#Q-YePy#D}zfw(%C+b@X0#c-zN3MCMJ6SD<{L#RBm z$oL4Nagw}5HCOH?>C+i0cngSyUmhj>H3tI~83??%hvsn%;wJ|inY^t)XHZmXu8D0Y zGN40b>RF1y`ed~Z>`L?oIR0wGX1mdzaVG7J?sY6;ybi>fN&{7QS@$rut0 zF-*#{>UcGLLT%mt$#ixzvQ^Ter7yl_j^hCNLh;lJ*>lEFL2yepyZ96`f-NkmVXsd! ziwL{^rdbw;S1WlHC@do`wLpsLRIh##)){jPT5%;q$#3|JtTy|7_?QL3f4J>dC1D+T z7@4!PiEG=zJwKQzRoiHl>GFNDmNQt%m{}K&U@)MRImEkyErczG zf7DDVf0VH%#befMF=*PD%R%W3k2UyWYoQ&X&utO{wzE@not>*ytYM- zvkbkAhMe&hj4=fLlN%2higTGkN|Y{gC6d1Th*iOF{{T{$S*^Q>KANzh&9Ylz=_p~| zkUCpILZ1b~VG5KrHk;~eY|31CkMX((olj;!Fy=Lz^)ZrINPFTLEf=}qOF4^Ha8WbV zej0im#fw_>aK`SQr$Y8bh0@9rpqCC=k}slv%0=K*3q(#ySQN=WB5rqt;%8Fn_eFC8 z-drWrxM9sP&T|bPd6@-YObVd3B6AK7U~1K7u`_P$dSh9N;xG#(;ih5kCgpQF{z4<5 z`6X0wKUpBzsT8Rzl65Qv6r<{E;LDikW-R7=P%_}=qu84CHRS^=s_-l|EE7JX+cbvu z98*)1g_fhQ)D)SBy(XD&!$C}^1zkC)f-Pzp;BGG{xp64dkAO5YaW&C1>OClFD*J+4 znX$}KREs503JJurdW$Ve;!rG=Gc4HLN0-EY*vW?Gn|R#E7I3=R;~pwB+P^Wg2FRgt zS`qk%v~-DHPO%!*JVnU^eIpN%zG2_t@rVZB$?`bB-ni4JfwLYdEE^Fx)K- zkQwkUP}`p?GlXTCoW{4u#PTsEK=a(Lu^%I;W??3tqnGf06?KRCApWHj=THs6@iUbK zV8a)N;0oQQ*>jOhKs09gVG1iCdx63;iE!{Gcj78Uw~5>@Ll~pa?IZbae zs$YJ-CJZ<@pd?I$O!%3pi}8V}zLQ2C;50s_Rom3Cmm7}!%4)r z@J9soDAcB@j|Sr0IGBofM{v8i_;7%cVco!A1DFxqX?Enuw6$C?!;x=_jE8`va3Cl1q?r~XT%JQzM>Q;*HK~|%1hsjHa z{{WL8nej>!IzQXgL!aUuS$Nc*CXWzBUSDy*>A6dQ5^QDD zw;YXG9ETGSV&IE0@Up^$9*TQ{kZ?uSY8I$o+{A!;{{X~%fESc*^D5792Z4lYB|?4( zDJs4-DvB670jXjw1yhMlP9R)Cm|7rsa~!DJdAj&j?hhn$2{HxK@Fg)D`?7I$IUx#x z(+&JDs+yq++Pmf<241C+tL_mxVS9L->_zS+VjD>cRl?Y)GVbG!B6A6Y%M(m=978i- zd#Qw_ObzD-W8b%WsZ~dawGx^tp`wcU7B%q|w7mx}h!;r!wDVhiO(9D5&3*EF~?6+HFfF+761!&^50O=x0<<^a*0l5FF>9nvZ&Sy?p~d> z{R5V2CDB!Q64PZ|AN4jw;M8l&wn>I)O+j=MnO$KUj(~L;A+kJXR|}q;AO)G!YTFsa z!gH7s?jXi=@8YbwC8oxEXC;%ndyR3bh_$J zK}D~|o}p2WiZ}sl-+|ibY0PB$qX(P~0$l zl_6&SLo_D$1S-@C_hwv`u)#SdRY4iQa)e&d+iTR$*@rOK!v6sKiWxcaE_xucifFZ- zWfGKkH48hUUQm6LNU7>%%o~@AwDW8Ym?mkAXDm)*y@!;gZGUA;90bBwf*1XK_VYO% zeUUP|ga?jgwl8ktp$UYkMuQYN%rpmuM{~b%QUjRy%4!U3A$UPgDTn_6`dc*nKIY{| z%JM~NiEZ17d;K$C7yhpiPUj%N%~@ zN!fijI8vW5UZvYV5X&oFL@Dg!D*enTRGtIQ&Ay%nDx)zBLd<4{&RY`iU@hUsH@56GH{&xfLDN&AcR7}O#^z}8EdyMC7v2Cu)YE^E_m_#XjKQOC6 zX>l2#d%|*&_RS2r+T8IAbW86rPw5b-5g2Bd$h|rp_N2{n(E@=5O@P@ESlUV5>ii*Y2BAY4?f(E} zn-0EXMzqS80?A0znZz*436!kP-xh>%IHM8xxr=K3$F{Xk7C<-`cTgb>V7#*R1ec2D z4Z3wQl-W|y$DSZy8DUB1sBAR%1_n}LQFKNmAlk^&Qj558+6J|1AqCafeg+oQs?*is z2WyzJMKnhOw7kqbT1x1E4z6nQA3i0x*xj(oK|^+`l*h&X<)=`v%jDYWp6xe5hLr|Q zW)fy^brp+XT`v$0eq=vV>=gl~xs}KhLZZ}$f-5OEjmCvGne+w`nHIQj3?b&Q4$|a5 zgaB$_lGVE?0wCX%QCxE=du&*1{!RQM{R7QzIU|pT)XW3%RW4#ozSAX@MM2DS2rghJ zF@tSp1U1TQ2}1>HOs{htm#G^I=z~8De9{*kRZ;mTH$Q&@mo6$dQh71O&1~$RbEqI` zPz5s*m@Be>Jj>q-Y(AKl><$8Dxqfd*BAPrQJ9-gzdkd;q55ziJU$ZpRb1e{H%pT*U zRS@Ot>L_8^%xmjiM*`EEp69t?LdnWxdi^76x4jbD6?mH}OBXfx#i+Lq*Thy%(0VHi z&K6ZzEf!^LQFgAofq|h0L|_XzXUKCeGjzKv;@~qwn5Y+Xi>NX+{EAe};65Un11pR! z;bODmnbxdU9kE5{_#v+KH!VQ{jI34F7XdW@`9KE0Sb3MEkm!q{mrkNJ!WPee05wiA zEc7MdfmO_lIHfeVM0%e?%iL``;9L8A#K&n_n_=XfB?oS3HM-2USGwFxI2OfTQs)IL z_J|s}-L-Hkb#nqOcjluG$6UpHY?Vz zLZOAS9m`{hmoX|XCy@{m$lWkZF`6&Ad0O?1B{Yn!RKe4I^8tQDLB<{?UlmR6CGjph zMst+&r!o~&Ot9U|-ep^uC9s%RQSh`8(8#S2e(NvMX62KKiuKGp&B`VNHT+F#FgCx6Syx21 zS^7*dLX-tlDJ&?Q&jJLij%28Y@}0l|pU*od+~vzEN}ggJAO*^PTF0?im60mnB){yC zR8sgvi+)B`DfbXvPq+pPM>NmAWqRWBCMv&kF$lyl?aa#5m_LYd3T!_DMnJk(}HRs6;lex~miIZ?bgfN}<|th(sHe`4>c$=W4d6xK4fZ45oU#6B?ajki3* zYRA}{`M>a*v)T_zWHNe`0CI*5aRdb~ekIgc{`^!eel-G6In>rFz`5Q7JUz;d<{&e; zWLvTtigi=R#Sw!Jp5f&M*-&m_-R=>ZuaI|-7!eL2yh_v);0IBN3lIl@$)erf(g~10a+~{jt$l zFc9fs>SO}v!O;N|%iOxW;R<4P1lnlnT7*INYGAcYNE@k*9ZQWd0}(FiNeu7E2qMj` zVtMLR82BC00LHTxsiIY$gkjgA{i~ZxpsRpN>)xhL^-)j#Gx|XM&WTRyJd?!M}v2a#+qKDF80hOUvWbW>!`FYAzyop zi@ZTE6)gIh zII=c$L%hgpf<=0m=65uXqFhrGadNnxtj1yx0ERirA8&MOv~B6l8n+^min2333<3= z=hUn4MJp$9Xnm23yZDxjJGrM+MsLhd+DY!fCnC6#TY(p@N-ldSLo=|^bJOlCgs!n; zC70WYU;=Qb#e(sfcW92PV1a_>5EjX*#*na94ig_OYL7uOG+mg zkl-!W>?~{TFKfG(cR0jc&CSXmoF|Y?@d79=yt3P}%H}Fi(un&SCgU)~=z=OvAafPs zEWQAOU@8-tQKNMk*JaCq=z{t*L`O$5`N_gI%La%^FWREA;1oflvrG_Z?qR6EGL-;$ zk6RJik!isN(5S=^l!ml&al4C}r$o!NB*bybR21CYIOYJ{WjL2xA>PF^BV;OnV6$rZ zhJXypQQJ-;iPTtcy-d_p8KvIkYc~RhZL_INd31u_@`Y&rM5?IoEy9F2Q6G|ej}m2o z>8PKXW!KUh^(80g7Y=#n%wM*j}gFgG5Er&3`}&F;DHkyn3x)26x+lLR7VCF1ahCK zkikJAbVPSJhXg9?456FN#jIjt9ELpLK(Z5dI*tv;!ERAJ_?`UiMlm^avoZ_LVKmC1 zpkVm;+`}7bymJU(<_ccE9m-lX-FWz4-e61>9)98RG`Oj`>MkDUcG%`)UNZ#%Uc?lW zRW_Qv!ha8s3b7oIgZWM4FSImG8N3(og@6xH)Vba89Q`Jra0WhS_L`pt5xvdN@}vuB zxYOVnpa0qb3%4RT40>=K( zeLw`KKX;P8- z@-#zX?wNLx9AwxzL9wb4d+agZYi**+%<~vnH{a5so#ei=?MX<_qmDV6oUWZ(R0*t0 z3R|wf-sOup+S^B9=kiQ?%pO;0Qu=h#1?T>9)n9x*Pu6u0Isj2}F4Ig*TQhP$O<~!? zlYxb(uAkJG}s|a#B!Wy{yaW!cTMGGXh|A|xr)$>X+Mfuo{^1uX?9ly*eg2K(@)MqRgTXtR3j z?#TOp)j`(6dcDzXq&h!DFijigu+)8t!53@Y659A4zvf6g1M|0``Fapu%FQZSu4ETS zW5JlmBjBF%uEsXD;PTtd-5Gr~w`@yRSper$MRXJY03#%DpOg%p9y^;}@E|Iv+EDy& ztgp5(&Vd7JrtWSp1G*r-*{L>``jA_<0he~EnKmWmQYO7RZ0X5Lf{(5@+Nk8X)fvJn zHd8+&6^cyNgF<5A+=(&DPvAk~n0Rlr>`rIe^+Bj}2zyc5b`UA@5ql41p zImwy$$d+4ObC1);(&9?|j;md83_GL`O5nv-0)aDA_DIAGB4&BGG_}vHTJ5uIc5{@F z6uG*te%13zHbmt0{lyQ#lU_&}&V9DH^|&(Xb0ov7Lek1Egpx5hw{BuUwe37P{{Wf- z?T(`RDP>*;eA})zm1xfXyOpyOcX@(SHY9*kWo3p4X2d_&9cMcQ+ft>1cdA6lO$edi z63E799BdiKq90nmshlhbm=D{1Z%YX^`(P+`V+DLK3d&+VeR#60^PS&_k|s0YQ*{8* z)Zo)iafX^EWvhAoR@S{@SqK9m7TB&+Pg}=Z`+=u)y`An>n7EcjhaJd&Qsri4_VuIm zX#leWj(0VIZ4Mg$04In1)SSAIh;H7 zr#?i36H!W>KagPUaoLH`Iu)d-4((U!ooZ|EVYDKzX4`QC8aL=d`&2I37xixj7z?rD zoqtmAep4#)Xv*Zut^93=Zh)EFhq4wwEy2*4%Y=*B4tAfWdypP#-X}B2wWo?41e!w_ zYDUCQ)DU4?A9^x~Ny^bG?nr*qG)oX))a^OP_0Z^-L&w)o&WcxC3^hC=WqUts0Lt50Ox ztA%u0{Ni0Tu+v?wx$rn?N%uDI5*Uvnt| zPyYbn^_LSDbwd)|3;6CS9i&HdSDLF9{xtxg$K#6v8be>46zhuZ8))*S{v+20F8BWG z?RzeK4;_&E!+R}Zk{;vSoHnTkf2o8OEo$sde9JmsXkinyk1^#$wl`pg0!WKb;)UuT zQ$jQZaPY<-%CP!m0;Bb<>)d9~HB-cI4_nuiY$zvjx`eG*)9p6r{$};r|HJ?&5di=K z0s;a71Oov90RaF20096IAu$j^QDJc)fsvuH!O`&H@i70|00;pC0RcY{qoEE6$v2bc zS5vr_If|4@pr}BOCClN}kWoXK*me~b$VH|WlrwQ95hOt|0$9u$SIJba3YQp_WKj+g z=tme}x0k81Ge!#r2$+KtP_$ym7Dg(gGs;Fx#mpJ0?%*Rh2%XAl;yWo7sKNuXT|xrI zrz)Cd#pHufYMKy(cQ&kmQnM|V_QW0VDd38VMF?;$#s?^xP&-+5m=XXZmmIBPAv}?? zp*$v7;TY6g;9$n47?Tan%MoXTGPo;M9V(@Y0gG}p5^o6W1TEZ0v;ob_`YHz%C%F5i z`$h|fNk=I+5=PN)ih;!H2}O${Bykqwz~%-b3lFdeE?`Uo+X5%3%R51AO`yfPma!$8 zj#WER0tJ;j80PScC~+zjj|ljds#u0>1*#LcOb1Zi%&My6$b@0wE?!eCl|-_`)hv%S zGedAguL-iDG7uZw>a#IXqnU)Vd8P%$Op|OgYLHeK7gNEC>TgFk7BcYLm>j{8aR5x8 zEUw{Qz?)$kDS;qjN|O{I3W^}aC0QscFpM`*S{o;)C0)&-lvv^-g;{_Y_ll#3u`>gS zg(ZnDp>#vlD-jULB5@E+GVWt{0H}o!-A2eVGPQ^6gs(l3!b$NTjXolGQ6E&7P<3Je z)}b12%NQ|o)T}@#@#LljB5qX>+`D9UAkh_~{7T)Z&twLGu*m6$Lmj>d8`&7mX!wl2 z9X9@@+(;lzL3a{qh`3}_JtJ(mh!{?WD5d%#GOUx)E-jd`0d_(8Km{`zw>*&|IbvN6 zh;bN0E6kylgs_ap07Z2YFLAug7sC{lOs<8jUX%u4G-H6vTY=OoFevPUnh0DS#%Z=# z%pic`25TJZVzDmAEJ}IUyb2|#wc6YOJ$$9q*~O=lU1kntxQh^i*=3bwfK|jW3RViS zi)m{X;g!3WQMUk*BGUT_cICie@X9wI2(xg!Y*cKOP$lsivoj+S#PKu`nD7jrLKaeJ zd5Ym2#i%kQtR#SfD5C_8!)nkNvZ0`2Ut)<|+em*T4b)X0CVfE)Cf3~QV&XGcCqx*t zQDmc21USt=G0!NbSoKEDEVjUu)XH5&>5>l_BIOv}L`8yFI!sg*+@Xkz#A6F5W1=dU z(TRGPCB(2G8)B437R;jx6DZ+uOR4FY)kU`)#IP_tZdp%|jTw|i6=EE-B{NdY4aQul zNhf*xA7(Qyq9aO%y%(2*U#XBSlf+S`C&8s{(Y`Lk@qiixlyR6KjqhoZW z!?>3-7w#ybiMjxmwn`F&J;VxFfN=?^&!8h!XQxWivj%Lycm30l7n$%I=Wcx~9@Y#uip>MW-EcD@n zk5?;luyqn7y^*M6w-FdrqB{myg%MH+Kf-N6Gdool_X6d@Q#0HjO!QtB6@_5pQZ%X`XSq|A&1pY~tA-D9+GEu;O4QF1W+cM2@FW1~0;5sbaWI4>H?n|x z!SFA6jQWTOwQ6nax61AR0J?ykc?YC_=i!NrzYqv0hJA2;SL~k`vr7E`0N&wXe@yuJ zoojv0hCB{`ALL6aO^)TF9y4P;$^pSB-0eiQFRZg!mU&X8VucIKs!G;umO+;!IJhEU z!HtrSp;25CIoaMJL4b)J%ez7+FxSjSLsL!R67DKxhj9h%9_e)&^}z~&I(RzF@?^9L zVk>JIE$8i;RJR2Fq zP$V}D9!#>QkYw`?Fej;vg^iKmcL}OpVb{y4tl`m@<%QX6NJQiYcA@98df$lHG`?Ok zupAhx7`$dx@RcxJFP2oB+`XTOfkq;-zVRl_${LixJCr|(oiQ?H_%V+^m@3zQjg5J^ z-$HwfxB7?EFwi)J+*~`CW*Tp5QHZ5-Qscj?aLQeU;FXVn>LWV-Ab6Sf_4tbcxs*yvsCrHsntFRa zJ3e4nD~nvBn}e1ZnKut6fC0`w#iym!XEn7>POvFXeX-u?7KiE6FQ@C9!7`;R{B%i)&yZHcEsPCxJ5vZy|*k zLwIV!)uwdy7g{pq4FxQ&9mU$?iV@i4i$H(PLdZbP7%7Q}kLM7}Mp@xUW+s4`8b~U{ zdq~DGI2np*I`psNAeOiP0DNiy=4lc8gj$LiE?a<<2BA1&{{V;r3_#e34w9zWq%E0_ z(7OBeaH7RQS*f>urR<~M^qu|TBv#|BI{yG6N8Hy&FFJNZLRHLU<%V)YLJLR{T#Yx! z+%St(7?QSH#4MUZFeO|(CS?Gn6%C`daWV!_J4_8ZkDF5fyZnt^8J167&V;}K!ogt{ z^@&in)&-a4@%&0H*hPva6c%}Th{d?KF$S(C42uX`XxD)k^#CCXEJq4JD9{J?%eKDI z7zHjMOvictWgtSCmS=NMIescq)JoK(9Dc9<{{S%nD&f+FO7jam5;9WnEEy~*frz(m z58NAX&M>le??81a=91)cxt#%p9f43Mlmuueb#wF|g804KmQnC?iM=1_%)6$heNE~HTNqPt^C6Yvv6Wl0?|O3kOY`?xZLyz z7x4)05GBQJBVI{XM0=ZwNd{#c!O(%i$<*vaJUL_$ME1rP5K98LGhE3|xCE zOPDTSVlppK!}9Qc<#nH5+qds6scX(=CLM+c?b8sXrs@?8K4Nu;^#y~7a5!UpAG;gq zk&wgr9>~5t5G1IW@OK0&O)uuN9HVR0aiS|lUW{8RYA+TpSPe44;oL|#HUg-=a{eX&8oMAY)+REEY;Czrv@cL;Dy-^L@fvq6-55Pe z2c(z&;fA9s2|+t$ihwZ?3J|*n4YpCY3^KoY{c2@+? zp`_bTc`?T@BU{;zxfmoY@m8p5xFE_edE+KJj-I0w%6uULuP|2I2&)e;FgSrF$jy9E z_KUwQ%jAB@Lu{26?=Zg6h`>+G(>~!|G*{>o_J5&j1;wkigVZmb%w|zs zDu@S}pQVFjOlvAsg9CyJ5+ZJ4QpvOlc*=avi15u8n9@@V8zl`(_E)1U{P2oDEkSIz z!hdlJgP~ETfIb2vY~n_SWx2Ir;8C&(T##b>C1FbbC8yL)H55f!COdXT3Oj;SMY0Xr zppUtlvwQfdkw#w)`t{U%B7$gN%L0kiA;aXaLF>4;R1tsfqg8U9`SC5mB3poUHwu|< zAwqQ)*ewn(5V!!`7YdErVjUQbQy?mTD@;(vV${Lqk80B2yd;#vF=Crdz%S+^MJ-CEvaZsiu@GxKQ5A6WFfA%T zR^?+7gKW24AJ5DVl~g2~nH7p=V(-ysoJJ!&>H%#T(vBjw2)*H#bV^qL00;%HK7Y!9 zo zga|PR1U2R_le*RZ<4V}#H*TUbBgu~OE?=Gry8HhC)qSI_2Ulk0(zj>C}0rx)fu+e1RHOaa`DiJ4G;6`szD&vG0yX2I2 z2Pj@r{{WbZ%l1Q919!vm;r&95rrQIZi9rmZ!tj4=O;>(1{{V;X0K#-FxBFo%Uts-j^#uD6e|0Y<`#13E`$vI= zMl`%}d9ZR9EiK$AsX{y~+z+Ew&ejL|`XPSMrl0TbWZ-wKUmIYmj1zfcwx8d?VKWCM=;uT+`ctsEh zmmOSV!5$PaW`4YV;S|CHTqG#^jQ)uJLT$jYTniu!kW*5B)iq%J5BUr^ltcx}7jQFd zej;M{%;8F?TBlG_m2M0nsJR|V)WQT%FYi&^+gtXG2lM{`kzm-Jv3A)w(W!)6V!=Ct zVrQ}zV3tcZWA6|rh~~AhjE@nlz>oX(jK^gBHNd7wtG}RXQyQs?u*ILMq<=ucGioZ_ zTKkAavMCNB0kfhG+U95NMP;!60RI4E#51Pkj)lXK)D+1Tmcch06~NOMi9!pe5d@7^ zA`?8yEh^<<{6IwyUS*3Dqz6%?HYWUd`@~yfAWn&j#IWL3K<|&Z3F_o#Ue5~zw=hwO zy8)&AgTww$b1V5}eE_^P2QbGjU}E_U$^^@)Pl-}GS!ze_2DTlR?h9ar)Irt6qdxs& zI~Le(gu#}iOxz>kaw z0hS}8E--RF$xJ-(LzJsXxHQBaL1k3e3v($9{^$F^TpjRrVpkQvm&bA2&w=Q1iaUZb zg@B*Dv#m|4WwA11s6Aq3&kvc@b}pET$-9=cm_^@n5WD?Fe-lO2C9}k0su4hbAtZ@N z`Hi1H#~5Z%<|^?Lp%ibMj5aQI5sQFb#WitmYfxO=doZdwl!QTT#h9cE%-TOkVi6O* zpAqI(2<{5tdgB)L{g5cQq_AHSn`5F2S(zrveH$YQWM+Y>LN@;Z*8 z_IW&Z1bEi&DOkO>kUWf=y~Ma9W_Ga+r@F$~LnR zEqw3m?FKTX$ByQsm`Ce1HX;(`X5#4hF&*LsXN3d8UTzL9B}eSl{U&EoQmRYpdLZ~S z7$*=rSk-MEwk4)d(Ug@FX^6%qVq-F#4r*7>eGa1PrRDBedr%BuH@!X>n6cB-0>HJH z!bJ2c%l7>j3*4xmLSN8HoW)kyVq6fGPf`piHc|){rd5jSC~1Tn;;LmKy#^tmI!aa4 zS5erPIFuaAuH5*Iev^12X36Cmj4eD)_%cK2exW*-s*8JsY19eatBB+z_bYIn(Q(_| zzXW-*I?Qb@CY)+wQ1=Dsl*BPAw>KK=nt>9%s~4-5ZJ+tnV8UX`Rgtab876fMOZ6># zpC}Z|EO&@KF;az#B1dFID-y_wzFs1&#?YBqA%WA`0>Ov(5B~rFUM8)- zGkX}@goslA01(n(!NrZl0rMM6;3c6Y6%w7qWz=&FF1Ld!4sgGhsOjup;jmdHQDw!z z%T-@_ddN$d1!NF(BLv z#O@>4xkKV5VTb~ys9P>YYF{G8XMz@DyhNaiI+uo$w{VP>7h4Xmm|g|4!rd_rCZ(&E zSl>>fH3OqH6Czs#M{>W$5NXeF}r*AmgYPQG$B~m^4g^VP>VHY<-76nC2>1m=?mJ z+Y00D8`2cab{Vc_k)v>&nNp!6#6sa9|Fix+0aqQIj@Ekm8s`nU*<%nv})@Vy65Ms<^}zKpc-`)4IVti{cr> zUSZWB%1ohxlA{gEnP*#!SH9*A8OcSKFKlUEun4~GdZn~6~gix6YdQdrptq*_eF5Yd!s!7dbl)OP~f znuH9u)V|;YvRj3+*j4o?D=LPl4B_P-1WS)eZsnz=-sa(r%NeGpgt$mje1bXv_@A5v z8dUq2VE$$5cL-IE=W!Lrb1iNP?W_Dv!%!17jJF;IkZK+CC~8&8ma9UQ5oD^$N{Oxv zWS4gdS(*eT*~pQzgOhMmGi(bnxR7QTJCyEHO4J=oeMSm(m|Jm4dBA-^@aP4@oZWAk!HJi7^LIgQ+dt1_&Z6i3PyCK;r_cT96cDIyghA zUCaaKHd7jR0PrHxhUKC@G2hj(b0Vj5;V$M@mC{~bU5Z6`iXo{`7f=FU3!U)nsY!Z@ z+*HhogwiOMsZg7jCmxSrz)vJGE|SRrcpFvJ(}AYRbhsIUrPOM+ZHVHB$_>1uRyc~x zOv0c{%Jnu)a2#!%@VOCfx9ZeIw5-%43Pft)1|=NKMfWZZJDIqJh_V%QYABcVCjpxj z)ZZ0l2XRHA)@BikX%y5s4%o&TZYAnmT(VeTfEt8iD@&L`+*5bPls=NRM&?r3k(F(@ zvmPD+ailZIFBK$yt98`d7ZGjc!MGQ37F!ge6;wq;Vi1_VM{@{fB@(!)ZBI54I+q;n zLW^OTYF;EHbS14IyMpyBq`Igr5xiKXVC5}|jZoWA<|X=(#xB@Sij_>k&X(25SMH*#c`(-1kjf(Q7mDCn1;ZL zS;kNZ9;)~Qw7xY`jZ3&O5pN3Ok%D)a33z20iELa&!HA`VGN5&qhAr`=ti}=C%kywe zlBI~lP|d}bP-0`COm!;S38QlJh6sX^m?N{e3aAvb5EMn2Q^d(_DZ!8?qFqs)U?ZSqnz;=1q?ox zG{Y*O#7J0RFbFdaY=&*o6k`iEMsWa`K7e-{O9O0Jv4}IpvBAOOJ;;|mRt-!icg0R) z6*mz`#4aJm5Q@9u;>kgXDiQ4jN+4TI7Q|)2ivhsX5>&UHGkzL!6J%+G%se_pgdq<2 zHsqOmnw%_AopHAv@H=5DHitV+2uE|ceJtCDTsw@|;58U$1ALK0Tsq?FC_^pXUZ^g)JKdAC~9|hBIS~s5=_u!wW!INMM z5E}_3>&WuW_RWY%9+EF%8V8aewguB0bohUO*@Fv){H_B#Dbb*BaOFq9X5U(xQ#=$eZgnpb^ibdt7GP0?Eo-|W5Q^{RIS~LR=(NUc51Vh-C70t!iGC~DzHYZ?)pP~xnCix%K0U}%@yteZ1#^t*i zi;V4v_@9gqNIq{$LF{@+4<*?7GDqyWV$wyD`$G|)%EQfE> z9G)O-W05$Dc7Ka@hSJ+JZjzW-dQL(avNuaEHeZjC^9vJ%51!p+7k%XG`E4*G>w7;AKQ`?AHnQ_il1p94nv@1g7Nn!> z0n!>{bu5+JdwR3ZAu%F&ZCj=hJTqn_#u!g zvLnlZ84s3b-HXx|gu2Lb7ffBS51y?HU(?}7*z1Gv+;Vh5+>9Q^y0a$&QVlN&F9_2w zVE}Rvk@hii;xp85B~0@n((nGPV3P|IBjj7s!sK~`r`bGE%WPgsu>3&m zpQKN1dO&vAaJKArIm`Z5{@VP6jO5vVK^V*Yk@~n=NKch%vO>vqgQWieV?X+qkV4XN z-pCx7q8lb{{^*{^B1GgK3D^y({j_zbc0+e!0686nk`03lEL+K4Wj~~n11lc(*}F^h zKY3tbV!yEoIrA`y$vGT=dccMFZqjA4cm;?pk7dpYUL$4z?%NHLkXG6d(wf5~P}L5-!6rqX!&pA}FH$(rZmSFhx$!+#E41^)oO{?`40 zd1OePMC!oplnk^Y9Be*C3kzdkEn6;^?vvNXO`YlG{H#xq?4Jg}IQeMe57}~CmdJS+ zPBKmmBldKWBR<$AelKbTjD}C-rK!lmTsPQFC4Ndf0lMm!x7&Wq9EPo)GBI#sY(W12 z{7ZCyG@O{G;;Z=Y-u1IAS^OY9folNE1_gt+I$VV6 z1>o}I%O#(4;J>MI&b6_UqVZ+NVO#*Mn zvc6uKKdghR{aPDqg7e_N2&y21^4$}pPf2!7r`9my-6#1Za0IYg3pLCk0me*AcT!}0Xw&ZWE?~VSU%5mcEbQlo9bHt3m;7WLk1`hjj2Jq zdn<$Y{{T~-)&Br|hHc;Zmp+e={^8O)^~c|x)pF(MkUkObCBpG!`Mv0oW7soK{3N@Q zpJDz(zwS}&<>P~7w5mkdD&(&ux`F*5epp$P{{X$vblc zxX;p8#}~Z*{{UmRsNyrrk6{b`W)IkZk}v}cm{@w*?jfl36Cacv1dp}sGB;Fx-;a=- zM5?gkG#r*_PFcgl=B2xNa^JrsUVdD|?0CsoU%P?q*dAL!{D!Ha`u_lSku9UOfBX9| zdL~%+YzXjk@d*73=4IqZSy zB=l{SDrEEf{lB~?t~1+5{e&wVW4>C>Nj>=4(ZU?;>URgy%sB{|G}~|9Oxm@y`D~1~ z3P{Ff{-oHp_J>HIe1H$^hhC9x(!$vZwtHcHvBjsrJHM+o1_!KIKO+Qd^D|tCHBGwg zj51-~WNsOtJ1`nQjKBV$_Lv^e{;rMECrV;&<*UCgi9uV$%scRgpGyWu zt)1e+!V}3$%(310{{U!uUS-$IabF~u(1>g)KOeT6HGYyEJ+wQg=l=k|X2aJPs5n?R z0Hha_j08#ECojPu+>2?W+sJ3JVAfhmI}5J2l`FGiOwVluf}j5X0B{<1)vhz3H2$BK zqkMmCL;jcFJ%%{H_P5*Y8{gXk^&v0^KJ@&1Z#fS~P}p=X7&(v}pTaW{%L&QTe)-HoWGV(@xQD7ACLESI|k5nkRFzfOXNhp5^#1;7j8Xa^@b104NYx% zgJ~ze!`~;$!>I|!kovt264Wg=2N{{U8|HnlMR!qwl6aPrX|KOrIR z$(F?VrsRE1`N`NJO@Nm~eSr2Hly!2_--)JM@wWThNyHL}V#pMiSz&f1_DKH#f#i4y z7~;Uo{)yGpC$V+LFl`=A?!s8c0p$6X*1!f9WZoO{$*WHdiN2s$KH7?Jv38Js6CEME zn}5V=hBYnZnt(MWuEg7I`0cZ5@5$kl(eMFM9NYeO{@V@R+jFWb@|!xglactggQ@qR za845_auI7=!0ZoU3yFRUGl2g9U(fx)_S<2rvh?5gWZkuR`2+K$35%E zFk>=D<{SHO0`y;i9fcE*-|ddQfFMukv$5Z)vM_&ZVaZ33VT3e4&x5f}oWXx^h_3GsUi_Z}a~Et5+wnV^S~>B|qpli+P2x>G1iw&*>qt z0CGtv=Fj^Bcjn8HjzO6c_8}QQBLdhb2-(Xdcj?*T8|tx#meOIG0~a5^Fvs@MsTYwE zxB@>5OY9ORdNKS@Z9y#K487Lai+nI}IaL zNMhxuNrmBNef_rCZEXC%NzRu1-nh4_yoj*L%SV>w+e`LsqKV&0BtNqb0foqRe^OK= zCtbGo*AJx5SiAoKq=CrY)_djQ{e%Ai5JqlB^=v1EAKPez>NkBw0$^BnF3dk*A_OB# zVT?915yEij+YoO<_R}u{={>SMKQ1_d^tgDC~fByh2&?Egs ze+R~FbLZz_T_WctJQF&^aE7vBv8I-GQ1%MDqb$1kP~QIlsZJuq?Y~{H55_tKyOXP` ze9ifBC#9m_IBaj?m})N&9a|3E=&HZMx^re3ID!R+91 z3t;|X7z|1Do-qOVUzl;9<(F9gNGIdo7JuBm6KgBU5Wlekc?0$%{_Q3{#16*{kHTjE z04+tI-c>8cXeQazpqk~~(kwQu6L^S*Ulfzq+Uz;qk)9%E1~2*A;f6T*{Cw}h z-?{bezObH7B>w;;*4pNpQraui^^cG+!s^EK|ESabUs zno5!TaudeK)s=Vh>cSsOWq;i31GTM#=k+abBZ&UUM>`)T{)zE6dd35nPJGBe&vO3& zjGxNE*?mjCM$M3U2%Dde{_I`(+y|Bs1{|FC;c$n0K2N*kgR=a74`x))%fQR@wEK52 zJipRQxHHeXvc<>;Vqp#7XZ*t}-_}z*{{Vw!F;o7Kc#=K%aj*#1BpyDq=8%n-zu~{& zH(mZ7$YBTl*iLl+0Eyx;Zd(uNhy$M!OkxOf1>^Yt0Q_zpxJFZZvGGC4@>pa$C*yiv zGBc3DFwnH)vTjUFR_3#bCfQxc?2zHN4%)Wa4WSY@KQBWjULXA1^A^}U{tckTfXjRS z58h+flcj3F8k4z36XIECO|Y4YAj@*jsG9D5;m`)qbU z%Wc?bH(xK>@b*2r@TUI&xa0@R+k>`$B8@$p)Q{|ilABezw-fkF+zSEyMd=2AgC+ix z*mLT(?4RgeJ9!dCq~M2bXCGuQDttklcuAkJ9;Ra;nVhGbHW2HU^UZSi#wHAEg4Zwc~UD02SkrTrJ7%ff3lc z4VCaey9ewChs|KX6rPC>Aka(p4wvj4U6TI*UBp;@mbv_&Esyme;6i;O;k}YewvS{^ zypQR(`Y-ic!DRB)o7mSS$nrh{S`lO#?Ten;H}ro#B6ck|=ClBCzFW2SNv@VCADA3o zW-RpW)<5o+VHWr1&Hn(TKTr+_CBq{t`gt7#&p+I_mTaH&_|0{YLve(LadivC-`m(e zki7C6ZGxP)`+sl5d}AAse8OMkk>#O{qn6=yGyIpwzZpNSLw#Olx<`I^@6MC{?fkaT ze^$9=upzT}{{RQXGHs23!)+4CL;bA9{W3T|`h!p9`7hv=vi|u*>i+;A{_XkaACeS+ z{oE0IFu!{fZN2{h2H)`HjoU&#q;UTLEQHe~Z_~>q#X*E{$ia8_=d$QbJ^FZvw*0`d zhnGx`!pnxvVdNLfP;}aJ`E@fNw!_GB7cj-|Z#V1I42UvAVXVlD}q6h&JAf*!)esSY4%( z%(0J)^mpU)J{8dr?1%clBf`f^G6dN0?fKXH{v6-C{{X?#44<8B@LK&@C(=Y;$a7x8 zIkvqJj#-7N_;nT}v&#%3_eR%HOXW5^tACLGbakSw8Ft^wC z(UA3#?gtYpztn$;WDd5yZQrN+wn6sa=fNC4Y`@8RO~1HRungitJucvuEDy^h{(Ay0 zxnm4fiKNnEwDbki3xfw%!OZpJaKLsR+P?^X8W8XVsP2m1P0s2IC}< zha32VfAMqEWhur1%YgR$g@?|X-lXu;|YsLkN7ks zty`yN;pg(l(95$i^nSL7v$tKa@+0@(j+~q|Y#RRj2xs#0Gud)2`Z(FV+BW=S5x;YP zyCi`>Z{l6G{6z>!autjZ_I*ck?B>Y#)bB?ifM=z`{`>GlPBM65{UO##>5PYvT{x6F zn^SNcnAqO8EMp(wo|Avs1$B)>V?V(s7Uw-~Ycq8`op?)FGq?3xERXRez=mF0<0J?_ zx1L!2wEclLaV3a)Y-9UtZ{Z+h250qzI>r5o@GtMP!-VwPi2nfZ{{XvRJ+z#E?*WCB zoSAkGi~7pA!X}ruj>%1A4o9Gn>3RMOZNE>LZ1A_e{{R%O#Hrg0BiIKd$z``XM|<EvemJIF45Sf!X>v@1oJjru`BQcp^{{Ts2 zT(EGC_6^J;bx%kM1BAd0WY2=GUScGizDoSrC*1!4;Lq@F34_letr;9G$#>gAb;3_y z@Kz6OeqY+aNX>0gX0AgFvT^oI0d>nDj7@dRv41pckUCiWyZnKez#y~kL zyjxkALO**OS8vsN*KGy=03QoG_kY8C$adLo%$6m9NKYYT5z%%<>hlZFZC`^sYi4U> zG%=|l9CBoML$~Fzzp@A+{hM+uHV%tfPANhLyyKS_6CL*yDa%2gW-KuPm68wnzd!2@_lVT0X);$(C;;419s@;U>=|x02zkYqlMP z;$Unl(GJ}?Ah`BV#EAoWZR@sdhu8tn^6lk=w_TIGlbI$E3_f=JZa}cZzZMU#%>Mun z6uih`9U<;~V|4yl{G9Ya^~NAJ>}bZ^kZ&{O_u^iy(`*3##0)HFV|sb~ztm<&PQjkt zTZFf6PTM+_Vzumo?~%j5;KcNdG4DxWI-Z$5j*uXJLv65ayQV(?Kf!)BV+Hg#VfnLk zTP@KjZ=~SWve{sI{L&bQFGunWN&$?Uts~qmxh12>^6U`6PqyWw^gUngy7T<=hm+1; zG3NbCgJF*^^hhEeTK-8pbK5BX;67eMue-llA)9D`=Wapd2>PX6emFB3&z8xCvJz8l zf@oXH@;4vG3C!4;$o~LV$gVTqzIqFS{kOQ>Izu0Z$MQJx-%elDr2bp|`a!Y}55bU0 z@Q!jky}zuNt&m2WM}U0D9kJ&^q}4q7(Wp4h|z@v!}$J0HTv&y2gA zhE!`9Fo^5e&z6z-L4;n&j=5{0@I3fa{-FaWjmVz6`bKZ;!{fi$G~V0452LaDm%#~Z z$ky1!>as3A5;v~e@w2jrAt;|Gh0%Kwz+lTPKDXqY$bDAqd}i9XUEW6i{rBilWigW* z3&{EYtxfeI$Jq`}D!<-0K#nYK-93PB)*6)N&rR9#_UXBJAiN0E;=j`O@#~k6(%fX7 zBYlJW@v-cGfv=WwKCU}&@-_be0sdT!dk@Bbc#k9B@Y$ayk1sFCb@BS~{sZS6(aA z_VEc+F0JZRz_OxS7_W%pSt=kmaY?~8!YlU(U=|vdxq&(sph+LnS`HnO1X5+VwukcrzLCT+OIKTg6t(K&;WlCl zKqA1y#AF7U#|%>zbVA{I=3=&MGiMPwhk&Z!mH=9~hQ$Xu)GO#>!eq#Gh!_op=Hf~h zG)h|n)8;o~mw8E z?jZvVNQ-@t0l>c#AP1bzRsN2O$@JGWKu+NyVH+ZX>kBN2xg?}ko=x|fqMQTvpuxuVu)etd}M=!QG zs`=a^Bo+s9;TF?KDGPNTm{&x+gD#lOJMXxSZ1|N`oN+A*$*jYCpA#*>xlIcGVlai) z8F(60%zy&4+%@Y;2DdmLP#{`RY|MhVUJ%$0L#ShHE-Dne3dCl$bq9EOn1b^GWs$_t z)+I0{!DxGyj0spSTb22=ngZ~Vjjw4NcoaobvK3a_n9VBJ5TK`4aSbRvj&5$k#$x$e zim?H^{-*x!Ob3XnzBawF(Ngl$`j3(?7~35QHk!F6HoKj^o-_arFx2 zU#OK_UU3a3C9B+XDHyWiWEeESjO) zGw$9o>l9Obk>x6&a~2gTp{balnn|G?+^d-^Sb`gCp%mKGtD0cI%Djb;y+MIhh^d!q zZaQvO_ZF7?lA~WTvSoGu0AgH^bktZ_>CB=Lz=2LOz7WkrgoL%AU$~tKb$7(7u|{1! z0#oT`-lb0ns@!ng=%S}gOAbj_3xt^4U7R5k301_slV$k-0I&!nTdb1yp>vmNQxGUy zX7qw_Qh`@O`MT@|du*?4dbXB+#2Gvmt1H=YrVSLdO*h|oq)bR#c#6C%kyp3+) z05G^z6^5c9Q+$!{I+eUbxS^Y5v_xv?!m@jW z6eF2eVXGK~gv!?u^vY!*RAqM*K$pr=#3&mbTrkH$NR7j@DX1rCg?d;-pdL_E2F+1I z=1|0jw=kS+0M#h3aZ#J^0C=4iGPS`(Sw}{lN*ur+S z8VG?7G!aw_rkf_}Uvpy8nM<3zoD%dSVQ`UJ=KlZ^;SwAW8O7K7OY0+qfc{ULV8NZ>AQcxlr2 zIXa7&B5li$EC-v4W*UrGP8cj`T(wshz8$eE_W5FfcV+cBU9-9(IEYMMq8lBTnP?%q z!yNJ0TLwU)>J;*)f;_};I*MFjbx>X|a9Jr!S}m)NTj3?M)By#Ar7ZkL+zVYx^rL*H zv{csOaI`j@P7yYlPnmk<8eGgUhJIZUiG7QN%62>T1E}$7%mF68Wxzd`X&f}U$Yu*7 zE?Ew*zkML7si+dLBcVKaM~yj)H|J0hi1c9E?FT#>xwIL%5_8?|OR6<7^Jq}Y_@ z57Id^2k^GZ?- zJS^38(DMf+;D2!YOXfKJg>E!2XNYT7b)-^(xUrCJ(#@0}1cb6syY@vRtPJ8-hCo)k ziaiw^OR?}+hNy3Omh}wWHq=`Cid6%VoTcCHV1Jk_I!{x|=~v;dhD4Z=)>AT7x*(06}BQpd>~@gyhruIzafbW zc^68|PYGiB%m~%W@#O%(iz~qZkY$0It-*Xm78wW3dY?u*oJ@C2^Bo`wvZ|$k5b-J< zki-`0N*Ae1E^31caEk#1Feas=fh8g_fyQAQEN(eg8W6G~%w`s#8EcwO8n5{Z8#t)I z$PA#~AJn}iDwbH>UJ0Ke&_b@>>I#V4J!YdSrA~rZ^BoJdv)gkb%i0R0`hO8}#|vo? zH~#8W^4J9VJhzCv)a%|(3-wSlEi)OFy2hZXQHMkafLL0w*?=HZQwgIUlAeGHAeg(w z%hk}~)Fu6Faq6Jq2x&1q4&{m(3zrp&Dp~IqsB*BfWbqu)eS!lOhW$)Y%ZN2wyZpyv ztzugR>v2F0QD;@^4_)v_3QLw1Kv9BJcD+Wz!FT=SU`czcb=7u;bLCqB2$^nhNE_r6ja)#8+53++bOr_c}w^ zK}rf@4;c3bcYq5FmX@`M`PSD3c|HVwp)Tz-U#B1W4UUOKvBO81V?3GVMdz#BsLCk9 zfFsn$S}1aF71I9zal}%~F4=kov{|9z3Oo$=5*08qFA)L#wH;GD4dykAn#4QQ-IX(| zhX-*oX~S_H+-bZ^(uH44D&0_2U>Pl4kfTPS#R1AuEQ-o?cE-X@H4hN|Qp{7p->bG*PLW(FZ?zNm3fM98xT=^k8EEid9BRm(_gg8)M#{3~VN zVPWWlYTu7h53@wNc{q(J6Cm*lDk`nbKuQ5ma1zR~*$4x5Fv2ghWT7c48;D^FXAyz9 z-7#>a3LpeH&=NBk z5YZOG>c+L4K`O?C%nl9fnSa&zC3t^`Z0W}!l_^1J+Dl-pm7*~NC`=ESf%t+|B9o01 zxxZ1tDhvyXd62P`zzn{Wha8b=K*Z(#9qLpR1;Z@H6>Up|F+-SAOuNB3(R-}oR~Qs4 z+~f^o5dd-VEURLLD6A^ki|+i&7Hf&jgj0oPDUuqJv|VK4GnZoK2Ju+bsR`C(ZKBxQ zD(Jawl?ZDz0%0L#r=2eKVnaV0kpi10S{V)JU9zf!EAal!upV$dyRh*OOM zLsZc?v+JF{^C$tyiCCKg;91sgVth2W9u)hZ5e!ZqRRd)&nTWfAhFh>d~ z-3EPNh^Q<~UJ_ZaPBUGXP9V$HZd1br5W6@X-xZ0RDo4bjTJaUO7y(L^8h~4Ey+?Mi zsyMjhsgoC9>_kGov<-1Q41tr#!ZILWKwXYny!e$w6B*<8&M0OnWZJIag;3ZCJqQfc zLv8c9VY=LJCogas{>ZMkhyuQdFj<2U)nrEEm?6WNff}NO2Cy71=46gLx{P^KHIa{lYyC$UJAb0ppRD2KJQ$NamS#jq*ZmSOTXu^fAajCScp0k0C2? ztaI}WBCe78fw1wl1rC*=Od87=T{%;tDHRu|m~Xh5Zm9#|;&z}l`>sz6T%fqsD}JGl zX{xD24OfUGaAL!ol&H#@$`T%xO(lgc!~>xALRK|fa_|O|iItfNRRO%&HyPqHW-r8G zx78Pgo@Os7034fFtYSN0Q(v_j-)s_aSgD#VqWf+pWx;aj8?T7iV^F|)8vZAg&meVt zzySfP*zprED66(k{{Y*77>X6xM_uCXII=bYl4RAS$c$yXPLz+>Ku;s}Tia5BcN zep5WFYZA|n!;iKA)D&d6cP~o|zYq{aa-V2TOwaU;%68;o*4nJ37{x2*?hxyRJ)45I zESLsuhE6<2K;f)0!zf`~j4X$9Y&d*ruQI-%@+)-^ZJntp5W!TXmg$*tX0$9YD<$D7 z9x#?B(>0lQ(+ z&dvFVRHCc_%f)VNr4U=Q#K?4WL-!Qr4o;z64L(m-9Bj6{;#vbnGZbUxtAQn;jgcuI zcqLXnHTNtahCvo+5!-YU4fE*#~v^d=e^RYzjo z>Hx<-n2uOm;HyBhBE;0Ac2HzqFW3Y2!^vnl`(KEQGysA<~I$J z#DoqQY=SFdvF0>(0uybXBc-}PPGO*1h8;lfakx$@*gKfafZB3Oa57zIAMDNfGMdb( z;zef3S_t19KFa{`RJ&O(Ei7UPR@_ih#;pCzl3dD{AyQu~=a@KyC@*+Mhr^qL-E7E4 zN_N)pKy?%&E>|n_0`hgBcq^jMGnnK>a?!Ofl z^n36_5n$s}{lw8h33whOivwPLO5O*@=tAe3S27U|l^y)(4ded+BYsw{rFTkW-_*LD z?4LH(EUK$&!5Ra`E6yh5-Tjq9dM(*-+r5ukVd|m0{{SNHWSmaVh*6zmP#`C2pj;Az z4

j7pq^emWNvrOdW|=Q0mI&rRh!Q{>_^1D7vF)OF#ptgqW#_V?vo&Udg9z%NZ{~ zQ+S6=PEq5i#CZ{yXM=Vn!5gwuTVoY>OMzpp<$-qF!Uij-@?+_FtRb`(Kov0s_=b}l z4LT!N;Az8%nGLX80){4==2ozrvZWIH;$qS(vDC@58jFEmeWURp!0BDp8T*ah(=gK2 zIWB^pWAk?+0P;VGc4Q3rg74!|*-s%uS_3c*u{YaLpdeeoA?CvBw97xEei=<%L#a|I z8iX~szNeo+8>zSoO!eYB76W#M50;_=Y~iGGAFtG=xK~>o3EA^A^C@tvV!(TTB^Y8+ zP&clBuA!MGXfX$%yY3zt3De2$ zH;VwF>i+=SgYIy~!P^Cx$2r^~L0VTgj-lp6R><}^Na;n8$3M~a0mp%-JO?H-j_Y!+ ziCDAj_tc{_86s8z@W;9mv|MP}$%m?fa%dh1EqLFf)O?N(NsGaU6KDmt>McMF`Iax0 z+Z(#P9K=wJ+(hJA-XaAQjl~X;aJ2~6Qurt8;E}j;FsRz<#>Nr`DxAGk0H~c2ftxyI zfgq&3MmY-eiEj+;OgRz(!@8ZcBRP>!^t#R_r?% znp{ZB?9inI7Lm= zEj$rPrCYOEl^bIYm)*_wE`ydFY!nvtDwtk`<~dnR(yai{@G6b;k@#Gwa;Z;RAZVymfxI^o1VAy25Ltb>?IWpU!W>Lh_JKtM{< zBIU-#h=LRpWY*#9OtaSm6Uj5=uGv%_@HO)V^OZ6t zpZh2UMy>EB!7EYk2-Y?*N~FCp>QIEbjjy+k`%z1AbLD)yhu9=7gi>t|44|R34*m6acKw2w1YsCvLM0wcW1|`!J)_!r@vT zNriIxi4@8(JVG=Vr*j6mZKe=Xn@Fc!uCIm!*6$*w(5TYDA{)&+mRh-q)T%NprmN?P zb#EAME8GIzaaDJ}aq|$jbZ)P#zjChf+7SZGs_p7wJ=CRKb}nx=uNz1(@qNo;8?qOg z^$QWGYd`8dE&!+!u@O~nWAu`&ARPd;D5`~_1S&-~ z!WdDb8>_>(Q7u8Dn!gOBuTp>)HovbD(DQh_(Rn_4gX4s<30Hkfpa7))A;Ox&kq7R^ z81RlkO|Q9+1RF82LeT-cI+ximA}M*0ZlQz~PG97W42;N}aZKrG!CDop8F ziPqhjTKO|7C>icDMJ!{8+{H`mv8xk1Dp#UpH|9502r?^7cqvp}<;SSwBo5fv^RLV% zP#{_+P*{d0)(l&Ta8b~65j|B1^5RgNlP#<`?i*@LEVzE**=X9BS23ofG`cxsya*|% zynbV8ik8>RrU`C*z*Ao0j!$f=CEKXAf}Wu{FTV+(@*`S;R!&H?%xqw@Vbx;gUD-`W z$I0ej4113&?UeS`qk%H;hqv<;WkwsriDE^RHt@sQgEYghFeDRb%KL&yHcIp^A`PyY z6?@b`87xx5Iy(cq>JVUHd+Ui#<`IcU0MW!*QCP=94*Bx}Yt_l{Vf&XVts-AK8u{*3 z=8#K&Jbot;$xq3paMjj`FdXhr46l65TI!G#(Y33@;ekw|@EieA;5bt)G6Pm*#wB#N z;8wUEdWV66i#kEebkkJnmsB)csecUA=gh>bqBBuzHx;(n8wwx6f}fFD-g}jtffrX} z9+z){tnL=1t3pi`#qwa_uAIZgC6rJ*fwMJ;5Vfvl9kf8V-%t$DOk*{fTEoSR ze+44k(NJwsAULaq+i;a>LtMd;DNhH?Rw_}&bvT6b`hZu5aWpHZd`8To+81H*xH4QS zsoM7o8}e-3wZHbI3-pfNr^FNN?gxNGN^u)*^>7edGjIw7T^+>4FdJv?Cc1m5It##G z>@Q~Him_KIgDWm#$;Gh}vZ|pk>v8OXw$?#cea@W{gM~(c?^70&e{h&jP`CxU;%Ude z)aDd=8cqc&^LgAEAV*f2MLhY12w4R=TZJRlbi>*$SFe@Wh%#MaR!E*G(liYrw-9bY=O~ z%kwb2@{K+`&GhxGzC%aEIGoC&pIyNfLud>QWDaXmh`f77nLaLFX%S^u4I8fnHS||( zB8>1}mxw&5Skr1Yw|)vD0%6BVZuhq@nAL-B8zB;4S;RX_qe4|PL)rj5L}!>BlZ;KZ z>S-XeAZ@@4!F~S#a>;&_-Fm(trh#i)Yvv&AifYlxG8)Ar=hiRq@olBq!nEka=I0(0821{oGI30?5>cF1uDIB z`-~ozn$CHSSR{-H9Kw-`BA~kKXkt4^+1Hk>u3#s!OCf7+oQBHAB0`l7oKHw>gLu6I zh;XPT&lh#Xcdzu z{^I1>G#7|!Al9c6mAiu3V--642!pmZal~viv4WaSBra9OaTV7O5k?7yrOJqMLtywt z{{R+ZLX_?SO86d3Rz7C3~%%I8SZoNd~dEI9;gDljCJ6J2bDF~0o#H2i|L%WkUk5$j#jmR z_+s2Hm0J<={_YYr!(8_G)W((@9A7W}j;YUf)?a)Uxs(=wzB_;lf{R5s`IW>RC*Eb= zrBlm^XG@t51z__TR#^}k#1|ApX`=Go+`sZs>g*d067geA(^*4I_+f1=^0-V@<|@lP zJEI8tfCnmpPdSGa(-f|-c0~@)y~Zr%HiQc-hw+$7a6Tiu!9;A++`TM*oNK+*T8ZHQ z0I84cC7~c20@3OvD#dwBp zH!mL-FPj6*TNcB`KzG61vzip}Ww=Gr#PGE!AR~o88cGvrX@<_m3QggLQV*=gtw6Tx zxm>qPm=WfekZ+JMY_%Z3XJ!D+)8D_uGRhXA=Nlk!%k7ULnu~C;Y%M$_3tu$br^Dom zc$ZB)za%HRlWiG{K4C(1FbZ$Yj{M63+C{t`NkWJw6gHnR$2Jg`MIO0ed)p6XsCMZ_ zPStF7QgA_@uGqGjRM-CiAXK(4APvJPb)`h|>M^WyD18ydO4HP(+)NmVtms9n*vi3M z8nV2`11tJh$1tp&-5n9^Mp>d%ND`=F`-ZEng4{Ec0j9N)!xp121i8yEC)8QakGCj( zoI+B}kz2>>Ux?I8Wo=WFPq+rE3ZUgn%ae&r5LmFhdLn7e5lk!eW6bD`1qZ}K3YBtd zHrJ4c&6J}hDmgXCIb~V~`+_wn!YX0xM%t@@wO1`~6}Sl~e2hc5ZfF?S$3MBu^+nMg zr-h9w{lpMNOcq(h8WyVSEu-92RglMg+_R4DvBVYJbC(!BvojCH=bHDKg`~8&kIAxY zb<|O37y$6%hLI7SU zVLXszsdHXO_Yv*19i(~wAmLcYLUK#~0$c#m_CyG4T;K0<^qmZY-P9ix+hg?&xmh8X z%1ZcREUBE*oaPilkjXe-2@8Y`02HZ^W7AkRIef$p&$ymt-H8ygrCMR?pkm6x>Wnhb z-HWP#@x)W1i@(9s=+^k z=cak2Q)Fx2B1L7wja2zA5hG?U)ySu2dj;_R9AT$HGaE%=SzbQqe00HW` zBGxKbJt`~K%sNs|4-QE~`11VW)u+$uD#G31MAt^;=0Braj2 z<-vbZ7p`$!9;F~Fw^D=}5Ty+tocv7aPyx}*sp*4EK}c;jTb=rjRJdd*!gUCvlmz^| z@eV^kFb0B9L`{NmDB%`Y>Rs|h!|?$6aF|Zx_4**5QrdB%pGaUSP{<&5l$9?Ka_p90 z$t`hQxQ^M7OWb8vK3ZmN0v6RIfl=l(-TR*H+nHi1$KzG|Qvs2XzF z=2$9lzt&?bX|?eN_s&i>&w5Z|QCsfBM zHG3~{pRF9#pfOU|TsQdFF{yYi5@0ov%ytDg`HzSYEx_wARg?sy;#c&v_J8CO;W_|f z6hT#JGpG{AN>>-^F5!(W&dZEPNiU}{ixwGH!ivC|ih3ajBqa#k+;)=fM+dk5Og>jg z*!;uQeuyy4PGzDhY1GXn9Ca{2=9GC43#o}SePP^hJT&g5F^B4;N;dCi>F^=MtF}hw8#r`3ig9G#q zXCHN1yp_y0?p)Au{gK4Amh=aJ!4U_!ZGdh|@+C!}X2wV=)Hz4>5f_ccY)cHqg=MGe z0;@vaIDxuR85rHj^#Q8v9Lx#EQO_~3vd>be`I}U_$-wTSF61TXwSTh`&9USU-d~d`f{<>nZLB6e3~();!E!vabZjLls}3 z^UM>ND&gk+N|9CBRxyaF)my3S!wEH36$TII%n{Qe9`OJj@fQ;4?gkQeFtOacoFlP_ z28-o%9jEGBRi5doS-DuYGht7B%CWN8PdQ`|OdW+R&1f5-vhcXv)jH}LD9DQ=(=k@) z@$80150^f+LxS4|u$O}6P@rU(fU(+^K7#iX$y%lOPJUusEww9=RQZ&GREC$wFU%p- zQWggX3w00xsLX76<(Q`%27FX=ZYA?=wRFDVD(v)yJqx!pwwH;7N^g#)O14Sq%v6EI zWz27)9LuJkk<<`q;qwQ}5CBrMPDlw0OeYL$A4F|pHw_UB$2`Org@cb|Gpt9#9;pNO z#IR-B*5bE!T!F!G;4Ych;Y7ma*I;tzR>G`hkN1y;MS+B2yi zq<7@CiEE4EWq<%XFaFkQ>uwwFWud=L><_Fe-&nL*D$IUAWEI26%FIx+PbpE`!O4Au^uN1+?M;3bn3 zUq}GubsQFtj%OugK9THoT|$WsOdP*InK1U74A+@e+F55AB@~>af{PyOcP~#0{K*o8k%Gv@_yOh8az)uZ`~GF0nul>GDP;NjGbCZzIF;FQ-l+ zW8xxd3#*D{yWV1rQyj+^73NqM$8dre6S#RGr#@u>2UA2RfcoWyM$F!)1YK21Vyxp+ zUPqa9L0Hv7trk2?goIhHy|C~w3Zz^a0<5N>ZY(jPV5?ujpl84U+72vpL67#tCn52tyA(KFIcva&z-4WMe&{rzjgMUHF+|Rqg@$ zf>_(BrxmralC@0H-3%_ejch@(jyYF}L3B#HDb&KmDLLOY}?EWI%l{nWnNuE3NEU0j=69!=1zdg z*7>~rO@lR#X{npKYE^<~7Z;t@Wr;}}1~Bm`>skE5p3gHma@P4laC~kn za2zpgmtUz*m2m*bjj3z685LFRG5x?5EG*=xtV%-{TthkoH+W?^=Gv6;6>3yga>@?d z7Ic5e)D=gAemjcnM&M}t*X9e2oB+4MsKVH?%-l-aUK6xH&G}kk%qE4dN!52X!_Ll6 zh-;;3rbAB$nW7$vuTY&~5xQbP;8$CsC*=;3gwQBm5 z##;w0P%BAxq+X_Nq&}@$cHzvSA~bfruuD~@)@)neaS&ipm2@1&0QdzO;Fx~}^e$F3 zsilKhZ0|5QTecl8ut!w@OQlyg)Wj8V35GR*O32Ft)@uqymmgCz)d#6d24UV~j&63p zFltS6e8J3RRm0!+#9TfYUq~TJ-ujr~SPv|=Y=uftn@erySc2NGs7|>5H9TY%9ksWIN(t0Y;e6Ebe7S#;~jYppA;yN!Uo0M{od*RXD1H zQ7m3UE=XNl#pQ;bVk~i6l)`}y%ld?YTJb?&xFx~E0Hq7cVd@@mdAZ58RhTzW)YXa= z8GT8TvneKa2j%fHXh9iKcYOMlwW8Ui;t&o|eZ?|d0gA)@+)))Ju}!YH;DA~ny1J*j zh83z=$%#%{K}j2GkE@nkeL;3q+O+&dB4{oOzE8OKuwZHLDiAr!wXdm4hHA9bKx(h} zAoWeV?o%m3jSHw0SBbdcN)Fg~8*zmGaf8dm4I%(2$Cx5b#Q?uh#~>RaiOzG9<)fYV z0Cjizfn-{#MnYw}6;PS3dfXAA(9OB2w)#!4ZS=&@h*L{zmv z-Re=$0)R-D=O3j+tlH(f?gr40Jj@V7&*mytM?2XcLC87WKzsTAe&tkQp?_?kx+qyN zxrz#=+*ZxGO19(!ZYrZ5*Mv_FOvICYq4Q~}c~;4x0Dj*TPWqv90i!)bJqu(76= zY&>OwYs=ah)p_@gRcVS1QS9$ z-7Z&imM!trAH6;C1#z`=_<=`_F+y4Ma@xZ`%L_Ay;}cI3FdSzU3tbDO2WoS!I+utm zE26D#?w;nN9DB8Cu)4lxdB;9sDMiC8e|T1;|=!Yo2(sErkXubH`FHq6ubi`848 z;5wU|dzeU4wS2&=;jx!llvtv{ra8^lxKJ&M*hC=(L6r9hWHpz8nVzxK%gDPi32rc6 z2e|6se&d>rhU?S$V=c|CwmZyeWhP+ZUQrCC$mAMv+X%(p!A#D|vM&T{5#(O+VM@W6x2Ia$%<5`u1 z0h5*~D!-_x-JC!yk0&5@J|l~1x5E!pR8tUvydy%2^HkrMB)m54`jj&$twNO4q(W$ z!ej8EtvtcW6bh=D&tn_WXT?R)I8-hp!!}|FWup7x`-V;-+jP{l)kV_<==@3@7Q(+V z01OpLFO)9Tl`;hED*Vlyflf$XaA0dtGR@jnZW}KejMwCHvYS^JRQ~`F1y;enH9dT$ zPq}y_tH0V|16V6J2s${ZoR?3(Z~$7)qU&EVYyc!29dqS^s5r(cg5FIE?b`nU5yjLN z-+i#N$$rPqiG)Ui-cQ_omu$wu>D;D7EnhKsDaDbITr`-JLbpUEC~QZ#0w@yrd4tXH zQ?GH@_LkH#@bv|{Yif)jip0Baj^%tpt4oC`uEtpu3MkJZRqEkv1;edt5Y2trf&LP} z*-BhKVwDT4{{YEAw}`E_d}E1o!l<+79O#+Vu1=;d-l_<=e-VaY64k6VF@m+KPGX+W zs4Q5u#K&St($t1blw36&RCjI7{OmL9GX)^WZCz_c4pY+_gKZd^=Xtz%hSP5OTFZ+q z+ePy@LXks`!_0FFx4bb;-L;~=VZJD^m!TGcN4{dOv`D^G*VM*xFI_A)_bC#UmH6g5 zJ)F2kKM|fNj|>n3D{qN}+eeCm4s2uG5mpevz+ePY#Rka%)>71DTk769$%%mX#cQI0Ra5m}D6EsFS+omofxsdTtqx*s#k z*3Ep&;zcaN^*Bgf-v0p1=VQt`goU?m4a*V;wZ0*&em1W43~FyrvVRe_^w^}eyoF{s zN`58Vtn?-!bzQPlYlL1Xm*KD}7!tVN)sL{UTAhR0HGkzcjz)aQI zPdJO1i?YW}oA`hQP(&lzpNVV~3xEupldll1D5kR+xVte73_?yp_FQzV)D*#0TKmB( zfd%J?rUfc2hY6_o#`-c~G9!{Xzyo_Mro+FS$ zqFh!59SpmB)UV~1cXX63_$Xj&Y~&+t-^+c7d)HghTlRb;JuoWml&!cnaFG@elJ zIeTICi(ak?OtW@zUCXS=<1s9z7h~%XS_>l0=YJ3Blsl1a4{$z1h3B|7(Ev0nuA#Jz8#qibfSMF-gTem*v72g!CvgKt zx|P~|Tuw6*-fA0hS{y<80b!1~d!tYVJa;6PRm=E>#zW!qK6M;5+P~+;tpX$ zv;sm>yY*0CINZ=IxQz>G$l{`FOKN}?h2G%OifOOJS}G2>K49B_CcfgEwd*q49@v$! zUrAu8)X7`sRRG?aS8*sG0i&p)SXEnjeE5o7 zg=+FHVb^|c{?Jj;n@OIrD=VB8C&eVzt*lA2y9ONe#?~oy7tBrrb&Pp^6j|{Egi11l zg~n2{%!ZDBBF;;x?2@7AgD7lPDvHhXcNW3b0SaL8i(c;MP6i?YC_Cp-j#r0$3V2Hs zxS83uv`sDpgA*rEP0I7IcYd2Q+%&Mp~%j*WdW7#eVl~q>lwv%xJg;EN)sLbRx zZ768<4340tt`M@dkpkZ%geHS#=Ig|vK{k2#meTq;Vo+=v%Ls!qza2(UPpAtrv7pC3 zA<{S0A4Ftx64WshRSuVNiF7Q_CAY){0C!WrIXdb9SUDUk=ee1ywh58-;$ImTIfl+t zBFO+Nb%n)ctq3gnh9#3~_y{Yy7i>s8a79_yWlnGn^gYTVp-Mz_&MkPESvAbg!EwM6 zuq+m?h?qcAJ|=crxsXa>xl}3)^G(7f8i;9YrU`4E9kQMV`nYTaq;55pV|+{i!v&T* z7yq#z!NIlRxXQ(=o?E1VXEw(2L~9I3=*}Y>@qQ`l@Rdb4HIH<@m5|W6m;9X5N)X$Rd2Fs2V978U# zFk7xf4z>*Sk8=8KATS+_$Ydxg*Tgk!n+xUc8lvo`^9B!%#Icb(maY0$E0R_n{{SOW zi%xllhdpXHCs|pr;)bykT9b&qW0zcGB-^S63uQj#02Y^9q74u#^I`u0gf#J|mzcv? z4EmNe+Q4Qy742ot=S%?>s%3CAnAWoGW6@5M)k8YG@?e%tI2y0wISiMEIc>M9idHRp zhs6Tr0|j)-jY>9AfqQN$-AaM^W>$zP5AA~;FIG&s*t9K*XKKVR2n8nwl>lTe=*$#Lv{VD(DKW7_Y>%()V>+FJTI<~yomq*|{`bgyhR^)3)CI-jV+U=7B2Vh8k+%Y#T% z=iH?@Zmm#w;GAZ%Ti&S#44HrUTN&GiYP+b zQMJ;WuAv}ynl(+F246A7&E7yMH_rXTsu@d^g^TMK6a@fkt{0Rb@-Hxj8G&LNcz|+> z4o>;|l+NY$fui6t;L^a-%qGKlc#7QXSc`xZa~i&-m^M^+3B20iAX&w242#lNwsUN8 zm6V7Ms|9!0{eY@8Q(V2#!~-Z~)#Df5SQf4d8z{>9EtFbS4Ns>+DC|h>bw}ZVc&qPLTswwJ#`JNo5`i&>QOAX*nLk(>Y`5-zTm-VB@#FL zb)Wr+mi#=?zb4~(q1~kgmIR36qGns(e^Ss`0J8;Dw<*7#qv4X`)ZfAwB~~rUYc1%b ztBBs@R#mvQDb4tWkttMyn^z|5Y(fFoqPmN~VI1yhq%5lKUjZE_rV#G$hNb{2hl{Gj zPHgZ%N3aR$Fp|%M3YX>~Uv#fY$>u2>D!HRKCE<90(@CxKYyuT^$?95YG&P8=+XYKY zx@>YpHUK=?w6da(jJLRTSr$gVy~nUXhVQoV00gW`x}qofY?a}IXBU_kU^4?%$+>zM zfWND{pR(q!`wSa^<$9LqRkZvtOb)d=2RJx}O~iMcN&<$k#Wh6@)P1JA7TCVxu&G@h z-{L8)3ZgF4nh3kPb~7dXz)e+N_Z8T6LlCYC)rwKHm&7YCK7B8S8tkI~sA+fOa z6mOLA>_v5jHwwCi9hES?kd_`)dw~?I2RN1mq60_Zz4(t_%3hgK0fTYJaW1LFa(12`}Gj{13vE=nC?21?*=QqiS$3awT&H>x~LIHpR0mXD;Z$#jj z7*>SF_Gn8R@9w8nABP)6d>4I6H!p=Y+?2+=bq0lWE5Mtv@e)^7#uyr`x5+E4v5JdmH(2vni;~>dXx%-J2~2(oLA?(iVA7V0Ra_M=VQ7p8 zWNHFqeURA;W$1Wg4_`c^%q$$1Y4;uJT%&?g+%D?f##1S6WXGBTCd9)^Zo zR6Ao%mIM{%;(^;@$rr?AzTJ|DSSjveS^#b0UoCZz)jTj@9pdxc4UkW&#CD=4`-U>q z9z>@f1fz)EgIzbK{BkDSXSN|QZUE;h$@41Cz9{r~IK*yaFTm@%I9H0oMN3&5O1jVLGRz7f11-%vbo0Jb z63-k~hTdR43Ut|IETQM>Cy7%CQ#~$K)3B>Tx#kgbnE=q2sP~ea&Q+5y5M8mE4Je^2 za*8;dfC0YPUvL3XbV4){L@%cdKbe3kYPN;p7AGD_=#VwGH88k-Of#33`yUqgn7Oe5 zJ_zWX(r8ZQjA8Ec4IJA!l_lfB6VXV-brwz4_vJhLB{XuOmHPKBQLlu2O2BBhjmIkU zxkHHa0Jv500>Hd<#RL+d7TX^ablpK;7iZKkLr+?YEHN!t;#4~GD9|rEF#!%DWuso&R{4JRV#oF(A2QyauBre0p??d zf}t!5MeO6^1xXJIu3{+HyN#S2D!7l10jT$EpzyCl<1s|s+$<1qRp!};0^F~L8Byf2 z-GF@8)Y0TFlcT*$9i$t7SPNKDr8RI)3CM68_2K~SKsrAhMJCJPr-C#90BC>7a}fpy z3=<=$EuBSmZQNCiygGuVj^!$okwW2}0ad4)fgTESG>Q2sEzEHzwR9a234xt zramJl!o{_CWsy{xYO!70M7#{^n&9;ojH6f%5aYxdd0~p(#G2W0aD=}xmW92eASNQO z7Q(Pq5i7V^@VTJa`irSvu8tIW;-Anu5l3|3`J>C&BCV1=cuY#yOi)!tF9(M*{7*ZHJ0@p zIWdH}`4}@s?z0sz!VN_@s_qGw0{Vyxy0`{_IhjziW>^tO<;}w&0`Npa>Qxf$TdlzV z00^m8`N~JooxE3Zyx*S5c(;Shri2P9-w>%%qL|frjN$>wQP85WM!tw_Ta0?<0B{|b zw#eXMEB4j=!W#gt2~$+z%)psoFA$wz2AX0bi0h z37&(7PRKD~I#^krITmMKKq>+FKp>^)$s5tj?mAd68TY9gGpJR2tlXtPQV9~(Ia>$c z?j37%*>rWNR}`OY4cC}q6ETHwELsE_IxB$Y`|%2FG@}Uh64X>#rYq6%YGj~l&BX_I zVq&5=cPOJCo+0lsY}CVpK5xXZyU1_&m8#$#QzQEhWfJx^8pT9!%&mrUx~FpzD9Eg_ z;E|;lm;qZ9Y&=U-0A%$UplNN&G(9d*i-}F95OY^BBb#T5Z9fqw1JiM&XyVXiM19p^ z@$oO9w3UfWfgR=tBTrD4z{3)r8+(gE0|oIGtzCP75zkT1v8%WR9HUp0{{Ucp+uDj1 zxDm06mu}e{^$Mv=*%i!gjlv$yk>7~%VwqCjY9FaJnS0b^vsNvS5pfcLhuQqYI#vR| zxZ}=wjh4tAlC74*o5Z-3^1VkiIy#mXQI|n$sN+W{oI#;Rf}dCO6B!Mrh;>sC#(0dW zECvVmv>sTvK^!nlO4DWy21Wo4bp%YIvv@i82aJ3oLxJZf$UL=S6*O^#ofOVkWlTM8Oq2*%8Q^T zTFndvVJ*{`IYrP`2#GDYU~3&tANc@^d6A064Q|)7hzI26Q#L88RLAP)Bq@l~&Bs(7 zXVkS-(#E*%SV-kC03MEB$YD7biO4V(uB^S0^3_L4Zk{VpNapfGTZJx@{J~3@X4t+J z1%cxGfJ-4{rlW`ba2n&nh((TyAX$rbj$x4C8A8iL%L;Ngr$|PK=aC*E>$iySgNnJ0 zsHd5Et8U^&YV$I8Fyh}o?qv?q3n5 ziF6|p!%ggb!H6gUM(c^k68)-B(ZC)FrQVQKpVS;>rj=$c;?vPhq-!htiJ1!B3cR2nL zRUoqz(-3Mf5!p7N(o+(hY7m_RAOFK$a5|lIIG@-<_MP2vI zc>1xKLu95kMqpqrnmnP%)oAJO+bKh@fbHnSOnsvuY)A7e2*wolxGK%Au9sI(;K|9Z$Ow4BtO)01BaCg7Zlz`mq7gX>i4?<2s8)kF)VK@1#V2JPZxs`I7T_$cD5ZqG zT{KnsmmTMvN{lx2@f*ls?y~}|SmBtFNu!v!GFcJ|gHK!=f{vUL^3HV!U;|qP{{UPI ztpf(RE7qe^smV&^IEu9lZ~YK8g;v&^fd*ZLC&Uq41y*o_S|aEGc#rhg4S@F%RV-K^ zaZVuK1FMcA^J=eVI+q{6P}nofT7tYmO`n1zLr+jT9D#U(`;~(Xn(|1HfKp*(u~nwl z4O&`m1|u)xVyPFkL0{bka~bgqZfa-(3%G?NQjMM?R&_W*0$J7IXG6mnsNuDnWKR&& z(1uqrZJ-t^`bgn-D!`fM5CE!9NNwz$&u}G;HBiYxn|SdMphuCGUR@G{uMQnAfRp3ZYF! z{CL3%-rU=9;Q%K0EblGsBhvXcqTLO{L5ZPNnqBs5g<_FYquJe!L%mL@1kAJu&y9e zOi=zKH3hbvz`tAz#Y?JH@iXAZ6abDCj$j(mmk{+3e&aZ0AGtBGF>oPfGew|$#e_Rr zoi`uh+OAJ%_5{jOKD2XE%7V!Uc(6w}=VAYSLfhEK6PlH&>g*O2}p?51QP? z6RoepDj`FmmG@h=PjTXwVm8iUiJP_~JDiyXF~kV|`AWR>;mkfE{9?=g3Z9Z*iqFDNEn4Fqvs9 z1%Jrv3C-Ie;83c&x0VlOZyoU)TkDeM@mPltO>D=H1Ke7bF>K?w zXl!inh)&c6OB_-NeTYvgO3-_e(26L#hvn{0B>?k9Erx)wzLfQlUvmx?aym$^p+ zZsu6%W1~oxE1*lVi<=myCe_qCuq#-&*jAR@TT(6m0J?#}?TZF=#4#_)2S3D27r+z{ z5USo`fvX?jz(OL*$jcE1;KcZZq-o}M>K7R?#G@T?2S$ly)FYeb_Yk~h-*X@5?Gmub z%(?6>nSyjdlN_`(mS-xqb0`JJHx*wfVRVsy6;|^dY6TnnmVirWxYwM(IoS!=qli9g z_Q2LL9hY!$32!*~>I^n8$pEEZ4M4$Oz|(uJMY3>8f9rl=raFaO9j|fpt3~4bsbw*k zs`cN@pwK3#f-T0u3M$%~iwfPsgsfsjD^?I0NJGkk zdpcpCfsW8Hq}9Q)i)-zc#WwCxroqopW-!D3AS+yl3YA>o4xYW}I<2BJ)3Sq*Si`!4)c) zsER;dhX%=?llqM`$mGMQtk06UNdm>uyg~p0)?Q!tF@8`%3vjNu+{DZkbvStA2HHCe z3}EGq-0tWy9 literal 0 HcmV?d00001 diff --git a/dist/images/imgo.png b/dist/images/imgo.png new file mode 100644 index 0000000000000000000000000000000000000000..b3f79e5e8dce963c410bc14c36f31f5186abab6e GIT binary patch literal 1333 zcmex=%kxU@K!VDr=Sy-4^*jU-vz?hwr zgN>b&osEryn}d@J1b{3aZY~}W2V@9DD-$a-Gb5A z1R0qH8UG()kY`|EWCc5qkpT)AnV4Bv+1P>3;07w#DgbmoGc(Z9tUwn7Ro4RL8CV2a zg%k}P*@OcV*_8@Kj2b5{ECr+Nabot8FYu9hwy!G(W<0ns_J%91?)yGet zzkL1n{m0K=Ab&A3FhjfrBq1I{^OqpdUreAlU=!0ld(M2vX6_bamA3VSHoUZ3eWMd|M+Te%&yJadBIKE$b$FgdcQcYFWUO_`@@Y@T^eis zZJxeZICbK-T@&1sT`QkoVHF8b8mmhIjv#WU2^l$#2eEXBZi>0Y4Nqsw%n>4kjd}9Jy zhy}0mn0Ba3W0i`=qAmt(_|~PZfo1!Ao(u8+sahXyw$ZD1XEaNR>DHz9PL>Nswx5|} z%=dM#<$brxh&B3~zdzn^H`pus=;uY!De^zQZ%wk=Wau6vcu@56Ro!TxzL&g*WH)Jj z{r6#M(A=-C2_J*H1E$^O@zVU~{Hx2R{j2Dys>d43fAYW5_#}TNfSCX@RK+_Pt|U~* VsH=X$zeW9ue_a_UXV(9}2>=t<79Rir literal 0 HcmV?d00001 diff --git a/dist/images/robot.png b/dist/images/robot.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d9c7b03527e408fa4e027cb90cd287b46647a5 GIT binary patch literal 139132 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

>0eGiM?*eiZ``EZnwet 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 + + + + + diff --git a/dist/images/tick-mask.svg b/dist/images/tick-mask.svg new file mode 100644 index 0000000..b098920 --- /dev/null +++ b/dist/images/tick-mask.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/dist/images/tick.svg b/dist/images/tick.svg new file mode 100644 index 0000000..b3d6ec8 --- /dev/null +++ b/dist/images/tick.svg @@ -0,0 +1,15 @@ + + + + diff --git a/dist/images/tick_dark.svg b/dist/images/tick_dark.svg new file mode 100644 index 0000000..b6356f7 --- /dev/null +++ b/dist/images/tick_dark.svg @@ -0,0 +1,15 @@ + + + + diff --git a/dist/images/watch_white.svg b/dist/images/watch_white.svg new file mode 100644 index 0000000..432b776 --- /dev/null +++ b/dist/images/watch_white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/images/weather_bck.png b/dist/images/weather_bck.png new file mode 100644 index 0000000000000000000000000000000000000000..13419412b023f477640a49e63e26fd2a7d93e4ec GIT binary patch literal 211795 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

lJA6_jegJUwe&*Gxw)15w#Zw-k( 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 literal 0 HcmV?d00001 diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..8381435 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,530 @@ + + + + + + + + + + Material Dashboard Lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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

My Day

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

Now

+ +
+
+ room + Minsk, Belarus +
+
+
+

-11°

+ +

+ Cloudy and snow +

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

Cotoneaster

+
+
+
+ Cotoneaster is a genus of flowering plants in the rose family, Roseaceae, netive to the + Palaearctic region, with a strong concentration of diversity in the genus in the + mountains + of southwestern China and the Himalayas. +
+ Wikipedia +
+
+
+ +
+
+
+

Startup Financing Cycle

+
+
+
+ +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProjectResponsibleClient contactDeadlineProgress
Darkboard + Alex + Dina + Misha + Luke@skywalker.comJun 15 +
+
+ 44% +
+
Big financial app + Vlada + Boss@financial.comMar 1 +
+
+ 14% +
+
New Year office decoration + Dina + Vlada + info@creativeit.ioDec 25 + done +
Don't worry, be happy!!! + Everybody + Contact@happyness.comYesterday +
+
+ 31% +
+
+
+
+ +
+ +
+
+
+

BB-8

+
+
+
+ A skittish but loyal astromech, BB-8 accompanied Poe Dameron on many missions for the + Resistance helping keep his X-wing in working order. +
+ Star Wars Databank +
+
+
+ +
+
+
+

To-do list

+
+
+
    + +
+
+
+ + +
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + diff --git a/dist/js/d3.js b/dist/js/d3.js new file mode 100644 index 0000000..2e70a83 --- /dev/null +++ b/dist/js/d3.js @@ -0,0 +1,9554 @@ +!function() { + var d3 = { + version: "3.5.16" + }; + var d3_arraySlice = [].slice, d3_array = function(list) { + return d3_arraySlice.call(list); + }; + var d3_document = this.document; + function d3_documentElement(node) { + return node && (node.ownerDocument || node.document || node).documentElement; + } + function d3_window(node) { + return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); + } + if (d3_document) { + try { + d3_array(d3_document.documentElement.childNodes)[0].nodeType; + } catch (e) { + d3_array = function(list) { + var i = list.length, array = new Array(i); + while (i--) array[i] = list[i]; + return array; + }; + } + } + if (!Date.now) Date.now = function() { + return +new Date(); + }; + if (d3_document) { + try { + d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); + } catch (error) { + var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; + d3_element_prototype.setAttribute = function(name, value) { + d3_element_setAttribute.call(this, name, value + ""); + }; + d3_element_prototype.setAttributeNS = function(space, local, value) { + d3_element_setAttributeNS.call(this, space, local, value + ""); + }; + d3_style_prototype.setProperty = function(name, value, priority) { + d3_style_setProperty.call(this, name, value + "", priority); + }; + } + } + d3.ascending = d3_ascending; + function d3_ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + }; + d3.min = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && a > b) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; + } + return a; + }; + d3.max = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && b > a) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; + } + return a; + }; + d3.extent = function(array, f) { + var i = -1, n = array.length, a, b, c; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = array[i]) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } + return [ a, c ]; + }; + function d3_number(x) { + return x === null ? NaN : +x; + } + function d3_numeric(x) { + return !isNaN(x); + } + d3.sum = function(array, f) { + var s = 0, n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = +array[i])) s += a; + } else { + while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; + } + return s; + }; + d3.mean = function(array, f) { + var s = 0, n = array.length, a, i = -1, j = n; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; + } + if (j) return s / j; + }; + d3.quantile = function(values, p) { + var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; + return e ? v + e * (values[h] - v) : v; + }; + d3.median = function(array, f) { + var numbers = [], n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); + } + if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); + }; + d3.variance = function(array, f) { + var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; + if (arguments.length === 1) { + while (++i < n) { + if (d3_numeric(a = d3_number(array[i]))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } else { + while (++i < n) { + if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + if (j > 1) return s / (j - 1); + }; + d3.deviation = function() { + var v = d3.variance.apply(this, arguments); + return v ? Math.sqrt(v) : v; + }; + function d3_bisector(compare) { + return { + left: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; + } + return lo; + } + }; + } + var d3_bisect = d3_bisector(d3_ascending); + d3.bisectLeft = d3_bisect.left; + d3.bisect = d3.bisectRight = d3_bisect.right; + d3.bisector = function(f) { + return d3_bisector(f.length === 1 ? function(d, x) { + return d3_ascending(f(d), x); + } : f); + }; + d3.shuffle = function(array, i0, i1) { + if ((m = arguments.length) < 3) { + i1 = array.length; + if (m < 2) i0 = 0; + } + var m = i1 - i0, t, i; + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; + } + return array; + }; + d3.permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; + }; + d3.pairs = function(array) { + var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; + return pairs; + }; + d3.transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { + row[j] = matrix[j][i]; + } + } + return transpose; + }; + function d3_transposeLength(d) { + return d.length; + } + d3.zip = function() { + return d3.transpose(arguments); + }; + d3.keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; + }; + d3.values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; + }; + d3.entries = function(map) { + var entries = []; + for (var key in map) entries.push({ + key: key, + value: map[key] + }); + return entries; + }; + d3.merge = function(arrays) { + var n = arrays.length, m, i = -1, j = 0, merged, array; + while (++i < n) j += arrays[i].length; + merged = new Array(j); + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + return merged; + }; + var abs = Math.abs; + d3.range = function(start, stop, step) { + if (arguments.length < 3) { + step = 1; + if (arguments.length < 2) { + stop = start; + start = 0; + } + } + if ((stop - start) / step === Infinity) throw new Error("infinite range"); + var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; + start *= k, stop *= k, step *= k; + if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); + return range; + }; + function d3_range_integerScale(x) { + var k = 1; + while (x * k % 1) k *= 10; + return k; + } + function d3_class(ctor, properties) { + for (var key in properties) { + Object.defineProperty(ctor.prototype, key, { + value: properties[key], + enumerable: false + }); + } + } + d3.map = function(object, f) { + var map = new d3_Map(); + if (object instanceof d3_Map) { + object.forEach(function(key, value) { + map.set(key, value); + }); + } else if (Array.isArray(object)) { + var i = -1, n = object.length, o; + if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); + } else { + for (var key in object) map.set(key, object[key]); + } + return map; + }; + function d3_Map() { + this._ = Object.create(null); + } + var d3_map_proto = "__proto__", d3_map_zero = "\x00"; + d3_class(d3_Map, { + has: d3_map_has, + get: function(key) { + return this._[d3_map_escape(key)]; + }, + set: function(key, value) { + return this._[d3_map_escape(key)] = value; + }, + remove: d3_map_remove, + keys: d3_map_keys, + values: function() { + var values = []; + for (var key in this._) values.push(this._[key]); + return values; + }, + entries: function() { + var entries = []; + for (var key in this._) entries.push({ + key: d3_map_unescape(key), + value: this._[key] + }); + return entries; + }, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); + } + }); + function d3_map_escape(key) { + return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; + } + function d3_map_unescape(key) { + return (key += "")[0] === d3_map_zero ? key.slice(1) : key; + } + function d3_map_has(key) { + return d3_map_escape(key) in this._; + } + function d3_map_remove(key) { + return (key = d3_map_escape(key)) in this._ && delete this._[key]; + } + function d3_map_keys() { + var keys = []; + for (var key in this._) keys.push(d3_map_unescape(key)); + return keys; + } + function d3_map_size() { + var size = 0; + for (var key in this._) ++size; + return size; + } + function d3_map_empty() { + for (var key in this._) return false; + return true; + } + d3.nest = function() { + var nest = {}, keys = [], sortKeys = [], sortValues, rollup; + function map(mapType, array, depth) { + if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; + var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(object = array[i]))) { + values.push(object); + } else { + valuesByKey.set(keyValue, [ object ]); + } + } + if (mapType) { + object = mapType(); + setter = function(keyValue, values) { + object.set(keyValue, map(mapType, values, depth)); + }; + } else { + object = {}; + setter = function(keyValue, values) { + object[keyValue] = map(mapType, values, depth); + }; + } + valuesByKey.forEach(setter); + return object; + } + function entries(map, depth) { + if (depth >= keys.length) return map; + var array = [], sortKey = sortKeys[depth++]; + map.forEach(function(key, keyMap) { + array.push({ + key: key, + values: entries(keyMap, depth) + }); + }); + return sortKey ? array.sort(function(a, b) { + return sortKey(a.key, b.key); + }) : array; + } + nest.map = function(array, mapType) { + return map(mapType, array, 0); + }; + nest.entries = function(array) { + return entries(map(d3.map, array, 0), 0); + }; + nest.key = function(d) { + keys.push(d); + return nest; + }; + nest.sortKeys = function(order) { + sortKeys[keys.length - 1] = order; + return nest; + }; + nest.sortValues = function(order) { + sortValues = order; + return nest; + }; + nest.rollup = function(f) { + rollup = f; + return nest; + }; + return nest; + }; + d3.set = function(array) { + var set = new d3_Set(); + if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); + return set; + }; + function d3_Set() { + this._ = Object.create(null); + } + d3_class(d3_Set, { + has: d3_map_has, + add: function(key) { + this._[d3_map_escape(key += "")] = true; + return key; + }, + remove: d3_map_remove, + values: d3_map_keys, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key)); + } + }); + d3.behavior = {}; + function d3_identity(d) { + return d; + } + d3.rebind = function(target, source) { + var i = 1, n = arguments.length, method; + while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); + return target; + }; + function d3_rebind(target, source, method) { + return function() { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; + } + function d3_vendorSymbol(object, name) { + if (name in object) return name; + name = name.charAt(0).toUpperCase() + name.slice(1); + for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { + var prefixName = d3_vendorPrefixes[i] + name; + if (prefixName in object) return prefixName; + } + } + var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; + function d3_noop() {} + d3.dispatch = function() { + var dispatch = new d3_dispatch(), i = -1, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + return dispatch; + }; + function d3_dispatch() {} + d3_dispatch.prototype.on = function(type, listener) { + var i = type.indexOf("."), name = ""; + if (i >= 0) { + name = type.slice(i + 1); + type = type.slice(0, i); + } + if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); + if (arguments.length === 2) { + if (listener == null) for (type in this) { + if (this.hasOwnProperty(type)) this[type].on(name, null); + } + return this; + } + }; + function d3_dispatch_event(dispatch) { + var listeners = [], listenerByName = new d3_Map(); + function event() { + var z = listeners, i = -1, n = z.length, l; + while (++i < n) if (l = z[i].on) l.apply(this, arguments); + return dispatch; + } + event.on = function(name, listener) { + var l = listenerByName.get(name), i; + if (arguments.length < 2) return l && l.on; + if (l) { + l.on = null; + listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); + listenerByName.remove(name); + } + if (listener) listeners.push(listenerByName.set(name, { + on: listener + })); + return dispatch; + }; + return event; + } + d3.event = null; + function d3_eventPreventDefault() { + d3.event.preventDefault(); + } + function d3_eventSource() { + var e = d3.event, s; + while (s = e.sourceEvent) e = s; + return e; + } + function d3_eventDispatch(target) { + var dispatch = new d3_dispatch(), i = 0, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + dispatch.of = function(thiz, argumentz) { + return function(e1) { + try { + var e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + return dispatch; + } + d3.requote = function(s) { + return s.replace(d3_requote_re, "\\$&"); + }; + var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + var d3_subclass = {}.__proto__ ? function(object, prototype) { + object.__proto__ = prototype; + } : function(object, prototype) { + for (var property in prototype) object[property] = prototype[property]; + }; + function d3_selection(groups) { + d3_subclass(groups, d3_selectionPrototype); + return groups; + } + var d3_select = function(s, n) { + return n.querySelector(s); + }, d3_selectAll = function(s, n) { + return n.querySelectorAll(s); + }, d3_selectMatches = function(n, s) { + var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; + d3_selectMatches = function(n, s) { + return d3_selectMatcher.call(n, s); + }; + return d3_selectMatches(n, s); + }; + if (typeof Sizzle === "function") { + d3_select = function(s, n) { + return Sizzle(s, n)[0] || null; + }; + d3_selectAll = Sizzle; + d3_selectMatches = Sizzle.matchesSelector; + } + d3.selection = function() { + return d3.select(d3_document.documentElement); + }; + var d3_selectionPrototype = d3.selection.prototype = []; + d3_selectionPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, group, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(subnode = selector.call(node, node.__data__, i, j)); + if (subnode && "__data__" in node) subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selector(selector) { + return typeof selector === "function" ? selector : function() { + return d3_select(selector, this); + }; + } + d3_selectionPrototype.selectAll = function(selector) { + var subgroups = [], subgroup, node; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); + subgroup.parentNode = node; + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selectorAll(selector) { + return typeof selector === "function" ? selector : function() { + return d3_selectAll(selector, this); + }; + } + var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; + var d3_nsPrefix = { + svg: "http://www.w3.org/2000/svg", + xhtml: d3_nsXhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: d3_nsPrefix, + qualify: function(name) { + var i = name.indexOf(":"), prefix = name; + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return d3_nsPrefix.hasOwnProperty(prefix) ? { + space: d3_nsPrefix[prefix], + local: name + } : name; + } + }; + d3_selectionPrototype.attr = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(); + name = d3.ns.qualify(name); + return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); + } + for (value in name) this.each(d3_selection_attr(value, name[value])); + return this; + } + return this.each(d3_selection_attr(name, value)); + }; + function d3_selection_attr(name, value) { + name = d3.ns.qualify(name); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrConstant() { + this.setAttribute(name, value); + } + function attrConstantNS() { + this.setAttributeNS(name.space, name.local, value); + } + function attrFunction() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); + } + function attrFunctionNS() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); + } + return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; + } + function d3_collapse(s) { + return s.trim().replace(/\s+/g, " "); + } + d3_selectionPrototype.classed = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; + if (value = node.classList) { + while (++i < n) if (!value.contains(name[i])) return false; + } else { + value = node.getAttribute("class"); + while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; + } + return true; + } + for (value in name) this.each(d3_selection_classed(value, name[value])); + return this; + } + return this.each(d3_selection_classed(name, value)); + }; + function d3_selection_classedRe(name) { + return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); + } + function d3_selection_classes(name) { + return (name + "").trim().split(/^|\s+/); + } + function d3_selection_classed(name, value) { + name = d3_selection_classes(name).map(d3_selection_classedName); + var n = name.length; + function classedConstant() { + var i = -1; + while (++i < n) name[i](this, value); + } + function classedFunction() { + var i = -1, x = value.apply(this, arguments); + while (++i < n) name[i](this, x); + } + return typeof value === "function" ? classedFunction : classedConstant; + } + function d3_selection_classedName(name) { + var re = d3_selection_classedRe(name); + return function(node, value) { + if (c = node.classList) return value ? c.add(name) : c.remove(name); + var c = node.getAttribute("class") || ""; + if (value) { + re.lastIndex = 0; + if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); + } else { + node.setAttribute("class", d3_collapse(c.replace(re, " "))); + } + }; + } + d3_selectionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); + return this; + } + if (n < 2) { + var node = this.node(); + return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); + } + priority = ""; + } + return this.each(d3_selection_style(name, value, priority)); + }; + function d3_selection_style(name, value, priority) { + function styleNull() { + this.style.removeProperty(name); + } + function styleConstant() { + this.style.setProperty(name, value, priority); + } + function styleFunction() { + var x = value.apply(this, arguments); + if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); + } + return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; + } + d3_selectionPrototype.property = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") return this.node()[name]; + for (value in name) this.each(d3_selection_property(value, name[value])); + return this; + } + return this.each(d3_selection_property(name, value)); + }; + function d3_selection_property(name, value) { + function propertyNull() { + delete this[name]; + } + function propertyConstant() { + this[name] = value; + } + function propertyFunction() { + var x = value.apply(this, arguments); + if (x == null) delete this[name]; else this[name] = x; + } + return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; + } + d3_selectionPrototype.text = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + } : value == null ? function() { + this.textContent = ""; + } : function() { + this.textContent = value; + }) : this.node().textContent; + }; + d3_selectionPrototype.html = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + } : value == null ? function() { + this.innerHTML = ""; + } : function() { + this.innerHTML = value; + }) : this.node().innerHTML; + }; + d3_selectionPrototype.append = function(name) { + name = d3_selection_creator(name); + return this.select(function() { + return this.appendChild(name.apply(this, arguments)); + }); + }; + function d3_selection_creator(name) { + function create() { + var document = this.ownerDocument, namespace = this.namespaceURI; + return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); + } + function createNS() { + return this.ownerDocument.createElementNS(name.space, name.local); + } + return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; + } + d3_selectionPrototype.insert = function(name, before) { + name = d3_selection_creator(name); + before = d3_selection_selector(before); + return this.select(function() { + return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); + }); + }; + d3_selectionPrototype.remove = function() { + return this.each(d3_selectionRemove); + }; + function d3_selectionRemove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + } + d3_selectionPrototype.data = function(value, key) { + var i = -1, n = this.length, group, node; + if (!arguments.length) { + value = new Array(n = (group = this[0]).length); + while (++i < n) { + if (node = group[i]) { + value[i] = node.__data__; + } + } + return value; + } + function bind(group, groupData) { + var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; + if (key) { + var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; + for (i = -1; ++i < n; ) { + if (node = group[i]) { + if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { + exitNodes[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + keyValues[i] = keyValue; + } + } + for (i = -1; ++i < m; ) { + if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { + enterNodes[i] = d3_selection_dataNode(nodeData); + } else if (node !== true) { + updateNodes[i] = node; + node.__data__ = nodeData; + } + nodeByKeyValue.set(keyValue, true); + } + for (i = -1; ++i < n; ) { + if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { + exitNodes[i] = group[i]; + } + } + } else { + for (i = -1; ++i < n0; ) { + node = group[i]; + nodeData = groupData[i]; + if (node) { + node.__data__ = nodeData; + updateNodes[i] = node; + } else { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + } + for (;i < m; ++i) { + enterNodes[i] = d3_selection_dataNode(groupData[i]); + } + for (;i < n; ++i) { + exitNodes[i] = group[i]; + } + } + enterNodes.update = updateNodes; + enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; + enter.push(enterNodes); + update.push(updateNodes); + exit.push(exitNodes); + } + var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); + if (typeof value === "function") { + while (++i < n) { + bind(group = this[i], value.call(group, group.parentNode.__data__, i)); + } + } else { + while (++i < n) { + bind(group = this[i], value); + } + } + update.enter = function() { + return enter; + }; + update.exit = function() { + return exit; + }; + return update; + }; + function d3_selection_dataNode(data) { + return { + __data__: data + }; + } + d3_selectionPrototype.datum = function(value) { + return arguments.length ? this.property("__data__", value) : this.property("__data__"); + }; + d3_selectionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_filter(selector) { + return function() { + return d3_selectMatches(this, selector); + }; + } + d3_selectionPrototype.order = function() { + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + }; + d3_selectionPrototype.sort = function(comparator) { + comparator = d3_selection_sortComparator.apply(this, arguments); + for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); + return this.order(); + }; + function d3_selection_sortComparator(comparator) { + if (!arguments.length) comparator = d3_ascending; + return function(a, b) { + return a && b ? comparator(a.__data__, b.__data__) : !a - !b; + }; + } + d3_selectionPrototype.each = function(callback) { + return d3_selection_each(this, function(node, i, j) { + callback.call(node, node.__data__, i, j); + }); + }; + function d3_selection_each(groups, callback) { + for (var j = 0, m = groups.length; j < m; j++) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { + if (node = group[i]) callback(node, i, j); + } + } + return groups; + } + d3_selectionPrototype.call = function(callback) { + var args = d3_array(arguments); + callback.apply(args[0] = this, args); + return this; + }; + d3_selectionPrototype.empty = function() { + return !this.node(); + }; + d3_selectionPrototype.node = function() { + for (var j = 0, m = this.length; j < m; j++) { + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + var node = group[i]; + if (node) return node; + } + } + return null; + }; + d3_selectionPrototype.size = function() { + var n = 0; + d3_selection_each(this, function() { + ++n; + }); + return n; + }; + function d3_selection_enter(selection) { + d3_subclass(selection, d3_selection_enterPrototype); + return selection; + } + var d3_selection_enterPrototype = []; + d3.selection.enter = d3_selection_enter; + d3.selection.enter.prototype = d3_selection_enterPrototype; + d3_selection_enterPrototype.append = d3_selectionPrototype.append; + d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; + d3_selection_enterPrototype.node = d3_selectionPrototype.node; + d3_selection_enterPrototype.call = d3_selectionPrototype.call; + d3_selection_enterPrototype.size = d3_selectionPrototype.size; + d3_selection_enterPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, upgroup, group, node; + for (var j = -1, m = this.length; ++j < m; ) { + upgroup = (group = this[j]).update; + subgroups.push(subgroup = []); + subgroup.parentNode = group.parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); + subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + d3_selection_enterPrototype.insert = function(name, before) { + if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); + return d3_selectionPrototype.insert.call(this, name, before); + }; + function d3_selection_enterInsertBefore(enter) { + var i0, j0; + return function(d, i, j) { + var group = enter[j].update, n = group.length, node; + if (j != j0) j0 = j, i0 = 0; + if (i >= i0) i0 = i + 1; + while (!(node = group[i0]) && ++i0 < n) ; + return node; + }; + } + d3.select = function(node) { + var group; + if (typeof node === "string") { + group = [ d3_select(node, d3_document) ]; + group.parentNode = d3_document.documentElement; + } else { + group = [ node ]; + group.parentNode = d3_documentElement(node); + } + return d3_selection([ group ]); + }; + d3.selectAll = function(nodes) { + var group; + if (typeof nodes === "string") { + group = d3_array(d3_selectAll(nodes, d3_document)); + group.parentNode = d3_document.documentElement; + } else { + group = d3_array(nodes); + group.parentNode = null; + } + return d3_selection([ group ]); + }; + d3_selectionPrototype.on = function(type, listener, capture) { + var n = arguments.length; + if (n < 3) { + if (typeof type !== "string") { + if (n < 2) listener = false; + for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); + return this; + } + if (n < 2) return (n = this.node()["__on" + type]) && n._; + capture = false; + } + return this.each(d3_selection_on(type, listener, capture)); + }; + function d3_selection_on(type, listener, capture) { + var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; + if (i > 0) type = type.slice(0, i); + var filter = d3_selection_onFilters.get(type); + if (filter) type = filter, wrap = d3_selection_onFilter; + function onRemove() { + var l = this[name]; + if (l) { + this.removeEventListener(type, l, l.$); + delete this[name]; + } + } + function onAdd() { + var l = wrap(listener, d3_array(arguments)); + onRemove.call(this); + this.addEventListener(type, this[name] = l, l.$ = capture); + l._ = listener; + } + function removeAll() { + var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; + for (var name in this) { + if (match = name.match(re)) { + var l = this[name]; + this.removeEventListener(match[1], l, l.$); + delete this[name]; + } + } + } + return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; + } + var d3_selection_onFilters = d3.map({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }); + if (d3_document) { + d3_selection_onFilters.forEach(function(k) { + if ("on" + k in d3_document) d3_selection_onFilters.remove(k); + }); + } + function d3_selection_onListener(listener, argumentz) { + return function(e) { + var o = d3.event; + d3.event = e; + argumentz[0] = this.__data__; + try { + listener.apply(this, argumentz); + } finally { + d3.event = o; + } + }; + } + function d3_selection_onFilter(listener, argumentz) { + var l = d3_selection_onListener(listener, argumentz); + return function(e) { + var target = this, related = e.relatedTarget; + if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { + l.call(target, e); + } + }; + } + var d3_event_dragSelect, d3_event_dragId = 0; + function d3_event_dragSuppress(node) { + var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); + if (d3_event_dragSelect == null) { + d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); + } + if (d3_event_dragSelect) { + var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; + style[d3_event_dragSelect] = "none"; + } + return function(suppressClick) { + w.on(name, null); + if (d3_event_dragSelect) style[d3_event_dragSelect] = select; + if (suppressClick) { + var off = function() { + w.on(click, null); + }; + w.on(click, function() { + d3_eventPreventDefault(); + off(); + }, true); + setTimeout(off, 0); + } + }; + } + d3.mouse = function(container) { + return d3_mousePoint(container, d3_eventSource()); + }; + var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; + function d3_mousePoint(container, e) { + if (e.changedTouches) e = e.changedTouches[0]; + var svg = container.ownerSVGElement || container; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + if (d3_mouse_bug44083 < 0) { + var window = d3_window(container); + if (window.scrollX || window.scrollY) { + svg = d3.select("body").append("svg").style({ + position: "absolute", + top: 0, + left: 0, + margin: 0, + padding: 0, + border: "none" + }, "important"); + var ctm = svg[0][0].getScreenCTM(); + d3_mouse_bug44083 = !(ctm.f || ctm.e); + svg.remove(); + } + } + if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, + point.y = e.clientY; + point = point.matrixTransform(container.getScreenCTM().inverse()); + return [ point.x, point.y ]; + } + var rect = container.getBoundingClientRect(); + return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; + } + d3.touch = function(container, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; + if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return d3_mousePoint(container, touch); + } + } + }; + d3.behavior.drag = function() { + var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); + function drag() { + this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); + } + function dragstart(id, position, subject, move, end) { + return function() { + var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); + if (origin) { + dragOffset = origin.apply(that, arguments); + dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; + } else { + dragOffset = [ 0, 0 ]; + } + dispatch({ + type: "dragstart" + }); + function moved() { + var position1 = position(parent, dragId), dx, dy; + if (!position1) return; + dx = position1[0] - position0[0]; + dy = position1[1] - position0[1]; + dragged |= dx | dy; + position0 = position1; + dispatch({ + type: "drag", + x: position1[0] + dragOffset[0], + y: position1[1] + dragOffset[1], + dx: dx, + dy: dy + }); + } + function ended() { + if (!position(parent, dragId)) return; + dragSubject.on(move + dragName, null).on(end + dragName, null); + dragRestore(dragged); + dispatch({ + type: "dragend" + }); + } + }; + } + drag.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return drag; + }; + return d3.rebind(drag, event, "on"); + }; + function d3_behavior_dragTouchId() { + return d3.event.changedTouches[0].identifier; + } + d3.touches = function(container, touches) { + if (arguments.length < 2) touches = d3_eventSource().touches; + return touches ? d3_array(touches).map(function(touch) { + var point = d3_mousePoint(container, touch); + point.identifier = touch.identifier; + return point; + }) : []; + }; + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; + function d3_sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function d3_cross2d(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + function d3_acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); + } + function d3_asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); + } + function d3_sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + function d3_cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + function d3_tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + function d3_haversin(x) { + return (x = Math.sin(x / 2)) * x; + } + var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; + d3.interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; + if (d2 < ε2) { + S = Math.log(w1 / w0) / ρ; + i = function(t) { + return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; + }; + } else { + var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / ρ; + i = function(t) { + var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); + return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; + }; + } + i.duration = S * 1e3; + return i; + }; + d3.behavior.zoom = function() { + var view = { + x: 0, + y: 0, + k: 1 + }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; + if (!d3_behavior_zoomWheel) { + d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); + }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return d3.event.wheelDelta; + }, "mousewheel") : (d3_behavior_zoomDelta = function() { + return -d3.event.detail; + }, "MozMousePixelScroll"); + } + function zoom(g) { + g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); + } + zoom.event = function(g) { + g.each(function() { + var dispatch = event.of(this, arguments), view1 = view; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.zoom", function() { + view = this.__chart__ || { + x: 0, + y: 0, + k: 1 + }; + zoomstarted(dispatch); + }).tween("zoom:zoom", function() { + var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); + return function(t) { + var l = i(t), k = dx / l[2]; + this.__chart__ = view = { + x: cx - l[0] * k, + y: cy - l[1] * k, + k: k + }; + zoomed(dispatch); + }; + }).each("interrupt.zoom", function() { + zoomended(dispatch); + }).each("end.zoom", function() { + zoomended(dispatch); + }); + } else { + this.__chart__ = view; + zoomstarted(dispatch); + zoomed(dispatch); + zoomended(dispatch); + } + }); + }; + zoom.translate = function(_) { + if (!arguments.length) return [ view.x, view.y ]; + view = { + x: +_[0], + y: +_[1], + k: view.k + }; + rescale(); + return zoom; + }; + zoom.scale = function(_) { + if (!arguments.length) return view.k; + view = { + x: view.x, + y: view.y, + k: null + }; + scaleTo(+_); + rescale(); + return zoom; + }; + zoom.scaleExtent = function(_) { + if (!arguments.length) return scaleExtent; + scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; + return zoom; + }; + zoom.center = function(_) { + if (!arguments.length) return center; + center = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.size = function(_) { + if (!arguments.length) return size; + size = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.duration = function(_) { + if (!arguments.length) return duration; + duration = +_; + return zoom; + }; + zoom.x = function(z) { + if (!arguments.length) return x1; + x1 = z; + x0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + zoom.y = function(z) { + if (!arguments.length) return y1; + y1 = z; + y0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + function location(p) { + return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; + } + function point(l) { + return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; + } + function scaleTo(s) { + view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); + } + function translateTo(p, l) { + l = point(l); + view.x += p[0] - l[0]; + view.y += p[1] - l[1]; + } + function zoomTo(that, p, l, k) { + that.__chart__ = { + x: view.x, + y: view.y, + k: view.k + }; + scaleTo(Math.pow(2, k)); + translateTo(center0 = p, l); + that = d3.select(that); + if (duration > 0) that = that.transition().duration(duration); + that.call(zoom.event); + } + function rescale() { + if (x1) x1.domain(x0.range().map(function(x) { + return (x - view.x) / view.k; + }).map(x0.invert)); + if (y1) y1.domain(y0.range().map(function(y) { + return (y - view.y) / view.k; + }).map(y0.invert)); + } + function zoomstarted(dispatch) { + if (!zooming++) dispatch({ + type: "zoomstart" + }); + } + function zoomed(dispatch) { + rescale(); + dispatch({ + type: "zoom", + scale: view.k, + translate: [ view.x, view.y ] + }); + } + function zoomended(dispatch) { + if (!--zooming) dispatch({ + type: "zoomend" + }), center0 = null; + } + function mousedowned() { + var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); + d3_selection_interrupt.call(that); + zoomstarted(dispatch); + function moved() { + dragged = 1; + translateTo(d3.mouse(that), location0); + zoomed(dispatch); + } + function ended() { + subject.on(mousemove, null).on(mouseup, null); + dragRestore(dragged); + zoomended(dispatch); + } + } + function touchstarted() { + var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); + started(); + zoomstarted(dispatch); + subject.on(mousedown, null).on(touchstart, started); + function relocate() { + var touches = d3.touches(that); + scale0 = view.k; + touches.forEach(function(t) { + if (t.identifier in locations0) locations0[t.identifier] = location(t); + }); + return touches; + } + function started() { + var target = d3.event.target; + d3.select(target).on(touchmove, moved).on(touchend, ended); + targets.push(target); + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + locations0[changed[i].identifier] = null; + } + var touches = relocate(), now = Date.now(); + if (touches.length === 1) { + if (now - touchtime < 500) { + var p = touches[0]; + zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); + d3_eventPreventDefault(); + } + touchtime = now; + } else if (touches.length > 1) { + var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; + distance0 = dx * dx + dy * dy; + } + } + function moved() { + var touches = d3.touches(that), p0, l0, p1, l1; + d3_selection_interrupt.call(that); + for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { + p1 = touches[i]; + if (l1 = locations0[p1.identifier]) { + if (l0) break; + p0 = p1, l0 = l1; + } + } + if (l1) { + var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); + p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; + l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; + scaleTo(scale1 * scale0); + } + touchtime = null; + translateTo(p0, l0); + zoomed(dispatch); + } + function ended() { + if (d3.event.touches.length) { + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + delete locations0[changed[i].identifier]; + } + for (var identifier in locations0) { + return void relocate(); + } + } + d3.selectAll(targets).on(zoomName, null); + subject.on(mousedown, mousedowned).on(touchstart, touchstarted); + dragRestore(); + zoomended(dispatch); + } + } + function mousewheeled() { + var dispatch = event.of(this, arguments); + if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), + translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); + mousewheelTimer = setTimeout(function() { + mousewheelTimer = null; + zoomended(dispatch); + }, 50); + d3_eventPreventDefault(); + scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); + translateTo(center0, translate0); + zoomed(dispatch); + } + function dblclicked() { + var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; + zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); + } + return d3.rebind(zoom, event, "on"); + }; + var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; + d3.color = d3_color; + function d3_color() {} + d3_color.prototype.toString = function() { + return this.rgb() + ""; + }; + d3.hsl = d3_hsl; + function d3_hsl(h, s, l) { + return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); + } + var d3_hslPrototype = d3_hsl.prototype = new d3_color(); + d3_hslPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, this.l / k); + }; + d3_hslPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, k * this.l); + }; + d3_hslPrototype.rgb = function() { + return d3_hsl_rgb(this.h, this.s, this.l); + }; + function d3_hsl_rgb(h, s, l) { + var m1, m2; + h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; + s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; + l = l < 0 ? 0 : l > 1 ? 1 : l; + m2 = l <= .5 ? l * (1 + s) : l + s - l * s; + m1 = 2 * l - m2; + function v(h) { + if (h > 360) h -= 360; else if (h < 0) h += 360; + if (h < 60) return m1 + (m2 - m1) * h / 60; + if (h < 180) return m2; + if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; + return m1; + } + function vv(h) { + return Math.round(v(h) * 255); + } + return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); + } + d3.hcl = d3_hcl; + function d3_hcl(h, c, l) { + return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); + } + var d3_hclPrototype = d3_hcl.prototype = new d3_color(); + d3_hclPrototype.brighter = function(k) { + return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.darker = function(k) { + return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.rgb = function() { + return d3_hcl_lab(this.h, this.c, this.l).rgb(); + }; + function d3_hcl_lab(h, c, l) { + if (isNaN(h)) h = 0; + if (isNaN(c)) c = 0; + return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); + } + d3.lab = d3_lab; + function d3_lab(l, a, b) { + return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); + } + var d3_lab_K = 18; + var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; + var d3_labPrototype = d3_lab.prototype = new d3_color(); + d3_labPrototype.brighter = function(k) { + return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.darker = function(k) { + return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.rgb = function() { + return d3_lab_rgb(this.l, this.a, this.b); + }; + function d3_lab_rgb(l, a, b) { + var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; + x = d3_lab_xyz(x) * d3_lab_X; + y = d3_lab_xyz(y) * d3_lab_Y; + z = d3_lab_xyz(z) * d3_lab_Z; + return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); + } + function d3_lab_hcl(l, a, b) { + return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); + } + function d3_lab_xyz(x) { + return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; + } + function d3_xyz_lab(x) { + return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; + } + function d3_xyz_rgb(r) { + return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); + } + d3.rgb = d3_rgb; + function d3_rgb(r, g, b) { + return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); + } + function d3_rgbNumber(value) { + return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); + } + function d3_rgbString(value) { + return d3_rgbNumber(value) + ""; + } + var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); + d3_rgbPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + var r = this.r, g = this.g, b = this.b, i = 30; + if (!r && !g && !b) return new d3_rgb(i, i, i); + if (r && r < i) r = i; + if (g && g < i) g = i; + if (b && b < i) b = i; + return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + }; + d3_rgbPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_rgb(k * this.r, k * this.g, k * this.b); + }; + d3_rgbPrototype.hsl = function() { + return d3_rgb_hsl(this.r, this.g, this.b); + }; + d3_rgbPrototype.toString = function() { + return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + }; + function d3_rgb_hex(v) { + return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); + } + function d3_rgb_parse(format, rgb, hsl) { + var r = 0, g = 0, b = 0, m1, m2, color; + m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); + if (m1) { + m2 = m1[2].split(","); + switch (m1[1]) { + case "hsl": + { + return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); + } + + case "rgb": + { + return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); + } + } + } + if (color = d3_rgb_names.get(format)) { + return rgb(color.r, color.g, color.b); + } + if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { + if (format.length === 4) { + r = (color & 3840) >> 4; + r = r >> 4 | r; + g = color & 240; + g = g >> 4 | g; + b = color & 15; + b = b << 4 | b; + } else if (format.length === 7) { + r = (color & 16711680) >> 16; + g = (color & 65280) >> 8; + b = color & 255; + } + } + return rgb(r, g, b); + } + function d3_rgb_hsl(r, g, b) { + var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; + if (d) { + s = l < .5 ? d / (max + min) : d / (2 - max - min); + if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; + h *= 60; + } else { + h = NaN; + s = l > 0 && l < 1 ? 0 : h; + } + return new d3_hsl(h, s, l); + } + function d3_rgb_lab(r, g, b) { + r = d3_rgb_xyz(r); + g = d3_rgb_xyz(g); + b = d3_rgb_xyz(b); + var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); + return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); + } + function d3_rgb_xyz(r) { + return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); + } + function d3_rgb_parseNumber(c) { + var f = parseFloat(c); + return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; + } + var d3_rgb_names = d3.map({ + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }); + d3_rgb_names.forEach(function(key, value) { + d3_rgb_names.set(key, d3_rgbNumber(value)); + }); + function d3_functor(v) { + return typeof v === "function" ? v : function() { + return v; + }; + } + d3.functor = d3_functor; + d3.xhr = d3_xhrType(d3_identity); + function d3_xhrType(response) { + return function(url, mimeType, callback) { + if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, + mimeType = null; + return d3_xhr(url, mimeType, response, callback); + }; + } + function d3_xhr(url, mimeType, response, callback) { + var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; + if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); + "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { + request.readyState > 3 && respond(); + }; + function respond() { + var status = request.status, result; + if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { + try { + result = response.call(xhr, request); + } catch (e) { + dispatch.error.call(xhr, e); + return; + } + dispatch.load.call(xhr, result); + } else { + dispatch.error.call(xhr, request); + } + } + request.onprogress = function(event) { + var o = d3.event; + d3.event = event; + try { + dispatch.progress.call(xhr, request); + } finally { + d3.event = o; + } + }; + xhr.header = function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers[name]; + if (value == null) delete headers[name]; else headers[name] = value + ""; + return xhr; + }; + xhr.mimeType = function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return xhr; + }; + xhr.responseType = function(value) { + if (!arguments.length) return responseType; + responseType = value; + return xhr; + }; + xhr.response = function(value) { + response = value; + return xhr; + }; + [ "get", "post" ].forEach(function(method) { + xhr[method] = function() { + return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); + }; + }); + xhr.send = function(method, data, callback) { + if (arguments.length === 2 && typeof data === "function") callback = data, data = null; + request.open(method, url, true); + if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; + if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); + if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); + if (responseType != null) request.responseType = responseType; + if (callback != null) xhr.on("error", callback).on("load", function(request) { + callback(null, request); + }); + dispatch.beforesend.call(xhr, request); + request.send(data == null ? null : data); + return xhr; + }; + xhr.abort = function() { + request.abort(); + return xhr; + }; + d3.rebind(xhr, dispatch, "on"); + return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); + } + function d3_xhr_fixCallback(callback) { + return callback.length === 1 ? function(error, request) { + callback(error == null ? request : null); + } : callback; + } + function d3_xhrHasResponse(request) { + var type = request.responseType; + return type && type !== "text" ? request.response : request.responseText; + } + d3.dsv = function(delimiter, mimeType) { + var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); + function dsv(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); + xhr.row = function(_) { + return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; + }; + return xhr; + } + function response(request) { + return dsv.parse(request.responseText); + } + function typedResponse(f) { + return function(request) { + return dsv.parse(request.responseText, f); + }; + } + dsv.parse = function(text, f) { + var o; + return dsv.parseRows(text, function(row, i) { + if (o) return o(row, i - 1); + var a = new Function("d", "return {" + row.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); + o = f ? function(row, i) { + return f(a(row), i); + } : a; + }); + }; + dsv.parseRows = function(text, f) { + var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; + function token() { + if (I >= N) return EOF; + if (eol) return eol = false, EOL; + var j = I; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; + } + } + I = i + 2; + var c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; + } + return text.slice(j + 1, i).replace(/""/g, '"'); + } + while (I < N) { + var c = text.charCodeAt(I++), k = 1; + if (c === 10) eol = true; else if (c === 13) { + eol = true; + if (text.charCodeAt(I) === 10) ++I, ++k; + } else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } + return text.slice(j); + } + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); + } + if (f && (a = f(a, n++)) == null) continue; + rows.push(a); + } + return rows; + }; + dsv.format = function(rows) { + if (Array.isArray(rows[0])) return dsv.formatRows(rows); + var fieldSet = new d3_Set(), fields = []; + rows.forEach(function(row) { + for (var field in row) { + if (!fieldSet.has(field)) { + fields.push(fieldSet.add(field)); + } + } + }); + return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { + return fields.map(function(field) { + return formatValue(row[field]); + }).join(delimiter); + })).join("\n"); + }; + dsv.formatRows = function(rows) { + return rows.map(formatRow).join("\n"); + }; + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + function formatValue(text) { + return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; + } + return dsv; + }; + d3.csv = d3.dsv(",", "text/csv"); + d3.tsv = d3.dsv(" ", "text/tab-separated-values"); + var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { + setTimeout(callback, 17); + }; + d3.timer = function() { + d3_timer.apply(this, arguments); + }; + function d3_timer(callback, delay, then) { + var n = arguments.length; + if (n < 2) delay = 0; + if (n < 3) then = Date.now(); + var time = then + delay, timer = { + c: callback, + t: time, + n: null + }; + if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; + d3_timer_queueTail = timer; + if (!d3_timer_interval) { + d3_timer_timeout = clearTimeout(d3_timer_timeout); + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + return timer; + } + function d3_timer_step() { + var now = d3_timer_mark(), delay = d3_timer_sweep() - now; + if (delay > 24) { + if (isFinite(delay)) { + clearTimeout(d3_timer_timeout); + d3_timer_timeout = setTimeout(d3_timer_step, delay); + } + d3_timer_interval = 0; + } else { + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + } + d3.timer.flush = function() { + d3_timer_mark(); + d3_timer_sweep(); + }; + function d3_timer_mark() { + var now = Date.now(), timer = d3_timer_queueHead; + while (timer) { + if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; + timer = timer.n; + } + return now; + } + function d3_timer_sweep() { + var t0, t1 = d3_timer_queueHead, time = Infinity; + while (t1) { + if (t1.c) { + if (t1.t < time) time = t1.t; + t1 = (t0 = t1).n; + } else { + t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; + } + } + d3_timer_queueTail = t0; + return time; + } + function d3_format_precision(x, p) { + return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); + } + d3.round = function(x, n) { + return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); + }; + var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); + d3.formatPrefix = function(value, precision) { + var i = 0; + if (value = +value) { + if (value < 0) value *= -1; + if (precision) value = d3.round(value, d3_format_precision(value, precision)); + i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); + i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); + } + return d3_formatPrefixes[8 + i / 3]; + }; + function d3_formatPrefix(d, i) { + var k = Math.pow(10, abs(8 - i) * 3); + return { + scale: i > 8 ? function(d) { + return d / k; + } : function(d) { + return d * k; + }, + symbol: d + }; + } + function d3_locale_numberFormat(locale) { + var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { + var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = locale_grouping[j = (j + 1) % locale_grouping.length]; + } + return t.reverse().join(locale_thousands); + } : d3_identity; + return function(specifier) { + var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; + if (precision) precision = +precision.substring(1); + if (zfill || fill === "0" && align === "=") { + zfill = fill = "0"; + align = "="; + } + switch (type) { + case "n": + comma = true; + type = "g"; + break; + + case "%": + scale = 100; + suffix = "%"; + type = "f"; + break; + + case "p": + scale = 100; + suffix = "%"; + type = "r"; + break; + + case "b": + case "o": + case "x": + case "X": + if (symbol === "#") prefix = "0" + type.toLowerCase(); + + case "c": + exponent = false; + + case "d": + integer = true; + precision = 0; + break; + + case "s": + scale = -1; + type = "r"; + break; + } + if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; + if (type == "r" && !precision) type = "g"; + if (precision != null) { + if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); + } + type = d3_format_types.get(type) || d3_format_typeDefault; + var zcomma = zfill && comma; + return function(value) { + var fullSuffix = suffix; + if (integer && value % 1) return ""; + var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; + if (scale < 0) { + var unit = d3.formatPrefix(value, precision); + value = unit.scale(value); + fullSuffix = unit.symbol + suffix; + } else { + value *= scale; + } + value = type(value, precision); + var i = value.lastIndexOf("."), before, after; + if (i < 0) { + var j = exponent ? value.lastIndexOf("e") : -1; + if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); + } else { + before = value.substring(0, i); + after = locale_decimal + value.substring(i + 1); + } + if (!zfill && comma) before = formatGroup(before, Infinity); + var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; + if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); + negative += prefix; + value = before + after; + return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; + }; + }; + } + var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; + var d3_format_types = d3.map({ + b: function(x) { + return x.toString(2); + }, + c: function(x) { + return String.fromCharCode(x); + }, + o: function(x) { + return x.toString(8); + }, + x: function(x) { + return x.toString(16); + }, + X: function(x) { + return x.toString(16).toUpperCase(); + }, + g: function(x, p) { + return x.toPrecision(p); + }, + e: function(x, p) { + return x.toExponential(p); + }, + f: function(x, p) { + return x.toFixed(p); + }, + r: function(x, p) { + return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); + } + }); + function d3_format_typeDefault(x) { + return x + ""; + } + var d3_time = d3.time = {}, d3_date = Date; + function d3_date_utc() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); + } + d3_date_utc.prototype = { + getDate: function() { + return this._.getUTCDate(); + }, + getDay: function() { + return this._.getUTCDay(); + }, + getFullYear: function() { + return this._.getUTCFullYear(); + }, + getHours: function() { + return this._.getUTCHours(); + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds(); + }, + getMinutes: function() { + return this._.getUTCMinutes(); + }, + getMonth: function() { + return this._.getUTCMonth(); + }, + getSeconds: function() { + return this._.getUTCSeconds(); + }, + getTime: function() { + return this._.getTime(); + }, + getTimezoneOffset: function() { + return 0; + }, + valueOf: function() { + return this._.valueOf(); + }, + setDate: function() { + d3_time_prototype.setUTCDate.apply(this._, arguments); + }, + setDay: function() { + d3_time_prototype.setUTCDay.apply(this._, arguments); + }, + setFullYear: function() { + d3_time_prototype.setUTCFullYear.apply(this._, arguments); + }, + setHours: function() { + d3_time_prototype.setUTCHours.apply(this._, arguments); + }, + setMilliseconds: function() { + d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); + }, + setMinutes: function() { + d3_time_prototype.setUTCMinutes.apply(this._, arguments); + }, + setMonth: function() { + d3_time_prototype.setUTCMonth.apply(this._, arguments); + }, + setSeconds: function() { + d3_time_prototype.setUTCSeconds.apply(this._, arguments); + }, + setTime: function() { + d3_time_prototype.setTime.apply(this._, arguments); + } + }; + var d3_time_prototype = Date.prototype; + function d3_time_interval(local, step, number) { + function round(date) { + var d0 = local(date), d1 = offset(d0, 1); + return date - d0 < d1 - date ? d0 : d1; + } + function ceil(date) { + step(date = local(new d3_date(date - 1)), 1); + return date; + } + function offset(date, k) { + step(date = new d3_date(+date), k); + return date; + } + function range(t0, t1, dt) { + var time = ceil(t0), times = []; + if (dt > 1) { + while (time < t1) { + if (!(number(time) % dt)) times.push(new Date(+time)); + step(time, 1); + } + } else { + while (time < t1) times.push(new Date(+time)), step(time, 1); + } + return times; + } + function range_utc(t0, t1, dt) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = t0; + return range(utc, t1, dt); + } finally { + d3_date = Date; + } + } + local.floor = local; + local.round = round; + local.ceil = ceil; + local.offset = offset; + local.range = range; + var utc = local.utc = d3_time_interval_utc(local); + utc.floor = utc; + utc.round = d3_time_interval_utc(round); + utc.ceil = d3_time_interval_utc(ceil); + utc.offset = d3_time_interval_utc(offset); + utc.range = range_utc; + return local; + } + function d3_time_interval_utc(method) { + return function(date, k) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = date; + return method(utc, k)._; + } finally { + d3_date = Date; + } + }; + } + d3_time.year = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setMonth(0, 1); + return date; + }, function(date, offset) { + date.setFullYear(date.getFullYear() + offset); + }, function(date) { + return date.getFullYear(); + }); + d3_time.years = d3_time.year.range; + d3_time.years.utc = d3_time.year.utc.range; + d3_time.day = d3_time_interval(function(date) { + var day = new d3_date(2e3, 0); + day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + return day; + }, function(date, offset) { + date.setDate(date.getDate() + offset); + }, function(date) { + return date.getDate() - 1; + }); + d3_time.days = d3_time.day.range; + d3_time.days.utc = d3_time.day.utc.range; + d3_time.dayOfYear = function(date) { + var year = d3_time.year(date); + return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); + }; + [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { + i = 7 - i; + var interval = d3_time[day] = d3_time_interval(function(date) { + (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); + return date; + }, function(date, offset) { + date.setDate(date.getDate() + Math.floor(offset) * 7); + }, function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); + }); + d3_time[day + "s"] = interval.range; + d3_time[day + "s"].utc = interval.utc.range; + d3_time[day + "OfYear"] = function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); + }; + }); + d3_time.week = d3_time.sunday; + d3_time.weeks = d3_time.sunday.range; + d3_time.weeks.utc = d3_time.sunday.utc.range; + d3_time.weekOfYear = d3_time.sundayOfYear; + function d3_locale_timeFormat(locale) { + var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; + function d3_time_format(template) { + var n = template.length; + function format(date) { + var string = [], i = -1, j = 0, c, p, f; + while (++i < n) { + if (template.charCodeAt(i) === 37) { + string.push(template.slice(j, i)); + if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); + if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); + string.push(c); + j = i + 1; + } + } + string.push(template.slice(j, i)); + return string.join(""); + } + format.parse = function(string) { + var d = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0, + Z: null + }, i = d3_time_parse(d, template, string, 0); + if (i != string.length) return null; + if ("p" in d) d.H = d.H % 12 + d.p * 12; + var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); + if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + date.setFullYear(d.y, 0, 1); + date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); + } else date.setFullYear(d.y, d.m, d.d); + date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); + return localZ ? date._ : date; + }; + format.toString = function() { + return template; + }; + return format; + } + function d3_time_parse(date, template, string, j) { + var c, p, t, i = 0, n = template.length, m = string.length; + while (i < n) { + if (j >= m) return -1; + c = template.charCodeAt(i++); + if (c === 37) { + t = template.charAt(i++); + p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; + if (!p || (j = p(date, string, j)) < 0) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + return j; + } + d3_time_format.utc = function(template) { + var local = d3_time_format(template); + function format(date) { + try { + d3_date = d3_date_utc; + var utc = new d3_date(); + utc._ = date; + return local(utc); + } finally { + d3_date = Date; + } + } + format.parse = function(string) { + try { + d3_date = d3_date_utc; + var date = local.parse(string); + return date && date._; + } finally { + d3_date = Date; + } + }; + format.toString = local.toString; + return format; + }; + d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; + var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); + locale_periods.forEach(function(p, i) { + d3_time_periodLookup.set(p.toLowerCase(), i); + }); + var d3_time_formats = { + a: function(d) { + return locale_shortDays[d.getDay()]; + }, + A: function(d) { + return locale_days[d.getDay()]; + }, + b: function(d) { + return locale_shortMonths[d.getMonth()]; + }, + B: function(d) { + return locale_months[d.getMonth()]; + }, + c: d3_time_format(locale_dateTime), + d: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + e: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + H: function(d, p) { + return d3_time_formatPad(d.getHours(), p, 2); + }, + I: function(d, p) { + return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); + }, + j: function(d, p) { + return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); + }, + L: function(d, p) { + return d3_time_formatPad(d.getMilliseconds(), p, 3); + }, + m: function(d, p) { + return d3_time_formatPad(d.getMonth() + 1, p, 2); + }, + M: function(d, p) { + return d3_time_formatPad(d.getMinutes(), p, 2); + }, + p: function(d) { + return locale_periods[+(d.getHours() >= 12)]; + }, + S: function(d, p) { + return d3_time_formatPad(d.getSeconds(), p, 2); + }, + U: function(d, p) { + return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); + }, + w: function(d) { + return d.getDay(); + }, + W: function(d, p) { + return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); + }, + x: d3_time_format(locale_date), + X: d3_time_format(locale_time), + y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 100, p, 2); + }, + Y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); + }, + Z: d3_time_zone, + "%": function() { + return "%"; + } + }; + var d3_time_parsers = { + a: d3_time_parseWeekdayAbbrev, + A: d3_time_parseWeekday, + b: d3_time_parseMonthAbbrev, + B: d3_time_parseMonth, + c: d3_time_parseLocaleFull, + d: d3_time_parseDay, + e: d3_time_parseDay, + H: d3_time_parseHour24, + I: d3_time_parseHour24, + j: d3_time_parseDayOfYear, + L: d3_time_parseMilliseconds, + m: d3_time_parseMonthNumber, + M: d3_time_parseMinutes, + p: d3_time_parseAmPm, + S: d3_time_parseSeconds, + U: d3_time_parseWeekNumberSunday, + w: d3_time_parseWeekdayNumber, + W: d3_time_parseWeekNumberMonday, + x: d3_time_parseLocaleDate, + X: d3_time_parseLocaleTime, + y: d3_time_parseYear, + Y: d3_time_parseFullYear, + Z: d3_time_parseZone, + "%": d3_time_parseLiteralPercent + }; + function d3_time_parseWeekdayAbbrev(date, string, i) { + d3_time_dayAbbrevRe.lastIndex = 0; + var n = d3_time_dayAbbrevRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseWeekday(date, string, i) { + d3_time_dayRe.lastIndex = 0; + var n = d3_time_dayRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonthAbbrev(date, string, i) { + d3_time_monthAbbrevRe.lastIndex = 0; + var n = d3_time_monthAbbrevRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonth(date, string, i) { + d3_time_monthRe.lastIndex = 0; + var n = d3_time_monthRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseLocaleFull(date, string, i) { + return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + } + function d3_time_parseLocaleDate(date, string, i) { + return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + } + function d3_time_parseLocaleTime(date, string, i) { + return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + } + function d3_time_parseAmPm(date, string, i) { + var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); + return n == null ? -1 : (date.p = n, i); + } + return d3_time_format; + } + var d3_time_formatPads = { + "-": "", + _: " ", + "0": "0" + }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; + function d3_time_formatPad(value, fill, width) { + var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); + } + function d3_time_formatRe(names) { + return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); + } + function d3_time_formatLookup(names) { + var map = new d3_Map(), i = -1, n = names.length; + while (++i < n) map.set(names[i].toLowerCase(), i); + return map; + } + function d3_time_parseWeekdayNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 1)); + return n ? (date.w = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberSunday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.U = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberMonday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.W = +n[0], i + n[0].length) : -1; + } + function d3_time_parseFullYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 4)); + return n ? (date.y = +n[0], i + n[0].length) : -1; + } + function d3_time_parseYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; + } + function d3_time_parseZone(date, string, i) { + return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, + i + 5) : -1; + } + function d3_time_expandYear(d) { + return d + (d > 68 ? 1900 : 2e3); + } + function d3_time_parseMonthNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.m = n[0] - 1, i + n[0].length) : -1; + } + function d3_time_parseDay(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.d = +n[0], i + n[0].length) : -1; + } + function d3_time_parseDayOfYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.j = +n[0], i + n[0].length) : -1; + } + function d3_time_parseHour24(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.H = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMinutes(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.M = +n[0], i + n[0].length) : -1; + } + function d3_time_parseSeconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.S = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMilliseconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.L = +n[0], i + n[0].length) : -1; + } + function d3_time_zone(d) { + var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; + return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + } + function d3_time_parseLiteralPercent(date, string, i) { + d3_time_percentRe.lastIndex = 0; + var n = d3_time_percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; + } + function d3_time_formatMulti(formats) { + var n = formats.length, i = -1; + while (++i < n) formats[i][0] = this(formats[i][0]); + return function(date) { + var i = 0, f = formats[i]; + while (!f[1](date)) f = formats[++i]; + return f[0](date); + }; + } + d3.locale = function(locale) { + return { + numberFormat: d3_locale_numberFormat(locale), + timeFormat: d3_locale_timeFormat(locale) + }; + }; + var d3_locale_enUS = d3.locale({ + decimal: ".", + thousands: ",", + grouping: [ 3 ], + currency: [ "$", "" ], + dateTime: "%a %b %e %X %Y", + date: "%m/%d/%Y", + time: "%H:%M:%S", + periods: [ "AM", "PM" ], + days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], + shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] + }); + d3.format = d3_locale_enUS.numberFormat; + d3.geo = {}; + function d3_adder() {} + d3_adder.prototype = { + s: 0, + t: 0, + add: function(y) { + d3_adderSum(y, this.t, d3_adderTemp); + d3_adderSum(d3_adderTemp.s, this.s, this); + if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; + }, + reset: function() { + this.s = this.t = 0; + }, + valueOf: function() { + return this.s; + } + }; + var d3_adderTemp = new d3_adder(); + function d3_adderSum(a, b, o) { + var x = o.s = a + b, bv = x - a, av = x - bv; + o.t = a - av + (b - bv); + } + d3.geo.stream = function(object, listener) { + if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { + d3_geo_streamObjectType[object.type](object, listener); + } else { + d3_geo_streamGeometry(object, listener); + } + }; + function d3_geo_streamGeometry(geometry, listener) { + if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { + d3_geo_streamGeometryType[geometry.type](geometry, listener); + } + } + var d3_geo_streamObjectType = { + Feature: function(feature, listener) { + d3_geo_streamGeometry(feature.geometry, listener); + }, + FeatureCollection: function(object, listener) { + var features = object.features, i = -1, n = features.length; + while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); + } + }; + var d3_geo_streamGeometryType = { + Sphere: function(object, listener) { + listener.sphere(); + }, + Point: function(object, listener) { + object = object.coordinates; + listener.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); + }, + LineString: function(object, listener) { + d3_geo_streamLine(object.coordinates, listener, 0); + }, + MultiLineString: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); + }, + Polygon: function(object, listener) { + d3_geo_streamPolygon(object.coordinates, listener); + }, + MultiPolygon: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); + }, + GeometryCollection: function(object, listener) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + } + }; + function d3_geo_streamLine(coordinates, listener, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + listener.lineStart(); + while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); + listener.lineEnd(); + } + function d3_geo_streamPolygon(coordinates, listener) { + var i = -1, n = coordinates.length; + listener.polygonStart(); + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); + listener.polygonEnd(); + } + d3.geo.area = function(object) { + d3_geo_areaSum = 0; + d3.geo.stream(object, d3_geo_area); + return d3_geo_areaSum; + }; + var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); + var d3_geo_area = { + sphere: function() { + d3_geo_areaSum += 4 * π; + }, + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_areaRingSum.reset(); + d3_geo_area.lineStart = d3_geo_areaRingStart; + }, + polygonEnd: function() { + var area = 2 * d3_geo_areaRingSum; + d3_geo_areaSum += area < 0 ? 4 * π + area : area; + d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; + } + }; + function d3_geo_areaRingStart() { + var λ00, φ00, λ0, cosφ0, sinφ0; + d3_geo_area.point = function(λ, φ) { + d3_geo_area.point = nextPoint; + λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), + sinφ0 = Math.sin(φ); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + φ = φ * d3_radians / 2 + π / 4; + var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); + d3_geo_areaRingSum.add(Math.atan2(v, u)); + λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; + } + d3_geo_area.lineEnd = function() { + nextPoint(λ00, φ00); + }; + } + function d3_geo_cartesian(spherical) { + var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); + return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; + } + function d3_geo_cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + function d3_geo_cartesianCross(a, b) { + return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; + } + function d3_geo_cartesianAdd(a, b) { + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; + } + function d3_geo_cartesianScale(vector, k) { + return [ vector[0] * k, vector[1] * k, vector[2] * k ]; + } + function d3_geo_cartesianNormalize(d) { + var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l; + d[1] /= l; + d[2] /= l; + } + function d3_geo_spherical(cartesian) { + return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; + } + function d3_geo_sphericalEqual(a, b) { + return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + } + d3.geo.bounds = function() { + var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; + var bound = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + bound.point = ringPoint; + bound.lineStart = ringStart; + bound.lineEnd = ringEnd; + dλSum = 0; + d3_geo_area.polygonStart(); + }, + polygonEnd: function() { + d3_geo_area.polygonEnd(); + bound.point = point; + bound.lineStart = lineStart; + bound.lineEnd = lineEnd; + if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; + range[0] = λ0, range[1] = λ1; + } + }; + function point(λ, φ) { + ranges.push(range = [ λ0 = λ, λ1 = λ ]); + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + function linePoint(λ, φ) { + var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); + if (p0) { + var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); + d3_geo_cartesianNormalize(inflection); + inflection = d3_geo_spherical(inflection); + var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; + if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = inflection[1] * d3_degrees; + if (φi > φ1) φ1 = φi; + } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = -inflection[1] * d3_degrees; + if (φi < φ0) φ0 = φi; + } else { + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + if (antimeridian) { + if (λ < λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } else { + if (λ1 >= λ0) { + if (λ < λ0) λ0 = λ; + if (λ > λ1) λ1 = λ; + } else { + if (λ > λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } + } + } else { + point(λ, φ); + } + p0 = p, λ_ = λ; + } + function lineStart() { + bound.point = linePoint; + } + function lineEnd() { + range[0] = λ0, range[1] = λ1; + bound.point = point; + p0 = null; + } + function ringPoint(λ, φ) { + if (p0) { + var dλ = λ - λ_; + dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; + } else λ__ = λ, φ__ = φ; + d3_geo_area.point(λ, φ); + linePoint(λ, φ); + } + function ringStart() { + d3_geo_area.lineStart(); + } + function ringEnd() { + ringPoint(λ__, φ__); + d3_geo_area.lineEnd(); + if (abs(dλSum) > ε) λ0 = -(λ1 = 180); + range[0] = λ0, range[1] = λ1; + p0 = null; + } + function angle(λ0, λ1) { + return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + } + function compareRanges(a, b) { + return a[0] - b[0]; + } + function withinRange(x, range) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + return function(feature) { + φ1 = λ1 = -(λ0 = φ0 = Infinity); + ranges = []; + d3.geo.stream(feature, bound); + var n = ranges.length; + if (n) { + ranges.sort(compareRanges); + for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { + b = ranges[i]; + if (withinRange(b[0], a) || withinRange(b[1], a)) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + var best = -Infinity, dλ; + for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { + b = merged[i]; + if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + } + } + ranges = range = null; + return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }; + }(); + d3.geo.centroid = function(object) { + d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, d3_geo_centroid); + var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; + if (m < ε2) { + x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; + if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; + m = x * x + y * y + z * z; + if (m < ε2) return [ NaN, NaN ]; + } + return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; + }; + var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; + var d3_geo_centroid = { + sphere: d3_noop, + point: d3_geo_centroidPoint, + lineStart: d3_geo_centroidLineStart, + lineEnd: d3_geo_centroidLineEnd, + polygonStart: function() { + d3_geo_centroid.lineStart = d3_geo_centroidRingStart; + }, + polygonEnd: function() { + d3_geo_centroid.lineStart = d3_geo_centroidLineStart; + } + }; + function d3_geo_centroidPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); + } + function d3_geo_centroidPointXYZ(x, y, z) { + ++d3_geo_centroidW0; + d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; + d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; + d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; + } + function d3_geo_centroidLineStart() { + var x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroid.point = nextPoint; + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_centroidLineEnd() { + d3_geo_centroid.point = d3_geo_centroidPoint; + } + function d3_geo_centroidRingStart() { + var λ00, φ00, x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ00 = λ, φ00 = φ; + d3_geo_centroid.point = nextPoint; + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + d3_geo_centroid.lineEnd = function() { + nextPoint(λ00, φ00); + d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; + d3_geo_centroid.point = d3_geo_centroidPoint; + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); + d3_geo_centroidX2 += v * cx; + d3_geo_centroidY2 += v * cy; + d3_geo_centroidZ2 += v * cz; + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_compose(a, b) { + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + return compose; + } + function d3_true() { + return true; + } + function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { + var subject = [], clip = []; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n]; + if (d3_geo_sphericalEqual(p0, p1)) { + listener.lineStart(); + for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); + listener.lineEnd(); + return; + } + var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); + a.o = b; + subject.push(a); + clip.push(b); + a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); + b = new d3_geo_clipPolygonIntersection(p1, null, a, true); + a.o = b; + subject.push(a); + clip.push(b); + }); + clip.sort(compare); + d3_geo_clipPolygonLinkCircular(subject); + d3_geo_clipPolygonLinkCircular(clip); + if (!subject.length) return; + for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { + clip[i].e = entry = !entry; + } + var start = subject[0], points, point; + while (1) { + var current = start, isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + listener.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, listener); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, listener); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + listener.lineEnd(); + } + } + function d3_geo_clipPolygonLinkCircular(array) { + if (!(n = array.length)) return; + var n, i = 0, a = array[0], b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; + } + function d3_geo_clipPolygonIntersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; + this.e = entry; + this.v = false; + this.n = this.p = null; + } + function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { + return function(rotate, listener) { + var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3.merge(segments); + var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); + if (segments.length) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); + } else if (clipStartInside) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (polygonStarted) listener.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + listener.polygonStart(); + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + listener.polygonEnd(); + } + }; + function point(λ, φ) { + var point = rotate(λ, φ); + if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); + } + function pointLine(λ, φ) { + var point = rotate(λ, φ); + line.point(point[0], point[1]); + } + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + var segments; + var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; + function pointRing(λ, φ) { + ring.push([ λ, φ ]); + var point = rotate(λ, φ); + ringListener.point(point[0], point[1]); + } + function ringStart() { + ringListener.lineStart(); + ring = []; + } + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringListener.lineEnd(); + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; + ring.pop(); + polygon.push(ring); + ring = null; + if (!n) return; + if (clean & 1) { + segment = ringSegments[0]; + var n = segment.length - 1, i = -1, point; + if (n > 0) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + while (++i < n) listener.point((point = segment[i])[0], point[1]); + listener.lineEnd(); + } + return; + } + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + } + return clip; + }; + } + function d3_geo_clipSegmentLength1(segment) { + return segment.length > 1; + } + function d3_geo_clipBufferListener() { + var lines = [], line; + return { + lineStart: function() { + lines.push(line = []); + }, + point: function(λ, φ) { + line.push([ λ, φ ]); + }, + lineEnd: d3_noop, + buffer: function() { + var buffer = lines; + lines = []; + line = null; + return buffer; + }, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + } + }; + } + function d3_geo_clipSort(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); + } + var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); + function d3_geo_clipAntimeridianLine(listener) { + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; + return { + lineStart: function() { + listener.lineStart(); + clean = 1; + }, + point: function(λ1, φ1) { + var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); + if (abs(dλ - π) < ε) { + listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + listener.point(λ1, φ0); + clean = 0; + } else if (sλ0 !== sλ1 && dλ >= π) { + if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; + if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; + φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + clean = 0; + } + listener.point(λ0 = λ1, φ0 = φ1); + sλ0 = sλ1; + }, + lineEnd: function() { + listener.lineEnd(); + λ0 = φ0 = NaN; + }, + clean: function() { + return 2 - clean; + } + }; + } + function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { + var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); + return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; + } + function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { + var φ; + if (from == null) { + φ = direction * halfπ; + listener.point(-π, φ); + listener.point(0, φ); + listener.point(π, φ); + listener.point(π, 0); + listener.point(π, -φ); + listener.point(0, -φ); + listener.point(-π, -φ); + listener.point(-π, 0); + listener.point(-π, φ); + } else if (abs(from[0] - to[0]) > ε) { + var s = from[0] < to[0] ? π : -π; + φ = direction * s / 2; + listener.point(-s, φ); + listener.point(0, φ); + listener.point(s, φ); + } else { + listener.point(to[0], to[1]); + } + } + function d3_geo_pointInPolygon(point, polygon) { + var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; + d3_geo_areaRingSum.reset(); + for (var i = 0, n = polygon.length; i < n; ++i) { + var ring = polygon[i], m = ring.length; + if (!m) continue; + var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; + while (true) { + if (j === m) j = 0; + point = ring[j]; + var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; + d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); + polarAngle += antimeridian ? dλ + sdλ * τ : dλ; + if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { + var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); + d3_geo_cartesianNormalize(arc); + var intersection = d3_geo_cartesianCross(meridianNormal, arc); + d3_geo_cartesianNormalize(intersection); + var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); + if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { + winding += antimeridian ^ dλ >= 0 ? 1 : -1; + } + } + if (!j++) break; + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; + } + } + return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; + } + function d3_geo_clipCircle(radius) { + var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); + return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); + function visible(λ, φ) { + return Math.cos(λ) * Math.cos(φ) > cr; + } + function clipLine(listener) { + var point0, c0, v0, v00, clean; + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(λ, φ) { + var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; + if (!point0 && (v00 = v0 = v)) listener.lineStart(); + if (v !== v0) { + point2 = intersect(point0, point1); + if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { + point1[0] += ε; + point1[1] += ε; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + listener.lineStart(); + point2 = intersect(point1, point0); + listener.point(point2[0], point2[1]); + } else { + point2 = intersect(point0, point1); + listener.point(point2[0], point2[1]); + listener.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + } else { + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { + listener.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) listener.lineEnd(); + point0 = null; + }, + clean: function() { + return clean | (v00 && v0) << 1; + } + }; + } + function intersect(a, b, two) { + var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); + var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; + if (!determinant) return !two && a; + var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); + d3_geo_cartesianAdd(A, B); + var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); + if (t2 < 0) return; + var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); + d3_geo_cartesianAdd(q, A); + q = d3_geo_spherical(q); + if (!two) return q; + var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; + if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; + var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; + if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; + if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { + var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); + d3_geo_cartesianAdd(q1, A); + return [ q, d3_geo_spherical(q1) ]; + } + } + function code(λ, φ) { + var r = smallRadius ? radius : π - radius, code = 0; + if (λ < -r) code |= 1; else if (λ > r) code |= 2; + if (φ < -r) code |= 4; else if (φ > r) code |= 8; + return code; + } + } + function d3_geom_clipLine(x0, y0, x1, y1) { + return function(line) { + var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + if (t0 > 0) line.a = { + x: ax + t0 * dx, + y: ay + t0 * dy + }; + if (t1 < 1) line.b = { + x: ax + t1 * dx, + y: ay + t1 * dy + }; + return line; + }; + } + var d3_geo_clipExtentMAX = 1e9; + d3.geo.clipExtent = function() { + var x0, y0, x1, y1, stream, clip, clipExtent = { + stream: function(output) { + if (stream) stream.valid = false; + stream = clip(output); + stream.valid = true; + return stream; + }, + extent: function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); + if (stream) stream.valid = false, stream = null; + return clipExtent; + } + }; + return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); + }; + function d3_geo_clipExtent(x0, y0, x1, y1) { + return function(listener) { + var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + listener = bufferListener; + segments = []; + polygon = []; + clean = true; + }, + polygonEnd: function() { + listener = listener_; + segments = d3.merge(segments); + var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; + if (inside || visible) { + listener.polygonStart(); + if (inside) { + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (visible) { + d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + } + listener.polygonEnd(); + } + segments = polygon = ring = null; + } + }; + function insidePolygon(p) { + var wn = 0, n = polygon.length, y = p[1]; + for (var i = 0; i < n; ++i) { + for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { + b = v[j]; + if (a[1] <= y) { + if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; + } else { + if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; + } + a = b; + } + } + return wn !== 0; + } + function interpolate(from, to, direction, listener) { + var a = 0, a1 = 0; + if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { + do { + listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + } while ((a = (a + direction + 4) % 4) !== a1); + } else { + listener.point(to[0], to[1]); + } + } + function pointVisible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + function point(x, y) { + if (pointVisible(x, y)) listener.point(x, y); + } + var x__, y__, v__, x_, y_, v_, first, clean; + function lineStart() { + clip.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferListener.rejoin(); + segments.push(bufferListener.buffer()); + } + clip.point = point; + if (v_) listener.lineEnd(); + } + function linePoint(x, y) { + x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); + y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); + var v = pointVisible(x, y); + if (polygon) ring.push([ x, y ]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + listener.lineStart(); + listener.point(x, y); + } + } else { + if (v && v_) listener.point(x, y); else { + var l = { + a: { + x: x_, + y: y_ + }, + b: { + x: x, + y: y + } + }; + if (clipLine(l)) { + if (!v_) { + listener.lineStart(); + listener.point(l.a.x, l.a.y); + } + listener.point(l.b.x, l.b.y); + if (!v) listener.lineEnd(); + clean = false; + } else if (v) { + listener.lineStart(); + listener.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + return clip; + }; + function corner(p, direction) { + return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; + } + function compare(a, b) { + return comparePoints(a.x, b.x); + } + function comparePoints(a, b) { + var ca = corner(a, 1), cb = corner(b, 1); + return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; + } + } + function d3_geo_conic(projectAt) { + var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); + p.parallels = function(_) { + if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; + return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); + }; + return p; + } + function d3_geo_conicEqualArea(φ0, φ1) { + var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; + function forward(λ, φ) { + var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; + return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = ρ0 - y; + return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; + }; + return forward; + } + (d3.geo.conicEqualArea = function() { + return d3_geo_conic(d3_geo_conicEqualArea); + }).raw = d3_geo_conicEqualArea; + d3.geo.albers = function() { + return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); + }; + d3.geo.albersUsa = function() { + var lower48 = d3.geo.albers(); + var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); + var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); + var point, pointStream = { + point: function(x, y) { + point = [ x, y ]; + } + }, lower48Point, alaskaPoint, hawaiiPoint; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + point = null; + (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); + return point; + } + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; + return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); + }; + albersUsa.stream = function(stream) { + var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); + return { + point: function(x, y) { + lower48Stream.point(x, y); + alaskaStream.point(x, y); + hawaiiStream.point(x, y); + }, + sphere: function() { + lower48Stream.sphere(); + alaskaStream.sphere(); + hawaiiStream.sphere(); + }, + lineStart: function() { + lower48Stream.lineStart(); + alaskaStream.lineStart(); + hawaiiStream.lineStart(); + }, + lineEnd: function() { + lower48Stream.lineEnd(); + alaskaStream.lineEnd(); + hawaiiStream.lineEnd(); + }, + polygonStart: function() { + lower48Stream.polygonStart(); + alaskaStream.polygonStart(); + hawaiiStream.polygonStart(); + }, + polygonEnd: function() { + lower48Stream.polygonEnd(); + alaskaStream.polygonEnd(); + hawaiiStream.polygonEnd(); + } + }; + }; + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + return albersUsa; + }; + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * .35); + hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; + alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + return albersUsa; + }; + return albersUsa.scale(1070); + }; + var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_pathAreaPolygon = 0; + d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; + }, + polygonEnd: function() { + d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; + d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); + } + }; + function d3_geo_pathAreaRingStart() { + var x00, y00, x0, y0; + d3_geo_pathArea.point = function(x, y) { + d3_geo_pathArea.point = nextPoint; + x00 = x0 = x, y00 = y0 = y; + }; + function nextPoint(x, y) { + d3_geo_pathAreaPolygon += y0 * x - x0 * y; + x0 = x, y0 = y; + } + d3_geo_pathArea.lineEnd = function() { + nextPoint(x00, y00); + }; + } + var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; + var d3_geo_pathBounds = { + point: d3_geo_pathBoundsPoint, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_pathBoundsPoint(x, y) { + if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; + if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; + if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; + if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; + } + function d3_geo_pathBuffer() { + var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointCircle = d3_geo_pathBufferCircle(_); + return stream; + }, + result: function() { + if (buffer.length) { + var result = buffer.join(""); + buffer = []; + return result; + } + } + }; + function point(x, y) { + buffer.push("M", x, ",", y, pointCircle); + } + function pointLineStart(x, y) { + buffer.push("M", x, ",", y); + stream.point = pointLine; + } + function pointLine(x, y) { + buffer.push("L", x, ",", y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + buffer.push("Z"); + } + return stream; + } + function d3_geo_pathBufferCircle(radius) { + return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; + } + var d3_geo_pathCentroid = { + point: d3_geo_pathCentroidPoint, + lineStart: d3_geo_pathCentroidLineStart, + lineEnd: d3_geo_pathCentroidLineEnd, + polygonStart: function() { + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; + }, + polygonEnd: function() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; + d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; + } + }; + function d3_geo_pathCentroidPoint(x, y) { + d3_geo_centroidX0 += x; + d3_geo_centroidY0 += y; + ++d3_geo_centroidZ0; + } + function d3_geo_pathCentroidLineStart() { + var x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + } + function d3_geo_pathCentroidLineEnd() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + } + function d3_geo_pathCentroidRingStart() { + var x00, y00, x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + z = y0 * x - x0 * y; + d3_geo_centroidX2 += z * (x0 + x); + d3_geo_centroidY2 += z * (y0 + y); + d3_geo_centroidZ2 += z * 3; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + d3_geo_pathCentroid.lineEnd = function() { + nextPoint(x00, y00); + }; + } + function d3_geo_pathContext(context) { + var pointRadius = 4.5; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointRadius = _; + return stream; + }, + result: d3_noop + }; + function point(x, y) { + context.moveTo(x + pointRadius, y); + context.arc(x, y, pointRadius, 0, τ); + } + function pointLineStart(x, y) { + context.moveTo(x, y); + stream.point = pointLine; + } + function pointLine(x, y) { + context.lineTo(x, y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + context.closePath(); + } + return stream; + } + function d3_geo_resample(project) { + var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; + function resample(stream) { + return (maxDepth ? resampleRecursive : resampleNone)(stream); + } + function resampleNone(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + }); + } + function resampleRecursive(stream) { + var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; + var resample = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + stream.polygonStart(); + resample.lineStart = ringStart; + }, + polygonEnd: function() { + stream.polygonEnd(); + resample.lineStart = lineStart; + } + }; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + function lineStart() { + x0 = NaN; + resample.point = linePoint; + stream.lineStart(); + } + function linePoint(λ, φ) { + var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); + resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + function lineEnd() { + resample.point = point; + stream.lineEnd(); + } + function ringStart() { + lineStart(); + resample.point = ringPoint; + resample.lineEnd = ringEnd; + } + function ringPoint(λ, φ) { + linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resample.point = linePoint; + } + function ringEnd() { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); + resample.lineEnd = lineEnd; + lineEnd(); + } + return resample; + } + function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; + if (d2 > 4 * δ2 && depth--) { + var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); + } + } + } + resample.precision = function(_) { + if (!arguments.length) return Math.sqrt(δ2); + maxDepth = (δ2 = _ * _) > 0 && 16; + return resample; + }; + return resample; + } + d3.geo.path = function() { + var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); + d3.geo.stream(object, cacheStream); + } + return contextStream.result(); + } + path.area = function(object) { + d3_geo_pathAreaSum = 0; + d3.geo.stream(object, projectStream(d3_geo_pathArea)); + return d3_geo_pathAreaSum; + }; + path.centroid = function(object) { + d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); + return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; + }; + path.bounds = function(object) { + d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); + d3.geo.stream(object, projectStream(d3_geo_pathBounds)); + return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; + }; + path.projection = function(_) { + if (!arguments.length) return projection; + projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; + return reset(); + }; + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return reset(); + }; + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + function reset() { + cacheStream = null; + return path; + } + return path.projection(d3.geo.albersUsa()).context(null); + }; + function d3_geo_pathProjectStream(project) { + var resample = d3_geo_resample(function(x, y) { + return project([ x * d3_degrees, y * d3_degrees ]); + }); + return function(stream) { + return d3_geo_projectionRadians(resample(stream)); + }; + } + d3.geo.transform = function(methods) { + return { + stream: function(stream) { + var transform = new d3_geo_transform(stream); + for (var k in methods) transform[k] = methods[k]; + return transform; + } + }; + }; + function d3_geo_transform(stream) { + this.stream = stream; + } + d3_geo_transform.prototype = { + point: function(x, y) { + this.stream.point(x, y); + }, + sphere: function() { + this.stream.sphere(); + }, + lineStart: function() { + this.stream.lineStart(); + }, + lineEnd: function() { + this.stream.lineEnd(); + }, + polygonStart: function() { + this.stream.polygonStart(); + }, + polygonEnd: function() { + this.stream.polygonEnd(); + } + }; + function d3_geo_transformPoint(stream, point) { + return { + point: point, + sphere: function() { + stream.sphere(); + }, + lineStart: function() { + stream.lineStart(); + }, + lineEnd: function() { + stream.lineEnd(); + }, + polygonStart: function() { + stream.polygonStart(); + }, + polygonEnd: function() { + stream.polygonEnd(); + } + }; + } + d3.geo.projection = d3_geo_projection; + d3.geo.projectionMutator = d3_geo_projectionMutator; + function d3_geo_projection(project) { + return d3_geo_projectionMutator(function() { + return project; + })(); + } + function d3_geo_projectionMutator(projectAt) { + var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { + x = project(x, y); + return [ x[0] * k + δx, δy - x[1] * k ]; + }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; + function projection(point) { + point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); + return [ point[0] * k + δx, δy - point[1] * k ]; + } + function invert(point) { + point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); + return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; + } + projection.stream = function(output) { + if (stream) stream.valid = false; + stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); + stream.valid = true; + return stream; + }; + projection.clipAngle = function(_) { + if (!arguments.length) return clipAngle; + preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); + return invalidate(); + }; + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; + return invalidate(); + }; + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return reset(); + }; + projection.translate = function(_) { + if (!arguments.length) return [ x, y ]; + x = +_[0]; + y = +_[1]; + return reset(); + }; + projection.center = function(_) { + if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; + λ = _[0] % 360 * d3_radians; + φ = _[1] % 360 * d3_radians; + return reset(); + }; + projection.rotate = function(_) { + if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; + δλ = _[0] % 360 * d3_radians; + δφ = _[1] % 360 * d3_radians; + δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; + return reset(); + }; + d3.rebind(projection, projectResample, "precision"); + function reset() { + projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); + var center = project(λ, φ); + δx = x - center[0] * k; + δy = y + center[1] * k; + return invalidate(); + } + function invalidate() { + if (stream) stream.valid = false, stream = null; + return projection; + } + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return reset(); + }; + } + function d3_geo_projectionRadians(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + stream.point(x * d3_radians, y * d3_radians); + }); + } + function d3_geo_equirectangular(λ, φ) { + return [ λ, φ ]; + } + (d3.geo.equirectangular = function() { + return d3_geo_projection(d3_geo_equirectangular); + }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; + d3.geo.rotation = function(rotate) { + rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); + function forward(coordinates) { + coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + } + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + }; + return forward; + }; + function d3_geo_identityRotation(λ, φ) { + return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + } + d3_geo_identityRotation.invert = d3_geo_equirectangular; + function d3_geo_rotation(δλ, δφ, δγ) { + return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; + } + function d3_geo_forwardRotationλ(δλ) { + return function(λ, φ) { + return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + }; + } + function d3_geo_rotationλ(δλ) { + var rotation = d3_geo_forwardRotationλ(δλ); + rotation.invert = d3_geo_forwardRotationλ(-δλ); + return rotation; + } + function d3_geo_rotationφγ(δφ, δγ) { + var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); + function rotation(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; + return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; + } + rotation.invert = function(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; + return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; + }; + return rotation; + } + d3.geo.circle = function() { + var origin = [ 0, 0 ], angle, precision = 6, interpolate; + function circle() { + var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; + interpolate(null, null, 1, { + point: function(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= d3_degrees, x[1] *= d3_degrees; + } + }); + return { + type: "Polygon", + coordinates: [ ring ] + }; + } + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; + }; + circle.angle = function(x) { + if (!arguments.length) return angle; + interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); + return circle; + }; + circle.precision = function(_) { + if (!arguments.length) return precision; + interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); + return circle; + }; + return circle.angle(90); + }; + function d3_geo_circleInterpolate(radius, precision) { + var cr = Math.cos(radius), sr = Math.sin(radius); + return function(from, to, direction, listener) { + var step = direction * precision; + if (from != null) { + from = d3_geo_circleAngle(cr, from); + to = d3_geo_circleAngle(cr, to); + if (direction > 0 ? from < to : from > to) from += direction * τ; + } else { + from = radius + direction * τ; + to = radius - .5 * step; + } + for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { + listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); + } + }; + } + function d3_geo_circleAngle(cr, point) { + var a = d3_geo_cartesian(point); + a[0] -= cr; + d3_geo_cartesianNormalize(a); + var angle = d3_acos(-a[1]); + return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + } + d3.geo.distance = function(a, b) { + var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; + return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); + }; + d3.geo.graticule = function() { + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; + function graticule() { + return { + type: "MultiLineString", + coordinates: lines() + }; + } + function lines() { + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { + return abs(x % DX) > ε; + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { + return abs(y % DY) > ε; + }).map(y)); + } + graticule.lines = function() { + return lines().map(function(coordinates) { + return { + type: "LineString", + coordinates: coordinates + }; + }); + }; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] + }; + }; + graticule.extent = function(_) { + if (!arguments.length) return graticule.minorExtent(); + return graticule.majorExtent(_).minorExtent(_); + }; + graticule.majorExtent = function(_) { + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + graticule.minorExtent = function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + graticule.step = function(_) { + if (!arguments.length) return graticule.minorStep(); + return graticule.majorStep(_).minorStep(_); + }; + graticule.majorStep = function(_) { + if (!arguments.length) return [ DX, DY ]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + graticule.minorStep = function(_) { + if (!arguments.length) return [ dx, dy ]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = d3_geo_graticuleX(y0, y1, 90); + y = d3_geo_graticuleY(x0, x1, precision); + X = d3_geo_graticuleX(Y0, Y1, 90); + Y = d3_geo_graticuleY(X0, X1, precision); + return graticule; + }; + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); + }; + function d3_geo_graticuleX(y0, y1, dy) { + var y = d3.range(y0, y1 - ε, dy).concat(y1); + return function(x) { + return y.map(function(y) { + return [ x, y ]; + }); + }; + } + function d3_geo_graticuleY(x0, x1, dx) { + var x = d3.range(x0, x1 - ε, dx).concat(x1); + return function(y) { + return x.map(function(x) { + return [ x, y ]; + }); + }; + } + function d3_source(d) { + return d.source; + } + function d3_target(d) { + return d.target; + } + d3.geo.greatArc = function() { + var source = d3_source, source_, target = d3_target, target_; + function greatArc() { + return { + type: "LineString", + coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] + }; + } + greatArc.distance = function() { + return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); + }; + greatArc.source = function(_) { + if (!arguments.length) return source; + source = _, source_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.target = function(_) { + if (!arguments.length) return target; + target = _, target_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.precision = function() { + return arguments.length ? greatArc : 0; + }; + return greatArc; + }; + d3.geo.interpolate = function(source, target) { + return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + }; + function d3_geo_interpolate(x0, y0, x1, y1) { + var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); + var interpolate = d ? function(t) { + var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; + return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; + } : function() { + return [ x0 * d3_degrees, y0 * d3_degrees ]; + }; + interpolate.distance = d; + return interpolate; + } + d3.geo.length = function(object) { + d3_geo_lengthSum = 0; + d3.geo.stream(object, d3_geo_length); + return d3_geo_lengthSum; + }; + var d3_geo_lengthSum; + var d3_geo_length = { + sphere: d3_noop, + point: d3_noop, + lineStart: d3_geo_lengthLineStart, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_lengthLineStart() { + var λ0, sinφ0, cosφ0; + d3_geo_length.point = function(λ, φ) { + λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); + d3_geo_length.point = nextPoint; + }; + d3_geo_length.lineEnd = function() { + d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + }; + function nextPoint(λ, φ) { + var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); + d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; + } + } + function d3_geo_azimuthal(scale, angle) { + function azimuthal(λ, φ) { + var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); + return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + } + azimuthal.invert = function(x, y) { + var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); + return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; + }; + return azimuthal; + } + var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { + return Math.sqrt(2 / (1 + cosλcosφ)); + }, function(ρ) { + return 2 * Math.asin(ρ / 2); + }); + (d3.geo.azimuthalEqualArea = function() { + return d3_geo_projection(d3_geo_azimuthalEqualArea); + }).raw = d3_geo_azimuthalEqualArea; + var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { + var c = Math.acos(cosλcosφ); + return c && c / Math.sin(c); + }, d3_identity); + (d3.geo.azimuthalEquidistant = function() { + return d3_geo_projection(d3_geo_azimuthalEquidistant); + }).raw = d3_geo_azimuthalEquidistant; + function d3_geo_conicConformal(φ0, φ1) { + var cosφ0 = Math.cos(φ0), t = function(φ) { + return Math.tan(π / 4 + φ / 2); + }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; + if (!n) return d3_geo_mercator; + function forward(λ, φ) { + if (F > 0) { + if (φ < -halfπ + ε) φ = -halfπ + ε; + } else { + if (φ > halfπ - ε) φ = halfπ - ε; + } + var ρ = F / Math.pow(t(φ), n); + return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); + return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; + }; + return forward; + } + (d3.geo.conicConformal = function() { + return d3_geo_conic(d3_geo_conicConformal); + }).raw = d3_geo_conicConformal; + function d3_geo_conicEquidistant(φ0, φ1) { + var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; + if (abs(n) < ε) return d3_geo_equirectangular; + function forward(λ, φ) { + var ρ = G - φ; + return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = G - y; + return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; + }; + return forward; + } + (d3.geo.conicEquidistant = function() { + return d3_geo_conic(d3_geo_conicEquidistant); + }).raw = d3_geo_conicEquidistant; + var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / cosλcosφ; + }, Math.atan); + (d3.geo.gnomonic = function() { + return d3_geo_projection(d3_geo_gnomonic); + }).raw = d3_geo_gnomonic; + function d3_geo_mercator(λ, φ) { + return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; + } + d3_geo_mercator.invert = function(x, y) { + return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; + }; + function d3_geo_mercatorProjection(project) { + var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; + m.scale = function() { + var v = scale.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.translate = function() { + var v = translate.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.clipExtent = function(_) { + var v = clipExtent.apply(m, arguments); + if (v === m) { + if (clipAuto = _ == null) { + var k = π * scale(), t = translate(); + clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); + } + } else if (clipAuto) { + v = null; + } + return v; + }; + return m.clipExtent(null); + } + (d3.geo.mercator = function() { + return d3_geo_mercatorProjection(d3_geo_mercator); + }).raw = d3_geo_mercator; + var d3_geo_orthographic = d3_geo_azimuthal(function() { + return 1; + }, Math.asin); + (d3.geo.orthographic = function() { + return d3_geo_projection(d3_geo_orthographic); + }).raw = d3_geo_orthographic; + var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / (1 + cosλcosφ); + }, function(ρ) { + return 2 * Math.atan(ρ); + }); + (d3.geo.stereographic = function() { + return d3_geo_projection(d3_geo_stereographic); + }).raw = d3_geo_stereographic; + function d3_geo_transverseMercator(λ, φ) { + return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; + } + d3_geo_transverseMercator.invert = function(x, y) { + return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; + }; + (d3.geo.transverseMercator = function() { + var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; + projection.center = function(_) { + return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); + }; + projection.rotate = function(_) { + return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), + [ _[0], _[1], _[2] - 90 ]); + }; + return rotate([ 0, 0, 90 ]); + }).raw = d3_geo_transverseMercator; + d3.geom = {}; + function d3_geom_pointX(d) { + return d[0]; + } + function d3_geom_pointY(d) { + return d[1]; + } + d3.geom.hull = function(vertices) { + var x = d3_geom_pointX, y = d3_geom_pointY; + if (arguments.length) return hull(vertices); + function hull(data) { + if (data.length < 3) return []; + var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; + for (i = 0; i < n; i++) { + points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + } + points.sort(d3_geom_hullOrder); + for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); + var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); + var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; + for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); + for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); + return polygon; + } + hull.x = function(_) { + return arguments.length ? (x = _, hull) : x; + }; + hull.y = function(_) { + return arguments.length ? (y = _, hull) : y; + }; + return hull; + }; + function d3_geom_hullUpper(points) { + var n = points.length, hull = [ 0, 1 ], hs = 2; + for (var i = 2; i < n; i++) { + while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; + hull[hs++] = i; + } + return hull.slice(0, hs); + } + function d3_geom_hullOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + d3.geom.polygon = function(coordinates) { + d3_subclass(coordinates, d3_geom_polygonPrototype); + return coordinates; + }; + var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; + d3_geom_polygonPrototype.area = function() { + var i = -1, n = this.length, a, b = this[n - 1], area = 0; + while (++i < n) { + a = b; + b = this[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + return area * .5; + }; + d3_geom_polygonPrototype.centroid = function(k) { + var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; + if (!arguments.length) k = -1 / (6 * this.area()); + while (++i < n) { + a = b; + b = this[i]; + c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + return [ x * k, y * k ]; + }; + d3_geom_polygonPrototype.clip = function(subject) { + var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; + while (++i < n) { + input = subject.slice(); + subject.length = 0; + b = this[i]; + c = input[(m = input.length - closed) - 1]; + j = -1; + while (++j < m) { + d = input[j]; + if (d3_geom_polygonInside(d, a, b)) { + if (!d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + subject.push(d); + } else if (d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + c = d; + } + if (closed) subject.push(subject[0]); + a = b; + } + return subject; + }; + function d3_geom_polygonInside(p, a, b) { + return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); + } + function d3_geom_polygonIntersect(c, d, a, b) { + var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); + return [ x1 + ua * x21, y1 + ua * y21 ]; + } + function d3_geom_polygonClosed(coordinates) { + var a = coordinates[0], b = coordinates[coordinates.length - 1]; + return !(a[0] - b[0] || a[1] - b[1]); + } + var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; + function d3_geom_voronoiBeach() { + d3_geom_voronoiRedBlackNode(this); + this.edge = this.site = this.circle = null; + } + function d3_geom_voronoiCreateBeach(site) { + var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); + beach.site = site; + return beach; + } + function d3_geom_voronoiDetachBeach(beach) { + d3_geom_voronoiDetachCircle(beach); + d3_geom_voronoiBeaches.remove(beach); + d3_geom_voronoiBeachPool.push(beach); + d3_geom_voronoiRedBlackNode(beach); + } + function d3_geom_voronoiRemoveBeach(beach) { + var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { + x: x, + y: y + }, previous = beach.P, next = beach.N, disappearing = [ beach ]; + d3_geom_voronoiDetachBeach(beach); + var lArc = previous; + while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { + previous = lArc.P; + disappearing.unshift(lArc); + d3_geom_voronoiDetachBeach(lArc); + lArc = previous; + } + disappearing.unshift(lArc); + d3_geom_voronoiDetachCircle(lArc); + var rArc = next; + while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { + next = rArc.N; + disappearing.push(rArc); + d3_geom_voronoiDetachBeach(rArc); + rArc = next; + } + disappearing.push(rArc); + d3_geom_voronoiDetachCircle(rArc); + var nArcs = disappearing.length, iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiAddBeach(site) { + var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; + while (node) { + dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; + if (dxl > ε) node = node.L; else { + dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); + if (dxr > ε) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -ε) { + lArc = node.P; + rArc = node; + } else if (dxr > -ε) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + var newArc = d3_geom_voronoiCreateBeach(site); + d3_geom_voronoiBeaches.insert(lArc, newArc); + if (!lArc && !rArc) return; + if (lArc === rArc) { + d3_geom_voronoiDetachCircle(lArc); + rArc = d3_geom_voronoiCreateBeach(lArc.site); + d3_geom_voronoiBeaches.insert(newArc, rArc); + newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + return; + } + if (!rArc) { + newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + return; + } + d3_geom_voronoiDetachCircle(lArc); + d3_geom_voronoiDetachCircle(rArc); + var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { + x: (cy * hb - by * hc) / d + ax, + y: (bx * hc - cx * hb) / d + ay + }; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); + rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiLeftBreakPoint(arc, directrix) { + var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; + if (!pby2) return rfocx; + var lArc = arc.P; + if (!lArc) return -Infinity; + site = lArc.site; + var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; + if (!plby2) return lfocx; + var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + return (rfocx + lfocx) / 2; + } + function d3_geom_voronoiRightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); + var site = arc.site; + return site.y === directrix ? site.x : Infinity; + } + function d3_geom_voronoiCell(site) { + this.site = site; + this.edges = []; + } + d3_geom_voronoiCell.prototype.prepare = function() { + var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; + while (iHalfEdge--) { + edge = halfEdges[iHalfEdge].edge; + if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); + } + halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); + return halfEdges.length; + }; + function d3_geom_voronoiCloseCells(extent) { + var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; + while (iCell--) { + cell = cells[iCell]; + if (!cell || !cell.prepare()) continue; + halfEdges = cell.edges; + nHalfEdges = halfEdges.length; + iHalfEdge = 0; + while (iHalfEdge < nHalfEdges) { + end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; + start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; + if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { + halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { + x: x0, + y: abs(x2 - x0) < ε ? y2 : y1 + } : abs(y3 - y1) < ε && x1 - x3 > ε ? { + x: abs(y2 - y1) < ε ? x2 : x1, + y: y1 + } : abs(x3 - x1) < ε && y3 - y0 > ε ? { + x: x1, + y: abs(x2 - x1) < ε ? y2 : y0 + } : abs(y3 - y0) < ε && x3 - x0 > ε ? { + x: abs(y2 - y0) < ε ? x2 : x0, + y: y0 + } : null), cell.site, null)); + ++nHalfEdges; + } + } + } + } + function d3_geom_voronoiHalfEdgeOrder(a, b) { + return b.angle - a.angle; + } + function d3_geom_voronoiCircle() { + d3_geom_voronoiRedBlackNode(this); + this.x = this.y = this.arc = this.site = this.cy = null; + } + function d3_geom_voronoiAttachCircle(arc) { + var lArc = arc.P, rArc = arc.N; + if (!lArc || !rArc) return; + var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; + if (lSite === rSite) return; + var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; + var d = 2 * (ax * cy - ay * cx); + if (d >= -ε2) return; + var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; + var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = cy + Math.sqrt(x * x + y * y); + circle.cy = cy; + arc.circle = circle; + var before = null, node = d3_geom_voronoiCircles._; + while (node) { + if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { + if (node.L) node = node.L; else { + before = node.P; + break; + } + } else { + if (node.R) node = node.R; else { + before = node; + break; + } + } + } + d3_geom_voronoiCircles.insert(before, circle); + if (!before) d3_geom_voronoiFirstCircle = circle; + } + function d3_geom_voronoiDetachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; + d3_geom_voronoiCircles.remove(circle); + d3_geom_voronoiCirclePool.push(circle); + d3_geom_voronoiRedBlackNode(circle); + arc.circle = null; + } + } + function d3_geom_voronoiClipEdges(extent) { + var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; + while (i--) { + e = edges[i]; + if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { + e.a = e.b = null; + edges.splice(i, 1); + } + } + } + function d3_geom_voronoiConnectEdge(edge, extent) { + var vb = edge.b; + if (vb) return true; + var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!va) va = { + x: fx, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: fx, + y: y1 + }; + } else { + if (!va) va = { + x: fx, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: fx, + y: y0 + }; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!va) va = { + x: (y0 - fb) / fm, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: (y1 - fb) / fm, + y: y1 + }; + } else { + if (!va) va = { + x: (y1 - fb) / fm, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: (y0 - fb) / fm, + y: y0 + }; + } + } else { + if (ly < ry) { + if (!va) va = { + x: x0, + y: fm * x0 + fb + }; else if (va.x >= x1) return; + vb = { + x: x1, + y: fm * x1 + fb + }; + } else { + if (!va) va = { + x: x1, + y: fm * x1 + fb + }; else if (va.x < x0) return; + vb = { + x: x0, + y: fm * x0 + fb + }; + } + } + } + edge.a = va; + edge.b = vb; + return true; + } + function d3_geom_voronoiEdge(lSite, rSite) { + this.l = lSite; + this.r = rSite; + this.a = this.b = null; + } + function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, rSite); + d3_geom_voronoiEdges.push(edge); + if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); + if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); + d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); + d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); + return edge; + } + function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, null); + edge.a = va; + edge.b = vb; + d3_geom_voronoiEdges.push(edge); + return edge; + } + function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { + if (!edge.a && !edge.b) { + edge.a = vertex; + edge.l = lSite; + edge.r = rSite; + } else if (edge.l === rSite) { + edge.b = vertex; + } else { + edge.a = vertex; + } + } + function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { + var va = edge.a, vb = edge.b; + this.edge = edge; + this.site = lSite; + this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); + } + d3_geom_voronoiHalfEdge.prototype = { + start: function() { + return this.edge.l === this.site ? this.edge.a : this.edge.b; + }, + end: function() { + return this.edge.l === this.site ? this.edge.b : this.edge.a; + } + }; + function d3_geom_voronoiRedBlackTree() { + this._ = null; + } + function d3_geom_voronoiRedBlackNode(node) { + node.U = node.C = node.L = node.R = node.P = node.N = null; + } + d3_geom_voronoiRedBlackTree.prototype = { + insert: function(after, node) { + var parent, grandpa, uncle; + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = d3_geom_voronoiRedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + d3_geom_voronoiRedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + d3_geom_voronoiRedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + var parent = node.U, sibling, left = node.L, right = node.R, next, red; + if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); + if (parent) { + if (parent.L === node) parent.L = next; else parent.R = next; + } else { + this._ = next; + } + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + if (node) node.U = parent; + if (red) return; + if (node && node.C) { + node.C = false; + return; + } + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateRight(this, parent); + sibling = parent.L; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + d3_geom_voronoiRedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + if (node) node.C = false; + } + }; + function d3_geom_voronoiRedBlackRotateLeft(tree, node) { + var p = node, q = node.R, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; + } + function d3_geom_voronoiRedBlackRotateRight(tree, node) { + var p = node, q = node.L, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; + } + function d3_geom_voronoiRedBlackFirst(node) { + while (node.L) node = node.L; + return node; + } + function d3_geom_voronoi(sites, bbox) { + var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; + d3_geom_voronoiEdges = []; + d3_geom_voronoiCells = new Array(sites.length); + d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); + d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); + while (true) { + circle = d3_geom_voronoiFirstCircle; + if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { + if (site.x !== x0 || site.y !== y0) { + d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); + d3_geom_voronoiAddBeach(site); + x0 = site.x, y0 = site.y; + } + site = sites.pop(); + } else if (circle) { + d3_geom_voronoiRemoveBeach(circle.arc); + } else { + break; + } + } + if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); + var diagram = { + cells: d3_geom_voronoiCells, + edges: d3_geom_voronoiEdges + }; + d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; + return diagram; + } + function d3_geom_voronoiVertexOrder(a, b) { + return b.y - a.y || b.x - a.x; + } + d3.geom.voronoi = function(points) { + var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; + if (points) return voronoi(points); + function voronoi(data) { + var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; + d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { + var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { + var s = e.start(); + return [ s.x, s.y ]; + }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; + polygon.point = data[i]; + }); + return polygons; + } + function sites(data) { + return data.map(function(d, i) { + return { + x: Math.round(fx(d, i) / ε) * ε, + y: Math.round(fy(d, i) / ε) * ε, + i: i + }; + }); + } + voronoi.links = function(data) { + return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { + return edge.l && edge.r; + }).map(function(edge) { + return { + source: data[edge.l.i], + target: data[edge.r.i] + }; + }); + }; + voronoi.triangles = function(data) { + var triangles = []; + d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { + var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; + while (++j < m) { + e0 = e1; + s0 = s1; + e1 = edges[j].edge; + s1 = e1.l === site ? e1.r : e1.l; + if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { + triangles.push([ data[i], data[s0.i], data[s1.i] ]); + } + } + }); + return triangles; + }; + voronoi.x = function(_) { + return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; + }; + voronoi.y = function(_) { + return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; + }; + voronoi.clipExtent = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; + clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; + return voronoi; + }; + voronoi.size = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; + return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + }; + return voronoi; + }; + var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; + function d3_geom_voronoiTriangleArea(a, b, c) { + return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); + } + d3.geom.delaunay = function(vertices) { + return d3.geom.voronoi().triangles(vertices); + }; + d3.geom.quadtree = function(points, x1, y1, x2, y2) { + var x = d3_geom_pointX, y = d3_geom_pointY, compat; + if (compat = arguments.length) { + x = d3_geom_quadtreeCompatX; + y = d3_geom_quadtreeCompatY; + if (compat === 3) { + y2 = y1; + x2 = x1; + y1 = x1 = 0; + } + return quadtree(points); + } + function quadtree(data) { + var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; + if (x1 != null) { + x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; + } else { + x2_ = y2_ = -(x1_ = y1_ = Infinity); + xs = [], ys = []; + n = data.length; + if (compat) for (i = 0; i < n; ++i) { + d = data[i]; + if (d.x < x1_) x1_ = d.x; + if (d.y < y1_) y1_ = d.y; + if (d.x > x2_) x2_ = d.x; + if (d.y > y2_) y2_ = d.y; + xs.push(d.x); + ys.push(d.y); + } else for (i = 0; i < n; ++i) { + var x_ = +fx(d = data[i], i), y_ = +fy(d, i); + if (x_ < x1_) x1_ = x_; + if (y_ < y1_) y1_ = y_; + if (x_ > x2_) x2_ = x_; + if (y_ > y2_) y2_ = y_; + xs.push(x_); + ys.push(y_); + } + } + var dx = x2_ - x1_, dy = y2_ - y1_; + if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; + function insert(n, d, x, y, x1, y1, x2, y2) { + if (isNaN(x) || isNaN(y)) return; + if (n.leaf) { + var nx = n.x, ny = n.y; + if (nx != null) { + if (abs(nx - x) + abs(ny - y) < .01) { + insertChild(n, d, x, y, x1, y1, x2, y2); + } else { + var nPoint = n.point; + n.x = n.y = n.point = null; + insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } else { + n.x = x, n.y = y, n.point = d; + } + } else { + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } + function insertChild(n, d, x, y, x1, y1, x2, y2) { + var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; + n.leaf = false; + n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); + if (right) x1 = xm; else x2 = xm; + if (below) y1 = ym; else y2 = ym; + insert(n, d, x, y, x1, y1, x2, y2); + } + var root = d3_geom_quadtreeNode(); + root.add = function(d) { + insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); + }; + root.visit = function(f) { + d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); + }; + root.find = function(point) { + return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); + }; + i = -1; + if (x1 == null) { + while (++i < n) { + insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); + } + --i; + } else data.forEach(root.add); + xs = ys = data = d = null; + return root; + } + quadtree.x = function(_) { + return arguments.length ? (x = _, quadtree) : x; + }; + quadtree.y = function(_) { + return arguments.length ? (y = _, quadtree) : y; + }; + quadtree.extent = function(_) { + if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], + y2 = +_[1][1]; + return quadtree; + }; + quadtree.size = function(_) { + if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; + return quadtree; + }; + return quadtree; + }; + function d3_geom_quadtreeCompatX(d) { + return d.x; + } + function d3_geom_quadtreeCompatY(d) { + return d.y; + } + function d3_geom_quadtreeNode() { + return { + leaf: true, + nodes: [], + point: null, + x: null, + y: null + }; + } + function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { + if (!f(node, x1, y1, x2, y2)) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; + if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); + if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); + if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); + if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); + } + } + function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { + var minDistance2 = Infinity, closestPoint; + (function find(node, x1, y1, x2, y2) { + if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; + if (point = node.point) { + var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; + if (distance2 < minDistance2) { + var distance = Math.sqrt(minDistance2 = distance2); + x0 = x - distance, y0 = y - distance; + x3 = x + distance, y3 = y + distance; + closestPoint = point; + } + } + var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; + for (var i = below << 1 | right, j = i + 4; i < j; ++i) { + if (node = children[i & 3]) switch (i & 3) { + case 0: + find(node, x1, y1, xm, ym); + break; + + case 1: + find(node, xm, y1, x2, ym); + break; + + case 2: + find(node, x1, ym, xm, y2); + break; + + case 3: + find(node, xm, ym, x2, y2); + break; + } + } + })(root, x0, y0, x3, y3); + return closestPoint; + } + d3.interpolateRgb = d3_interpolateRgb; + function d3_interpolateRgb(a, b) { + a = d3.rgb(a); + b = d3.rgb(b); + var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; + return function(t) { + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + }; + } + d3.interpolateObject = d3_interpolateObject; + function d3_interpolateObject(a, b) { + var i = {}, c = {}, k; + for (k in a) { + if (k in b) { + i[k] = d3_interpolate(a[k], b[k]); + } else { + c[k] = a[k]; + } + } + for (k in b) { + if (!(k in a)) { + c[k] = b[k]; + } + } + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; + } + d3.interpolateNumber = d3_interpolateNumber; + function d3_interpolateNumber(a, b) { + a = +a, b = +b; + return function(t) { + return a * (1 - t) + b * t; + }; + } + d3.interpolateString = d3_interpolateString; + function d3_interpolateString(a, b) { + var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a = a + "", b = b + ""; + while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) s[i] += bm; else s[++i] = bm; + } else { + s[++i] = null; + q.push({ + i: i, + x: d3_interpolateNumber(am, bm) + }); + } + bi = d3_interpolate_numberB.lastIndex; + } + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { + return b(t) + ""; + }) : function() { + return b; + } : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); + d3.interpolate = d3_interpolate; + function d3_interpolate(a, b) { + var i = d3.interpolators.length, f; + while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; + return f; + } + d3.interpolators = [ function(a, b) { + var t = typeof b; + return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); + } ]; + d3.interpolateArray = d3_interpolateArray; + function d3_interpolateArray(a, b) { + var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; + for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); + for (;i < na; ++i) c[i] = a[i]; + for (;i < nb; ++i) c[i] = b[i]; + return function(t) { + for (i = 0; i < n0; ++i) c[i] = x[i](t); + return c; + }; + } + var d3_ease_default = function() { + return d3_identity; + }; + var d3_ease = d3.map({ + linear: d3_ease_default, + poly: d3_ease_poly, + quad: function() { + return d3_ease_quad; + }, + cubic: function() { + return d3_ease_cubic; + }, + sin: function() { + return d3_ease_sin; + }, + exp: function() { + return d3_ease_exp; + }, + circle: function() { + return d3_ease_circle; + }, + elastic: d3_ease_elastic, + back: d3_ease_back, + bounce: function() { + return d3_ease_bounce; + } + }); + var d3_ease_mode = d3.map({ + "in": d3_identity, + out: d3_ease_reverse, + "in-out": d3_ease_reflect, + "out-in": function(f) { + return d3_ease_reflect(d3_ease_reverse(f)); + } + }); + d3.ease = function(name) { + var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; + t = d3_ease.get(t) || d3_ease_default; + m = d3_ease_mode.get(m) || d3_identity; + return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); + }; + function d3_ease_clamp(f) { + return function(t) { + return t <= 0 ? 0 : t >= 1 ? 1 : f(t); + }; + } + function d3_ease_reverse(f) { + return function(t) { + return 1 - f(1 - t); + }; + } + function d3_ease_reflect(f) { + return function(t) { + return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); + }; + } + function d3_ease_quad(t) { + return t * t; + } + function d3_ease_cubic(t) { + return t * t * t; + } + function d3_ease_cubicInOut(t) { + if (t <= 0) return 0; + if (t >= 1) return 1; + var t2 = t * t, t3 = t2 * t; + return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + } + function d3_ease_poly(e) { + return function(t) { + return Math.pow(t, e); + }; + } + function d3_ease_sin(t) { + return 1 - Math.cos(t * halfπ); + } + function d3_ease_exp(t) { + return Math.pow(2, 10 * (t - 1)); + } + function d3_ease_circle(t) { + return 1 - Math.sqrt(1 - t * t); + } + function d3_ease_elastic(a, p) { + var s; + if (arguments.length < 2) p = .45; + if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; + return function(t) { + return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); + }; + } + function d3_ease_back(s) { + if (!s) s = 1.70158; + return function(t) { + return t * t * ((s + 1) * t - s); + }; + } + function d3_ease_bounce(t) { + return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; + } + d3.interpolateHcl = d3_interpolateHcl; + function d3_interpolateHcl(a, b) { + a = d3.hcl(a); + b = d3.hcl(b); + var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; + if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + }; + } + d3.interpolateHsl = d3_interpolateHsl; + function d3_interpolateHsl(a, b) { + a = d3.hsl(a); + b = d3.hsl(b); + var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; + if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + }; + } + d3.interpolateLab = d3_interpolateLab; + function d3_interpolateLab(a, b) { + a = d3.lab(a); + b = d3.lab(b); + var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; + return function(t) { + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + }; + } + d3.interpolateRound = d3_interpolateRound; + function d3_interpolateRound(a, b) { + b -= a; + return function(t) { + return Math.round(a + b * t); + }; + } + d3.transform = function(string) { + var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); + return (d3.transform = function(string) { + if (string != null) { + g.setAttribute("transform", string); + var t = g.transform.baseVal.consolidate(); + } + return new d3_transform(t ? t.matrix : d3_transformIdentity); + })(string); + }; + function d3_transform(m) { + var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; + if (r0[0] * r1[1] < r1[0] * r0[1]) { + r0[0] *= -1; + r0[1] *= -1; + kx *= -1; + kz *= -1; + } + this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; + this.translate = [ m.e, m.f ]; + this.scale = [ kx, ky ]; + this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + } + d3_transform.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + }; + function d3_transformDot(a, b) { + return a[0] * b[0] + a[1] * b[1]; + } + function d3_transformNormalize(a) { + var k = Math.sqrt(d3_transformDot(a, a)); + if (k) { + a[0] /= k; + a[1] /= k; + } + return k; + } + function d3_transformCombine(a, b, k) { + a[0] += k * b[0]; + a[1] += k * b[1]; + return a; + } + var d3_transformIdentity = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + d3.interpolateTransform = d3_interpolateTransform; + function d3_interpolateTransformPop(s) { + return s.length ? s.pop() + "," : ""; + } + function d3_interpolateTranslate(ta, tb, s, q) { + if (ta[0] !== tb[0] || ta[1] !== tb[1]) { + var i = s.push("translate(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ta[0], tb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ta[1], tb[1]) + }); + } else if (tb[0] || tb[1]) { + s.push("translate(" + tb + ")"); + } + } + function d3_interpolateRotate(ra, rb, s, q) { + if (ra !== rb) { + if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, + x: d3_interpolateNumber(ra, rb) + }); + } else if (rb) { + s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); + } + } + function d3_interpolateSkew(wa, wb, s, q) { + if (wa !== wb) { + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, + x: d3_interpolateNumber(wa, wb) + }); + } else if (wb) { + s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); + } + } + function d3_interpolateScale(ka, kb, s, q) { + if (ka[0] !== kb[0] || ka[1] !== kb[1]) { + var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ka[0], kb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ka[1], kb[1]) + }); + } else if (kb[0] !== 1 || kb[1] !== 1) { + s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); + } + } + function d3_interpolateTransform(a, b) { + var s = [], q = []; + a = d3.transform(a), b = d3.transform(b); + d3_interpolateTranslate(a.translate, b.translate, s, q); + d3_interpolateRotate(a.rotate, b.rotate, s, q); + d3_interpolateSkew(a.skew, b.skew, s, q); + d3_interpolateScale(a.scale, b.scale, s, q); + a = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + } + function d3_uninterpolateNumber(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return (x - a) / b; + }; + } + function d3_uninterpolateClamp(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return Math.max(0, Math.min(1, (x - a) / b)); + }; + } + d3.layout = {}; + d3.layout.bundle = function() { + return function(links) { + var paths = [], i = -1, n = links.length; + while (++i < n) paths.push(d3_layout_bundlePath(links[i])); + return paths; + }; + }; + function d3_layout_bundlePath(link) { + var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; + while (start !== lca) { + start = start.parent; + points.push(start); + } + var k = points.length; + while (end !== lca) { + points.splice(k, 0, end); + end = end.parent; + } + return points; + } + function d3_layout_bundleAncestors(node) { + var ancestors = [], parent = node.parent; + while (parent != null) { + ancestors.push(node); + node = parent; + parent = parent.parent; + } + ancestors.push(node); + return ancestors; + } + function d3_layout_bundleLeastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; + while (aNode === bNode) { + sharedNode = aNode; + aNode = aNodes.pop(); + bNode = bNodes.pop(); + } + return sharedNode; + } + d3.layout.chord = function() { + var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; + function relayout() { + var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; + chords = []; + groups = []; + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3.range(n)); + k += x; + } + if (sortGroups) { + groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + } + if (sortSubgroups) { + subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + } + k = (τ - padding * n) / k; + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; + subgroups[di + "-" + dj] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += padding; + } + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; + if (source.value || target.value) { + chords.push(source.value < target.value ? { + source: target, + target: source + } : { + source: source, + target: target + }); + } + } + } + if (sortChords) resort(); + } + function resort() { + chords.sort(function(a, b) { + return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); + }); + } + chord.matrix = function(x) { + if (!arguments.length) return matrix; + n = (matrix = x) && matrix.length; + chords = groups = null; + return chord; + }; + chord.padding = function(x) { + if (!arguments.length) return padding; + padding = x; + chords = groups = null; + return chord; + }; + chord.sortGroups = function(x) { + if (!arguments.length) return sortGroups; + sortGroups = x; + chords = groups = null; + return chord; + }; + chord.sortSubgroups = function(x) { + if (!arguments.length) return sortSubgroups; + sortSubgroups = x; + chords = null; + return chord; + }; + chord.sortChords = function(x) { + if (!arguments.length) return sortChords; + sortChords = x; + if (chords) resort(); + return chord; + }; + chord.chords = function() { + if (!chords) relayout(); + return chords; + }; + chord.groups = function() { + if (!groups) relayout(); + return groups; + }; + return chord; + }; + d3.layout.force = function() { + var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; + function repulse(node) { + return function(quad, x1, _, x2) { + if (quad.point !== node) { + var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; + if (dw * dw / theta2 < dn) { + if (dn < chargeDistance2) { + var k = quad.charge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + return true; + } + if (quad.point && dn && dn < chargeDistance2) { + var k = quad.pointCharge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + } + return !quad.charge; + }; + } + force.tick = function() { + if ((alpha *= .99) < .005) { + timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + return true; + } + var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; + for (i = 0; i < m; ++i) { + o = links[i]; + s = o.source; + t = o.target; + x = t.x - s.x; + y = t.y - s.y; + if (l = x * x + y * y) { + l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; + x *= l; + y *= l; + t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; + } + } + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; + if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } + } + if (charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); + i = -1; + while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o)); + } + } + } + i = -1; + while (++i < n) { + o = nodes[i]; + if (o.fixed) { + o.x = o.px; + o.y = o.py; + } else { + o.x -= (o.px - (o.px = o.x)) * friction; + o.y -= (o.py - (o.py = o.y)) * friction; + } + } + event.tick({ + type: "tick", + alpha: alpha + }); + }; + force.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return force; + }; + force.links = function(x) { + if (!arguments.length) return links; + links = x; + return force; + }; + force.size = function(x) { + if (!arguments.length) return size; + size = x; + return force; + }; + force.linkDistance = function(x) { + if (!arguments.length) return linkDistance; + linkDistance = typeof x === "function" ? x : +x; + return force; + }; + force.distance = force.linkDistance; + force.linkStrength = function(x) { + if (!arguments.length) return linkStrength; + linkStrength = typeof x === "function" ? x : +x; + return force; + }; + force.friction = function(x) { + if (!arguments.length) return friction; + friction = +x; + return force; + }; + force.charge = function(x) { + if (!arguments.length) return charge; + charge = typeof x === "function" ? x : +x; + return force; + }; + force.chargeDistance = function(x) { + if (!arguments.length) return Math.sqrt(chargeDistance2); + chargeDistance2 = x * x; + return force; + }; + force.gravity = function(x) { + if (!arguments.length) return gravity; + gravity = +x; + return force; + }; + force.theta = function(x) { + if (!arguments.length) return Math.sqrt(theta2); + theta2 = x * x; + return force; + }; + force.alpha = function(x) { + if (!arguments.length) return alpha; + x = +x; + if (alpha) { + if (x > 0) { + alpha = x; + } else { + timer.c = null, timer.t = NaN, timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + } + } else if (x > 0) { + event.start({ + type: "start", + alpha: alpha = x + }); + timer = d3_timer(force.tick); + } + return force; + }; + force.start = function() { + var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; + for (i = 0; i < n; ++i) { + (o = nodes[i]).index = i; + o.weight = 0; + } + for (i = 0; i < m; ++i) { + o = links[i]; + if (typeof o.source == "number") o.source = nodes[o.source]; + if (typeof o.target == "number") o.target = nodes[o.target]; + ++o.source.weight; + ++o.target.weight; + } + for (i = 0; i < n; ++i) { + o = nodes[i]; + if (isNaN(o.x)) o.x = position("x", w); + if (isNaN(o.y)) o.y = position("y", h); + if (isNaN(o.px)) o.px = o.x; + if (isNaN(o.py)) o.py = o.y; + } + distances = []; + if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; + strengths = []; + if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; + charges = []; + if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; + function position(dimension, size) { + if (!neighbors) { + neighbors = new Array(n); + for (j = 0; j < n; ++j) { + neighbors[j] = []; + } + for (j = 0; j < m; ++j) { + var o = links[j]; + neighbors[o.source.index].push(o.target); + neighbors[o.target.index].push(o.source); + } + } + var candidates = neighbors[i], j = -1, l = candidates.length, x; + while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; + return Math.random() * size; + } + return force.resume(); + }; + force.resume = function() { + return force.alpha(.1); + }; + force.stop = function() { + return force.alpha(0); + }; + force.drag = function() { + if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); + if (!arguments.length) return drag; + this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); + }; + function dragmove(d) { + d.px = d3.event.x, d.py = d3.event.y; + force.resume(); + } + return d3.rebind(force, event, "on"); + }; + function d3_layout_forceDragstart(d) { + d.fixed |= 2; + } + function d3_layout_forceDragend(d) { + d.fixed &= ~6; + } + function d3_layout_forceMouseover(d) { + d.fixed |= 4; + d.px = d.x, d.py = d.y; + } + function d3_layout_forceMouseout(d) { + d.fixed &= ~4; + } + function d3_layout_forceAccumulate(quad, alpha, charges) { + var cx = 0, cy = 0; + quad.charge = 0; + if (!quad.leaf) { + var nodes = quad.nodes, n = nodes.length, i = -1, c; + while (++i < n) { + c = nodes[i]; + if (c == null) continue; + d3_layout_forceAccumulate(c, alpha, charges); + quad.charge += c.charge; + cx += c.charge * c.cx; + cy += c.charge * c.cy; + } + } + if (quad.point) { + if (!quad.leaf) { + quad.point.x += Math.random() - .5; + quad.point.y += Math.random() - .5; + } + var k = alpha * charges[quad.point.index]; + quad.charge += quad.pointCharge = k; + cx += k * quad.point.x; + cy += k * quad.point.y; + } + quad.cx = cx / quad.charge; + quad.cy = cy / quad.charge; + } + var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; + d3.layout.hierarchy = function() { + var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; + function hierarchy(root) { + var stack = [ root ], nodes = [], node; + root.depth = 0; + while ((node = stack.pop()) != null) { + nodes.push(node); + if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { + var n, childs, child; + while (--n >= 0) { + stack.push(child = childs[n]); + child.parent = node; + child.depth = node.depth + 1; + } + if (value) node.value = 0; + node.children = childs; + } else { + if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; + delete node.children; + } + } + d3_layout_hierarchyVisitAfter(root, function(node) { + var childs, parent; + if (sort && (childs = node.children)) childs.sort(sort); + if (value && (parent = node.parent)) parent.value += node.value; + }); + return nodes; + } + hierarchy.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return hierarchy; + }; + hierarchy.children = function(x) { + if (!arguments.length) return children; + children = x; + return hierarchy; + }; + hierarchy.value = function(x) { + if (!arguments.length) return value; + value = x; + return hierarchy; + }; + hierarchy.revalue = function(root) { + if (value) { + d3_layout_hierarchyVisitBefore(root, function(node) { + if (node.children) node.value = 0; + }); + d3_layout_hierarchyVisitAfter(root, function(node) { + var parent; + if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; + if (parent = node.parent) parent.value += node.value; + }); + } + return root; + }; + return hierarchy; + }; + function d3_layout_hierarchyRebind(object, hierarchy) { + d3.rebind(object, hierarchy, "sort", "children", "value"); + object.nodes = object; + object.links = d3_layout_hierarchyLinks; + return object; + } + function d3_layout_hierarchyVisitBefore(node, callback) { + var nodes = [ node ]; + while ((node = nodes.pop()) != null) { + callback(node); + if ((children = node.children) && (n = children.length)) { + var n, children; + while (--n >= 0) nodes.push(children[n]); + } + } + } + function d3_layout_hierarchyVisitAfter(node, callback) { + var nodes = [ node ], nodes2 = []; + while ((node = nodes.pop()) != null) { + nodes2.push(node); + if ((children = node.children) && (n = children.length)) { + var i = -1, n, children; + while (++i < n) nodes.push(children[i]); + } + } + while ((node = nodes2.pop()) != null) { + callback(node); + } + } + function d3_layout_hierarchyChildren(d) { + return d.children; + } + function d3_layout_hierarchyValue(d) { + return d.value; + } + function d3_layout_hierarchySort(a, b) { + return b.value - a.value; + } + function d3_layout_hierarchyLinks(nodes) { + return d3.merge(nodes.map(function(parent) { + return (parent.children || []).map(function(child) { + return { + source: parent, + target: child + }; + }); + })); + } + d3.layout.partition = function() { + var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; + function position(node, x, dx, dy) { + var children = node.children; + node.x = x; + node.y = node.depth * dy; + node.dx = dx; + node.dy = dy; + if (children && (n = children.length)) { + var i = -1, n, c, d; + dx = node.value ? dx / node.value : 0; + while (++i < n) { + position(c = children[i], x, d = c.value * dx, dy); + x += d; + } + } + } + function depth(node) { + var children = node.children, d = 0; + if (children && (n = children.length)) { + var i = -1, n; + while (++i < n) d = Math.max(d, depth(children[i])); + } + return 1 + d; + } + function partition(d, i) { + var nodes = hierarchy.call(this, d, i); + position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); + return nodes; + } + partition.size = function(x) { + if (!arguments.length) return size; + size = x; + return partition; + }; + return d3_layout_hierarchyRebind(partition, hierarchy); + }; + d3.layout.pie = function() { + var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; + function pie(data) { + var n = data.length, values = data.map(function(d, i) { + return +value.call(pie, d, i); + }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; + if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { + return values[j] - values[i]; + } : function(i, j) { + return sort(data[i], data[j]); + }); + index.forEach(function(i) { + arcs[i] = { + data: data[i], + value: v = values[i], + startAngle: a, + endAngle: a += v * k + pa, + padAngle: p + }; + }); + return arcs; + } + pie.value = function(_) { + if (!arguments.length) return value; + value = _; + return pie; + }; + pie.sort = function(_) { + if (!arguments.length) return sort; + sort = _; + return pie; + }; + pie.startAngle = function(_) { + if (!arguments.length) return startAngle; + startAngle = _; + return pie; + }; + pie.endAngle = function(_) { + if (!arguments.length) return endAngle; + endAngle = _; + return pie; + }; + pie.padAngle = function(_) { + if (!arguments.length) return padAngle; + padAngle = _; + return pie; + }; + return pie; + }; + var d3_layout_pieSortByValue = {}; + d3.layout.stack = function() { + var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; + function stack(data, index) { + if (!(n = data.length)) return data; + var series = data.map(function(d, i) { + return values.call(stack, d, i); + }); + var points = series.map(function(d) { + return d.map(function(v, i) { + return [ x.call(stack, v, i), y.call(stack, v, i) ]; + }); + }); + var orders = order.call(stack, points, index); + series = d3.permute(series, orders); + points = d3.permute(points, orders); + var offsets = offset.call(stack, points, index); + var m = series[0].length, n, i, j, o; + for (j = 0; j < m; ++j) { + out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); + for (i = 1; i < n; ++i) { + out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + } + } + return data; + } + stack.values = function(x) { + if (!arguments.length) return values; + values = x; + return stack; + }; + stack.order = function(x) { + if (!arguments.length) return order; + order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; + return stack; + }; + stack.offset = function(x) { + if (!arguments.length) return offset; + offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; + return stack; + }; + stack.x = function(z) { + if (!arguments.length) return x; + x = z; + return stack; + }; + stack.y = function(z) { + if (!arguments.length) return y; + y = z; + return stack; + }; + stack.out = function(z) { + if (!arguments.length) return out; + out = z; + return stack; + }; + return stack; + }; + function d3_layout_stackX(d) { + return d.x; + } + function d3_layout_stackY(d) { + return d.y; + } + function d3_layout_stackOut(d, y0, y) { + d.y0 = y0; + d.y = y; + } + var d3_layout_stackOrders = d3.map({ + "inside-out": function(data) { + var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { + return max[a] - max[b]; + }), top = 0, bottom = 0, tops = [], bottoms = []; + for (i = 0; i < n; ++i) { + j = index[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + return bottoms.reverse().concat(tops); + }, + reverse: function(data) { + return d3.range(data.length).reverse(); + }, + "default": d3_layout_stackOrderDefault + }); + var d3_layout_stackOffsets = d3.map({ + silhouette: function(data) { + var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o > max) max = o; + sums.push(o); + } + for (j = 0; j < m; ++j) { + y0[j] = (max - sums[j]) / 2; + } + return y0; + }, + wiggle: function(data) { + var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; + y0[0] = o = o0 = 0; + for (j = 1; j < m; ++j) { + for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; + for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { + for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { + s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; + } + s2 += s3 * data[i][j][1]; + } + y0[j] = o -= s1 ? s2 / s1 * dx : 0; + if (o < o0) o0 = o; + } + for (j = 0; j < m; ++j) y0[j] -= o0; + return y0; + }, + expand: function(data) { + var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }, + zero: d3_layout_stackOffsetZero + }); + function d3_layout_stackOrderDefault(data) { + return d3.range(data.length); + } + function d3_layout_stackOffsetZero(data) { + var j = -1, m = data[0].length, y0 = []; + while (++j < m) y0[j] = 0; + return y0; + } + function d3_layout_stackMaxIndex(array) { + var i = 1, j = 0, v = array[0][1], k, n = array.length; + for (;i < n; ++i) { + if ((k = array[i][1]) > v) { + j = i; + v = k; + } + } + return j; + } + function d3_layout_stackReduceSum(d) { + return d.reduce(d3_layout_stackSum, 0); + } + function d3_layout_stackSum(p, d) { + return p + d[1]; + } + d3.layout.histogram = function() { + var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; + function histogram(data, i) { + var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; + while (++i < m) { + bin = bins[i] = []; + bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); + bin.y = 0; + } + if (m > 0) { + i = -1; + while (++i < n) { + x = values[i]; + if (x >= range[0] && x <= range[1]) { + bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; + bin.y += k; + bin.push(data[i]); + } + } + } + return bins; + } + histogram.value = function(x) { + if (!arguments.length) return valuer; + valuer = x; + return histogram; + }; + histogram.range = function(x) { + if (!arguments.length) return ranger; + ranger = d3_functor(x); + return histogram; + }; + histogram.bins = function(x) { + if (!arguments.length) return binner; + binner = typeof x === "number" ? function(range) { + return d3_layout_histogramBinFixed(range, x); + } : d3_functor(x); + return histogram; + }; + histogram.frequency = function(x) { + if (!arguments.length) return frequency; + frequency = !!x; + return histogram; + }; + return histogram; + }; + function d3_layout_histogramBinSturges(range, values) { + return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); + } + function d3_layout_histogramBinFixed(range, n) { + var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; + while (++x <= n) f[x] = m * x + b; + return f; + } + function d3_layout_histogramRange(values) { + return [ d3.min(values), d3.max(values) ]; + } + d3.layout.pack = function() { + var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; + function pack(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { + return radius; + }; + root.x = root.y = 0; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r = +r(d.value); + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + if (padding) { + var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r += dr; + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r -= dr; + }); + } + d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); + return nodes; + } + pack.size = function(_) { + if (!arguments.length) return size; + size = _; + return pack; + }; + pack.radius = function(_) { + if (!arguments.length) return radius; + radius = _ == null || typeof _ === "function" ? _ : +_; + return pack; + }; + pack.padding = function(_) { + if (!arguments.length) return padding; + padding = +_; + return pack; + }; + return d3_layout_hierarchyRebind(pack, hierarchy); + }; + function d3_layout_packSort(a, b) { + return a.value - b.value; + } + function d3_layout_packInsert(a, b) { + var c = a._pack_next; + a._pack_next = b; + b._pack_prev = a; + b._pack_next = c; + c._pack_prev = b; + } + function d3_layout_packSplice(a, b) { + a._pack_next = b; + b._pack_prev = a; + } + function d3_layout_packIntersects(a, b) { + var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; + return .999 * dr * dr > dx * dx + dy * dy; + } + function d3_layout_packSiblings(node) { + if (!(nodes = node.children) || !(n = nodes.length)) return; + var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; + function bound(node) { + xMin = Math.min(node.x - node.r, xMin); + xMax = Math.max(node.x + node.r, xMax); + yMin = Math.min(node.y - node.r, yMin); + yMax = Math.max(node.y + node.r, yMax); + } + nodes.forEach(d3_layout_packLink); + a = nodes[0]; + a.x = -a.r; + a.y = 0; + bound(a); + if (n > 1) { + b = nodes[1]; + b.x = b.r; + b.y = 0; + bound(b); + if (n > 2) { + c = nodes[2]; + d3_layout_packPlace(a, b, c); + bound(c); + d3_layout_packInsert(a, c); + a._pack_prev = c; + d3_layout_packInsert(c, b); + b = a._pack_next; + for (i = 3; i < n; i++) { + d3_layout_packPlace(a, b, c = nodes[i]); + var isect = 0, s1 = 1, s2 = 1; + for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { + if (d3_layout_packIntersects(j, c)) { + isect = 1; + break; + } + } + if (isect == 1) { + for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { + if (d3_layout_packIntersects(k, c)) { + break; + } + } + } + if (isect) { + if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); + i--; + } else { + d3_layout_packInsert(a, c); + b = c; + bound(c); + } + } + } + } + var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; + for (i = 0; i < n; i++) { + c = nodes[i]; + c.x -= cx; + c.y -= cy; + cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); + } + node.r = cr; + nodes.forEach(d3_layout_packUnlink); + } + function d3_layout_packLink(node) { + node._pack_next = node._pack_prev = node; + } + function d3_layout_packUnlink(node) { + delete node._pack_next; + delete node._pack_prev; + } + function d3_layout_packTransform(node, x, y, k) { + var children = node.children; + node.x = x += k * node.x; + node.y = y += k * node.y; + node.r *= k; + if (children) { + var i = -1, n = children.length; + while (++i < n) d3_layout_packTransform(children[i], x, y, k); + } + } + function d3_layout_packPlace(a, b, c) { + var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; + if (db && (dx || dy)) { + var da = b.r + c.r, dc = dx * dx + dy * dy; + da *= da; + db *= db; + var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = a.x + x * dx + y * dy; + c.y = a.y + x * dy - y * dx; + } else { + c.x = a.x + db; + c.y = a.y; + } + } + d3.layout.tree = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; + function tree(d, i) { + var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); + d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; + d3_layout_hierarchyVisitBefore(root1, secondWalk); + if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { + var left = root0, right = root0, bottom = root0; + d3_layout_hierarchyVisitBefore(root0, function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); + d3_layout_hierarchyVisitBefore(root0, function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + return nodes; + } + function wrapTree(root0) { + var root1 = { + A: null, + children: [ root0 ] + }, queue = [ root1 ], node1; + while ((node1 = queue.pop()) != null) { + for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { + queue.push((children[i] = child = { + _: children[i], + parent: node1, + children: (child = children[i].children) && child.slice() || [], + A: null, + a: null, + z: 0, + m: 0, + c: 0, + s: 0, + t: null, + i: i + }).a = child); + } + } + return root1.children[0]; + } + function firstWalk(v) { + var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; + if (children.length) { + d3_layout_treeShift(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + function apportion(v, w, ancestor) { + if (w) { + var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; + while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { + vom = d3_layout_treeLeft(vom); + vop = d3_layout_treeRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !d3_layout_treeRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !d3_layout_treeLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + function sizeNode(node) { + node.x *= size[0]; + node.y = node.depth * size[1]; + } + tree.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return tree; + }; + tree.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null ? sizeNode : null; + return tree; + }; + tree.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) == null ? null : sizeNode; + return tree; + }; + return d3_layout_hierarchyRebind(tree, hierarchy); + }; + function d3_layout_treeSeparation(a, b) { + return a.parent == b.parent ? 1 : 2; + } + function d3_layout_treeLeft(v) { + var children = v.children; + return children.length ? children[0] : v.t; + } + function d3_layout_treeRight(v) { + var children = v.children, n; + return (n = children.length) ? children[n - 1] : v.t; + } + function d3_layout_treeMove(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; + } + function d3_layout_treeShift(v) { + var shift = 0, change = 0, children = v.children, i = children.length, w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } + } + function d3_layout_treeAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + d3.layout.cluster = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; + function cluster(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; + d3_layout_hierarchyVisitAfter(root, function(node) { + var children = node.children; + if (children && children.length) { + node.x = d3_layout_clusterX(children); + node.y = d3_layout_clusterY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; + d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { + node.x = (node.x - root.x) * size[0]; + node.y = (root.y - node.y) * size[1]; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * size[0]; + node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + }); + return nodes; + } + cluster.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return cluster; + }; + cluster.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null; + return cluster; + }; + cluster.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) != null; + return cluster; + }; + return d3_layout_hierarchyRebind(cluster, hierarchy); + }; + function d3_layout_clusterY(children) { + return 1 + d3.max(children, function(child) { + return child.y; + }); + } + function d3_layout_clusterX(children) { + return children.reduce(function(x, child) { + return x + child.x; + }, 0) / children.length; + } + function d3_layout_clusterLeft(node) { + var children = node.children; + return children && children.length ? d3_layout_clusterLeft(children[0]) : node; + } + function d3_layout_clusterRight(node) { + var children = node.children, n; + return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + } + d3.layout.treemap = function() { + var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); + function scale(children, k) { + var i = -1, n = children.length, child, area; + while (++i < n) { + area = (child = children[i]).value * (k < 0 ? 0 : k); + child.area = isNaN(area) || area <= 0 ? 0 : area; + } + } + function squarify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while ((n = remaining.length) > 0) { + row.push(child = remaining[n - 1]); + row.area += child.area; + if (mode !== "squarify" || (score = worst(row, u)) <= best) { + remaining.pop(); + best = score; + } else { + row.area -= row.pop().area; + position(row, u, rect, false); + u = Math.min(rect.dx, rect.dy); + row.length = row.area = 0; + best = Infinity; + } + } + if (row.length) { + position(row, u, rect, true); + row.length = row.area = 0; + } + children.forEach(squarify); + } + } + function stickify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), remaining = children.slice(), child, row = []; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while (child = remaining.pop()) { + row.push(child); + row.area += child.area; + if (child.z != null) { + position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); + row.length = row.area = 0; + } + } + children.forEach(stickify); + } + } + function worst(row, u) { + var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; + while (++i < n) { + if (!(r = row[i].area)) continue; + if (r < rmin) rmin = r; + if (r > rmax) rmax = r; + } + s *= s; + u *= u; + return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; + } + function position(row, u, rect, flush) { + var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; + if (u == rect.dx) { + if (flush || v > rect.dy) v = rect.dy; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dy = v; + x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); + } + o.z = true; + o.dx += rect.x + rect.dx - x; + rect.y += v; + rect.dy -= v; + } else { + if (flush || v > rect.dx) v = rect.dx; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dx = v; + y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); + } + o.z = false; + o.dy += rect.y + rect.dy - y; + rect.x += v; + rect.dx -= v; + } + } + function treemap(d) { + var nodes = stickies || hierarchy(d), root = nodes[0]; + root.x = root.y = 0; + if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; + if (stickies) hierarchy.revalue(root); + scale([ root ], root.dx * root.dy / root.value); + (stickies ? stickify : squarify)(root); + if (sticky) stickies = nodes; + return nodes; + } + treemap.size = function(x) { + if (!arguments.length) return size; + size = x; + return treemap; + }; + treemap.padding = function(x) { + if (!arguments.length) return padding; + function padFunction(node) { + var p = x.call(treemap, node, node.depth); + return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); + } + function padConstant(node) { + return d3_layout_treemapPad(node, x); + } + var type; + pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], + padConstant) : padConstant; + return treemap; + }; + treemap.round = function(x) { + if (!arguments.length) return round != Number; + round = x ? Math.round : Number; + return treemap; + }; + treemap.sticky = function(x) { + if (!arguments.length) return sticky; + sticky = x; + stickies = null; + return treemap; + }; + treemap.ratio = function(x) { + if (!arguments.length) return ratio; + ratio = x; + return treemap; + }; + treemap.mode = function(x) { + if (!arguments.length) return mode; + mode = x + ""; + return treemap; + }; + return d3_layout_hierarchyRebind(treemap, hierarchy); + }; + function d3_layout_treemapPadNull(node) { + return { + x: node.x, + y: node.y, + dx: node.dx, + dy: node.dy + }; + } + function d3_layout_treemapPad(node, padding) { + var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; + if (dx < 0) { + x += dx / 2; + dx = 0; + } + if (dy < 0) { + y += dy / 2; + dy = 0; + } + return { + x: x, + y: y, + dx: dx, + dy: dy + }; + } + d3.random = { + normal: function(µ, σ) { + var n = arguments.length; + if (n < 2) σ = 1; + if (n < 1) µ = 0; + return function() { + var x, y, r; + do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); + }; + }, + logNormal: function() { + var random = d3.random.normal.apply(d3, arguments); + return function() { + return Math.exp(random()); + }; + }, + bates: function(m) { + var random = d3.random.irwinHall(m); + return function() { + return random() / m; + }; + }, + irwinHall: function(m) { + return function() { + for (var s = 0, j = 0; j < m; j++) s += Math.random(); + return s; + }; + } + }; + d3.scale = {}; + function d3_scaleExtent(domain) { + var start = domain[0], stop = domain[domain.length - 1]; + return start < stop ? [ start, stop ] : [ stop, start ]; + } + function d3_scaleRange(scale) { + return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + } + function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { + var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); + return function(x) { + return i(u(x)); + }; + } + function d3_scale_nice(domain, nice) { + var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; + if (x1 < x0) { + dx = i0, i0 = i1, i1 = dx; + dx = x0, x0 = x1, x1 = dx; + } + domain[i0] = nice.floor(x0); + domain[i1] = nice.ceil(x1); + return domain; + } + function d3_scale_niceStep(step) { + return step ? { + floor: function(x) { + return Math.floor(x / step) * step; + }, + ceil: function(x) { + return Math.ceil(x / step) * step; + } + } : d3_scale_niceIdentity; + } + var d3_scale_niceIdentity = { + floor: d3_identity, + ceil: d3_identity + }; + function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { + var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; + if (domain[k] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + while (++j <= k) { + u.push(uninterpolate(domain[j - 1], domain[j])); + i.push(interpolate(range[j - 1], range[j])); + } + return function(x) { + var j = d3.bisect(domain, x, 1, k) - 1; + return i[j](u[j](x)); + }; + } + d3.scale.linear = function() { + return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + }; + function d3_scale_linear(domain, range, interpolate, clamp) { + var output, input; + function rescale() { + var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; + output = linear(domain, range, uninterpolate, interpolate); + input = linear(range, domain, uninterpolate, d3_interpolate); + return scale; + } + function scale(x) { + return output(x); + } + scale.invert = function(y) { + return input(y); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(Number); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.rangeRound = function(x) { + return scale.range(x).interpolate(d3_interpolateRound); + }; + scale.clamp = function(x) { + if (!arguments.length) return clamp; + clamp = x; + return rescale(); + }; + scale.interpolate = function(x) { + if (!arguments.length) return interpolate; + interpolate = x; + return rescale(); + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + d3_scale_linearNice(domain, m); + return rescale(); + }; + scale.copy = function() { + return d3_scale_linear(domain, range, interpolate, clamp); + }; + return rescale(); + } + function d3_scale_linearRebind(scale, linear) { + return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); + } + function d3_scale_linearNice(domain, m) { + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + return domain; + } + function d3_scale_linearTickRange(domain, m) { + if (m == null) m = 10; + var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; + if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; + extent[0] = Math.ceil(extent[0] / step) * step; + extent[1] = Math.floor(extent[1] / step) * step + step * .5; + extent[2] = step; + return extent; + } + function d3_scale_linearTicks(domain, m) { + return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); + } + function d3_scale_linearTickFormat(domain, m, format) { + var range = d3_scale_linearTickRange(domain, m); + if (format) { + var match = d3_format_re.exec(format); + match.shift(); + if (match[8] === "s") { + var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); + if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); + match[8] = "f"; + format = d3.format(match.join("")); + return function(d) { + return format(prefix.scale(d)) + prefix.symbol; + }; + } + if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); + format = match.join(""); + } else { + format = ",." + d3_scale_linearPrecision(range[2]) + "f"; + } + return d3.format(format); + } + var d3_scale_linearFormatSignificant = { + s: 1, + g: 1, + p: 1, + r: 1, + e: 1 + }; + function d3_scale_linearPrecision(value) { + return -Math.floor(Math.log(value) / Math.LN10 + .01); + } + function d3_scale_linearFormatPrecision(type, range) { + var p = d3_scale_linearPrecision(range[2]); + return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; + } + d3.scale.log = function() { + return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); + }; + function d3_scale_log(linear, base, positive, domain) { + function log(x) { + return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); + } + function pow(x) { + return positive ? Math.pow(base, x) : -Math.pow(base, -x); + } + function scale(x) { + return linear(log(x)); + } + scale.invert = function(x) { + return pow(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + positive = x[0] >= 0; + linear.domain((domain = x.map(Number)).map(log)); + return scale; + }; + scale.base = function(_) { + if (!arguments.length) return base; + base = +_; + linear.domain(domain.map(log)); + return scale; + }; + scale.nice = function() { + var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); + linear.domain(niced); + domain = niced.map(pow); + return scale; + }; + scale.ticks = function() { + var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; + if (isFinite(j - i)) { + if (positive) { + for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); + ticks.push(pow(i)); + } else { + ticks.push(pow(i)); + for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); + } + for (i = 0; ticks[i] < u; i++) {} + for (j = ticks.length; ticks[j - 1] > v; j--) {} + ticks = ticks.slice(i, j); + } + return ticks; + }; + scale.tickFormat = function(n, format) { + if (!arguments.length) return d3_scale_logFormat; + if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); + var k = Math.max(1, base * n / scale.ticks().length); + return function(d) { + var i = d / pow(Math.round(log(d))); + if (i * base < base - .5) i *= base; + return i <= k ? format(d) : ""; + }; + }; + scale.copy = function() { + return d3_scale_log(linear.copy(), base, positive, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { + floor: function(x) { + return -Math.ceil(-x); + }, + ceil: function(x) { + return -Math.floor(-x); + } + }; + d3.scale.pow = function() { + return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); + }; + function d3_scale_pow(linear, exponent, domain) { + var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); + function scale(x) { + return linear(powp(x)); + } + scale.invert = function(x) { + return powb(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + linear.domain((domain = x.map(Number)).map(powp)); + return scale; + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + return scale.domain(d3_scale_linearNice(domain, m)); + }; + scale.exponent = function(x) { + if (!arguments.length) return exponent; + powp = d3_scale_powPow(exponent = x); + powb = d3_scale_powPow(1 / exponent); + linear.domain(domain.map(powp)); + return scale; + }; + scale.copy = function() { + return d3_scale_pow(linear.copy(), exponent, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_scale_powPow(e) { + return function(x) { + return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + }; + } + d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5); + }; + d3.scale.ordinal = function() { + return d3_scale_ordinal([], { + t: "range", + a: [ [] ] + }); + }; + function d3_scale_ordinal(domain, ranger) { + var index, range, rangeBand; + function scale(x) { + return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; + } + function steps(start, step) { + return d3.range(domain.length).map(function(i) { + return start + step * i; + }); + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = []; + index = new d3_Map(); + var i = -1, n = x.length, xi; + while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); + return scale[ranger.t].apply(scale, ranger.a); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + rangeBand = 0; + ranger = { + t: "range", + a: arguments + }; + return scale; + }; + scale.rangePoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, + 0) : (stop - start) / (domain.length - 1 + padding); + range = steps(start + step * padding / 2, step); + rangeBand = 0; + ranger = { + t: "rangePoints", + a: arguments + }; + return scale; + }; + scale.rangeRoundPoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), + 0) : (stop - start) / (domain.length - 1 + padding) | 0; + range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); + rangeBand = 0; + ranger = { + t: "rangeRoundPoints", + a: arguments + }; + return scale; + }; + scale.rangeBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); + range = steps(start + step * outerPadding, step); + if (reverse) range.reverse(); + rangeBand = step * (1 - padding); + ranger = { + t: "rangeBands", + a: arguments + }; + return scale; + }; + scale.rangeRoundBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); + range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); + if (reverse) range.reverse(); + rangeBand = Math.round(step * (1 - padding)); + ranger = { + t: "rangeRoundBands", + a: arguments + }; + return scale; + }; + scale.rangeBand = function() { + return rangeBand; + }; + scale.rangeExtent = function() { + return d3_scaleExtent(ranger.a[0]); + }; + scale.copy = function() { + return d3_scale_ordinal(domain, ranger); + }; + return scale.domain(domain); + } + d3.scale.category10 = function() { + return d3.scale.ordinal().range(d3_category10); + }; + d3.scale.category20 = function() { + return d3.scale.ordinal().range(d3_category20); + }; + d3.scale.category20b = function() { + return d3.scale.ordinal().range(d3_category20b); + }; + d3.scale.category20c = function() { + return d3.scale.ordinal().range(d3_category20c); + }; + var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); + var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); + var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); + var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); + d3.scale.quantile = function() { + return d3_scale_quantile([], []); + }; + function d3_scale_quantile(domain, range) { + var thresholds; + function rescale() { + var k = 0, q = range.length; + thresholds = []; + while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); + return scale; + } + function scale(x) { + if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.quantiles = function() { + return thresholds; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; + }; + scale.copy = function() { + return d3_scale_quantile(domain, range); + }; + return rescale(); + } + d3.scale.quantize = function() { + return d3_scale_quantize(0, 1, [ 0, 1 ]); + }; + function d3_scale_quantize(x0, x1, range) { + var kx, i; + function scale(x) { + return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; + } + function rescale() { + kx = range.length / (x1 - x0); + i = range.length - 1; + return scale; + } + scale.domain = function(x) { + if (!arguments.length) return [ x0, x1 ]; + x0 = +x[0]; + x1 = +x[x.length - 1]; + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + y = y < 0 ? NaN : y / kx + x0; + return [ y, y + 1 / kx ]; + }; + scale.copy = function() { + return d3_scale_quantize(x0, x1, range); + }; + return rescale(); + } + d3.scale.threshold = function() { + return d3_scale_threshold([ .5 ], [ 0, 1 ]); + }; + function d3_scale_threshold(domain, range) { + function scale(x) { + if (x <= x) return range[d3.bisect(domain, x)]; + } + scale.domain = function(_) { + if (!arguments.length) return domain; + domain = _; + return scale; + }; + scale.range = function(_) { + if (!arguments.length) return range; + range = _; + return scale; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return [ domain[y - 1], domain[y] ]; + }; + scale.copy = function() { + return d3_scale_threshold(domain, range); + }; + return scale; + } + d3.scale.identity = function() { + return d3_scale_identity([ 0, 1 ]); + }; + function d3_scale_identity(domain) { + function identity(x) { + return +x; + } + identity.invert = identity; + identity.domain = identity.range = function(x) { + if (!arguments.length) return domain; + domain = x.map(identity); + return identity; + }; + identity.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + identity.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + identity.copy = function() { + return d3_scale_identity(domain); + }; + return identity; + } + d3.svg = {}; + function d3_zero() { + return 0; + } + d3.svg.arc = function() { + var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; + function arc() { + var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; + if (r1 < r0) rc = r1, r1 = r0, r0 = rc; + if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; + var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; + if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { + rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); + if (!cw) p1 *= -1; + if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); + if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); + } + if (r1) { + x0 = r1 * Math.cos(a0 + p1); + y0 = r1 * Math.sin(a0 + p1); + x1 = r1 * Math.cos(a1 - p1); + y1 = r1 * Math.sin(a1 - p1); + var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; + if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { + var h1 = (a0 + a1) / 2; + x0 = r1 * Math.cos(h1); + y0 = r1 * Math.sin(h1); + x1 = y1 = null; + } + } else { + x0 = y0 = 0; + } + if (r0) { + x2 = r0 * Math.cos(a1 - p0); + y2 = r0 * Math.sin(a1 - p0); + x3 = r0 * Math.cos(a0 + p0); + y3 = r0 * Math.sin(a0 + p0); + var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; + if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { + var h0 = (a0 + a1) / 2; + x2 = r0 * Math.cos(h0); + y2 = r0 * Math.sin(h0); + x3 = y3 = null; + } + } else { + x2 = y2 = 0; + } + if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { + cr = r0 < r1 ^ cw ? 0 : 1; + var rc1 = rc, rc0 = rc; + if (da < π) { + var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); + rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); + } + if (x1 != null) { + var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); + if (rc === rc1) { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); + } else { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); + } + } else { + path.push("M", x0, ",", y0); + } + if (x3 != null) { + var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); + if (rc === rc0) { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } else { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } + } else { + path.push("L", x2, ",", y2); + } + } else { + path.push("M", x0, ",", y0); + if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); + path.push("L", x2, ",", y2); + if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); + } + path.push("Z"); + return path.join(""); + } + function circleSegment(r1, cw) { + return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; + } + arc.innerRadius = function(v) { + if (!arguments.length) return innerRadius; + innerRadius = d3_functor(v); + return arc; + }; + arc.outerRadius = function(v) { + if (!arguments.length) return outerRadius; + outerRadius = d3_functor(v); + return arc; + }; + arc.cornerRadius = function(v) { + if (!arguments.length) return cornerRadius; + cornerRadius = d3_functor(v); + return arc; + }; + arc.padRadius = function(v) { + if (!arguments.length) return padRadius; + padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); + return arc; + }; + arc.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return arc; + }; + arc.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return arc; + }; + arc.padAngle = function(v) { + if (!arguments.length) return padAngle; + padAngle = d3_functor(v); + return arc; + }; + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; + return [ Math.cos(a) * r, Math.sin(a) * r ]; + }; + return arc; + }; + var d3_svg_arcAuto = "auto"; + function d3_svg_arcInnerRadius(d) { + return d.innerRadius; + } + function d3_svg_arcOuterRadius(d) { + return d.outerRadius; + } + function d3_svg_arcStartAngle(d) { + return d.startAngle; + } + function d3_svg_arcEndAngle(d) { + return d.endAngle; + } + function d3_svg_arcPadAngle(d) { + return d && d.padAngle; + } + function d3_svg_arcSweep(x0, y0, x1, y1) { + return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; + } + function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { + var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; + } + function d3_svg_line(projection) { + var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; + function line(data) { + var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); + function segment() { + segments.push("M", interpolate(projection(points), tension)); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); + } else if (points.length) { + segment(); + points = []; + } + } + if (points.length) segment(); + return segments.length ? segments.join("") : null; + } + line.x = function(_) { + if (!arguments.length) return x; + x = _; + return line; + }; + line.y = function(_) { + if (!arguments.length) return y; + y = _; + return line; + }; + line.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return line; + }; + line.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + return line; + }; + line.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return line; + }; + return line; + } + d3.svg.line = function() { + return d3_svg_line(d3_identity); + }; + var d3_svg_lineInterpolators = d3.map({ + linear: d3_svg_lineLinear, + "linear-closed": d3_svg_lineLinearClosed, + step: d3_svg_lineStep, + "step-before": d3_svg_lineStepBefore, + "step-after": d3_svg_lineStepAfter, + basis: d3_svg_lineBasis, + "basis-open": d3_svg_lineBasisOpen, + "basis-closed": d3_svg_lineBasisClosed, + bundle: d3_svg_lineBundle, + cardinal: d3_svg_lineCardinal, + "cardinal-open": d3_svg_lineCardinalOpen, + "cardinal-closed": d3_svg_lineCardinalClosed, + monotone: d3_svg_lineMonotone + }); + d3_svg_lineInterpolators.forEach(function(key, value) { + value.key = key; + value.closed = /-closed$/.test(key); + }); + function d3_svg_lineLinear(points) { + return points.length > 1 ? points.join("L") : points + "Z"; + } + function d3_svg_lineLinearClosed(points) { + return points.join("L") + "Z"; + } + function d3_svg_lineStep(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); + if (n > 1) path.push("H", p[0]); + return path.join(""); + } + function d3_svg_lineStepBefore(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); + return path.join(""); + } + function d3_svg_lineStepAfter(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); + return path.join(""); + } + function d3_svg_lineCardinalOpen(points, tension) { + return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineCardinalClosed(points, tension) { + return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), + points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + } + function d3_svg_lineCardinal(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineHermite(points, tangents) { + if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { + return d3_svg_lineLinear(points); + } + var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; + if (quad) { + path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; + p0 = points[1]; + pi = 2; + } + if (tangents.length > 1) { + t = tangents[1]; + p = points[pi]; + pi++; + path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + for (var i = 2; i < tangents.length; i++, pi++) { + p = points[pi]; + t = tangents[i]; + path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + } + } + if (quad) { + var lp = points[pi]; + path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + } + return path; + } + function d3_svg_lineCardinalTangents(points, tension) { + var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; + while (++i < n) { + p0 = p1; + p1 = p2; + p2 = points[i]; + tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + } + return tangents; + } + function d3_svg_lineBasis(points) { + if (points.length < 3) return d3_svg_lineLinear(points); + var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + points.push(points[n - 1]); + while (++i <= n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + points.pop(); + path.push("L", pi); + return path.join(""); + } + function d3_svg_lineBasisOpen(points) { + if (points.length < 4) return d3_svg_lineLinear(points); + var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; + while (++i < 3) { + pi = points[i]; + px.push(pi[0]); + py.push(pi[1]); + } + path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); + --i; + while (++i < n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBasisClosed(points) { + var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; + while (++i < 4) { + pi = points[i % n]; + px.push(pi[0]); + py.push(pi[1]); + } + path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + --i; + while (++i < m) { + pi = points[i % n]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBundle(points, tension) { + var n = points.length - 1; + if (n) { + var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; + while (++i <= n) { + p = points[i]; + t = i / n; + p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); + p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); + } + } + return d3_svg_lineBasis(points); + } + function d3_svg_lineDot4(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + } + var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; + function d3_svg_lineBasisBezier(path, x, y) { + path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); + } + function d3_svg_lineSlope(p0, p1) { + return (p1[1] - p0[1]) / (p1[0] - p0[0]); + } + function d3_svg_lineFiniteDifferences(points) { + var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); + while (++i < j) { + m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + } + m[i] = d; + return m; + } + function d3_svg_lineMonotoneTangents(points) { + var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; + while (++i < j) { + d = d3_svg_lineSlope(points[i], points[i + 1]); + if (abs(d) < ε) { + m[i] = m[i + 1] = 0; + } else { + a = m[i] / d; + b = m[i + 1] / d; + s = a * a + b * b; + if (s > 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } + } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); + tangents.push([ s || 0, m[i] * s || 0 ]); + } + return tangents; + } + function d3_svg_lineMonotone(points) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); + } + d3.svg.line.radial = function() { + var line = d3_svg_line(d3_svg_lineRadial); + line.radius = line.x, delete line.x; + line.angle = line.y, delete line.y; + return line; + }; + function d3_svg_lineRadial(points) { + var point, i = -1, n = points.length, r, a; + while (++i < n) { + point = points[i]; + r = point[0]; + a = point[1] - halfπ; + point[0] = r * Math.cos(a); + point[1] = r * Math.sin(a); + } + return points; + } + function d3_svg_area(projection) { + var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; + function area(data) { + var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { + return x; + } : d3_functor(x1), fy1 = y0 === y1 ? function() { + return y; + } : d3_functor(y1), x, y; + function segment() { + segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); + points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); + } else if (points0.length) { + segment(); + points0 = []; + points1 = []; + } + } + if (points0.length) segment(); + return segments.length ? segments.join("") : null; + } + area.x = function(_) { + if (!arguments.length) return x1; + x0 = x1 = _; + return area; + }; + area.x0 = function(_) { + if (!arguments.length) return x0; + x0 = _; + return area; + }; + area.x1 = function(_) { + if (!arguments.length) return x1; + x1 = _; + return area; + }; + area.y = function(_) { + if (!arguments.length) return y1; + y0 = y1 = _; + return area; + }; + area.y0 = function(_) { + if (!arguments.length) return y0; + y0 = _; + return area; + }; + area.y1 = function(_) { + if (!arguments.length) return y1; + y1 = _; + return area; + }; + area.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return area; + }; + area.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + interpolateReverse = interpolate.reverse || interpolate; + L = interpolate.closed ? "M" : "L"; + return area; + }; + area.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return area; + }; + return area; + } + d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; + d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; + d3.svg.area = function() { + return d3_svg_area(d3_identity); + }; + d3.svg.area.radial = function() { + var area = d3_svg_area(d3_svg_lineRadial); + area.radius = area.x, delete area.x; + area.innerRadius = area.x0, delete area.x0; + area.outerRadius = area.x1, delete area.x1; + area.angle = area.y, delete area.y; + area.startAngle = area.y0, delete area.y0; + area.endAngle = area.y1, delete area.y1; + return area; + }; + d3.svg.chord = function() { + var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; + function chord(d, i) { + var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); + return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; + } + function subgroup(self, f, d, i) { + var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; + return { + r: r, + a0: a0, + a1: a1, + p0: [ r * Math.cos(a0), r * Math.sin(a0) ], + p1: [ r * Math.cos(a1), r * Math.sin(a1) ] + }; + } + function equals(a, b) { + return a.a0 == b.a0 && a.a1 == b.a1; + } + function arc(r, p, a) { + return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; + } + function curve(r0, p0, r1, p1) { + return "Q 0,0 " + p1; + } + chord.radius = function(v) { + if (!arguments.length) return radius; + radius = d3_functor(v); + return chord; + }; + chord.source = function(v) { + if (!arguments.length) return source; + source = d3_functor(v); + return chord; + }; + chord.target = function(v) { + if (!arguments.length) return target; + target = d3_functor(v); + return chord; + }; + chord.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return chord; + }; + chord.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return chord; + }; + return chord; + }; + function d3_svg_chordRadius(d) { + return d.radius; + } + d3.svg.diagonal = function() { + var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; + function diagonal(d, i) { + var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { + x: p0.x, + y: m + }, { + x: p3.x, + y: m + }, p3 ]; + p = p.map(projection); + return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; + } + diagonal.source = function(x) { + if (!arguments.length) return source; + source = d3_functor(x); + return diagonal; + }; + diagonal.target = function(x) { + if (!arguments.length) return target; + target = d3_functor(x); + return diagonal; + }; + diagonal.projection = function(x) { + if (!arguments.length) return projection; + projection = x; + return diagonal; + }; + return diagonal; + }; + function d3_svg_diagonalProjection(d) { + return [ d.x, d.y ]; + } + d3.svg.diagonal.radial = function() { + var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; + diagonal.projection = function(x) { + return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; + }; + return diagonal; + }; + function d3_svg_diagonalRadialProjection(projection) { + return function() { + var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; + return [ r * Math.cos(a), r * Math.sin(a) ]; + }; + } + d3.svg.symbol = function() { + var type = d3_svg_symbolType, size = d3_svg_symbolSize; + function symbol(d, i) { + return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); + } + symbol.type = function(x) { + if (!arguments.length) return type; + type = d3_functor(x); + return symbol; + }; + symbol.size = function(x) { + if (!arguments.length) return size; + size = d3_functor(x); + return symbol; + }; + return symbol; + }; + function d3_svg_symbolSize() { + return 64; + } + function d3_svg_symbolType() { + return "circle"; + } + function d3_svg_symbolCircle(size) { + var r = Math.sqrt(size / π); + return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + } + var d3_svg_symbols = d3.map({ + circle: d3_svg_symbolCircle, + cross: function(size) { + var r = Math.sqrt(size / 5) / 2; + return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; + }, + diamond: function(size) { + var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; + return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; + }, + square: function(size) { + var r = Math.sqrt(size) / 2; + return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; + }, + "triangle-down": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; + }, + "triangle-up": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; + } + }); + d3.svg.symbolTypes = d3_svg_symbols.keys(); + var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); + d3_selectionPrototype.transition = function(name) { + var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { + time: Date.now(), + ease: d3_ease_cubicInOut, + delay: 0, + duration: 250 + }; + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id); + }; + d3_selectionPrototype.interrupt = function(name) { + return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); + }; + var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); + function d3_selection_interruptNS(ns) { + return function() { + var lock, activeId, active; + if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { + active.timer.c = null; + active.timer.t = NaN; + if (--lock.count) delete lock[activeId]; else delete this[ns]; + lock.active += .5; + active.event && active.event.interrupt.call(this, this.__data__, active.index); + } + }; + } + function d3_transition(groups, ns, id) { + d3_subclass(groups, d3_transitionPrototype); + groups.namespace = ns; + groups.id = id; + return groups; + } + var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; + d3_transitionPrototype.call = d3_selectionPrototype.call; + d3_transitionPrototype.empty = d3_selectionPrototype.empty; + d3_transitionPrototype.node = d3_selectionPrototype.node; + d3_transitionPrototype.size = d3_selectionPrototype.size; + d3.transition = function(selection, name) { + return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); + }; + d3.transition.prototype = d3_transitionPrototype; + d3_transitionPrototype.select = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + d3_transitionNode(subnode, i, ns, id, node[ns][id]); + subgroup.push(subnode); + } else { + subgroup.push(null); + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.selectAll = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + transition = node[ns][id]; + subnodes = selector.call(node, node.__data__, i, j); + subgroups.push(subgroup = []); + for (var k = -1, o = subnodes.length; ++k < o; ) { + if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); + subgroup.push(subnode); + } + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_transition(subgroups, this.namespace, this.id); + }; + d3_transitionPrototype.tween = function(name, tween) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) return this.node()[ns][id].tween.get(name); + return d3_selection_each(this, tween == null ? function(node) { + node[ns][id].tween.remove(name); + } : function(node) { + node[ns][id].tween.set(name, tween); + }); + }; + function d3_transition_tween(groups, name, value, tween) { + var id = groups.id, ns = groups.namespace; + return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { + node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); + } : (value = tween(value), function(node) { + node[ns][id].tween.set(name, value); + })); + } + d3_transitionPrototype.attr = function(nameNS, value) { + if (arguments.length < 2) { + for (value in nameNS) this.attr(value, nameNS[value]); + return this; + } + var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrTween(b) { + return b == null ? attrNull : (b += "", function() { + var a = this.getAttribute(name), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttribute(name, i(t)); + }); + }); + } + function attrTweenNS(b) { + return b == null ? attrNullNS : (b += "", function() { + var a = this.getAttributeNS(name.space, name.local), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttributeNS(name.space, name.local, i(t)); + }); + }); + } + return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.attrTween = function(nameNS, tween) { + var name = d3.ns.qualify(nameNS); + function attrTween(d, i) { + var f = tween.call(this, d, i, this.getAttribute(name)); + return f && function(t) { + this.setAttribute(name, f(t)); + }; + } + function attrTweenNS(d, i) { + var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); + return f && function(t) { + this.setAttributeNS(name.space, name.local, f(t)); + }; + } + return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.style(priority, name[priority], value); + return this; + } + priority = ""; + } + function styleNull() { + this.style.removeProperty(name); + } + function styleString(b) { + return b == null ? styleNull : (b += "", function() { + var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; + return a !== b && (i = d3_interpolate(a, b), function(t) { + this.style.setProperty(name, i(t), priority); + }); + }); + } + return d3_transition_tween(this, "style." + name, value, styleString); + }; + d3_transitionPrototype.styleTween = function(name, tween, priority) { + if (arguments.length < 3) priority = ""; + function styleTween(d, i) { + var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); + return f && function(t) { + this.style.setProperty(name, f(t), priority); + }; + } + return this.tween("style." + name, styleTween); + }; + d3_transitionPrototype.text = function(value) { + return d3_transition_tween(this, "text", value, d3_transition_text); + }; + function d3_transition_text(b) { + if (b == null) b = ""; + return function() { + this.textContent = b; + }; + } + d3_transitionPrototype.remove = function() { + var ns = this.namespace; + return this.each("end.transition", function() { + var p; + if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); + }); + }; + d3_transitionPrototype.ease = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].ease; + if (typeof value !== "function") value = d3.ease.apply(d3, arguments); + return d3_selection_each(this, function(node) { + node[ns][id].ease = value; + }); + }; + d3_transitionPrototype.delay = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].delay; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].delay = +value.call(node, node.__data__, i, j); + } : (value = +value, function(node) { + node[ns][id].delay = value; + })); + }; + d3_transitionPrototype.duration = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].duration; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); + } : (value = Math.max(1, value), function(node) { + node[ns][id].duration = value; + })); + }; + d3_transitionPrototype.each = function(type, listener) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) { + var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; + try { + d3_transitionInheritId = id; + d3_selection_each(this, function(node, i, j) { + d3_transitionInherit = node[ns][id]; + type.call(node, node.__data__, i, j); + }); + } finally { + d3_transitionInherit = inherit; + d3_transitionInheritId = inheritId; + } + } else { + d3_selection_each(this, function(node) { + var transition = node[ns][id]; + (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); + }); + } + return this; + }; + d3_transitionPrototype.transition = function() { + var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if (node = group[i]) { + transition = node[ns][id0]; + d3_transitionNode(node, i, ns, id1, { + time: transition.time, + ease: transition.ease, + delay: transition.delay + transition.duration, + duration: transition.duration + }); + } + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id1); + }; + function d3_transitionNamespace(name) { + return name == null ? "__transition__" : "__transition_" + name + "__"; + } + function d3_transitionNode(node, i, ns, id, inherit) { + var lock = node[ns] || (node[ns] = { + active: 0, + count: 0 + }), transition = lock[id], time, timer, duration, ease, tweens; + function schedule(elapsed) { + var delay = transition.delay; + timer.t = delay + time; + if (delay <= elapsed) return start(elapsed - delay); + timer.c = start; + } + function start(elapsed) { + var activeId = lock.active, active = lock[activeId]; + if (active) { + active.timer.c = null; + active.timer.t = NaN; + --lock.count; + delete lock[activeId]; + active.event && active.event.interrupt.call(node, node.__data__, active.index); + } + for (var cancelId in lock) { + if (+cancelId < id) { + var cancel = lock[cancelId]; + cancel.timer.c = null; + cancel.timer.t = NaN; + --lock.count; + delete lock[cancelId]; + } + } + timer.c = tick; + d3_timer(function() { + if (timer.c && tick(elapsed || 1)) { + timer.c = null; + timer.t = NaN; + } + return 1; + }, 0, time); + lock.active = id; + transition.event && transition.event.start.call(node, node.__data__, i); + tweens = []; + transition.tween.forEach(function(key, value) { + if (value = value.call(node, node.__data__, i)) { + tweens.push(value); + } + }); + ease = transition.ease; + duration = transition.duration; + } + function tick(elapsed) { + var t = elapsed / duration, e = ease(t), n = tweens.length; + while (n > 0) { + tweens[--n].call(node, e); + } + if (t >= 1) { + transition.event && transition.event.end.call(node, node.__data__, i); + if (--lock.count) delete lock[id]; else delete node[ns]; + return 1; + } + } + if (!transition) { + time = inherit.time; + timer = d3_timer(schedule, 0, time); + transition = lock[id] = { + tween: new d3_Map(), + time: time, + timer: timer, + delay: inherit.delay, + duration: inherit.duration, + ease: inherit.ease, + index: i + }; + inherit = null; + ++lock.count; + } + } + d3.svg.axis = function() { + var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; + function axis(g) { + g.each(function() { + var g = d3.select(this); + var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); + var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; + var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), + d3.transition(path)); + tickEnter.append("line"); + tickEnter.append("text"); + var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; + if (orient === "bottom" || orient === "top") { + tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; + text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); + } else { + tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; + text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); + pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); + } + lineEnter.attr(y2, sign * innerTickSize); + textEnter.attr(y1, sign * tickSpacing); + lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); + textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); + if (scale1.rangeBand) { + var x = scale1, dx = x.rangeBand() / 2; + scale0 = scale1 = function(d) { + return x(d) + dx; + }; + } else if (scale0.rangeBand) { + scale0 = scale1; + } else { + tickExit.call(tickTransform, scale1, scale0); + } + tickEnter.call(tickTransform, scale0, scale1); + tickUpdate.call(tickTransform, scale1, scale1); + }); + } + axis.scale = function(x) { + if (!arguments.length) return scale; + scale = x; + return axis; + }; + axis.orient = function(x) { + if (!arguments.length) return orient; + orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; + return axis; + }; + axis.ticks = function() { + if (!arguments.length) return tickArguments_; + tickArguments_ = d3_array(arguments); + return axis; + }; + axis.tickValues = function(x) { + if (!arguments.length) return tickValues; + tickValues = x; + return axis; + }; + axis.tickFormat = function(x) { + if (!arguments.length) return tickFormat_; + tickFormat_ = x; + return axis; + }; + axis.tickSize = function(x) { + var n = arguments.length; + if (!n) return innerTickSize; + innerTickSize = +x; + outerTickSize = +arguments[n - 1]; + return axis; + }; + axis.innerTickSize = function(x) { + if (!arguments.length) return innerTickSize; + innerTickSize = +x; + return axis; + }; + axis.outerTickSize = function(x) { + if (!arguments.length) return outerTickSize; + outerTickSize = +x; + return axis; + }; + axis.tickPadding = function(x) { + if (!arguments.length) return tickPadding; + tickPadding = +x; + return axis; + }; + axis.tickSubdivide = function() { + return arguments.length && axis; + }; + return axis; + }; + var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { + top: 1, + right: 1, + bottom: 1, + left: 1 + }; + function d3_svg_axisX(selection, x0, x1) { + selection.attr("transform", function(d) { + var v0 = x0(d); + return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; + }); + } + function d3_svg_axisY(selection, y0, y1) { + selection.attr("transform", function(d) { + var v0 = y0(d); + return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; + }); + } + d3.svg.brush = function() { + var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; + function brush(g) { + g.each(function() { + var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); + var background = g.selectAll(".background").data([ 0 ]); + background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); + g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); + var resize = g.selectAll(".resize").data(resizes, d3_identity); + resize.exit().remove(); + resize.enter().append("g").attr("class", function(d) { + return "resize " + d; + }).style("cursor", function(d) { + return d3_svg_brushCursor[d]; + }).append("rect").attr("x", function(d) { + return /[ew]$/.test(d) ? -3 : null; + }).attr("y", function(d) { + return /^[ns]/.test(d) ? -3 : null; + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); + resize.style("display", brush.empty() ? "none" : null); + var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; + if (x) { + range = d3_scaleRange(x); + backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); + redrawX(gUpdate); + } + if (y) { + range = d3_scaleRange(y); + backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); + redrawY(gUpdate); + } + redraw(gUpdate); + }); + } + brush.event = function(g) { + g.each(function() { + var event_ = event.of(this, arguments), extent1 = { + x: xExtent, + y: yExtent, + i: xExtentDomain, + j: yExtentDomain + }, extent0 = this.__chart__ || extent1; + this.__chart__ = extent1; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.brush", function() { + xExtentDomain = extent0.i; + yExtentDomain = extent0.j; + xExtent = extent0.x; + yExtent = extent0.y; + event_({ + type: "brushstart" + }); + }).tween("brush:brush", function() { + var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); + xExtentDomain = yExtentDomain = null; + return function(t) { + xExtent = extent1.x = xi(t); + yExtent = extent1.y = yi(t); + event_({ + type: "brush", + mode: "resize" + }); + }; + }).each("end.brush", function() { + xExtentDomain = extent1.i; + yExtentDomain = extent1.j; + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + }); + } else { + event_({ + type: "brushstart" + }); + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + } + }); + }; + function redraw(g) { + g.selectAll(".resize").attr("transform", function(d) { + return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; + }); + } + function redrawX(g) { + g.select(".extent").attr("x", xExtent[0]); + g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); + } + function redrawY(g) { + g.select(".extent").attr("y", yExtent[0]); + g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); + } + function brushstart() { + var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; + var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); + if (d3.event.changedTouches) { + w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); + } else { + w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); + } + g.interrupt().selectAll("*").interrupt(); + if (dragging) { + origin[0] = xExtent[0] - origin[0]; + origin[1] = yExtent[0] - origin[1]; + } else if (resizing) { + var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); + offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; + origin[0] = xExtent[ex]; + origin[1] = yExtent[ey]; + } else if (d3.event.altKey) center = origin.slice(); + g.style("pointer-events", "none").selectAll(".resize").style("display", null); + d3.select("body").style("cursor", eventTarget.style("cursor")); + event_({ + type: "brushstart" + }); + brushmove(); + function keydown() { + if (d3.event.keyCode == 32) { + if (!dragging) { + center = null; + origin[0] -= xExtent[1]; + origin[1] -= yExtent[1]; + dragging = 2; + } + d3_eventPreventDefault(); + } + } + function keyup() { + if (d3.event.keyCode == 32 && dragging == 2) { + origin[0] += xExtent[1]; + origin[1] += yExtent[1]; + dragging = 0; + d3_eventPreventDefault(); + } + } + function brushmove() { + var point = d3.mouse(target), moved = false; + if (offset) { + point[0] += offset[0]; + point[1] += offset[1]; + } + if (!dragging) { + if (d3.event.altKey) { + if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; + origin[0] = xExtent[+(point[0] < center[0])]; + origin[1] = yExtent[+(point[1] < center[1])]; + } else center = null; + } + if (resizingX && move1(point, x, 0)) { + redrawX(g); + moved = true; + } + if (resizingY && move1(point, y, 1)) { + redrawY(g); + moved = true; + } + if (moved) { + redraw(g); + event_({ + type: "brush", + mode: dragging ? "move" : "resize" + }); + } + } + function move1(point, scale, i) { + var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; + if (dragging) { + r0 -= position; + r1 -= size + position; + } + min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; + if (dragging) { + max = (min += position) + size; + } else { + if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); + if (position < min) { + max = min; + min = position; + } else { + max = position; + } + } + if (extent[0] != min || extent[1] != max) { + if (i) yExtentDomain = null; else xExtentDomain = null; + extent[0] = min; + extent[1] = max; + return true; + } + } + function brushend() { + brushmove(); + g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); + d3.select("body").style("cursor", null); + w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); + dragRestore(); + event_({ + type: "brushend" + }); + } + } + brush.x = function(z) { + if (!arguments.length) return x; + x = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.y = function(z) { + if (!arguments.length) return y; + y = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.clamp = function(z) { + if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; + if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; + return brush; + }; + brush.extent = function(z) { + var x0, x1, y0, y1, t; + if (!arguments.length) { + if (x) { + if (xExtentDomain) { + x0 = xExtentDomain[0], x1 = xExtentDomain[1]; + } else { + x0 = xExtent[0], x1 = xExtent[1]; + if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + } + } + if (y) { + if (yExtentDomain) { + y0 = yExtentDomain[0], y1 = yExtentDomain[1]; + } else { + y0 = yExtent[0], y1 = yExtent[1]; + if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + } + } + return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; + } + if (x) { + x0 = z[0], x1 = z[1]; + if (y) x0 = x0[0], x1 = x1[0]; + xExtentDomain = [ x0, x1 ]; + if (x.invert) x0 = x(x0), x1 = x(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; + } + if (y) { + y0 = z[0], y1 = z[1]; + if (x) y0 = y0[1], y1 = y1[1]; + yExtentDomain = [ y0, y1 ]; + if (y.invert) y0 = y(y0), y1 = y(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; + } + return brush; + }; + brush.clear = function() { + if (!brush.empty()) { + xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; + xExtentDomain = yExtentDomain = null; + } + return brush; + }; + brush.empty = function() { + return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + }; + return d3.rebind(brush, event, "on"); + }; + var d3_svg_brushCursor = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; + var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; + var d3_time_formatUtc = d3_time_format.utc; + var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; + function d3_time_formatIsoNative(date) { + return date.toISOString(); + } + d3_time_formatIsoNative.parse = function(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + }; + d3_time_formatIsoNative.toString = d3_time_formatIso.toString; + d3_time.second = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 1e3) * 1e3); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 1e3); + }, function(date) { + return date.getSeconds(); + }); + d3_time.seconds = d3_time.second.range; + d3_time.seconds.utc = d3_time.second.utc.range; + d3_time.minute = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 6e4) * 6e4); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 6e4); + }, function(date) { + return date.getMinutes(); + }); + d3_time.minutes = d3_time.minute.range; + d3_time.minutes.utc = d3_time.minute.utc.range; + d3_time.hour = d3_time_interval(function(date) { + var timezone = date.getTimezoneOffset() / 60; + return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 36e5); + }, function(date) { + return date.getHours(); + }); + d3_time.hours = d3_time.hour.range; + d3_time.hours.utc = d3_time.hour.utc.range; + d3_time.month = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setDate(1); + return date; + }, function(date, offset) { + date.setMonth(date.getMonth() + offset); + }, function(date) { + return date.getMonth(); + }); + d3_time.months = d3_time.month.range; + d3_time.months.utc = d3_time.month.utc.range; + function d3_time_scale(linear, methods, format) { + function scale(x) { + return linear(x); + } + scale.invert = function(x) { + return d3_time_scaleDate(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return linear.domain().map(d3_time_scaleDate); + linear.domain(x); + return scale; + }; + function tickMethod(extent, count) { + var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); + return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { + return d / 31536e6; + }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; + } + scale.nice = function(interval, skip) { + var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); + if (method) interval = method[0], skip = method[1]; + function skipped(date) { + return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; + } + return scale.domain(d3_scale_nice(domain, skip > 1 ? { + floor: function(date) { + while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); + return date; + }, + ceil: function(date) { + while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); + return date; + } + } : interval)); + }; + scale.ticks = function(interval, skip) { + var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { + range: interval + }, skip ]; + if (method) interval = method[0], skip = method[1]; + return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + }; + scale.tickFormat = function() { + return format; + }; + scale.copy = function() { + return d3_time_scale(linear.copy(), methods, format); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_time_scaleDate(t) { + return new Date(t); + } + var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; + var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; + var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { + return d.getMilliseconds(); + } ], [ ":%S", function(d) { + return d.getSeconds(); + } ], [ "%I:%M", function(d) { + return d.getMinutes(); + } ], [ "%I %p", function(d) { + return d.getHours(); + } ], [ "%a %d", function(d) { + return d.getDay() && d.getDate() != 1; + } ], [ "%b %d", function(d) { + return d.getDate() != 1; + } ], [ "%B", function(d) { + return d.getMonth(); + } ], [ "%Y", d3_true ] ]); + var d3_time_scaleMilliseconds = { + range: function(start, stop, step) { + return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); + }, + floor: d3_identity, + ceil: d3_identity + }; + d3_time_scaleLocalMethods.year = d3_time.year; + d3_time.scale = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + }; + var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { + return [ m[0].utc, m[1] ]; + }); + var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { + return d.getUTCMilliseconds(); + } ], [ ":%S", function(d) { + return d.getUTCSeconds(); + } ], [ "%I:%M", function(d) { + return d.getUTCMinutes(); + } ], [ "%I %p", function(d) { + return d.getUTCHours(); + } ], [ "%a %d", function(d) { + return d.getUTCDay() && d.getUTCDate() != 1; + } ], [ "%b %d", function(d) { + return d.getUTCDate() != 1; + } ], [ "%B", function(d) { + return d.getUTCMonth(); + } ], [ "%Y", d3_true ] ]); + d3_time_scaleUtcMethods.year = d3_time.year.utc; + d3_time.scale.utc = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); + }; + d3.text = d3_xhrType(function(request) { + return request.responseText; + }); + d3.json = function(url, callback) { + return d3_xhr(url, "application/json", d3_json, callback); + }; + function d3_json(request) { + return JSON.parse(request.responseText); + } + d3.html = function(url, callback) { + return d3_xhr(url, "text/html", d3_html, callback); + }; + function d3_html(request) { + var range = d3_document.createRange(); + range.selectNode(d3_document.body); + return range.createContextualFragment(request.responseText); + } + d3.xml = d3_xhrType(function(request) { + return request.responseXML; + }); + if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; +}(); \ No newline at end of file diff --git a/dist/js/getmdl-select.min.js b/dist/js/getmdl-select.min.js new file mode 100644 index 0000000..b114afa --- /dev/null +++ b/dist/js/getmdl-select.min.js @@ -0,0 +1,2 @@ +"use strict";window.onload=function(){getmdlSelect.init(".getmdl-select"),document.addEventListener("DOMNodeInserted",function(e){componentHandler.upgradeDom()},!1)};var getmdlSelect={addEventListeners:function(e){var t=e.querySelector("input"),n=e.querySelectorAll("li");[].forEach.call(n,function(e){e.onclick=function(){if(t.value=e.textContent,"createEvent"in document){var n=document.createEvent("HTMLEvents");n.initEvent("change",!1,!0),t.dispatchEvent(n)}else t.fireEvent("onchange")}})},init:function(e){var t=document.querySelectorAll(e);[].forEach.call(t,function(e){getmdlSelect.addEventListeners(e)})}}; +//# sourceMappingURL=getmdl-select.min.js.map \ No newline at end of file diff --git a/dist/js/material.js b/dist/js/material.js new file mode 100644 index 0000000..a216d21 --- /dev/null +++ b/dist/js/material.js @@ -0,0 +1,3946 @@ +;(function() { +"use strict"; + +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A component handler interface using the revealing module design pattern. + * More details on this design pattern here: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @author Jason Mayes. + */ +/* exported componentHandler */ + +// Pre-defining the componentHandler interface, for closure documentation and +// static verification. +var componentHandler = { + /** + * Searches existing DOM for elements of our component type and upgrades them + * if they have not already been upgraded. + * + * @param {string=} optJsClass the programatic name of the element class we + * need to create a new instance of. + * @param {string=} optCssClass the name of the CSS class elements of this + * type will have. + */ + upgradeDom: function(optJsClass, optCssClass) {}, + /** + * Upgrades a specific element rather than all in the DOM. + * + * @param {!Element} element The element we wish to upgrade. + * @param {string=} optJsClass Optional name of the class we want to upgrade + * the element to. + */ + upgradeElement: function(element, optJsClass) {}, + /** + * Upgrades a specific list of elements rather than all in the DOM. + * + * @param {!Element|!Array|!NodeList|!HTMLCollection} elements + * The elements we wish to upgrade. + */ + upgradeElements: function(elements) {}, + /** + * Upgrades all registered components found in the current DOM. This is + * automatically called on window load. + */ + upgradeAllRegistered: function() {}, + /** + * Allows user to be alerted to any upgrades that are performed for a given + * component type + * + * @param {string} jsClass The class name of the MDL component we wish + * to hook into for any upgrades performed. + * @param {function(!HTMLElement)} callback The function to call upon an + * upgrade. This function should expect 1 parameter - the HTMLElement which + * got upgraded. + */ + registerUpgradedCallback: function(jsClass, callback) {}, + /** + * Registers a class for future use and attempts to upgrade existing DOM. + * + * @param {componentHandler.ComponentConfigPublic} config the registration configuration + */ + register: function(config) {}, + /** + * Downgrade either a given node, an array of nodes, or a NodeList. + * + * @param {!Node|!Array|!NodeList} nodes + */ + downgradeElements: function(nodes) {} +}; + +componentHandler = (function() { + 'use strict'; + + /** @type {!Array} */ + var registeredComponents_ = []; + + /** @type {!Array} */ + var createdComponents_ = []; + + var componentConfigProperty_ = 'mdlComponentConfigInternal_'; + + /** + * Searches registered components for a class we are interested in using. + * Optionally replaces a match with passed object if specified. + * + * @param {string} name The name of a class we want to use. + * @param {componentHandler.ComponentConfig=} optReplace Optional object to replace match with. + * @return {!Object|boolean} + * @private + */ + function findRegisteredClass_(name, optReplace) { + for (var i = 0; i < registeredComponents_.length; i++) { + if (registeredComponents_[i].className === name) { + if (typeof optReplace !== 'undefined') { + registeredComponents_[i] = optReplace; + } + return registeredComponents_[i]; + } + } + return false; + } + + /** + * Returns an array of the classNames of the upgraded classes on the element. + * + * @param {!Element} element The element to fetch data from. + * @return {!Array} + * @private + */ + function getUpgradedListOfElement_(element) { + var dataUpgraded = element.getAttribute('data-upgraded'); + // Use `['']` as default value to conform the `,name,name...` style. + return dataUpgraded === null ? [''] : dataUpgraded.split(','); + } + + /** + * Returns true if the given element has already been upgraded for the given + * class. + * + * @param {!Element} element The element we want to check. + * @param {string} jsClass The class to check for. + * @returns {boolean} + * @private + */ + function isElementUpgraded_(element, jsClass) { + var upgradedList = getUpgradedListOfElement_(element); + return upgradedList.indexOf(jsClass) !== -1; + } + + /** + * Searches existing DOM for elements of our component type and upgrades them + * if they have not already been upgraded. + * + * @param {string=} optJsClass the programatic name of the element class we + * need to create a new instance of. + * @param {string=} optCssClass the name of the CSS class elements of this + * type will have. + */ + function upgradeDomInternal(optJsClass, optCssClass) { + if (typeof optJsClass === 'undefined' && + typeof optCssClass === 'undefined') { + for (var i = 0; i < registeredComponents_.length; i++) { + upgradeDomInternal(registeredComponents_[i].className, + registeredComponents_[i].cssClass); + } + } else { + var jsClass = /** @type {string} */ (optJsClass); + if (typeof optCssClass === 'undefined') { + var registeredClass = findRegisteredClass_(jsClass); + if (registeredClass) { + optCssClass = registeredClass.cssClass; + } + } + + var elements = document.querySelectorAll('.' + optCssClass); + for (var n = 0; n < elements.length; n++) { + upgradeElementInternal(elements[n], jsClass); + } + } + } + + /** + * Upgrades a specific element rather than all in the DOM. + * + * @param {!Element} element The element we wish to upgrade. + * @param {string=} optJsClass Optional name of the class we want to upgrade + * the element to. + */ + function upgradeElementInternal(element, optJsClass) { + // Verify argument type. + if (!(typeof element === 'object' && element instanceof Element)) { + throw new Error('Invalid argument provided to upgrade MDL element.'); + } + var upgradedList = getUpgradedListOfElement_(element); + var classesToUpgrade = []; + // If jsClass is not provided scan the registered components to find the + // ones matching the element's CSS classList. + if (!optJsClass) { + var classList = element.classList; + registeredComponents_.forEach(function(component) { + // Match CSS & Not to be upgraded & Not upgraded. + if (classList.contains(component.cssClass) && + classesToUpgrade.indexOf(component) === -1 && + !isElementUpgraded_(element, component.className)) { + classesToUpgrade.push(component); + } + }); + } else if (!isElementUpgraded_(element, optJsClass)) { + classesToUpgrade.push(findRegisteredClass_(optJsClass)); + } + + // Upgrade the element for each classes. + for (var i = 0, n = classesToUpgrade.length, registeredClass; i < n; i++) { + registeredClass = classesToUpgrade[i]; + if (registeredClass) { + // Mark element as upgraded. + upgradedList.push(registeredClass.className); + element.setAttribute('data-upgraded', upgradedList.join(',')); + var instance = new registeredClass.classConstructor(element); + instance[componentConfigProperty_] = registeredClass; + createdComponents_.push(instance); + // Call any callbacks the user has registered with this component type. + for (var j = 0, m = registeredClass.callbacks.length; j < m; j++) { + registeredClass.callbacks[j](element); + } + + if (registeredClass.widget) { + // Assign per element instance for control over API + element[registeredClass.className] = instance; + } + } else { + throw new Error( + 'Unable to find a registered component for the given class.'); + } + + var ev = document.createEvent('Events'); + ev.initEvent('mdl-componentupgraded', true, true); + element.dispatchEvent(ev); + } + } + + /** + * Upgrades a specific list of elements rather than all in the DOM. + * + * @param {!Element|!Array|!NodeList|!HTMLCollection} elements + * The elements we wish to upgrade. + */ + function upgradeElementsInternal(elements) { + if (!Array.isArray(elements)) { + if (typeof elements.item === 'function') { + elements = Array.prototype.slice.call(/** @type {Array} */ (elements)); + } else { + elements = [elements]; + } + } + for (var i = 0, n = elements.length, element; i < n; i++) { + element = elements[i]; + if (element instanceof HTMLElement) { + upgradeElementInternal(element); + if (element.children.length > 0) { + upgradeElementsInternal(element.children); + } + } + } + } + + /** + * Registers a class for future use and attempts to upgrade existing DOM. + * + * @param {componentHandler.ComponentConfigPublic} config + */ + function registerInternal(config) { + // In order to support both Closure-compiled and uncompiled code accessing + // this method, we need to allow for both the dot and array syntax for + // property access. You'll therefore see the `foo.bar || foo['bar']` + // pattern repeated across this method. + var widgetMissing = (typeof config.widget === 'undefined' && + typeof config['widget'] === 'undefined'); + var widget = true; + + if (!widgetMissing) { + widget = config.widget || config['widget']; + } + + var newConfig = /** @type {componentHandler.ComponentConfig} */ ({ + classConstructor: config.constructor || config['constructor'], + className: config.classAsString || config['classAsString'], + cssClass: config.cssClass || config['cssClass'], + widget: widget, + callbacks: [] + }); + + registeredComponents_.forEach(function(item) { + if (item.cssClass === newConfig.cssClass) { + throw new Error('The provided cssClass has already been registered: ' + item.cssClass); + } + if (item.className === newConfig.className) { + throw new Error('The provided className has already been registered'); + } + }); + + if (config.constructor.prototype + .hasOwnProperty(componentConfigProperty_)) { + throw new Error( + 'MDL component classes must not have ' + componentConfigProperty_ + + ' defined as a property.'); + } + + var found = findRegisteredClass_(config.classAsString, newConfig); + + if (!found) { + registeredComponents_.push(newConfig); + } + } + + /** + * Allows user to be alerted to any upgrades that are performed for a given + * component type + * + * @param {string} jsClass The class name of the MDL component we wish + * to hook into for any upgrades performed. + * @param {function(!HTMLElement)} callback The function to call upon an + * upgrade. This function should expect 1 parameter - the HTMLElement which + * got upgraded. + */ + function registerUpgradedCallbackInternal(jsClass, callback) { + var regClass = findRegisteredClass_(jsClass); + if (regClass) { + regClass.callbacks.push(callback); + } + } + + /** + * Upgrades all registered components found in the current DOM. This is + * automatically called on window load. + */ + function upgradeAllRegisteredInternal() { + for (var n = 0; n < registeredComponents_.length; n++) { + upgradeDomInternal(registeredComponents_[n].className); + } + } + + /** + * Check the component for the downgrade method. + * Execute if found. + * Remove component from createdComponents list. + * + * @param {?componentHandler.Component} component + */ + function deconstructComponentInternal(component) { + var componentIndex = createdComponents_.indexOf(component); + createdComponents_.splice(componentIndex, 1); + + var upgrades = component.element_.getAttribute('data-upgraded').split(','); + var componentPlace = upgrades.indexOf(component[componentConfigProperty_].classAsString); + upgrades.splice(componentPlace, 1); + component.element_.setAttribute('data-upgraded', upgrades.join(',')); + + var ev = document.createEvent('Events'); + ev.initEvent('mdl-componentdowngraded', true, true); + component.element_.dispatchEvent(ev); + } + + /** + * Downgrade either a given node, an array of nodes, or a NodeList. + * + * @param {!Node|!Array|!NodeList} nodes + */ + function downgradeNodesInternal(nodes) { + /** + * Auxiliary function to downgrade a single node. + * @param {!Node} node the node to be downgraded + */ + var downgradeNode = function(node) { + createdComponents_.filter(function(item) { + return item.element_ === node; + }).forEach(deconstructComponentInternal); + }; + if (nodes instanceof Array || nodes instanceof NodeList) { + for (var n = 0; n < nodes.length; n++) { + downgradeNode(nodes[n]); + } + } else if (nodes instanceof Node) { + downgradeNode(nodes); + } else { + throw new Error('Invalid argument provided to downgrade MDL nodes.'); + } + } + + // Now return the functions that should be made public with their publicly + // facing names... + return { + upgradeDom: upgradeDomInternal, + upgradeElement: upgradeElementInternal, + upgradeElements: upgradeElementsInternal, + upgradeAllRegistered: upgradeAllRegisteredInternal, + registerUpgradedCallback: registerUpgradedCallbackInternal, + register: registerInternal, + downgradeElements: downgradeNodesInternal + }; +})(); + +/** + * Describes the type of a registered component type managed by + * componentHandler. Provided for benefit of the Closure compiler. + * + * @typedef {{ + * constructor: Function, + * classAsString: string, + * cssClass: string, + * widget: (string|boolean|undefined) + * }} + */ +componentHandler.ComponentConfigPublic; // jshint ignore:line + +/** + * Describes the type of a registered component type managed by + * componentHandler. Provided for benefit of the Closure compiler. + * + * @typedef {{ + * constructor: !Function, + * className: string, + * cssClass: string, + * widget: (string|boolean), + * callbacks: !Array + * }} + */ +componentHandler.ComponentConfig; // jshint ignore:line + +/** + * Created component (i.e., upgraded element) type as managed by + * componentHandler. Provided for benefit of the Closure compiler. + * + * @typedef {{ + * element_: !HTMLElement, + * className: string, + * classAsString: string, + * cssClass: string, + * widget: string + * }} + */ +componentHandler.Component; // jshint ignore:line + +// Export all symbols, for the benefit of Closure compiler. +// No effect on uncompiled code. +componentHandler['upgradeDom'] = componentHandler.upgradeDom; +componentHandler['upgradeElement'] = componentHandler.upgradeElement; +componentHandler['upgradeElements'] = componentHandler.upgradeElements; +componentHandler['upgradeAllRegistered'] = + componentHandler.upgradeAllRegistered; +componentHandler['registerUpgradedCallback'] = + componentHandler.registerUpgradedCallback; +componentHandler['register'] = componentHandler.register; +componentHandler['downgradeElements'] = componentHandler.downgradeElements; +window.componentHandler = componentHandler; +window['componentHandler'] = componentHandler; + +window.addEventListener('load', function() { + 'use strict'; + + /** + * Performs a "Cutting the mustard" test. If the browser supports the features + * tested, adds a mdl-js class to the element. It then upgrades all MDL + * components requiring JavaScript. + */ + if ('classList' in document.createElement('div') && + 'querySelector' in document && + 'addEventListener' in window && Array.prototype.forEach) { + document.documentElement.classList.add('mdl-js'); + componentHandler.upgradeAllRegistered(); + } else { + /** + * Dummy function to avoid JS errors. + */ + componentHandler.upgradeElement = function() {}; + /** + * Dummy function to avoid JS errors. + */ + componentHandler.register = function() {}; + } +}); + +// Source: https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js +// Adapted from https://gist.github.com/paulirish/1579671 which derived from +// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ +// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating +// requestAnimationFrame polyfill by Erik Möller. +// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon +// MIT license +if (!Date.now) { + /** + * Date.now polyfill. + * @return {number} the current Date + */ + Date.now = function () { + return new Date().getTime(); + }; + Date['now'] = Date.now; +} +var vendors = [ + 'webkit', + 'moz' +]; +for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { + var vp = vendors[i]; + window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']; + window['requestAnimationFrame'] = window.requestAnimationFrame; + window['cancelAnimationFrame'] = window.cancelAnimationFrame; +} +if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { + var lastTime = 0; + /** + * requestAnimationFrame polyfill. + * @param {!Function} callback the callback function. + */ + window.requestAnimationFrame = function (callback) { + var now = Date.now(); + var nextTime = Math.max(lastTime + 16, now); + return setTimeout(function () { + callback(lastTime = nextTime); + }, nextTime - now); + }; + window.cancelAnimationFrame = clearTimeout; + window['requestAnimationFrame'] = window.requestAnimationFrame; + window['cancelAnimationFrame'] = window.cancelAnimationFrame; +} +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Button MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialButton = function MaterialButton(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialButton'] = MaterialButton; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialButton.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialButton.prototype.CssClasses_ = { + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_CONTAINER: 'mdl-button__ripple-container', + RIPPLE: 'mdl-ripple' +}; +/** + * Handle blur of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialButton.prototype.blurHandler_ = function (event) { + if (event) { + this.element_.blur(); + } +}; +// Public methods. +/** + * Disable button. + * + * @public + */ +MaterialButton.prototype.disable = function () { + this.element_.disabled = true; +}; +MaterialButton.prototype['disable'] = MaterialButton.prototype.disable; +/** + * Enable button. + * + * @public + */ +MaterialButton.prototype.enable = function () { + this.element_.disabled = false; +}; +MaterialButton.prototype['enable'] = MaterialButton.prototype.enable; +/** + * Initialize element. + */ +MaterialButton.prototype.init = function () { + if (this.element_) { + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleElement_ = document.createElement('span'); + this.rippleElement_.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(this.rippleElement_); + this.boundRippleBlurHandler = this.blurHandler_.bind(this); + this.rippleElement_.addEventListener('mouseup', this.boundRippleBlurHandler); + this.element_.appendChild(rippleContainer); + } + this.boundButtonBlurHandler = this.blurHandler_.bind(this); + this.element_.addEventListener('mouseup', this.boundButtonBlurHandler); + this.element_.addEventListener('mouseleave', this.boundButtonBlurHandler); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialButton, + classAsString: 'MaterialButton', + cssClass: 'mdl-js-button', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Checkbox MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialCheckbox = function MaterialCheckbox(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialCheckbox'] = MaterialCheckbox; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialCheckbox.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialCheckbox.prototype.CssClasses_ = { + INPUT: 'mdl-checkbox__input', + BOX_OUTLINE: 'mdl-checkbox__box-outline', + FOCUS_HELPER: 'mdl-checkbox__focus-helper', + TICK_OUTLINE: 'mdl-checkbox__tick-outline', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-checkbox__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked', + IS_UPGRADED: 'is-upgraded' +}; +/** + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onChange_ = function (event) { + this.updateClasses_(); +}; +/** + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialCheckbox.prototype.onMouseUp_ = function (event) { + this.blur_(); +}; +/** + * Handle class updates. + * + * @private + */ +MaterialCheckbox.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); +}; +/** + * Add blur. + * + * @private + */ +MaterialCheckbox.prototype.blur_ = function () { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); +}; +// Public methods. +/** + * Check the inputs toggle state and update display. + * + * @public + */ +MaterialCheckbox.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } +}; +MaterialCheckbox.prototype['checkToggleState'] = MaterialCheckbox.prototype.checkToggleState; +/** + * Check the inputs disabled state and update display. + * + * @public + */ +MaterialCheckbox.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } +}; +MaterialCheckbox.prototype['checkDisabled'] = MaterialCheckbox.prototype.checkDisabled; +/** + * Disable checkbox. + * + * @public + */ +MaterialCheckbox.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); +}; +MaterialCheckbox.prototype['disable'] = MaterialCheckbox.prototype.disable; +/** + * Enable checkbox. + * + * @public + */ +MaterialCheckbox.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); +}; +MaterialCheckbox.prototype['enable'] = MaterialCheckbox.prototype.enable; +/** + * Check checkbox. + * + * @public + */ +MaterialCheckbox.prototype.check = function () { + this.inputElement_.checked = true; + this.updateClasses_(); +}; +MaterialCheckbox.prototype['check'] = MaterialCheckbox.prototype.check; +/** + * Uncheck checkbox. + * + * @public + */ +MaterialCheckbox.prototype.uncheck = function () { + this.inputElement_.checked = false; + this.updateClasses_(); +}; +MaterialCheckbox.prototype['uncheck'] = MaterialCheckbox.prototype.uncheck; +/** + * Initialize element. + */ +MaterialCheckbox.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + var boxOutline = document.createElement('span'); + boxOutline.classList.add(this.CssClasses_.BOX_OUTLINE); + var tickContainer = document.createElement('span'); + tickContainer.classList.add(this.CssClasses_.FOCUS_HELPER); + var tickOutline = document.createElement('span'); + tickOutline.classList.add(this.CssClasses_.TICK_OUTLINE); + boxOutline.appendChild(tickOutline); + this.element_.appendChild(tickContainer); + this.element_.appendChild(boxOutline); + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.boundRippleMouseUp = this.onMouseUp_.bind(this); + this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundInputOnChange = this.onChange_.bind(this); + this.boundInputOnFocus = this.onFocus_.bind(this); + this.boundInputOnBlur = this.onBlur_.bind(this); + this.boundElementMouseUp = this.onMouseUp_.bind(this); + this.inputElement_.addEventListener('change', this.boundInputOnChange); + this.inputElement_.addEventListener('focus', this.boundInputOnFocus); + this.inputElement_.addEventListener('blur', this.boundInputOnBlur); + this.element_.addEventListener('mouseup', this.boundElementMouseUp); + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialCheckbox, + classAsString: 'MaterialCheckbox', + cssClass: 'mdl-js-checkbox', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for icon toggle MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialIconToggle = function MaterialIconToggle(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialIconToggle'] = MaterialIconToggle; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialIconToggle.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialIconToggle.prototype.CssClasses_ = { + INPUT: 'mdl-icon-toggle__input', + JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-icon-toggle__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked' +}; +/** + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onChange_ = function (event) { + this.updateClasses_(); +}; +/** + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialIconToggle.prototype.onMouseUp_ = function (event) { + this.blur_(); +}; +/** + * Handle class updates. + * + * @private + */ +MaterialIconToggle.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); +}; +/** + * Add blur. + * + * @private + */ +MaterialIconToggle.prototype.blur_ = function () { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); +}; +// Public methods. +/** + * Check the inputs toggle state and update display. + * + * @public + */ +MaterialIconToggle.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } +}; +MaterialIconToggle.prototype['checkToggleState'] = MaterialIconToggle.prototype.checkToggleState; +/** + * Check the inputs disabled state and update display. + * + * @public + */ +MaterialIconToggle.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } +}; +MaterialIconToggle.prototype['checkDisabled'] = MaterialIconToggle.prototype.checkDisabled; +/** + * Disable icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); +}; +MaterialIconToggle.prototype['disable'] = MaterialIconToggle.prototype.disable; +/** + * Enable icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); +}; +MaterialIconToggle.prototype['enable'] = MaterialIconToggle.prototype.enable; +/** + * Check icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.check = function () { + this.inputElement_.checked = true; + this.updateClasses_(); +}; +MaterialIconToggle.prototype['check'] = MaterialIconToggle.prototype.check; +/** + * Uncheck icon toggle. + * + * @public + */ +MaterialIconToggle.prototype.uncheck = function () { + this.inputElement_.checked = false; + this.updateClasses_(); +}; +MaterialIconToggle.prototype['uncheck'] = MaterialIconToggle.prototype.uncheck; +/** + * Initialize element. + */ +MaterialIconToggle.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.boundRippleMouseUp = this.onMouseUp_.bind(this); + this.rippleContainerElement_.addEventListener('mouseup', this.boundRippleMouseUp); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundInputOnChange = this.onChange_.bind(this); + this.boundInputOnFocus = this.onFocus_.bind(this); + this.boundInputOnBlur = this.onBlur_.bind(this); + this.boundElementOnMouseUp = this.onMouseUp_.bind(this); + this.inputElement_.addEventListener('change', this.boundInputOnChange); + this.inputElement_.addEventListener('focus', this.boundInputOnFocus); + this.inputElement_.addEventListener('blur', this.boundInputOnBlur); + this.element_.addEventListener('mouseup', this.boundElementOnMouseUp); + this.updateClasses_(); + this.element_.classList.add('is-upgraded'); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialIconToggle, + classAsString: 'MaterialIconToggle', + cssClass: 'mdl-js-icon-toggle', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for dropdown MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialMenu = function MaterialMenu(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialMenu'] = MaterialMenu; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialMenu.prototype.Constant_ = { + // Total duration of the menu animation. + TRANSITION_DURATION_SECONDS: 0.3, + // The fraction of the total duration we want to use for menu item animations. + TRANSITION_DURATION_FRACTION: 0.8, + // How long the menu stays open after choosing an option (so the user can see + // the ripple). + CLOSE_TIMEOUT: 150 +}; +/** + * Keycodes, for code readability. + * + * @enum {number} + * @private + */ +MaterialMenu.prototype.Keycodes_ = { + ENTER: 13, + ESCAPE: 27, + SPACE: 32, + UP_ARROW: 38, + DOWN_ARROW: 40 +}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialMenu.prototype.CssClasses_ = { + CONTAINER: 'mdl-menu__container', + OUTLINE: 'mdl-menu__outline', + ITEM: 'mdl-menu__item', + ITEM_RIPPLE_CONTAINER: 'mdl-menu__item-ripple-container', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE: 'mdl-ripple', + // Statuses + IS_UPGRADED: 'is-upgraded', + IS_VISIBLE: 'is-visible', + IS_ANIMATING: 'is-animating', + // Alignment options + BOTTOM_LEFT: 'mdl-menu--bottom-left', + // This is the default. + BOTTOM_RIGHT: 'mdl-menu--bottom-right', + TOP_LEFT: 'mdl-menu--top-left', + TOP_RIGHT: 'mdl-menu--top-right', + UNALIGNED: 'mdl-menu--unaligned' +}; +/** + * Initialize element. + */ +MaterialMenu.prototype.init = function () { + if (this.element_) { + // Create container for the menu. + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + this.container_ = container; + // Create outline for the menu (shadow and background). + var outline = document.createElement('div'); + outline.classList.add(this.CssClasses_.OUTLINE); + this.outline_ = outline; + container.insertBefore(outline, this.element_); + // Find the "for" element and bind events to it. + var forElId = this.element_.getAttribute('for') || this.element_.getAttribute('data-mdl-for'); + var forEl = null; + if (forElId) { + forEl = document.getElementById(forElId); + if (forEl) { + this.forElement_ = forEl; + forEl.addEventListener('click', this.handleForClick_.bind(this)); + forEl.addEventListener('keydown', this.handleForKeyboardEvent_.bind(this)); + } + } + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + this.boundItemKeydown_ = this.handleItemKeyboardEvent_.bind(this); + this.boundItemClick_ = this.handleItemClick_.bind(this); + for (var i = 0; i < items.length; i++) { + // Add a listener to each menu item. + items[i].addEventListener('click', this.boundItemClick_); + // Add a tab index to each menu item. + items[i].tabIndex = '-1'; + // Add a keyboard listener to each menu item. + items[i].addEventListener('keydown', this.boundItemKeydown_); + } + // Add ripple classes to each item, if the user has enabled ripples. + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + for (i = 0; i < items.length; i++) { + var item = items[i]; + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.ITEM_RIPPLE_CONTAINER); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + item.appendChild(rippleContainer); + item.classList.add(this.CssClasses_.RIPPLE_EFFECT); + } + } + // Copy alignment classes to the container, so the outline can use them. + if (this.element_.classList.contains(this.CssClasses_.BOTTOM_LEFT)) { + this.outline_.classList.add(this.CssClasses_.BOTTOM_LEFT); + } + if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + this.outline_.classList.add(this.CssClasses_.BOTTOM_RIGHT); + } + if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { + this.outline_.classList.add(this.CssClasses_.TOP_LEFT); + } + if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + this.outline_.classList.add(this.CssClasses_.TOP_RIGHT); + } + if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { + this.outline_.classList.add(this.CssClasses_.UNALIGNED); + } + container.classList.add(this.CssClasses_.IS_UPGRADED); + } +}; +/** + * Handles a click on the "for" element, by positioning the menu and then + * toggling it. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleForClick_ = function (evt) { + if (this.element_ && this.forElement_) { + var rect = this.forElement_.getBoundingClientRect(); + var forRect = this.forElement_.parentElement.getBoundingClientRect(); + if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { + } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + // Position below the "for" element, aligned to its right. + this.container_.style.right = forRect.right - rect.right + 'px'; + this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { + // Position above the "for" element, aligned to its left. + this.container_.style.left = this.forElement_.offsetLeft + 'px'; + this.container_.style.bottom = forRect.bottom - rect.top + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + // Position above the "for" element, aligned to its right. + this.container_.style.right = forRect.right - rect.right + 'px'; + this.container_.style.bottom = forRect.bottom - rect.top + 'px'; + } else { + // Default: position below the "for" element, aligned to its left. + this.container_.style.left = this.forElement_.offsetLeft + 'px'; + this.container_.style.top = this.forElement_.offsetTop + this.forElement_.offsetHeight + 'px'; + } + } + this.toggle(evt); +}; +/** + * Handles a keyboard event on the "for" element. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleForKeyboardEvent_ = function (evt) { + if (this.element_ && this.container_ && this.forElement_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])'); + if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { + if (evt.keyCode === this.Keycodes_.UP_ARROW) { + evt.preventDefault(); + items[items.length - 1].focus(); + } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { + evt.preventDefault(); + items[0].focus(); + } + } + } +}; +/** + * Handles a keyboard event on an item. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleItemKeyboardEvent_ = function (evt) { + if (this.element_ && this.container_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM + ':not([disabled])'); + if (items && items.length > 0 && this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { + var currentIndex = Array.prototype.slice.call(items).indexOf(evt.target); + if (evt.keyCode === this.Keycodes_.UP_ARROW) { + evt.preventDefault(); + if (currentIndex > 0) { + items[currentIndex - 1].focus(); + } else { + items[items.length - 1].focus(); + } + } else if (evt.keyCode === this.Keycodes_.DOWN_ARROW) { + evt.preventDefault(); + if (items.length > currentIndex + 1) { + items[currentIndex + 1].focus(); + } else { + items[0].focus(); + } + } else if (evt.keyCode === this.Keycodes_.SPACE || evt.keyCode === this.Keycodes_.ENTER) { + evt.preventDefault(); + // Send mousedown and mouseup to trigger ripple. + var e = new MouseEvent('mousedown'); + evt.target.dispatchEvent(e); + e = new MouseEvent('mouseup'); + evt.target.dispatchEvent(e); + // Send click. + evt.target.click(); + } else if (evt.keyCode === this.Keycodes_.ESCAPE) { + evt.preventDefault(); + this.hide(); + } + } + } +}; +/** + * Handles a click event on an item. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialMenu.prototype.handleItemClick_ = function (evt) { + if (evt.target.hasAttribute('disabled')) { + evt.stopPropagation(); + } else { + // Wait some time before closing menu, so the user can see the ripple. + this.closing_ = true; + window.setTimeout(function (evt) { + this.hide(); + this.closing_ = false; + }.bind(this), this.Constant_.CLOSE_TIMEOUT); + } +}; +/** + * Calculates the initial clip (for opening the menu) or final clip (for closing + * it), and applies it. This allows us to animate from or to the correct point, + * that is, the point it's aligned to in the "for" element. + * + * @param {number} height Height of the clip rectangle + * @param {number} width Width of the clip rectangle + * @private + */ +MaterialMenu.prototype.applyClip_ = function (height, width) { + if (this.element_.classList.contains(this.CssClasses_.UNALIGNED)) { + // Do not clip. + this.element_.style.clip = ''; + } else if (this.element_.classList.contains(this.CssClasses_.BOTTOM_RIGHT)) { + // Clip to the top right corner of the menu. + this.element_.style.clip = 'rect(0 ' + width + 'px ' + '0 ' + width + 'px)'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT)) { + // Clip to the bottom left corner of the menu. + this.element_.style.clip = 'rect(' + height + 'px 0 ' + height + 'px 0)'; + } else if (this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + // Clip to the bottom right corner of the menu. + this.element_.style.clip = 'rect(' + height + 'px ' + width + 'px ' + height + 'px ' + width + 'px)'; + } else { + // Default: do not clip (same as clipping to the top left corner). + this.element_.style.clip = ''; + } +}; +/** + * Cleanup function to remove animation listeners. + * + * @param {Event} evt + * @private + */ +MaterialMenu.prototype.removeAnimationEndListener_ = function (evt) { + evt.target.classList.remove(MaterialMenu.prototype.CssClasses_.IS_ANIMATING); +}; +/** + * Adds an event listener to clean up after the animation ends. + * + * @private + */ +MaterialMenu.prototype.addAnimationEndListener_ = function () { + this.element_.addEventListener('transitionend', this.removeAnimationEndListener_); + this.element_.addEventListener('webkitTransitionEnd', this.removeAnimationEndListener_); +}; +/** + * Displays the menu. + * + * @public + */ +MaterialMenu.prototype.show = function (evt) { + if (this.element_ && this.container_ && this.outline_) { + // Measure the inner element. + var height = this.element_.getBoundingClientRect().height; + var width = this.element_.getBoundingClientRect().width; + // Apply the inner element's size to the container and outline. + this.container_.style.width = width + 'px'; + this.container_.style.height = height + 'px'; + this.outline_.style.width = width + 'px'; + this.outline_.style.height = height + 'px'; + var transitionDuration = this.Constant_.TRANSITION_DURATION_SECONDS * this.Constant_.TRANSITION_DURATION_FRACTION; + // Calculate transition delays for individual menu items, so that they fade + // in one at a time. + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + for (var i = 0; i < items.length; i++) { + var itemDelay = null; + if (this.element_.classList.contains(this.CssClasses_.TOP_LEFT) || this.element_.classList.contains(this.CssClasses_.TOP_RIGHT)) { + itemDelay = (height - items[i].offsetTop - items[i].offsetHeight) / height * transitionDuration + 's'; + } else { + itemDelay = items[i].offsetTop / height * transitionDuration + 's'; + } + items[i].style.transitionDelay = itemDelay; + } + // Apply the initial clip to the text before we start animating. + this.applyClip_(height, width); + // Wait for the next frame, turn on animation, and apply the final clip. + // Also make it visible. This triggers the transitions. + window.requestAnimationFrame(function () { + this.element_.classList.add(this.CssClasses_.IS_ANIMATING); + this.element_.style.clip = 'rect(0 ' + width + 'px ' + height + 'px 0)'; + this.container_.classList.add(this.CssClasses_.IS_VISIBLE); + }.bind(this)); + // Clean up after the animation is complete. + this.addAnimationEndListener_(); + // Add a click listener to the document, to close the menu. + var callback = function (e) { + // Check to see if the document is processing the same event that + // displayed the menu in the first place. If so, do nothing. + // Also check to see if the menu is in the process of closing itself, and + // do nothing in that case. + // Also check if the clicked element is a menu item + // if so, do nothing. + if (e !== evt && !this.closing_ && e.target.parentNode !== this.element_) { + document.removeEventListener('click', callback); + this.hide(); + } + }.bind(this); + document.addEventListener('click', callback); + } +}; +MaterialMenu.prototype['show'] = MaterialMenu.prototype.show; +/** + * Hides the menu. + * + * @public + */ +MaterialMenu.prototype.hide = function () { + if (this.element_ && this.container_ && this.outline_) { + var items = this.element_.querySelectorAll('.' + this.CssClasses_.ITEM); + // Remove all transition delays; menu items fade out concurrently. + for (var i = 0; i < items.length; i++) { + items[i].style.removeProperty('transition-delay'); + } + // Measure the inner element. + var rect = this.element_.getBoundingClientRect(); + var height = rect.height; + var width = rect.width; + // Turn on animation, and apply the final clip. Also make invisible. + // This triggers the transitions. + this.element_.classList.add(this.CssClasses_.IS_ANIMATING); + this.applyClip_(height, width); + this.container_.classList.remove(this.CssClasses_.IS_VISIBLE); + // Clean up after the animation is complete. + this.addAnimationEndListener_(); + } +}; +MaterialMenu.prototype['hide'] = MaterialMenu.prototype.hide; +/** + * Displays or hides the menu, depending on current state. + * + * @public + */ +MaterialMenu.prototype.toggle = function (evt) { + if (this.container_.classList.contains(this.CssClasses_.IS_VISIBLE)) { + this.hide(); + } else { + this.show(evt); + } +}; +MaterialMenu.prototype['toggle'] = MaterialMenu.prototype.toggle; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialMenu, + classAsString: 'MaterialMenu', + cssClass: 'mdl-js-menu', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Progress MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialProgress = function MaterialProgress(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialProgress'] = MaterialProgress; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialProgress.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialProgress.prototype.CssClasses_ = { INDETERMINATE_CLASS: 'mdl-progress__indeterminate' }; +/** + * Set the current progress of the progressbar. + * + * @param {number} p Percentage of the progress (0-100) + * @public + */ +MaterialProgress.prototype.setProgress = function (p) { + if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) { + return; + } + this.progressbar_.style.width = p + '%'; +}; +MaterialProgress.prototype['setProgress'] = MaterialProgress.prototype.setProgress; +/** + * Set the current progress of the buffer. + * + * @param {number} p Percentage of the buffer (0-100) + * @public + */ +MaterialProgress.prototype.setBuffer = function (p) { + this.bufferbar_.style.width = p + '%'; + this.auxbar_.style.width = 100 - p + '%'; +}; +MaterialProgress.prototype['setBuffer'] = MaterialProgress.prototype.setBuffer; +/** + * Initialize element. + */ +MaterialProgress.prototype.init = function () { + if (this.element_) { + var el = document.createElement('div'); + el.className = 'progressbar bar bar1'; + this.element_.appendChild(el); + this.progressbar_ = el; + el = document.createElement('div'); + el.className = 'bufferbar bar bar2'; + this.element_.appendChild(el); + this.bufferbar_ = el; + el = document.createElement('div'); + el.className = 'auxbar bar bar3'; + this.element_.appendChild(el); + this.auxbar_ = el; + this.progressbar_.style.width = '0%'; + this.bufferbar_.style.width = '100%'; + this.auxbar_.style.width = '0%'; + this.element_.classList.add('is-upgraded'); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialProgress, + classAsString: 'MaterialProgress', + cssClass: 'mdl-js-progress', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Radio MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialRadio = function MaterialRadio(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialRadio'] = MaterialRadio; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialRadio.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialRadio.prototype.CssClasses_ = { + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked', + IS_UPGRADED: 'is-upgraded', + JS_RADIO: 'mdl-js-radio', + RADIO_BTN: 'mdl-radio__button', + RADIO_OUTER_CIRCLE: 'mdl-radio__outer-circle', + RADIO_INNER_CIRCLE: 'mdl-radio__inner-circle', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-radio__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple' +}; +/** + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onChange_ = function (event) { + // Since other radio buttons don't get change events, we need to look for + // them to update their classes. + var radios = document.getElementsByClassName(this.CssClasses_.JS_RADIO); + for (var i = 0; i < radios.length; i++) { + var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN); + // Different name == different group, so no point updating those. + if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) { + radios[i]['MaterialRadio'].updateClasses_(); + } + } +}; +/** + * Handle focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle lost focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRadio.prototype.onMouseup_ = function (event) { + this.blur_(); +}; +/** + * Update classes. + * + * @private + */ +MaterialRadio.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); +}; +/** + * Add blur. + * + * @private + */ +MaterialRadio.prototype.blur_ = function () { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.btnElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); +}; +// Public methods. +/** + * Check the components disabled state. + * + * @public + */ +MaterialRadio.prototype.checkDisabled = function () { + if (this.btnElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } +}; +MaterialRadio.prototype['checkDisabled'] = MaterialRadio.prototype.checkDisabled; +/** + * Check the components toggled state. + * + * @public + */ +MaterialRadio.prototype.checkToggleState = function () { + if (this.btnElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } +}; +MaterialRadio.prototype['checkToggleState'] = MaterialRadio.prototype.checkToggleState; +/** + * Disable radio. + * + * @public + */ +MaterialRadio.prototype.disable = function () { + this.btnElement_.disabled = true; + this.updateClasses_(); +}; +MaterialRadio.prototype['disable'] = MaterialRadio.prototype.disable; +/** + * Enable radio. + * + * @public + */ +MaterialRadio.prototype.enable = function () { + this.btnElement_.disabled = false; + this.updateClasses_(); +}; +MaterialRadio.prototype['enable'] = MaterialRadio.prototype.enable; +/** + * Check radio. + * + * @public + */ +MaterialRadio.prototype.check = function () { + this.btnElement_.checked = true; + this.updateClasses_(); +}; +MaterialRadio.prototype['check'] = MaterialRadio.prototype.check; +/** + * Uncheck radio. + * + * @public + */ +MaterialRadio.prototype.uncheck = function () { + this.btnElement_.checked = false; + this.updateClasses_(); +}; +MaterialRadio.prototype['uncheck'] = MaterialRadio.prototype.uncheck; +/** + * Initialize element. + */ +MaterialRadio.prototype.init = function () { + if (this.element_) { + this.btnElement_ = this.element_.querySelector('.' + this.CssClasses_.RADIO_BTN); + this.boundChangeHandler_ = this.onChange_.bind(this); + this.boundFocusHandler_ = this.onChange_.bind(this); + this.boundBlurHandler_ = this.onBlur_.bind(this); + this.boundMouseUpHandler_ = this.onMouseup_.bind(this); + var outerCircle = document.createElement('span'); + outerCircle.classList.add(this.CssClasses_.RADIO_OUTER_CIRCLE); + var innerCircle = document.createElement('span'); + innerCircle.classList.add(this.CssClasses_.RADIO_INNER_CIRCLE); + this.element_.appendChild(outerCircle); + this.element_.appendChild(innerCircle); + var rippleContainer; + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + rippleContainer = document.createElement('span'); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT); + rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER); + rippleContainer.addEventListener('mouseup', this.boundMouseUpHandler_); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + this.element_.appendChild(rippleContainer); + } + this.btnElement_.addEventListener('change', this.boundChangeHandler_); + this.btnElement_.addEventListener('focus', this.boundFocusHandler_); + this.btnElement_.addEventListener('blur', this.boundBlurHandler_); + this.element_.addEventListener('mouseup', this.boundMouseUpHandler_); + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialRadio, + classAsString: 'MaterialRadio', + cssClass: 'mdl-js-radio', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Slider MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialSlider = function MaterialSlider(element) { + this.element_ = element; + // Browser feature detection. + this.isIE_ = window.navigator.msPointerEnabled; + // Initialize instance. + this.init(); +}; +window['MaterialSlider'] = MaterialSlider; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialSlider.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialSlider.prototype.CssClasses_ = { + IE_CONTAINER: 'mdl-slider__ie-container', + SLIDER_CONTAINER: 'mdl-slider__container', + BACKGROUND_FLEX: 'mdl-slider__background-flex', + BACKGROUND_LOWER: 'mdl-slider__background-lower', + BACKGROUND_UPPER: 'mdl-slider__background-upper', + IS_LOWEST_VALUE: 'is-lowest-value', + IS_UPGRADED: 'is-upgraded' +}; +/** + * Handle input on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onInput_ = function (event) { + this.updateValueStyles_(); +}; +/** + * Handle change on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onChange_ = function (event) { + this.updateValueStyles_(); +}; +/** + * Handle mouseup on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSlider.prototype.onMouseUp_ = function (event) { + event.target.blur(); +}; +/** + * Handle mousedown on container element. + * This handler is purpose is to not require the use to click + * exactly on the 2px slider element, as FireFox seems to be very + * strict about this. + * + * @param {Event} event The event that fired. + * @private + * @suppress {missingProperties} + */ +MaterialSlider.prototype.onContainerMouseDown_ = function (event) { + // If this click is not on the parent element (but rather some child) + // ignore. It may still bubble up. + if (event.target !== this.element_.parentElement) { + return; + } + // Discard the original event and create a new event that + // is on the slider element. + event.preventDefault(); + var newEvent = new MouseEvent('mousedown', { + target: event.target, + buttons: event.buttons, + clientX: event.clientX, + clientY: this.element_.getBoundingClientRect().y + }); + this.element_.dispatchEvent(newEvent); +}; +/** + * Handle updating of values. + * + * @private + */ +MaterialSlider.prototype.updateValueStyles_ = function () { + // Calculate and apply percentages to div structure behind slider. + var fraction = (this.element_.value - this.element_.min) / (this.element_.max - this.element_.min); + if (fraction === 0) { + this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE); + } else { + this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE); + } + if (!this.isIE_) { + this.backgroundLower_.style.flex = fraction; + this.backgroundLower_.style.webkitFlex = fraction; + this.backgroundUpper_.style.flex = 1 - fraction; + this.backgroundUpper_.style.webkitFlex = 1 - fraction; + } +}; +// Public methods. +/** + * Disable slider. + * + * @public + */ +MaterialSlider.prototype.disable = function () { + this.element_.disabled = true; +}; +MaterialSlider.prototype['disable'] = MaterialSlider.prototype.disable; +/** + * Enable slider. + * + * @public + */ +MaterialSlider.prototype.enable = function () { + this.element_.disabled = false; +}; +MaterialSlider.prototype['enable'] = MaterialSlider.prototype.enable; +/** + * Update slider value. + * + * @param {number} value The value to which to set the control (optional). + * @public + */ +MaterialSlider.prototype.change = function (value) { + if (typeof value !== 'undefined') { + this.element_.value = value; + } + this.updateValueStyles_(); +}; +MaterialSlider.prototype['change'] = MaterialSlider.prototype.change; +/** + * Initialize element. + */ +MaterialSlider.prototype.init = function () { + if (this.element_) { + if (this.isIE_) { + // Since we need to specify a very large height in IE due to + // implementation limitations, we add a parent here that trims it down to + // a reasonable size. + var containerIE = document.createElement('div'); + containerIE.classList.add(this.CssClasses_.IE_CONTAINER); + this.element_.parentElement.insertBefore(containerIE, this.element_); + this.element_.parentElement.removeChild(this.element_); + containerIE.appendChild(this.element_); + } else { + // For non-IE browsers, we need a div structure that sits behind the + // slider and allows us to style the left and right sides of it with + // different colors. + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.SLIDER_CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + var backgroundFlex = document.createElement('div'); + backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX); + container.appendChild(backgroundFlex); + this.backgroundLower_ = document.createElement('div'); + this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER); + backgroundFlex.appendChild(this.backgroundLower_); + this.backgroundUpper_ = document.createElement('div'); + this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER); + backgroundFlex.appendChild(this.backgroundUpper_); + } + this.boundInputHandler = this.onInput_.bind(this); + this.boundChangeHandler = this.onChange_.bind(this); + this.boundMouseUpHandler = this.onMouseUp_.bind(this); + this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this); + this.element_.addEventListener('input', this.boundInputHandler); + this.element_.addEventListener('change', this.boundChangeHandler); + this.element_.addEventListener('mouseup', this.boundMouseUpHandler); + this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler); + this.updateValueStyles_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialSlider, + classAsString: 'MaterialSlider', + cssClass: 'mdl-js-slider', + widget: true +}); +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Snackbar MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialSnackbar = function MaterialSnackbar(element) { + this.element_ = element; + this.textElement_ = this.element_.querySelector('.' + this.cssClasses_.MESSAGE); + this.actionElement_ = this.element_.querySelector('.' + this.cssClasses_.ACTION); + if (!this.textElement_) { + throw new Error('There must be a message element for a snackbar.'); + } + if (!this.actionElement_) { + throw new Error('There must be an action element for a snackbar.'); + } + this.active = false; + this.actionHandler_ = undefined; + this.message_ = undefined; + this.actionText_ = undefined; + this.queuedNotifications_ = []; + this.setActionHidden_(true); +}; +window['MaterialSnackbar'] = MaterialSnackbar; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialSnackbar.prototype.Constant_ = { + // The duration of the snackbar show/hide animation, in ms. + ANIMATION_LENGTH: 250 +}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialSnackbar.prototype.cssClasses_ = { + SNACKBAR: 'mdl-snackbar', + MESSAGE: 'mdl-snackbar__text', + ACTION: 'mdl-snackbar__action', + ACTIVE: 'mdl-snackbar--active' +}; +/** + * Display the snackbar. + * + * @private + */ +MaterialSnackbar.prototype.displaySnackbar_ = function () { + this.element_.setAttribute('aria-hidden', 'true'); + if (this.actionHandler_) { + this.actionElement_.textContent = this.actionText_; + this.actionElement_.addEventListener('click', this.actionHandler_); + this.setActionHidden_(false); + } + this.textElement_.textContent = this.message_; + this.element_.classList.add(this.cssClasses_.ACTIVE); + this.element_.setAttribute('aria-hidden', 'false'); + setTimeout(this.cleanup_.bind(this), this.timeout_); +}; +/** + * Show the snackbar. + * + * @param {Object} data The data for the notification. + * @public + */ +MaterialSnackbar.prototype.showSnackbar = function (data) { + if (data === undefined) { + throw new Error('Please provide a data object with at least a message to display.'); + } + if (data['message'] === undefined) { + throw new Error('Please provide a message to be displayed.'); + } + if (data['actionHandler'] && !data['actionText']) { + throw new Error('Please provide action text with the handler.'); + } + if (this.active) { + this.queuedNotifications_.push(data); + } else { + this.active = true; + this.message_ = data['message']; + if (data['timeout']) { + this.timeout_ = data['timeout']; + } else { + this.timeout_ = 2750; + } + if (data['actionHandler']) { + this.actionHandler_ = data['actionHandler']; + } + if (data['actionText']) { + this.actionText_ = data['actionText']; + } + this.displaySnackbar_(); + } +}; +MaterialSnackbar.prototype['showSnackbar'] = MaterialSnackbar.prototype.showSnackbar; +/** + * Check if the queue has items within it. + * If it does, display the next entry. + * + * @private + */ +MaterialSnackbar.prototype.checkQueue_ = function () { + if (this.queuedNotifications_.length > 0) { + this.showSnackbar(this.queuedNotifications_.shift()); + } +}; +/** + * Cleanup the snackbar event listeners and accessiblity attributes. + * + * @private + */ +MaterialSnackbar.prototype.cleanup_ = function () { + this.element_.classList.remove(this.cssClasses_.ACTIVE); + setTimeout(function () { + this.element_.setAttribute('aria-hidden', 'true'); + this.textElement_.textContent = ''; + if (!Boolean(this.actionElement_.getAttribute('aria-hidden'))) { + this.setActionHidden_(true); + this.actionElement_.textContent = ''; + this.actionElement_.removeEventListener('click', this.actionHandler_); + } + this.actionHandler_ = undefined; + this.message_ = undefined; + this.actionText_ = undefined; + this.active = false; + this.checkQueue_(); + }.bind(this), this.Constant_.ANIMATION_LENGTH); +}; +/** + * Set the action handler hidden state. + * + * @param {boolean} value + * @private + */ +MaterialSnackbar.prototype.setActionHidden_ = function (value) { + if (value) { + this.actionElement_.setAttribute('aria-hidden', 'true'); + } else { + this.actionElement_.removeAttribute('aria-hidden'); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialSnackbar, + classAsString: 'MaterialSnackbar', + cssClass: 'mdl-js-snackbar', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Spinner MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @param {HTMLElement} element The element that will be upgraded. + * @constructor + */ +var MaterialSpinner = function MaterialSpinner(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialSpinner'] = MaterialSpinner; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialSpinner.prototype.Constant_ = { MDL_SPINNER_LAYER_COUNT: 4 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialSpinner.prototype.CssClasses_ = { + MDL_SPINNER_LAYER: 'mdl-spinner__layer', + MDL_SPINNER_CIRCLE_CLIPPER: 'mdl-spinner__circle-clipper', + MDL_SPINNER_CIRCLE: 'mdl-spinner__circle', + MDL_SPINNER_GAP_PATCH: 'mdl-spinner__gap-patch', + MDL_SPINNER_LEFT: 'mdl-spinner__left', + MDL_SPINNER_RIGHT: 'mdl-spinner__right' +}; +/** + * Auxiliary method to create a spinner layer. + * + * @param {number} index Index of the layer to be created. + * @public + */ +MaterialSpinner.prototype.createLayer = function (index) { + var layer = document.createElement('div'); + layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER); + layer.classList.add(this.CssClasses_.MDL_SPINNER_LAYER + '-' + index); + var leftClipper = document.createElement('div'); + leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); + leftClipper.classList.add(this.CssClasses_.MDL_SPINNER_LEFT); + var gapPatch = document.createElement('div'); + gapPatch.classList.add(this.CssClasses_.MDL_SPINNER_GAP_PATCH); + var rightClipper = document.createElement('div'); + rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE_CLIPPER); + rightClipper.classList.add(this.CssClasses_.MDL_SPINNER_RIGHT); + var circleOwners = [ + leftClipper, + gapPatch, + rightClipper + ]; + for (var i = 0; i < circleOwners.length; i++) { + var circle = document.createElement('div'); + circle.classList.add(this.CssClasses_.MDL_SPINNER_CIRCLE); + circleOwners[i].appendChild(circle); + } + layer.appendChild(leftClipper); + layer.appendChild(gapPatch); + layer.appendChild(rightClipper); + this.element_.appendChild(layer); +}; +MaterialSpinner.prototype['createLayer'] = MaterialSpinner.prototype.createLayer; +/** + * Stops the spinner animation. + * Public method for users who need to stop the spinner for any reason. + * + * @public + */ +MaterialSpinner.prototype.stop = function () { + this.element_.classList.remove('is-active'); +}; +MaterialSpinner.prototype['stop'] = MaterialSpinner.prototype.stop; +/** + * Starts the spinner animation. + * Public method for users who need to manually start the spinner for any reason + * (instead of just adding the 'is-active' class to their markup). + * + * @public + */ +MaterialSpinner.prototype.start = function () { + this.element_.classList.add('is-active'); +}; +MaterialSpinner.prototype['start'] = MaterialSpinner.prototype.start; +/** + * Initialize element. + */ +MaterialSpinner.prototype.init = function () { + if (this.element_) { + for (var i = 1; i <= this.Constant_.MDL_SPINNER_LAYER_COUNT; i++) { + this.createLayer(i); + } + this.element_.classList.add('is-upgraded'); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialSpinner, + classAsString: 'MaterialSpinner', + cssClass: 'mdl-js-spinner', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Checkbox MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialSwitch = function MaterialSwitch(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialSwitch'] = MaterialSwitch; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialSwitch.prototype.Constant_ = { TINY_TIMEOUT: 0.001 }; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialSwitch.prototype.CssClasses_ = { + INPUT: 'mdl-switch__input', + TRACK: 'mdl-switch__track', + THUMB: 'mdl-switch__thumb', + FOCUS_HELPER: 'mdl-switch__focus-helper', + RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE_CONTAINER: 'mdl-switch__ripple-container', + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE: 'mdl-ripple', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_CHECKED: 'is-checked' +}; +/** + * Handle change of state. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onChange_ = function (event) { + this.updateClasses_(); +}; +/** + * Handle focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle lost focus of element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle mouseup. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialSwitch.prototype.onMouseUp_ = function (event) { + this.blur_(); +}; +/** + * Handle class updates. + * + * @private + */ +MaterialSwitch.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkToggleState(); +}; +/** + * Add blur. + * + * @private + */ +MaterialSwitch.prototype.blur_ = function () { + // TODO: figure out why there's a focus event being fired after our blur, + // so that we can avoid this hack. + window.setTimeout(function () { + this.inputElement_.blur(); + }.bind(this), this.Constant_.TINY_TIMEOUT); +}; +// Public methods. +/** + * Check the components disabled state. + * + * @public + */ +MaterialSwitch.prototype.checkDisabled = function () { + if (this.inputElement_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } +}; +MaterialSwitch.prototype['checkDisabled'] = MaterialSwitch.prototype.checkDisabled; +/** + * Check the components toggled state. + * + * @public + */ +MaterialSwitch.prototype.checkToggleState = function () { + if (this.inputElement_.checked) { + this.element_.classList.add(this.CssClasses_.IS_CHECKED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_CHECKED); + } +}; +MaterialSwitch.prototype['checkToggleState'] = MaterialSwitch.prototype.checkToggleState; +/** + * Disable switch. + * + * @public + */ +MaterialSwitch.prototype.disable = function () { + this.inputElement_.disabled = true; + this.updateClasses_(); +}; +MaterialSwitch.prototype['disable'] = MaterialSwitch.prototype.disable; +/** + * Enable switch. + * + * @public + */ +MaterialSwitch.prototype.enable = function () { + this.inputElement_.disabled = false; + this.updateClasses_(); +}; +MaterialSwitch.prototype['enable'] = MaterialSwitch.prototype.enable; +/** + * Activate switch. + * + * @public + */ +MaterialSwitch.prototype.on = function () { + this.inputElement_.checked = true; + this.updateClasses_(); +}; +MaterialSwitch.prototype['on'] = MaterialSwitch.prototype.on; +/** + * Deactivate switch. + * + * @public + */ +MaterialSwitch.prototype.off = function () { + this.inputElement_.checked = false; + this.updateClasses_(); +}; +MaterialSwitch.prototype['off'] = MaterialSwitch.prototype.off; +/** + * Initialize element. + */ +MaterialSwitch.prototype.init = function () { + if (this.element_) { + this.inputElement_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + var track = document.createElement('div'); + track.classList.add(this.CssClasses_.TRACK); + var thumb = document.createElement('div'); + thumb.classList.add(this.CssClasses_.THUMB); + var focusHelper = document.createElement('span'); + focusHelper.classList.add(this.CssClasses_.FOCUS_HELPER); + thumb.appendChild(focusHelper); + this.element_.appendChild(track); + this.element_.appendChild(thumb); + this.boundMouseUpHandler = this.onMouseUp_.bind(this); + if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + this.rippleContainerElement_ = document.createElement('span'); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CONTAINER); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_EFFECT); + this.rippleContainerElement_.classList.add(this.CssClasses_.RIPPLE_CENTER); + this.rippleContainerElement_.addEventListener('mouseup', this.boundMouseUpHandler); + var ripple = document.createElement('span'); + ripple.classList.add(this.CssClasses_.RIPPLE); + this.rippleContainerElement_.appendChild(ripple); + this.element_.appendChild(this.rippleContainerElement_); + } + this.boundChangeHandler = this.onChange_.bind(this); + this.boundFocusHandler = this.onFocus_.bind(this); + this.boundBlurHandler = this.onBlur_.bind(this); + this.inputElement_.addEventListener('change', this.boundChangeHandler); + this.inputElement_.addEventListener('focus', this.boundFocusHandler); + this.inputElement_.addEventListener('blur', this.boundBlurHandler); + this.element_.addEventListener('mouseup', this.boundMouseUpHandler); + this.updateClasses_(); + this.element_.classList.add('is-upgraded'); + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialSwitch, + classAsString: 'MaterialSwitch', + cssClass: 'mdl-js-switch', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Tabs MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {Element} element The element that will be upgraded. + */ +var MaterialTabs = function MaterialTabs(element) { + // Stores the HTML element. + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialTabs'] = MaterialTabs; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string} + * @private + */ +MaterialTabs.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialTabs.prototype.CssClasses_ = { + TAB_CLASS: 'mdl-tabs__tab', + PANEL_CLASS: 'mdl-tabs__panel', + ACTIVE_CLASS: 'is-active', + UPGRADED_CLASS: 'is-upgraded', + MDL_JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + MDL_RIPPLE_CONTAINER: 'mdl-tabs__ripple-container', + MDL_RIPPLE: 'mdl-ripple', + MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events' +}; +/** + * Handle clicks to a tabs component + * + * @private + */ +MaterialTabs.prototype.initTabs_ = function () { + if (this.element_.classList.contains(this.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { + this.element_.classList.add(this.CssClasses_.MDL_JS_RIPPLE_EFFECT_IGNORE_EVENTS); + } + // Select element tabs, document panels + this.tabs_ = this.element_.querySelectorAll('.' + this.CssClasses_.TAB_CLASS); + this.panels_ = this.element_.querySelectorAll('.' + this.CssClasses_.PANEL_CLASS); + // Create new tabs for each tab element + for (var i = 0; i < this.tabs_.length; i++) { + new MaterialTab(this.tabs_[i], this); + } + this.element_.classList.add(this.CssClasses_.UPGRADED_CLASS); +}; +/** + * Reset tab state, dropping active classes + * + * @private + */ +MaterialTabs.prototype.resetTabState_ = function () { + for (var k = 0; k < this.tabs_.length; k++) { + this.tabs_[k].classList.remove(this.CssClasses_.ACTIVE_CLASS); + } +}; +/** + * Reset panel state, droping active classes + * + * @private + */ +MaterialTabs.prototype.resetPanelState_ = function () { + for (var j = 0; j < this.panels_.length; j++) { + this.panels_[j].classList.remove(this.CssClasses_.ACTIVE_CLASS); + } +}; +/** + * Initialize element. + */ +MaterialTabs.prototype.init = function () { + if (this.element_) { + this.initTabs_(); + } +}; +/** + * Constructor for an individual tab. + * + * @constructor + * @param {Element} tab The HTML element for the tab. + * @param {MaterialTabs} ctx The MaterialTabs object that owns the tab. + */ +function MaterialTab(tab, ctx) { + if (tab) { + if (ctx.element_.classList.contains(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(ctx.CssClasses_.MDL_RIPPLE_CONTAINER); + rippleContainer.classList.add(ctx.CssClasses_.MDL_JS_RIPPLE_EFFECT); + var ripple = document.createElement('span'); + ripple.classList.add(ctx.CssClasses_.MDL_RIPPLE); + rippleContainer.appendChild(ripple); + tab.appendChild(rippleContainer); + } + tab.addEventListener('click', function (e) { + e.preventDefault(); + var href = tab.href.split('#')[1]; + var panel = ctx.element_.querySelector('#' + href); + ctx.resetTabState_(); + ctx.resetPanelState_(); + tab.classList.add(ctx.CssClasses_.ACTIVE_CLASS); + panel.classList.add(ctx.CssClasses_.ACTIVE_CLASS); + }); + } +} +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialTabs, + classAsString: 'MaterialTabs', + cssClass: 'mdl-js-tabs' +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Textfield MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialTextfield = function MaterialTextfield(element) { + this.element_ = element; + this.maxRows = this.Constant_.NO_MAX_ROWS; + // Initialize instance. + this.init(); +}; +window['MaterialTextfield'] = MaterialTextfield; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialTextfield.prototype.Constant_ = { + NO_MAX_ROWS: -1, + MAX_ROWS_ATTRIBUTE: 'maxrows' +}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialTextfield.prototype.CssClasses_ = { + LABEL: 'mdl-textfield__label', + INPUT: 'mdl-textfield__input', + IS_DIRTY: 'is-dirty', + IS_FOCUSED: 'is-focused', + IS_DISABLED: 'is-disabled', + IS_INVALID: 'is-invalid', + IS_UPGRADED: 'is-upgraded' +}; +/** + * Handle input being entered. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onKeyDown_ = function (event) { + var currentRowCount = event.target.value.split('\n').length; + if (event.keyCode === 13) { + if (currentRowCount >= this.maxRows) { + event.preventDefault(); + } + } +}; +/** + * Handle focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onFocus_ = function (event) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle lost focus. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onBlur_ = function (event) { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); +}; +/** + * Handle reset event from out side. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTextfield.prototype.onReset_ = function (event) { + this.updateClasses_(); +}; +/** + * Handle class updates. + * + * @private + */ +MaterialTextfield.prototype.updateClasses_ = function () { + this.checkDisabled(); + this.checkValidity(); + this.checkDirty(); + this.checkFocus(); +}; +// Public methods. +/** + * Check the disabled state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkDisabled = function () { + if (this.input_.disabled) { + this.element_.classList.add(this.CssClasses_.IS_DISABLED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DISABLED); + } +}; +MaterialTextfield.prototype['checkDisabled'] = MaterialTextfield.prototype.checkDisabled; +/** + * Check the focus state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkFocus = function () { + if (Boolean(this.element_.querySelector(':focus'))) { + this.element_.classList.add(this.CssClasses_.IS_FOCUSED); + } else { + this.element_.classList.remove(this.CssClasses_.IS_FOCUSED); + } +}; +MaterialTextfield.prototype['checkFocus'] = MaterialTextfield.prototype.checkFocus; +/** + * Check the validity state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkValidity = function () { + if (this.input_.validity) { + if (this.input_.validity.valid) { + this.element_.classList.remove(this.CssClasses_.IS_INVALID); + } else { + this.element_.classList.add(this.CssClasses_.IS_INVALID); + } + } +}; +MaterialTextfield.prototype['checkValidity'] = MaterialTextfield.prototype.checkValidity; +/** + * Check the dirty state and update field accordingly. + * + * @public + */ +MaterialTextfield.prototype.checkDirty = function () { + if (this.input_.value && this.input_.value.length > 0) { + this.element_.classList.add(this.CssClasses_.IS_DIRTY); + } else { + this.element_.classList.remove(this.CssClasses_.IS_DIRTY); + } +}; +MaterialTextfield.prototype['checkDirty'] = MaterialTextfield.prototype.checkDirty; +/** + * Disable text field. + * + * @public + */ +MaterialTextfield.prototype.disable = function () { + this.input_.disabled = true; + this.updateClasses_(); +}; +MaterialTextfield.prototype['disable'] = MaterialTextfield.prototype.disable; +/** + * Enable text field. + * + * @public + */ +MaterialTextfield.prototype.enable = function () { + this.input_.disabled = false; + this.updateClasses_(); +}; +MaterialTextfield.prototype['enable'] = MaterialTextfield.prototype.enable; +/** + * Update text field value. + * + * @param {string} value The value to which to set the control (optional). + * @public + */ +MaterialTextfield.prototype.change = function (value) { + this.input_.value = value || ''; + this.updateClasses_(); +}; +MaterialTextfield.prototype['change'] = MaterialTextfield.prototype.change; +/** + * Initialize element. + */ +MaterialTextfield.prototype.init = function () { + if (this.element_) { + this.label_ = this.element_.querySelector('.' + this.CssClasses_.LABEL); + this.input_ = this.element_.querySelector('.' + this.CssClasses_.INPUT); + if (this.input_) { + if (this.input_.hasAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE)) { + this.maxRows = parseInt(this.input_.getAttribute(this.Constant_.MAX_ROWS_ATTRIBUTE), 10); + if (isNaN(this.maxRows)) { + this.maxRows = this.Constant_.NO_MAX_ROWS; + } + } + this.boundUpdateClassesHandler = this.updateClasses_.bind(this); + this.boundFocusHandler = this.onFocus_.bind(this); + this.boundBlurHandler = this.onBlur_.bind(this); + this.boundResetHandler = this.onReset_.bind(this); + this.input_.addEventListener('input', this.boundUpdateClassesHandler); + this.input_.addEventListener('focus', this.boundFocusHandler); + this.input_.addEventListener('blur', this.boundBlurHandler); + this.input_.addEventListener('reset', this.boundResetHandler); + if (this.maxRows !== this.Constant_.NO_MAX_ROWS) { + // TODO: This should handle pasting multi line text. + // Currently doesn't. + this.boundKeyDownHandler = this.onKeyDown_.bind(this); + this.input_.addEventListener('keydown', this.boundKeyDownHandler); + } + var invalid = this.element_.classList.contains(this.CssClasses_.IS_INVALID); + this.updateClasses_(); + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + if (invalid) { + this.element_.classList.add(this.CssClasses_.IS_INVALID); + } + if (this.input_.hasAttribute('autofocus')) { + this.element_.focus(); + this.checkFocus(); + } + } + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialTextfield, + classAsString: 'MaterialTextfield', + cssClass: 'mdl-js-textfield', + widget: true +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Tooltip MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialTooltip = function MaterialTooltip(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialTooltip'] = MaterialTooltip; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialTooltip.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialTooltip.prototype.CssClasses_ = { + IS_ACTIVE: 'is-active', + BOTTOM: 'mdl-tooltip--bottom', + LEFT: 'mdl-tooltip--left', + RIGHT: 'mdl-tooltip--right', + TOP: 'mdl-tooltip--top' +}; +/** + * Handle mouseenter for tooltip. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialTooltip.prototype.handleMouseEnter_ = function (event) { + var props = event.target.getBoundingClientRect(); + var left = props.left + props.width / 2; + var top = props.top + props.height / 2; + var marginLeft = -1 * (this.element_.offsetWidth / 2); + var marginTop = -1 * (this.element_.offsetHeight / 2); + if (this.element_.classList.contains(this.CssClasses_.LEFT) || this.element_.classList.contains(this.CssClasses_.RIGHT)) { + left = props.width / 2; + if (top + marginTop < 0) { + this.element_.style.top = 0; + this.element_.style.marginTop = 0; + } else { + this.element_.style.top = top + 'px'; + this.element_.style.marginTop = marginTop + 'px'; + } + } else { + if (left + marginLeft < 0) { + this.element_.style.left = 0; + this.element_.style.marginLeft = 0; + } else { + this.element_.style.left = left + 'px'; + this.element_.style.marginLeft = marginLeft + 'px'; + } + } + if (this.element_.classList.contains(this.CssClasses_.TOP)) { + this.element_.style.top = props.top - this.element_.offsetHeight - 10 + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.RIGHT)) { + this.element_.style.left = props.left + props.width + 10 + 'px'; + } else if (this.element_.classList.contains(this.CssClasses_.LEFT)) { + this.element_.style.left = props.left - this.element_.offsetWidth - 10 + 'px'; + } else { + this.element_.style.top = props.top + props.height + 10 + 'px'; + } + this.element_.classList.add(this.CssClasses_.IS_ACTIVE); +}; +/** + * Handle mouseleave for tooltip. + * + * @private + */ +MaterialTooltip.prototype.handleMouseLeave_ = function () { + this.element_.classList.remove(this.CssClasses_.IS_ACTIVE); +}; +/** + * Initialize element. + */ +MaterialTooltip.prototype.init = function () { + if (this.element_) { + var forElId = this.element_.getAttribute('for'); + if (forElId) { + this.forElement_ = document.getElementById(forElId); + } + if (this.forElement_) { + // It's left here because it prevents accidental text selection on Android + if (!this.forElement_.hasAttribute('tabindex')) { + this.forElement_.setAttribute('tabindex', '0'); + } + this.boundMouseEnterHandler = this.handleMouseEnter_.bind(this); + this.boundMouseLeaveHandler = this.handleMouseLeave_.bind(this); + this.forElement_.addEventListener('mouseenter', this.boundMouseEnterHandler, false); + this.forElement_.addEventListener('touchend', this.boundMouseEnterHandler, false); + this.forElement_.addEventListener('mouseleave', this.boundMouseLeaveHandler, false); + window.addEventListener('touchstart', this.boundMouseLeaveHandler); + } + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialTooltip, + classAsString: 'MaterialTooltip', + cssClass: 'mdl-tooltip' +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Layout MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialLayout = function MaterialLayout(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialLayout'] = MaterialLayout; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialLayout.prototype.Constant_ = { + MAX_WIDTH: '(max-width: 1024px)', + TAB_SCROLL_PIXELS: 100, + MENU_ICON: '', + CHEVRON_LEFT: 'chevron_left', + CHEVRON_RIGHT: 'chevron_right' +}; +/** + * Keycodes, for code readability. + * + * @enum {number} + * @private + */ +MaterialLayout.prototype.Keycodes_ = { + ENTER: 13, + ESCAPE: 27, + SPACE: 32 +}; +/** + * Modes. + * + * @enum {number} + * @private + */ +MaterialLayout.prototype.Mode_ = { + STANDARD: 0, + SEAMED: 1, + WATERFALL: 2, + SCROLL: 3 +}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialLayout.prototype.CssClasses_ = { + CONTAINER: 'mdl-layout__container', + HEADER: 'mdl-layout__header', + DRAWER: 'mdl-layout__drawer', + CONTENT: 'mdl-layout__content', + DRAWER_BTN: 'mdl-layout__drawer-button', + ICON: 'material-icons', + JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect', + RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container', + RIPPLE: 'mdl-ripple', + RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + HEADER_SEAMED: 'mdl-layout__header--seamed', + HEADER_WATERFALL: 'mdl-layout__header--waterfall', + HEADER_SCROLL: 'mdl-layout__header--scroll', + FIXED_HEADER: 'mdl-layout--fixed-header', + OBFUSCATOR: 'mdl-layout__obfuscator', + TAB_BAR: 'mdl-layout__tab-bar', + TAB_CONTAINER: 'mdl-layout__tab-bar-container', + TAB: 'mdl-layout__tab', + TAB_BAR_BUTTON: 'mdl-layout__tab-bar-button', + TAB_BAR_LEFT_BUTTON: 'mdl-layout__tab-bar-left-button', + TAB_BAR_RIGHT_BUTTON: 'mdl-layout__tab-bar-right-button', + PANEL: 'mdl-layout__tab-panel', + HAS_DRAWER: 'has-drawer', + HAS_TABS: 'has-tabs', + HAS_SCROLLING_HEADER: 'has-scrolling-header', + CASTING_SHADOW: 'is-casting-shadow', + IS_COMPACT: 'is-compact', + IS_SMALL_SCREEN: 'is-small-screen', + IS_DRAWER_OPEN: 'is-visible', + IS_ACTIVE: 'is-active', + IS_UPGRADED: 'is-upgraded', + IS_ANIMATING: 'is-animating', + ON_LARGE_SCREEN: 'mdl-layout--large-screen-only', + ON_SMALL_SCREEN: 'mdl-layout--small-screen-only' +}; +/** + * Handles scrolling on the content. + * + * @private + */ +MaterialLayout.prototype.contentScrollHandler_ = function () { + if (this.header_.classList.contains(this.CssClasses_.IS_ANIMATING)) { + return; + } + var headerVisible = !this.element_.classList.contains(this.CssClasses_.IS_SMALL_SCREEN) || this.element_.classList.contains(this.CssClasses_.FIXED_HEADER); + if (this.content_.scrollTop > 0 && !this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); + this.header_.classList.add(this.CssClasses_.IS_COMPACT); + if (headerVisible) { + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } + } else if (this.content_.scrollTop <= 0 && this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); + this.header_.classList.remove(this.CssClasses_.IS_COMPACT); + if (headerVisible) { + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } + } +}; +/** + * Handles a keyboard event on the drawer. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialLayout.prototype.keyboardEventHandler_ = function (evt) { + if (evt.keyCode === this.Keycodes_.ESCAPE) { + this.toggleDrawer(); + } +}; +/** + * Handles changes in screen size. + * + * @private + */ +MaterialLayout.prototype.screenSizeHandler_ = function () { + if (this.screenSizeMediaQuery_.matches) { + this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN); + } else { + this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN); + // Collapse drawer (if any) when moving to a large screen size. + if (this.drawer_) { + this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + } + } +}; +/** + * Handles events of drawer button. + * + * @param {Event} evt The event that fired. + * @private + */ +MaterialLayout.prototype.drawerToggleHandler_ = function (evt) { + if (evt && evt.type === 'keydown') { + if (evt.keyCode === this.Keycodes_.SPACE || evt.keyCode === this.Keycodes_.ENTER) { + // prevent scrolling in drawer nav + evt.preventDefault(); + } else { + // prevent other keys + return; + } + } + this.toggleDrawer(); +}; +/** + * Handles (un)setting the `is-animating` class + * + * @private + */ +MaterialLayout.prototype.headerTransitionEndHandler_ = function () { + this.header_.classList.remove(this.CssClasses_.IS_ANIMATING); +}; +/** + * Handles expanding the header on click + * + * @private + */ +MaterialLayout.prototype.headerClickHandler_ = function () { + if (this.header_.classList.contains(this.CssClasses_.IS_COMPACT)) { + this.header_.classList.remove(this.CssClasses_.IS_COMPACT); + this.header_.classList.add(this.CssClasses_.IS_ANIMATING); + } +}; +/** + * Reset tab state, dropping active classes + * + * @private + */ +MaterialLayout.prototype.resetTabState_ = function (tabBar) { + for (var k = 0; k < tabBar.length; k++) { + tabBar[k].classList.remove(this.CssClasses_.IS_ACTIVE); + } +}; +/** + * Reset panel state, droping active classes + * + * @private + */ +MaterialLayout.prototype.resetPanelState_ = function (panels) { + for (var j = 0; j < panels.length; j++) { + panels[j].classList.remove(this.CssClasses_.IS_ACTIVE); + } +}; +/** + * Toggle drawer state + * + * @public + */ +MaterialLayout.prototype.toggleDrawer = function () { + var drawerButton = this.element_.querySelector('.' + this.CssClasses_.DRAWER_BTN); + this.drawer_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN); + this.obfuscator_.classList.toggle(this.CssClasses_.IS_DRAWER_OPEN); + // Set accessibility properties. + if (this.drawer_.classList.contains(this.CssClasses_.IS_DRAWER_OPEN)) { + this.drawer_.setAttribute('aria-hidden', 'false'); + drawerButton.setAttribute('aria-expanded', 'true'); + } else { + this.drawer_.setAttribute('aria-hidden', 'true'); + drawerButton.setAttribute('aria-expanded', 'false'); + } +}; +MaterialLayout.prototype['toggleDrawer'] = MaterialLayout.prototype.toggleDrawer; +/** + * Initialize element. + */ +MaterialLayout.prototype.init = function () { + if (this.element_) { + var container = document.createElement('div'); + container.classList.add(this.CssClasses_.CONTAINER); + this.element_.parentElement.insertBefore(container, this.element_); + this.element_.parentElement.removeChild(this.element_); + container.appendChild(this.element_); + var directChildren = this.element_.childNodes; + var numChildren = directChildren.length; + for (var c = 0; c < numChildren; c++) { + var child = directChildren[c]; + if (child.classList && child.classList.contains(this.CssClasses_.HEADER)) { + this.header_ = child; + } + if (child.classList && child.classList.contains(this.CssClasses_.DRAWER)) { + this.drawer_ = child; + } + if (child.classList && child.classList.contains(this.CssClasses_.CONTENT)) { + this.content_ = child; + } + } + window.addEventListener('pageshow', function (e) { + if (e.persisted) { + // when page is loaded from back/forward cache + // trigger repaint to let layout scroll in safari + this.element_.style.overflowY = 'hidden'; + requestAnimationFrame(function () { + this.element_.style.overflowY = ''; + }.bind(this)); + } + }.bind(this), false); + if (this.header_) { + this.tabBar_ = this.header_.querySelector('.' + this.CssClasses_.TAB_BAR); + } + var mode = this.Mode_.STANDARD; + if (this.header_) { + if (this.header_.classList.contains(this.CssClasses_.HEADER_SEAMED)) { + mode = this.Mode_.SEAMED; + } else if (this.header_.classList.contains(this.CssClasses_.HEADER_WATERFALL)) { + mode = this.Mode_.WATERFALL; + this.header_.addEventListener('transitionend', this.headerTransitionEndHandler_.bind(this)); + this.header_.addEventListener('click', this.headerClickHandler_.bind(this)); + } else if (this.header_.classList.contains(this.CssClasses_.HEADER_SCROLL)) { + mode = this.Mode_.SCROLL; + container.classList.add(this.CssClasses_.HAS_SCROLLING_HEADER); + } + if (mode === this.Mode_.STANDARD) { + this.header_.classList.add(this.CssClasses_.CASTING_SHADOW); + if (this.tabBar_) { + this.tabBar_.classList.add(this.CssClasses_.CASTING_SHADOW); + } + } else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) { + this.header_.classList.remove(this.CssClasses_.CASTING_SHADOW); + if (this.tabBar_) { + this.tabBar_.classList.remove(this.CssClasses_.CASTING_SHADOW); + } + } else if (mode === this.Mode_.WATERFALL) { + // Add and remove shadows depending on scroll position. + // Also add/remove auxiliary class for styling of the compact version of + // the header. + this.content_.addEventListener('scroll', this.contentScrollHandler_.bind(this)); + this.contentScrollHandler_(); + } + } + // Add drawer toggling button to our layout, if we have an openable drawer. + if (this.drawer_) { + var drawerButton = this.element_.querySelector('.' + this.CssClasses_.DRAWER_BTN); + if (!drawerButton) { + drawerButton = document.createElement('div'); + drawerButton.setAttribute('aria-expanded', 'false'); + drawerButton.setAttribute('role', 'button'); + drawerButton.setAttribute('tabindex', '0'); + drawerButton.classList.add(this.CssClasses_.DRAWER_BTN); + var drawerButtonIcon = document.createElement('i'); + drawerButtonIcon.classList.add(this.CssClasses_.ICON); + drawerButtonIcon.innerHTML = this.Constant_.MENU_ICON; + drawerButton.appendChild(drawerButtonIcon); + } + if (this.drawer_.classList.contains(this.CssClasses_.ON_LARGE_SCREEN)) { + //If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well. + drawerButton.classList.add(this.CssClasses_.ON_LARGE_SCREEN); + } else if (this.drawer_.classList.contains(this.CssClasses_.ON_SMALL_SCREEN)) { + //If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well. + drawerButton.classList.add(this.CssClasses_.ON_SMALL_SCREEN); + } + drawerButton.addEventListener('click', this.drawerToggleHandler_.bind(this)); + drawerButton.addEventListener('keydown', this.drawerToggleHandler_.bind(this)); + // Add a class if the layout has a drawer, for altering the left padding. + // Adds the HAS_DRAWER to the elements since this.header_ may or may + // not be present. + this.element_.classList.add(this.CssClasses_.HAS_DRAWER); + // If we have a fixed header, add the button to the header rather than + // the layout. + if (this.element_.classList.contains(this.CssClasses_.FIXED_HEADER)) { + this.header_.insertBefore(drawerButton, this.header_.firstChild); + } else { + this.element_.insertBefore(drawerButton, this.content_); + } + var obfuscator = document.createElement('div'); + obfuscator.classList.add(this.CssClasses_.OBFUSCATOR); + this.element_.appendChild(obfuscator); + obfuscator.addEventListener('click', this.drawerToggleHandler_.bind(this)); + this.obfuscator_ = obfuscator; + this.drawer_.addEventListener('keydown', this.keyboardEventHandler_.bind(this)); + this.drawer_.setAttribute('aria-hidden', 'true'); + } + // Keep an eye on screen size, and add/remove auxiliary class for styling + // of small screens. + this.screenSizeMediaQuery_ = window.matchMedia(this.Constant_.MAX_WIDTH); + this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this)); + this.screenSizeHandler_(); + // Initialize tabs, if any. + if (this.header_ && this.tabBar_) { + this.element_.classList.add(this.CssClasses_.HAS_TABS); + var tabContainer = document.createElement('div'); + tabContainer.classList.add(this.CssClasses_.TAB_CONTAINER); + this.header_.insertBefore(tabContainer, this.tabBar_); + this.header_.removeChild(this.tabBar_); + var leftButton = document.createElement('div'); + leftButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); + leftButton.classList.add(this.CssClasses_.TAB_BAR_LEFT_BUTTON); + var leftButtonIcon = document.createElement('i'); + leftButtonIcon.classList.add(this.CssClasses_.ICON); + leftButtonIcon.textContent = this.Constant_.CHEVRON_LEFT; + leftButton.appendChild(leftButtonIcon); + leftButton.addEventListener('click', function () { + this.tabBar_.scrollLeft -= this.Constant_.TAB_SCROLL_PIXELS; + }.bind(this)); + var rightButton = document.createElement('div'); + rightButton.classList.add(this.CssClasses_.TAB_BAR_BUTTON); + rightButton.classList.add(this.CssClasses_.TAB_BAR_RIGHT_BUTTON); + var rightButtonIcon = document.createElement('i'); + rightButtonIcon.classList.add(this.CssClasses_.ICON); + rightButtonIcon.textContent = this.Constant_.CHEVRON_RIGHT; + rightButton.appendChild(rightButtonIcon); + rightButton.addEventListener('click', function () { + this.tabBar_.scrollLeft += this.Constant_.TAB_SCROLL_PIXELS; + }.bind(this)); + tabContainer.appendChild(leftButton); + tabContainer.appendChild(this.tabBar_); + tabContainer.appendChild(rightButton); + // Add and remove buttons depending on scroll position. + var tabScrollHandler = function () { + if (this.tabBar_.scrollLeft > 0) { + leftButton.classList.add(this.CssClasses_.IS_ACTIVE); + } else { + leftButton.classList.remove(this.CssClasses_.IS_ACTIVE); + } + if (this.tabBar_.scrollLeft < this.tabBar_.scrollWidth - this.tabBar_.offsetWidth) { + rightButton.classList.add(this.CssClasses_.IS_ACTIVE); + } else { + rightButton.classList.remove(this.CssClasses_.IS_ACTIVE); + } + }.bind(this); + this.tabBar_.addEventListener('scroll', tabScrollHandler); + tabScrollHandler(); + if (this.tabBar_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) { + this.tabBar_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS); + } + // Select element tabs, document panels + var tabs = this.tabBar_.querySelectorAll('.' + this.CssClasses_.TAB); + var panels = this.content_.querySelectorAll('.' + this.CssClasses_.PANEL); + // Create new tabs for each tab element + for (var i = 0; i < tabs.length; i++) { + new MaterialLayoutTab(tabs[i], tabs, panels, this); + } + } + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + } +}; +/** + * Constructor for an individual tab. + * + * @constructor + * @param {HTMLElement} tab The HTML element for the tab. + * @param {!Array} tabs Array with HTML elements for all tabs. + * @param {!Array} panels Array with HTML elements for all panels. + * @param {MaterialLayout} layout The MaterialLayout object that owns the tab. + */ +function MaterialLayoutTab(tab, tabs, panels, layout) { + /** + * Auxiliary method to programmatically select a tab in the UI. + */ + function selectTab() { + var href = tab.href.split('#')[1]; + var panel = layout.content_.querySelector('#' + href); + layout.resetTabState_(tabs); + layout.resetPanelState_(panels); + tab.classList.add(layout.CssClasses_.IS_ACTIVE); + panel.classList.add(layout.CssClasses_.IS_ACTIVE); + } + if (layout.tabBar_.classList.contains(layout.CssClasses_.JS_RIPPLE_EFFECT)) { + var rippleContainer = document.createElement('span'); + rippleContainer.classList.add(layout.CssClasses_.RIPPLE_CONTAINER); + rippleContainer.classList.add(layout.CssClasses_.JS_RIPPLE_EFFECT); + var ripple = document.createElement('span'); + ripple.classList.add(layout.CssClasses_.RIPPLE); + rippleContainer.appendChild(ripple); + tab.appendChild(rippleContainer); + } + tab.addEventListener('click', function (e) { + if (tab.getAttribute('href').charAt(0) === '#') { + e.preventDefault(); + selectTab(); + } + }); + tab.show = selectTab; + tab.addEventListener('click', function (e) { + e.preventDefault(); + var href = tab.href.split('#')[1]; + var panel = layout.content_.querySelector('#' + href); + layout.resetTabState_(tabs); + layout.resetPanelState_(panels); + tab.classList.add(layout.CssClasses_.IS_ACTIVE); + panel.classList.add(layout.CssClasses_.IS_ACTIVE); + }); +} +window['MaterialLayoutTab'] = MaterialLayoutTab; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialLayout, + classAsString: 'MaterialLayout', + cssClass: 'mdl-js-layout' +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Data Table Card MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {Element} element The element that will be upgraded. + */ +var MaterialDataTable = function MaterialDataTable(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialDataTable'] = MaterialDataTable; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialDataTable.prototype.Constant_ = {}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialDataTable.prototype.CssClasses_ = { + DATA_TABLE: 'mdl-data-table', + SELECTABLE: 'mdl-data-table--selectable', + SELECT_ELEMENT: 'mdl-data-table__select', + IS_SELECTED: 'is-selected', + IS_UPGRADED: 'is-upgraded' +}; +/** + * Generates and returns a function that toggles the selection state of a + * single row (or multiple rows). + * + * @param {Element} checkbox Checkbox that toggles the selection state. + * @param {Element} row Row to toggle when checkbox changes. + * @param {(Array|NodeList)=} opt_rows Rows to toggle when checkbox changes. + * @private + */ +MaterialDataTable.prototype.selectRow_ = function (checkbox, row, opt_rows) { + if (row) { + return function () { + if (checkbox.checked) { + row.classList.add(this.CssClasses_.IS_SELECTED); + } else { + row.classList.remove(this.CssClasses_.IS_SELECTED); + } + }.bind(this); + } + if (opt_rows) { + return function () { + var i; + var el; + if (checkbox.checked) { + for (i = 0; i < opt_rows.length; i++) { + el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox'); + el['MaterialCheckbox'].check(); + opt_rows[i].classList.add(this.CssClasses_.IS_SELECTED); + } + } else { + for (i = 0; i < opt_rows.length; i++) { + el = opt_rows[i].querySelector('td').querySelector('.mdl-checkbox'); + el['MaterialCheckbox'].uncheck(); + opt_rows[i].classList.remove(this.CssClasses_.IS_SELECTED); + } + } + }.bind(this); + } +}; +/** + * Creates a checkbox for a single or or multiple rows and hooks up the + * event handling. + * + * @param {Element} row Row to toggle when checkbox changes. + * @param {(Array|NodeList)=} opt_rows Rows to toggle when checkbox changes. + * @private + */ +MaterialDataTable.prototype.createCheckbox_ = function (row, opt_rows) { + var label = document.createElement('label'); + var labelClasses = [ + 'mdl-checkbox', + 'mdl-js-checkbox', + 'mdl-js-ripple-effect', + this.CssClasses_.SELECT_ELEMENT + ]; + label.className = labelClasses.join(' '); + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.classList.add('mdl-checkbox__input'); + if (row) { + checkbox.checked = row.classList.contains(this.CssClasses_.IS_SELECTED); + checkbox.addEventListener('change', this.selectRow_(checkbox, row)); + } else if (opt_rows) { + checkbox.addEventListener('change', this.selectRow_(checkbox, null, opt_rows)); + } + label.appendChild(checkbox); + componentHandler.upgradeElement(label, 'MaterialCheckbox'); + return label; +}; +/** + * Initialize element. + */ +MaterialDataTable.prototype.init = function () { + if (this.element_) { + var firstHeader = this.element_.querySelector('th'); + var bodyRows = Array.prototype.slice.call(this.element_.querySelectorAll('tbody tr')); + var footRows = Array.prototype.slice.call(this.element_.querySelectorAll('tfoot tr')); + var rows = bodyRows.concat(footRows); + if (this.element_.classList.contains(this.CssClasses_.SELECTABLE)) { + var th = document.createElement('th'); + var headerCheckbox = this.createCheckbox_(null, rows); + th.appendChild(headerCheckbox); + firstHeader.parentElement.insertBefore(th, firstHeader); + for (var i = 0; i < rows.length; i++) { + var firstCell = rows[i].querySelector('td'); + if (firstCell) { + var td = document.createElement('td'); + if (rows[i].parentNode.nodeName.toUpperCase() === 'TBODY') { + var rowCheckbox = this.createCheckbox_(rows[i]); + td.appendChild(rowCheckbox); + } + rows[i].insertBefore(td, firstCell); + } + } + this.element_.classList.add(this.CssClasses_.IS_UPGRADED); + } + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialDataTable, + classAsString: 'MaterialDataTable', + cssClass: 'mdl-js-data-table' +}); +/** + * @license + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Class constructor for Ripple MDL component. + * Implements MDL component design pattern defined at: + * https://github.com/jasonmayes/mdl-component-design-pattern + * + * @constructor + * @param {HTMLElement} element The element that will be upgraded. + */ +var MaterialRipple = function MaterialRipple(element) { + this.element_ = element; + // Initialize instance. + this.init(); +}; +window['MaterialRipple'] = MaterialRipple; +/** + * Store constants in one place so they can be updated easily. + * + * @enum {string | number} + * @private + */ +MaterialRipple.prototype.Constant_ = { + INITIAL_SCALE: 'scale(0.0001, 0.0001)', + INITIAL_SIZE: '1px', + INITIAL_OPACITY: '0.4', + FINAL_OPACITY: '0', + FINAL_SCALE: '' +}; +/** + * Store strings for class names defined by this component that are used in + * JavaScript. This allows us to simply change it in one place should we + * decide to modify at a later date. + * + * @enum {string} + * @private + */ +MaterialRipple.prototype.CssClasses_ = { + RIPPLE_CENTER: 'mdl-ripple--center', + RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events', + RIPPLE: 'mdl-ripple', + IS_ANIMATING: 'is-animating', + IS_VISIBLE: 'is-visible' +}; +/** + * Handle mouse / finger down on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRipple.prototype.downHandler_ = function (event) { + if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) { + var rect = this.element_.getBoundingClientRect(); + this.boundHeight = rect.height; + this.boundWidth = rect.width; + this.rippleSize_ = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2; + this.rippleElement_.style.width = this.rippleSize_ + 'px'; + this.rippleElement_.style.height = this.rippleSize_ + 'px'; + } + this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE); + if (event.type === 'mousedown' && this.ignoringMouseDown_) { + this.ignoringMouseDown_ = false; + } else { + if (event.type === 'touchstart') { + this.ignoringMouseDown_ = true; + } + var frameCount = this.getFrameCount(); + if (frameCount > 0) { + return; + } + this.setFrameCount(1); + var bound = event.currentTarget.getBoundingClientRect(); + var x; + var y; + // Check if we are handling a keyboard click. + if (event.clientX === 0 && event.clientY === 0) { + x = Math.round(bound.width / 2); + y = Math.round(bound.height / 2); + } else { + var clientX = event.clientX ? event.clientX : event.touches[0].clientX; + var clientY = event.clientY ? event.clientY : event.touches[0].clientY; + x = Math.round(clientX - bound.left); + y = Math.round(clientY - bound.top); + } + this.setRippleXY(x, y); + this.setRippleStyles(true); + window.requestAnimationFrame(this.animFrameHandler.bind(this)); + } +}; +/** + * Handle mouse / finger up on element. + * + * @param {Event} event The event that fired. + * @private + */ +MaterialRipple.prototype.upHandler_ = function (event) { + // Don't fire for the artificial "mouseup" generated by a double-click. + if (event && event.detail !== 2) { + // Allow a repaint to occur before removing this class, so the animation + // shows for tap events, which seem to trigger a mouseup too soon after + // mousedown. + window.setTimeout(function () { + this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE); + }.bind(this), 0); + } +}; +/** + * Initialize element. + */ +MaterialRipple.prototype.init = function () { + if (this.element_) { + var recentering = this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER); + if (!this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) { + this.rippleElement_ = this.element_.querySelector('.' + this.CssClasses_.RIPPLE); + this.frameCount_ = 0; + this.rippleSize_ = 0; + this.x_ = 0; + this.y_ = 0; + // Touch start produces a compat mouse down event, which would cause a + // second ripples. To avoid that, we use this property to ignore the first + // mouse down after a touch start. + this.ignoringMouseDown_ = false; + this.boundDownHandler = this.downHandler_.bind(this); + this.element_.addEventListener('mousedown', this.boundDownHandler); + this.element_.addEventListener('touchstart', this.boundDownHandler); + this.boundUpHandler = this.upHandler_.bind(this); + this.element_.addEventListener('mouseup', this.boundUpHandler); + this.element_.addEventListener('mouseleave', this.boundUpHandler); + this.element_.addEventListener('touchend', this.boundUpHandler); + this.element_.addEventListener('blur', this.boundUpHandler); + /** + * Getter for frameCount_. + * @return {number} the frame count. + */ + this.getFrameCount = function () { + return this.frameCount_; + }; + /** + * Setter for frameCount_. + * @param {number} fC the frame count. + */ + this.setFrameCount = function (fC) { + this.frameCount_ = fC; + }; + /** + * Getter for rippleElement_. + * @return {Element} the ripple element. + */ + this.getRippleElement = function () { + return this.rippleElement_; + }; + /** + * Sets the ripple X and Y coordinates. + * @param {number} newX the new X coordinate + * @param {number} newY the new Y coordinate + */ + this.setRippleXY = function (newX, newY) { + this.x_ = newX; + this.y_ = newY; + }; + /** + * Sets the ripple styles. + * @param {boolean} start whether or not this is the start frame. + */ + this.setRippleStyles = function (start) { + if (this.rippleElement_ !== null) { + var transformString; + var scale; + var size; + var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)'; + if (start) { + scale = this.Constant_.INITIAL_SCALE; + size = this.Constant_.INITIAL_SIZE; + } else { + scale = this.Constant_.FINAL_SCALE; + size = this.rippleSize_ + 'px'; + if (recentering) { + offset = 'translate(' + this.boundWidth / 2 + 'px, ' + this.boundHeight / 2 + 'px)'; + } + } + transformString = 'translate(-50%, -50%) ' + offset + scale; + this.rippleElement_.style.webkitTransform = transformString; + this.rippleElement_.style.msTransform = transformString; + this.rippleElement_.style.transform = transformString; + if (start) { + this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING); + } else { + this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING); + } + } + }; + /** + * Handles an animation frame. + */ + this.animFrameHandler = function () { + if (this.frameCount_-- > 0) { + window.requestAnimationFrame(this.animFrameHandler.bind(this)); + } else { + this.setRippleStyles(false); + } + }; + } + } +}; +// The component registers itself. It can assume componentHandler is available +// in the global scope. +componentHandler.register({ + constructor: MaterialRipple, + classAsString: 'MaterialRipple', + cssClass: 'mdl-js-ripple-effect', + widget: false +}); +}()); diff --git a/dist/js/nv.d3.js b/dist/js/nv.d3.js new file mode 100644 index 0000000..b8314da --- /dev/null +++ b/dist/js/nv.d3.js @@ -0,0 +1,13789 @@ +/* nvd3 version 1.8.2 (https://github.com/novus/nvd3) 2016-01-24 */ +(function(){ + +// set up main nv object +var nv = {}; + +// the major global objects under the nv namespace +nv.dev = false; //set false when in production +nv.tooltip = nv.tooltip || {}; // For the tooltip system +nv.utils = nv.utils || {}; // Utility subsystem +nv.models = nv.models || {}; //stores all the possible models/components +nv.charts = {}; //stores all the ready to use charts +nv.logs = {}; //stores some statistics and potential error messages +nv.dom = {}; //DOM manipulation functions + +nv.dispatch = d3.dispatch('render_start', 'render_end'); + +// Function bind polyfill +// Needed ONLY for phantomJS as it's missing until version 2.0 which is unreleased as of this comment +// https://github.com/ariya/phantomjs/issues/10522 +// http://kangax.github.io/compat-table/es5/#Function.prototype.bind +// phantomJS is used for running the test suite +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== "function") { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} + +// Development render timers - disabled if dev = false +if (nv.dev) { + nv.dispatch.on('render_start', function(e) { + nv.logs.startTime = +new Date(); + }); + + nv.dispatch.on('render_end', function(e) { + nv.logs.endTime = +new Date(); + nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime; + nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times + }); +} + +// Logs all arguments, and returns the last so you can test things in place +// Note: in IE8 console.log is an object not a function, and if modernizr is used +// then calling Function.prototype.bind with with anything other than a function +// causes a TypeError to be thrown. +nv.log = function() { + if (nv.dev && window.console && console.log && console.log.apply) + console.log.apply(console, arguments); + else if (nv.dev && window.console && typeof console.log == "function" && Function.prototype.bind) { + var log = Function.prototype.bind.call(console.log, console); + log.apply(console, arguments); + } + return arguments[arguments.length - 1]; +}; + +// print console warning, should be used by deprecated functions +nv.deprecated = function(name, info) { + if (console && console.warn) { + console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || ''); + } +}; + +// The nv.render function is used to queue up chart rendering +// in non-blocking async functions. +// When all queued charts are done rendering, nv.dispatch.render_end is invoked. +nv.render = function render(step) { + // number of graphs to generate in each timeout loop + step = step || 1; + + nv.render.active = true; + nv.dispatch.render_start(); + + var renderLoop = function() { + var chart, graph; + + for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) { + chart = graph.generate(); + if (typeof graph.callback == typeof(Function)) graph.callback(chart); + } + + nv.render.queue.splice(0, i); + + if (nv.render.queue.length) { + setTimeout(renderLoop); + } + else { + nv.dispatch.render_end(); + nv.render.active = false; + } + }; + + setTimeout(renderLoop); +}; + +nv.render.active = false; +nv.render.queue = []; + +/* +Adds a chart to the async rendering queue. This method can take arguments in two forms: +nv.addGraph({ + generate: + callback: +}) + +or + +nv.addGraph(, ) + +The generate function should contain code that creates the NVD3 model, sets options +on it, adds data to an SVG element, and invokes the chart model. The generate function +should return the chart model. See examples/lineChart.html for a usage example. + +The callback function is optional, and it is called when the generate function completes. +*/ +nv.addGraph = function(obj) { + if (typeof arguments[0] === typeof(Function)) { + obj = {generate: arguments[0], callback: arguments[1]}; + } + + nv.render.queue.push(obj); + + if (!nv.render.active) { + nv.render(); + } +}; + +// Node/CommonJS exports +if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') { + module.exports = nv; +} + +if (typeof(window) !== 'undefined') { + window.nv = nv; +} +/* Facade for queueing DOM write operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.write = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.write(callback); + } + return callback(); +}; + +/* Facade for queueing DOM read operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.read = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.read(callback); + } + return callback(); +};/* Utility class to handle creation of an interactive layer. + This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch + containing the X-coordinate. It can also render a vertical line where the mouse is located. + + dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over + the rectangle. The dispatch is given one object which contains the mouseX/Y location. + It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale. + */ +nv.interactiveGuideline = function() { + "use strict"; + + var margin = { left: 0, top: 0 } //Pass the chart's top and left magins. Used to calculate the mouseX/Y. + , width = null + , height = null + , xScale = d3.scale.linear() + , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick', 'elementMouseDown', 'elementMouseUp') + , showGuideLine = true + , svgContainer = null // Must pass the chart's svg, we'll use its mousemove event. + , tooltip = nv.models.tooltip() + , isMSIE = "ActiveXObject" in window // Checkt if IE by looking for activeX. + ; + + tooltip + .duration(0) + .hideDelay(0) + .hidden(false); + + function layer(selection) { + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = (width || 960), availableHeight = (height || 400); + var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer") + .data([data]); + var wrapEnter = wrap.enter() + .append("g").attr("class", " nv-wrap nv-interactiveLineLayer"); + wrapEnter.append("g").attr("class","nv-interactiveGuideLine"); + + if (!svgContainer) { + return; + } + + function mouseHandler() { + var d3mouse = d3.mouse(this); + var mouseX = d3mouse[0]; + var mouseY = d3mouse[1]; + var subtractMargin = true; + var mouseOutAnyReason = false; + if (isMSIE) { + /* + D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10. + d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving + over a rect in IE 10. + However, d3.event.offsetX/Y also returns the mouse coordinates + relative to the triggering . So we use offsetX/Y on IE. + */ + mouseX = d3.event.offsetX; + mouseY = d3.event.offsetY; + + /* + On IE, if you attach a mouse event listener to the container, + it will actually trigger it for all the child elements (like , , etc). + When this happens on IE, the offsetX/Y is set to where ever the child element + is located. + As a result, we do NOT need to subtract margins to figure out the mouse X/Y + position under this scenario. Removing the line below *will* cause + the interactive layer to not work right on IE. + */ + if(d3.event.target.tagName !== "svg") { + subtractMargin = false; + } + + if (d3.event.target.className.baseVal.match("nv-legend")) { + mouseOutAnyReason = true; + } + + } + + if(subtractMargin) { + mouseX -= margin.left; + mouseY -= margin.top; + } + + /* If mouseX/Y is outside of the chart's bounds, + trigger a mouseOut event. + */ + if (mouseX < 0 || mouseY < 0 + || mouseX > availableWidth || mouseY > availableHeight + || (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined) + || mouseOutAnyReason + ) { + + if (isMSIE) { + if (d3.event.relatedTarget + && d3.event.relatedTarget.ownerSVGElement === undefined + && (d3.event.relatedTarget.className === undefined + || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) { + + return; + } + } + dispatch.elementMouseout({ + mouseX: mouseX, + mouseY: mouseY + }); + layer.renderGuideLine(null); //hide the guideline + tooltip.hidden(true); + return; + } else { + tooltip.hidden(false); + } + + + var scaleIsOrdinal = typeof xScale.rangeBands === 'function'; + var pointXValue = undefined; + + // Ordinal scale has no invert method + if (scaleIsOrdinal) { + var elementIndex = d3.bisect(xScale.range(), mouseX) - 1; + // Check if mouseX is in the range band + if (xScale.range()[elementIndex] + xScale.rangeBand() >= mouseX) { + pointXValue = xScale.domain()[d3.bisect(xScale.range(), mouseX) - 1]; + } + else { + dispatch.elementMouseout({ + mouseX: mouseX, + mouseY: mouseY + }); + layer.renderGuideLine(null); //hide the guideline + tooltip.hidden(true); + return; + } + } + else { + pointXValue = xScale.invert(mouseX); + } + + dispatch.elementMousemove({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + + //If user double clicks the layer, fire a elementDblclick + if (d3.event.type === "dblclick") { + dispatch.elementDblclick({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user single clicks the layer, fire elementClick + if (d3.event.type === 'click') { + dispatch.elementClick({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user presses mouse down the layer, fire elementMouseDown + if (d3.event.type === 'mousedown') { + dispatch.elementMouseDown({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user presses mouse down the layer, fire elementMouseUp + if (d3.event.type === 'mouseup') { + dispatch.elementMouseUp({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + } + + svgContainer + .on("touchmove",mouseHandler) + .on("mousemove",mouseHandler, true) + .on("mouseout" ,mouseHandler,true) + .on("mousedown" ,mouseHandler,true) + .on("mouseup" ,mouseHandler,true) + .on("dblclick" ,mouseHandler) + .on("click", mouseHandler) + ; + + layer.guideLine = null; + //Draws a vertical guideline at the given X postion. + layer.renderGuideLine = function(x) { + if (!showGuideLine) return; + if (layer.guideLine && layer.guideLine.attr("x1") === x) return; + nv.dom.write(function() { + var line = wrap.select(".nv-interactiveGuideLine") + .selectAll("line") + .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); + line.enter() + .append("line") + .attr("class", "nv-guideline") + .attr("x1", function(d) { return d;}) + .attr("x2", function(d) { return d;}) + .attr("y1", availableHeight) + .attr("y2",0); + line.exit().remove(); + }); + } + }); + } + + layer.dispatch = dispatch; + layer.tooltip = tooltip; + + layer.margin = function(_) { + if (!arguments.length) return margin; + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + return layer; + }; + + layer.width = function(_) { + if (!arguments.length) return width; + width = _; + return layer; + }; + + layer.height = function(_) { + if (!arguments.length) return height; + height = _; + return layer; + }; + + layer.xScale = function(_) { + if (!arguments.length) return xScale; + xScale = _; + return layer; + }; + + layer.showGuideLine = function(_) { + if (!arguments.length) return showGuideLine; + showGuideLine = _; + return layer; + }; + + layer.svgContainer = function(_) { + if (!arguments.length) return svgContainer; + svgContainer = _; + return layer; + }; + + return layer; +}; + +/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted. + This is different from normal bisectLeft; this function finds the nearest index to insert the search value. + + For instance, lets say your array is [1,2,3,5,10,30], and you search for 28. + Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5 + because 28 is closer to 30 than 10. + + Unit tests can be found in: interactiveBisectTest.html + + Has the following known issues: + * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order. + * Won't work if there are duplicate x coordinate values. + */ +nv.interactiveBisect = function (values, searchVal, xAccessor) { + "use strict"; + if (! (values instanceof Array)) { + return null; + } + var _xAccessor; + if (typeof xAccessor !== 'function') { + _xAccessor = function(d) { + return d.x; + } + } else { + _xAccessor = xAccessor; + } + var _cmp = function(d, v) { + // Accessors are no longer passed the index of the element along with + // the element itself when invoked by d3.bisector. + // + // Starting at D3 v3.4.4, d3.bisector() started inspecting the + // function passed to determine if it should consider it an accessor + // or a comparator. This meant that accessors that take two arguments + // (expecting an index as the second parameter) are treated as + // comparators where the second argument is the search value against + // which the first argument is compared. + return _xAccessor(d) - v; + }; + + var bisect = d3.bisector(_cmp).left; + var index = d3.max([0, bisect(values,searchVal) - 1]); + var currentValue = _xAccessor(values[index]); + + if (typeof currentValue === 'undefined') { + currentValue = index; + } + + if (currentValue === searchVal) { + return index; //found exact match + } + + var nextIndex = d3.min([index+1, values.length - 1]); + var nextValue = _xAccessor(values[nextIndex]); + + if (typeof nextValue === 'undefined') { + nextValue = nextIndex; + } + + if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal)) { + return index; + } else { + return nextIndex + } +}; + +/* + Returns the index in the array "values" that is closest to searchVal. + Only returns an index if searchVal is within some "threshold". + Otherwise, returns null. + */ +nv.nearestValueIndex = function (values, searchVal, threshold) { + "use strict"; + var yDistMax = Infinity, indexToHighlight = null; + values.forEach(function(d,i) { + var delta = Math.abs(searchVal - d); + if ( d != null && delta <= yDistMax && delta < threshold) { + yDistMax = delta; + indexToHighlight = i; + } + }); + return indexToHighlight; +}; + +/* Model which can be instantiated to handle tooltip rendering. + Example usage: + var tip = nv.models.tooltip().gravity('w').distance(23) + .data(myDataObject); + + tip(); //just invoke the returned function to render tooltip. + */ +nv.models.tooltip = function() { + "use strict"; + + /* + Tooltip data. If data is given in the proper format, a consistent tooltip is generated. + Example Format of data: + { + key: "Date", + value: "August 2009", + series: [ + {key: "Series 1", value: "Value 1", color: "#000"}, + {key: "Series 2", value: "Value 2", color: "#00f"} + ] + } + */ + var id = "nvtooltip-" + Math.floor(Math.random() * 100000) // Generates a unique id when you create a new tooltip() object. + , data = null + , gravity = 'w' // Can be 'n','s','e','w'. Determines how tooltip is positioned. + , distance = 25 // Distance to offset tooltip from the mouse location. + , snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) + , classes = null // Attaches additional CSS classes to the tooltip DIV that is created. + , chartContainer = null // Parent dom element of the SVG that holds the chart. + , hidden = true // Start off hidden, toggle with hide/show functions below. + , hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide(). + , tooltip = null // d3 select of the tooltip div. + , lastPosition = { left: null, top: null } // Last position the tooltip was in. + , enabled = true // True -> tooltips are rendered. False -> don't render tooltips. + , duration = 100 // Tooltip movement duration, in ms. + , headerEnabled = true // If is to show the tooltip header. + , nvPointerEventsClass = "nv-pointer-events-none" // CSS class to specify whether element should not have mouse events. + ; + + /* + Function that returns the position (relative to the viewport) the tooltip should be placed in. + Should return: { + left: , + top: + } + */ + var position = function() { + return { + left: d3.event !== null ? d3.event.clientX : 0, + top: d3.event !== null ? d3.event.clientY : 0 + }; + }; + + // Format function for the tooltip values column. + var valueFormatter = function(d, i) { + return d; + }; + + // Format function for the tooltip header value. + var headerFormatter = function(d) { + return d; + }; + + var keyFormatter = function(d, i) { + return d; + }; + + // By default, the tooltip model renders a beautiful table inside a DIV. + // You can override this function if a custom tooltip is desired. + var contentGenerator = function(d) { + if (d === null) { + return ''; + } + + var table = d3.select(document.createElement("table")); + if (headerEnabled) { + var theadEnter = table.selectAll("thead") + .data([d]) + .enter().append("thead"); + + theadEnter.append("tr") + .append("td") + .attr("colspan", 3) + .append("strong") + .classed("x-value", true) + .html(headerFormatter(d.value)); + } + + var tbodyEnter = table.selectAll("tbody") + .data([d]) + .enter().append("tbody"); + + var trowEnter = tbodyEnter.selectAll("tr") + .data(function(p) { return p.series}) + .enter() + .append("tr") + .classed("highlight", function(p) { return p.highlight}); + + trowEnter.append("td") + .classed("legend-color-guide",true) + .append("div") + .style("background-color", function(p) { return p.color}); + + trowEnter.append("td") + .classed("key",true) + .classed("total",function(p) { return !!p.total}) + .html(function(p, i) { return keyFormatter(p.key, i)}); + + trowEnter.append("td") + .classed("value",true) + .html(function(p, i) { return valueFormatter(p.value, i) }); + + trowEnter.selectAll("td").each(function(p) { + if (p.highlight) { + var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); + var opacity = 0.6; + d3.select(this) + .style("border-bottom-color", opacityScale(opacity)) + .style("border-top-color", opacityScale(opacity)) + ; + } + }); + + var html = table.node().outerHTML; + if (d.footer !== undefined) + html += ""; + return html; + + }; + + var dataSeriesExists = function(d) { + if (d && d.series) { + if (d.series instanceof Array) { + return !!d.series.length; + } + // if object, it's okay just convert to array of the object + if (d.series instanceof Object) { + d.series = [d.series]; + return true; + } + } + return false; + }; + + // Calculates the gravity offset of the tooltip. Parameter is position of tooltip + // relative to the viewport. + var calcGravityOffset = function(pos) { + var height = tooltip.node().offsetHeight, + width = tooltip.node().offsetWidth, + clientWidth = document.documentElement.clientWidth, // Don't want scrollbars. + clientHeight = document.documentElement.clientHeight, // Don't want scrollbars. + left, top, tmp; + + // calculate position based on gravity + switch (gravity) { + case 'e': + left = - width - distance; + top = - (height / 2); + if(pos.left + left < 0) left = distance; + if((tmp = pos.top + top) < 0) top -= tmp; + if((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; + break; + case 'w': + left = distance; + top = - (height / 2); + if (pos.left + left + width > clientWidth) left = - width - distance; + if ((tmp = pos.top + top) < 0) top -= tmp; + if ((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; + break; + case 'n': + left = - (width / 2) - 5; // - 5 is an approximation of the mouse's height. + top = distance; + if (pos.top + top + height > clientHeight) top = - height - distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; + break; + case 's': + left = - (width / 2); + top = - height - distance; + if (pos.top + top < 0) top = distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; + break; + case 'center': + left = - (width / 2); + top = - (height / 2); + break; + default: + left = 0; + top = 0; + break; + } + + return { 'left': left, 'top': top }; + }; + + /* + Positions the tooltip in the correct place, as given by the position() function. + */ + var positionTooltip = function() { + nv.dom.read(function() { + var pos = position(), + gravityOffset = calcGravityOffset(pos), + left = pos.left + gravityOffset.left, + top = pos.top + gravityOffset.top; + + // delay hiding a bit to avoid flickering + if (hidden) { + tooltip + .interrupt() + .transition() + .delay(hideDelay) + .duration(0) + .style('opacity', 0); + } else { + // using tooltip.style('transform') returns values un-usable for tween + var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)'; + var new_translate = 'translate(' + left + 'px, ' + top + 'px)'; + var translateInterpolator = d3.interpolateString(old_translate, new_translate); + var is_hidden = tooltip.style('opacity') < 0.1; + + tooltip + .interrupt() // cancel running transitions + .transition() + .duration(is_hidden ? 0 : duration) + // using tween since some versions of d3 can't auto-tween a translate on a div + .styleTween('transform', function (d) { + return translateInterpolator; + }, 'important') + // Safari has its own `-webkit-transform` and does not support `transform` + .styleTween('-webkit-transform', function (d) { + return translateInterpolator; + }) + .style('-ms-transform', new_translate) + .style('opacity', 1); + } + + lastPosition.left = left; + lastPosition.top = top; + }); + }; + + // Creates new tooltip container, or uses existing one on DOM. + function initTooltip() { + if (!tooltip) { + var container = chartContainer ? chartContainer : document.body; + + // Create new tooltip div if it doesn't exist on DOM. + tooltip = d3.select(container).append("div") + .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip")) + .attr("id", id); + tooltip.style("top", 0).style("left", 0); + tooltip.style('opacity', 0); + tooltip.style('position', 'fixed'); + tooltip.selectAll("div, table, td, tr").classed(nvPointerEventsClass, true); + tooltip.classed(nvPointerEventsClass, true); + } + } + + // Draw the tooltip onto the DOM. + function nvtooltip() { + if (!enabled) return; + if (!dataSeriesExists(data)) return; + + nv.dom.write(function () { + initTooltip(); + // Generate data and set it into tooltip. + // Bonus - If you override contentGenerator and return falsey you can use something like + // React or Knockout to bind the data for your tooltip. + var newContent = contentGenerator(data); + if (newContent) { + tooltip.node().innerHTML = newContent; + } + + positionTooltip(); + }); + + return nvtooltip; + } + + nvtooltip.nvPointerEventsClass = nvPointerEventsClass; + nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip); + + nvtooltip._options = Object.create({}, { + // simple read/write options + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}}, + distance: {get: function(){return distance;}, set: function(_){distance=_;}}, + snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}}, + classes: {get: function(){return classes;}, set: function(_){classes=_;}}, + chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}}, + enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}}, + hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}}, + contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}}, + valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}}, + headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}}, + keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}}, + headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}}, + position: {get: function(){return position;}, set: function(_){position=_;}}, + + // Deprecated options + fixedTop: {get: function(){return null;}, set: function(_){ + // deprecated after 1.8.1 + nv.deprecated('fixedTop', 'feature removed after 1.8.1'); + }}, + offset: {get: function(){return {left: 0, top: 0};}, set: function(_){ + // deprecated after 1.8.1 + nv.deprecated('offset', 'use chart.tooltip.distance() instead'); + }}, + + // options with extra logic + hidden: {get: function(){return hidden;}, set: function(_){ + if (hidden != _) { + hidden = !!_; + nvtooltip(); + } + }}, + data: {get: function(){return data;}, set: function(_){ + // if showing a single data point, adjust data format with that + if (_.point) { + _.value = _.point.x; + _.series = _.series || {}; + _.series.value = _.point.y; + _.series.color = _.point.color || _.series.color; + } + data = _; + }}, + + // read only properties + node: {get: function(){return tooltip.node();}, set: function(_){}}, + id: {get: function(){return id;}, set: function(_){}} + }); + + nv.utils.initOptions(nvtooltip); + return nvtooltip; +}; + + +/* +Gets the browser window size + +Returns object with height and width properties + */ +nv.utils.windowSize = function() { + // Sane defaults + var size = {width: 640, height: 480}; + + // Most recent browsers use + if (window.innerWidth && window.innerHeight) { + size.width = window.innerWidth; + size.height = window.innerHeight; + return (size); + } + + // IE can use depending on mode it is in + if (document.compatMode=='CSS1Compat' && + document.documentElement && + document.documentElement.offsetWidth ) { + + size.width = document.documentElement.offsetWidth; + size.height = document.documentElement.offsetHeight; + return (size); + } + + // Earlier IE uses Doc.body + if (document.body && document.body.offsetWidth) { + size.width = document.body.offsetWidth; + size.height = document.body.offsetHeight; + return (size); + } + + return (size); +}; + +/* +Binds callback function to run when window is resized + */ +nv.utils.windowResize = function(handler) { + if (window.addEventListener) { + window.addEventListener('resize', handler); + } else { + nv.log("ERROR: Failed to bind to window.resize with: ", handler); + } + // return object with clear function to remove the single added callback. + return { + callback: handler, + clear: function() { + window.removeEventListener('resize', handler); + } + } +}; + + +/* +Backwards compatible way to implement more d3-like coloring of graphs. +Can take in nothing, an array, or a function/scale +To use a normal scale, get the range and pass that because we must be able +to take two arguments and use the index to keep backward compatibility +*/ +nv.utils.getColor = function(color) { + //if you pass in nothing, get default colors back + if (color === undefined) { + return nv.utils.defaultColor(); + + //if passed an array, turn it into a color scale + // use isArray, instanceof fails if d3 range is created in an iframe + } else if(Array.isArray(color)) { + var color_scale = d3.scale.ordinal().range(color); + return function(d, i) { + var key = i === undefined ? d : i; + return d.color || color_scale(key); + }; + + //if passed a function or scale, return it, or whatever it may be + //external libs, such as angularjs-nvd3-directives use this + } else { + //can't really help it if someone passes rubbish as color + return color; + } +}; + + +/* +Default color chooser uses a color scale of 20 colors from D3 + https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors + */ +nv.utils.defaultColor = function() { + // get range of the scale so we'll turn it into our own function. + return nv.utils.getColor(d3.scale.category20().range()); +}; + + +/* +Returns a color function that takes the result of 'getKey' for each series and +looks for a corresponding color from the dictionary +*/ +nv.utils.customTheme = function(dictionary, getKey, defaultColors) { + // use default series.key if getKey is undefined + getKey = getKey || function(series) { return series.key }; + defaultColors = defaultColors || d3.scale.category20().range(); + + // start at end of default color list and walk back to index 0 + var defIndex = defaultColors.length; + + return function(series, index) { + var key = getKey(series); + if (typeof dictionary[key] === 'function') { + return dictionary[key](); + } else if (dictionary[key] !== undefined) { + return dictionary[key]; + } else { + // no match in dictionary, use a default color + if (!defIndex) { + // used all the default colors, start over + defIndex = defaultColors.length; + } + defIndex = defIndex - 1; + return defaultColors[defIndex]; + } + }; +}; + + +/* +From the PJAX example on d3js.org, while this is not really directly needed +it's a very cool method for doing pjax, I may expand upon it a little bit, +open to suggestions on anything that may be useful +*/ +nv.utils.pjax = function(links, content) { + + var load = function(href) { + d3.html(href, function(fragment) { + var target = d3.select(content).node(); + target.parentNode.replaceChild( + d3.select(fragment).select(content).node(), + target); + nv.utils.pjax(links, content); + }); + }; + + d3.selectAll(links).on("click", function() { + history.pushState(this.href, this.textContent, this.href); + load(this.href); + d3.event.preventDefault(); + }); + + d3.select(window).on("popstate", function() { + if (d3.event.state) { + load(d3.event.state); + } + }); +}; + + +/* +For when we want to approximate the width in pixels for an SVG:text element. +Most common instance is when the element is in a display:none; container. +Forumla is : text.length * font-size * constant_factor +*/ +nv.utils.calcApproxTextWidth = function (svgTextElem) { + if (typeof svgTextElem.style === 'function' + && typeof svgTextElem.text === 'function') { + + var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""), 10); + var textLength = svgTextElem.text().length; + return textLength * fontSize * 0.5; + } + return 0; +}; + + +/* +Numbers that are undefined, null or NaN, convert them to zeros. +*/ +nv.utils.NaNtoZero = function(n) { + if (typeof n !== 'number' + || isNaN(n) + || n === null + || n === Infinity + || n === -Infinity) { + + return 0; + } + return n; +}; + +/* +Add a way to watch for d3 transition ends to d3 +*/ +d3.selection.prototype.watchTransition = function(renderWatch){ + var args = [this].concat([].slice.call(arguments, 1)); + return renderWatch.transition.apply(renderWatch, args); +}; + + +/* +Helper object to watch when d3 has rendered something +*/ +nv.utils.renderWatch = function(dispatch, duration) { + if (!(this instanceof nv.utils.renderWatch)) { + return new nv.utils.renderWatch(dispatch, duration); + } + + var _duration = duration !== undefined ? duration : 250; + var renderStack = []; + var self = this; + + this.models = function(models) { + models = [].slice.call(arguments, 0); + models.forEach(function(model){ + model.__rendered = false; + (function(m){ + m.dispatch.on('renderEnd', function(arg){ + m.__rendered = true; + self.renderEnd('model'); + }); + })(model); + + if (renderStack.indexOf(model) < 0) { + renderStack.push(model); + } + }); + return this; + }; + + this.reset = function(duration) { + if (duration !== undefined) { + _duration = duration; + } + renderStack = []; + }; + + this.transition = function(selection, args, duration) { + args = arguments.length > 1 ? [].slice.call(arguments, 1) : []; + + if (args.length > 1) { + duration = args.pop(); + } else { + duration = _duration !== undefined ? _duration : 250; + } + selection.__rendered = false; + + if (renderStack.indexOf(selection) < 0) { + renderStack.push(selection); + } + + if (duration === 0) { + selection.__rendered = true; + selection.delay = function() { return this; }; + selection.duration = function() { return this; }; + return selection; + } else { + if (selection.length === 0) { + selection.__rendered = true; + } else if (selection.every( function(d){ return !d.length; } )) { + selection.__rendered = true; + } else { + selection.__rendered = false; + } + + var n = 0; + return selection + .transition() + .duration(duration) + .each(function(){ ++n; }) + .each('end', function(d, i) { + if (--n === 0) { + selection.__rendered = true; + self.renderEnd.apply(this, args); + } + }); + } + }; + + this.renderEnd = function() { + if (renderStack.every( function(d){ return d.__rendered; } )) { + renderStack.forEach( function(d){ d.__rendered = false; }); + dispatch.renderEnd.apply(this, arguments); + } + } + +}; + + +/* +Takes multiple objects and combines them into the first one (dst) +example: nv.utils.deepExtend({a: 1}, {a: 2, b: 3}, {c: 4}); +gives: {a: 2, b: 3, c: 4} +*/ +nv.utils.deepExtend = function(dst){ + var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : []; + sources.forEach(function(source) { + for (var key in source) { + var isArray = dst[key] instanceof Array; + var isObject = typeof dst[key] === 'object'; + var srcObj = typeof source[key] === 'object'; + + if (isObject && !isArray && srcObj) { + nv.utils.deepExtend(dst[key], source[key]); + } else { + dst[key] = source[key]; + } + } + }); +}; + + +/* +state utility object, used to track d3 states in the models +*/ +nv.utils.state = function(){ + if (!(this instanceof nv.utils.state)) { + return new nv.utils.state(); + } + var state = {}; + var _self = this; + var _setState = function(){}; + var _getState = function(){ return {}; }; + var init = null; + var changed = null; + + this.dispatch = d3.dispatch('change', 'set'); + + this.dispatch.on('set', function(state){ + _setState(state, true); + }); + + this.getter = function(fn){ + _getState = fn; + return this; + }; + + this.setter = function(fn, callback) { + if (!callback) { + callback = function(){}; + } + _setState = function(state, update){ + fn(state); + if (update) { + callback(); + } + }; + return this; + }; + + this.init = function(state){ + init = init || {}; + nv.utils.deepExtend(init, state); + }; + + var _set = function(){ + var settings = _getState(); + + if (JSON.stringify(settings) === JSON.stringify(state)) { + return false; + } + + for (var key in settings) { + if (state[key] === undefined) { + state[key] = {}; + } + state[key] = settings[key]; + changed = true; + } + return true; + }; + + this.update = function(){ + if (init) { + _setState(init, false); + init = null; + } + if (_set.call(this)) { + this.dispatch.change(state); + } + }; + +}; + + +/* +Snippet of code you can insert into each nv.models.* to give you the ability to +do things like: +chart.options({ + showXAxis: true, + tooltips: true +}); + +To enable in the chart: +chart.options = nv.utils.optionsFunc.bind(chart); +*/ +nv.utils.optionsFunc = function(args) { + if (args) { + d3.map(args).forEach((function(key,value) { + if (typeof this[key] === "function") { + this[key](value); + } + }).bind(this)); + } + return this; +}; + + +/* +numTicks: requested number of ticks +data: the chart data + +returns the number of ticks to actually use on X axis, based on chart data +to avoid duplicate ticks with the same value +*/ +nv.utils.calcTicksX = function(numTicks, data) { + // find max number of values from all data streams + var numValues = 1; + var i = 0; + for (i; i < data.length; i += 1) { + var stream_len = data[i] && data[i].values ? data[i].values.length : 0; + numValues = stream_len > numValues ? stream_len : numValues; + } + nv.log("Requested number of ticks: ", numTicks); + nv.log("Calculated max values to be: ", numValues); + // make sure we don't have more ticks than values to avoid duplicates + numTicks = numTicks > numValues ? numTicks = numValues - 1 : numTicks; + // make sure we have at least one tick + numTicks = numTicks < 1 ? 1 : numTicks; + // make sure it's an integer + numTicks = Math.floor(numTicks); + nv.log("Calculating tick count as: ", numTicks); + return numTicks; +}; + + +/* +returns number of ticks to actually use on Y axis, based on chart data +*/ +nv.utils.calcTicksY = function(numTicks, data) { + // currently uses the same logic but we can adjust here if needed later + return nv.utils.calcTicksX(numTicks, data); +}; + + +/* +Add a particular option from an options object onto chart +Options exposed on a chart are a getter/setter function that returns chart +on set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b'); + +option objects should be generated via Object.create() to provide +the option of manipulating data via get/set functions. +*/ +nv.utils.initOption = function(chart, name) { + // if it's a call option, just call it directly, otherwise do get/set + if (chart._calls && chart._calls[name]) { + chart[name] = chart._calls[name]; + } else { + chart[name] = function (_) { + if (!arguments.length) return chart._options[name]; + chart._overrides[name] = true; + chart._options[name] = _; + return chart; + }; + // calling the option as _option will ignore if set by option already + // so nvd3 can set options internally but the stop if set manually + chart['_' + name] = function(_) { + if (!arguments.length) return chart._options[name]; + if (!chart._overrides[name]) { + chart._options[name] = _; + } + return chart; + } + } +}; + + +/* +Add all options in an options object to the chart +*/ +nv.utils.initOptions = function(chart) { + chart._overrides = chart._overrides || {}; + var ops = Object.getOwnPropertyNames(chart._options || {}); + var calls = Object.getOwnPropertyNames(chart._calls || {}); + ops = ops.concat(calls); + for (var i in ops) { + nv.utils.initOption(chart, ops[i]); + } +}; + + +/* +Inherit options from a D3 object +d3.rebind makes calling the function on target actually call it on source +Also use _d3options so we can track what we inherit for documentation and chained inheritance +*/ +nv.utils.inheritOptionsD3 = function(target, d3_source, oplist) { + target._d3options = oplist.concat(target._d3options || []); + oplist.unshift(d3_source); + oplist.unshift(target); + d3.rebind.apply(this, oplist); +}; + + +/* +Remove duplicates from an array +*/ +nv.utils.arrayUnique = function(a) { + return a.sort().filter(function(item, pos) { + return !pos || item != a[pos - 1]; + }); +}; + + +/* +Keeps a list of custom symbols to draw from in addition to d3.svg.symbol +Necessary since d3 doesn't let you extend its list -_- +Add new symbols by doing nv.utils.symbols.set('name', function(size){...}); +*/ +nv.utils.symbolMap = d3.map(); + + +/* +Replaces d3.svg.symbol so that we can look both there and our own map + */ +nv.utils.symbol = function() { + var type, + size = 64; + function symbol(d,i) { + var t = type.call(this,d,i); + var s = size.call(this,d,i); + if (d3.svg.symbolTypes.indexOf(t) !== -1) { + return d3.svg.symbol().type(t).size(s)(); + } else { + return nv.utils.symbolMap.get(t)(s); + } + } + symbol.type = function(_) { + if (!arguments.length) return type; + type = d3.functor(_); + return symbol; + }; + symbol.size = function(_) { + if (!arguments.length) return size; + size = d3.functor(_); + return symbol; + }; + return symbol; +}; + + +/* +Inherit option getter/setter functions from source to target +d3.rebind makes calling the function on target actually call it on source +Also track via _inherited and _d3options so we can track what we inherit +for documentation generation purposes and chained inheritance +*/ +nv.utils.inheritOptions = function(target, source) { + // inherit all the things + var ops = Object.getOwnPropertyNames(source._options || {}); + var calls = Object.getOwnPropertyNames(source._calls || {}); + var inherited = source._inherited || []; + var d3ops = source._d3options || []; + var args = ops.concat(calls).concat(inherited).concat(d3ops); + args.unshift(source); + args.unshift(target); + d3.rebind.apply(this, args); + // pass along the lists to keep track of them, don't allow duplicates + target._inherited = nv.utils.arrayUnique(ops.concat(calls).concat(inherited).concat(ops).concat(target._inherited || [])); + target._d3options = nv.utils.arrayUnique(d3ops.concat(target._d3options || [])); +}; + + +/* +Runs common initialize code on the svg before the chart builds +*/ +nv.utils.initSVG = function(svg) { + svg.classed({'nvd3-svg':true}); +}; + + +/* +Sanitize and provide default for the container height. +*/ +nv.utils.sanitizeHeight = function(height, container) { + return (height || parseInt(container.style('height'), 10) || 400); +}; + + +/* +Sanitize and provide default for the container width. +*/ +nv.utils.sanitizeWidth = function(width, container) { + return (width || parseInt(container.style('width'), 10) || 960); +}; + + +/* +Calculate the available height for a chart. +*/ +nv.utils.availableHeight = function(height, container, margin) { + return Math.max(0,nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom); +}; + +/* +Calculate the available width for a chart. +*/ +nv.utils.availableWidth = function(width, container, margin) { + return Math.max(0,nv.utils.sanitizeWidth(width, container) - margin.left - margin.right); +}; + +/* +Clear any rendered chart components and display a chart's 'noData' message +*/ +nv.utils.noData = function(chart, container) { + var opt = chart.options(), + margin = opt.margin(), + noData = opt.noData(), + data = (noData == null) ? ["No Data Available."] : [noData], + height = nv.utils.availableHeight(null, container, margin), + width = nv.utils.availableWidth(null, container, margin), + x = margin.left + width/2, + y = margin.top + height/2; + + //Remove any previously created chart components + container.selectAll('g').remove(); + + var noDataText = container.selectAll('.nv-noData').data(data); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', x) + .attr('y', y) + .text(function(t){ return t; }); +}; + +/* + Wrap long labels. + */ +nv.utils.wrapTicks = function (text, width) { + text.each(function() { + var text = d3.select(this), + words = text.text().split(/\s+/).reverse(), + word, + line = [], + lineNumber = 0, + lineHeight = 1.1, + y = text.attr("y"), + dy = parseFloat(text.attr("dy")), + tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em"); + while (word = words.pop()) { + line.push(word); + tspan.text(line.join(" ")); + if (tspan.node().getComputedTextLength() > width) { + line.pop(); + tspan.text(line.join(" ")); + line = [word]; + tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); + } + } + }); +}; + +/* +Check equality of 2 array +*/ +nv.utils.arrayEquals = function (array1, array2) { + if (array1 === array2) + return true; + + if (!array1 || !array2) + return false; + + // compare lengths - can save a lot of time + if (array1.length != array2.length) + return false; + + for (var i = 0, + l = array1.length; i < l; i++) { + // Check if we have nested arrays + if (array1[i] instanceof Array && array2[i] instanceof Array) { + // recurse into the nested arrays + if (!nv.arrayEquals(array1[i], array2[i])) + return false; + } else if (array1[i] != array2[i]) { + // Warning - two different object instances will never be equal: {x:20} != {x:20} + return false; + } + } + return true; +};nv.models.axis = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var axis = d3.svg.axis(); + var scale = d3.scale.linear(); + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 75 //only used for tickLabel currently + , height = 60 //only used for tickLabel currently + , axisLabelText = null + , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes + , rotateLabels = 0 + , rotateYLabel = true + , staggerLabels = false + , isOrdinal = false + , ticks = null + , axisLabelDistance = 0 + , duration = 250 + , dispatch = d3.dispatch('renderEnd') + ; + axis + .scale(scale) + .orient('bottom') + .tickFormat(function(d) { return d }) + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var scale0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + if (ticks !== null) + axis.ticks(ticks); + else if (axis.orient() == 'top' || axis.orient() == 'bottom') + axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100); + + //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component + g.watchTransition(renderWatch, 'axis').call(axis); + + scale0 = scale0 || axis.scale(); + + var fmt = axis.tickFormat(); + if (fmt == null) { + fmt = scale0.tickFormat(); + } + + var axisLabel = g.selectAll('text.nv-axislabel') + .data([axisLabelText || null]); + axisLabel.exit().remove(); + + var xLabelMargin; + var axisMaxMin; + var w; + switch (axis.orient()) { + case 'top': + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; + } else if (scale.range().length === 2) { + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + }; + axisLabel + .attr('text-anchor', 'middle') + .attr('y', 0) + .attr('x', w/2); + if (showMaxMin) { + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero(scale(d)) + ',0)' + }) + .select('text') + .attr('dy', '-0.5em') + .attr('y', -axis.tickPadding()) + .attr('text-anchor', 'middle') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max top') + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero(scale.range()[i]) + ',0)' + }); + } + break; + case 'bottom': + xLabelMargin = axisLabelDistance + 36; + var maxTextWidth = 30; + var textHeight = 0; + var xTicks = g.selectAll('g').select("text"); + var rotateLabelsRule = ''; + if (rotateLabels%360) { + //Calculate the longest xTick width + xTicks.each(function(d,i){ + var box = this.getBoundingClientRect(); + var width = box.width; + textHeight = box.height; + if(width > maxTextWidth) maxTextWidth = width; + }); + rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')'; + //Convert to radians before calculating sin. Add 30 to margin for healthy padding. + var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180)); + xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; + //Rotate all xTicks + xTicks + .attr('transform', rotateLabelsRule) + .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end'); + } else { + if (staggerLabels) { + xTicks + .attr('transform', function(d,i) { + return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')' + }); + } else { + xTicks.attr('transform', "translate(0,0)"); + } + } + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; + } else if (scale.range().length === 2) { + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + }; + axisLabel + .attr('text-anchor', 'middle') + .attr('y', xLabelMargin) + .attr('x', w/2); + if (showMaxMin) { + //if (showMaxMin && !isOrdinal) { + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + //.data(scale.domain()) + .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)' + }) + .select('text') + .attr('dy', '.71em') + .attr('y', axis.tickPadding()) + .attr('transform', rotateLabelsRule) + .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max bottom') + .attr('transform', function(d,i) { + return 'translate(' + nv.utils.NaNtoZero((scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0))) + ',0)' + }); + } + + break; + case 'right': + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + axisLabel + .style('text-anchor', rotateYLabel ? 'middle' : 'begin') + .attr('transform', rotateYLabel ? 'rotate(90)' : '') + .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart + .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding()); + if (showMaxMin) { + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') + .style('opacity', 0); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale(d)) + ')' + }) + .select('text') + .attr('dy', '.32em') + .attr('y', 0) + .attr('x', axis.tickPadding()) + .style('text-anchor', 'start') + .text(function(d, i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max right') + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')' + }) + .select('text') + .style('opacity', 1); + } + break; + case 'left': + /* + //For dynamically placing the label. Can be used with dynamically-sized chart axis margins + var yTicks = g.selectAll('g').select("text"); + yTicks.each(function(d,i){ + var labelPadding = this.getBoundingClientRect().width + axis.tickPadding() + 16; + if(labelPadding > width) width = labelPadding; + }); + */ + axisLabel.enter().append('text').attr('class', 'nv-axislabel'); + axisLabel + .style('text-anchor', rotateYLabel ? 'middle' : 'end') + .attr('transform', rotateYLabel ? 'rotate(-90)' : '') + .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10) + .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding()); + if (showMaxMin) { + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + .data(scale.domain()); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') + .style('opacity', 0); + axisMaxMin.exit().remove(); + axisMaxMin + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale0(d)) + ')' + }) + .select('text') + .attr('dy', '.32em') + .attr('y', 0) + .attr('x', -axis.tickPadding()) + .attr('text-anchor', 'end') + .text(function(d,i) { + var v = fmt(d); + return ('' + v).match('NaN') ? '' : v; + }); + axisMaxMin.watchTransition(renderWatch, 'min-max right') + .attr('transform', function(d,i) { + return 'translate(0,' + nv.utils.NaNtoZero(scale.range()[i]) + ')' + }) + .select('text') + .style('opacity', 1); + } + break; + } + axisLabel.text(function(d) { return d }); + + if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) { + //check if max and min overlap other values, if so, hide the values that overlap + g.selectAll('g') // the g's wrapping each tick + .each(function(d,i) { + d3.select(this).select('text').attr('opacity', 1); + if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it! + if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL + d3.select(this).attr('opacity', 0); + + d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!! + } + }); + + //if Max and Min = 0 only show min, Issue #281 + if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0) { + wrap.selectAll('g.nv-axisMaxMin').style('opacity', function (d, i) { + return !i ? 1 : 0 + }); + } + } + + if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) { + var maxMinRange = []; + wrap.selectAll('g.nv-axisMaxMin') + .each(function(d,i) { + try { + if (i) // i== 1, max position + maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + else // i==0, min position + maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4) + }catch (err) { + if (i) // i== 1, max position + maxMinRange.push(scale(d) - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + else // i==0, min position + maxMinRange.push(scale(d) + 4); + } + }); + // the g's wrapping each tick + g.selectAll('g').each(function(d, i) { + if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) { + if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL + d3.select(this).remove(); + else + d3.select(this).select('text').remove(); // Don't remove the ZERO line!! + } + }); + } + + //Highlight zero tick line + g.selectAll('.tick') + .filter(function (d) { + /* + The filter needs to return only ticks at or near zero. + Numbers like 0.00001 need to count as zero as well, + and the arithmetic trick below solves that. + */ + return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined) + }) + .classed('zero', true); + + //store old scales for use in transitions on update + scale0 = scale.copy(); + + }); + + renderWatch.renderEnd('axis immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.axis = axis; + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + axisLabelDistance: {get: function(){return axisLabelDistance;}, set: function(_){axisLabelDistance=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}}, + showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}}, + axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}}, + width: {get: function(){return width;}, set: function(_){width=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration=_; + renderWatch.reset(duration); + }}, + scale: {get: function(){return scale;}, set: function(_){ + scale = _; + axis.scale(scale); + isOrdinal = typeof scale.rangeBands === 'function'; + nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']); + }} + }); + + nv.utils.initOptions(chart); + nv.utils.inheritOptionsD3(chart, axis, ['orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat']); + nv.utils.inheritOptionsD3(chart, scale, ['domain', 'range', 'rangeBand', 'rangeBands']); + + return chart; +}; +nv.models.boxPlot = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.defaultColor() + , container = null + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + , duration = 250 + , maxBoxWidth = null + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x .domain(xDomain || data.map(function(d,i) { return getX(d,i); })) + .rangeBands(xRange || [0, availableWidth], .1); + + // if we know yDomain, no need to calculate + var yData = [] + if (!yDomain) { + // (y-range is based on quartiles, whiskers and outliers) + + // lower values + var yMin = d3.min(data.map(function(d) { + var min_arr = []; + + min_arr.push(d.values.Q1); + if (d.values.hasOwnProperty('whisker_low') && d.values.whisker_low !== null) { min_arr.push(d.values.whisker_low); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { min_arr = min_arr.concat(d.values.outliers); } + + return d3.min(min_arr); + })); + + // upper values + var yMax = d3.max(data.map(function(d) { + var max_arr = []; + + max_arr.push(d.values.Q3); + if (d.values.hasOwnProperty('whisker_high') && d.values.whisker_high !== null) { max_arr.push(d.values.whisker_high); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { max_arr = max_arr.concat(d.values.outliers); } + + return d3.max(max_arr); + })); + + yData = [ yMin, yMax ] ; + } + + y.domain(yDomain || yData); + y.range(yRange || [availableHeight, 0]); + + //store old scales if they exist + x0 = x0 || x; + y0 = y0 || y.copy().range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d }); + var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6); + boxplots + .attr('class', 'nv-boxplot') + .attr('transform', function(d,i,j) { return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; }) + .classed('hover', function(d) { return d.hover }); + boxplots + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .style('stroke-opacity', 1) + .style('fill-opacity', .75) + .delay(function(d,i) { return i * duration / data.length }) + .attr('transform', function(d,i) { + return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; + }); + boxplots.exit().remove(); + + // ----- add the SVG elements for each boxPlot ----- + + // conditionally append whisker lines + boxEnter.each(function(d,i) { + var box = d3.select(this); + + ['low', 'high'].forEach(function(key) { + if (d.values.hasOwnProperty('whisker_' + key) && d.values['whisker_' + key] !== null) { + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key); + + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-tick nv-boxplot-' + key); + } + }); + }); + + // outliers + // TODO: support custom colors here + var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) { + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { return d.values.outliers; } + else { return []; } + }); + outliers.enter().append('circle') + .style('fill', function(d,i,j) { return color(d,j) }).style('stroke', function(d,i,j) { return color(d,j) }) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + outliers.attr('class', 'nv-boxplot-outlier'); + outliers + .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier') + .attr('cx', x.rangeBand() * .45) + .attr('cy', function(d,i,j) { return y(d); }) + .attr('r', '3'); + outliers.exit().remove(); + + var box_width = function() { return (maxBoxWidth === null ? x.rangeBand() * .9 : Math.min(75, x.rangeBand() * .9)); }; + var box_left = function() { return x.rangeBand() * .45 - box_width()/2; }; + var box_right = function() { return x.rangeBand() * .45 + box_width()/2; }; + + // update whisker lines and ticks + ['low', 'high'].forEach(function(key) { + var endpoint = (key === 'low') ? 'Q1' : 'Q3'; + + boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', x.rangeBand() * .45 ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', x.rangeBand() * .45 ) + .attr('y2', function(d,i) { return y(d.values[endpoint]); }); + + boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', box_left ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', box_right ) + .attr('y2', function(d,i) { return y(d.values['whisker_' + key]); }); + }); + + ['low', 'high'].forEach(function(key) { + boxEnter.selectAll('.nv-boxplot-' + key) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + }); + + // boxes + boxEnter.append('rect') + .attr('class', 'nv-boxplot-box') + // tooltip events + .on('mouseover', function(d,i) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + // box transitions + boxplots.select('rect.nv-boxplot-box') + .watchTransition(renderWatch, 'nv-boxplot: boxes') + .attr('y', function(d,i) { return y(d.values.Q3); }) + .attr('width', box_width) + .attr('x', box_left ) + + .attr('height', function(d,i) { return Math.abs(y(d.values.Q3) - y(d.values.Q1)) || 1 }) + .style('fill', function(d,i) { return d.color || color(d,i) }) + .style('stroke', function(d,i) { return d.color || color(d,i) }); + + // median line + boxEnter.append('line').attr('class', 'nv-boxplot-median'); + + boxplots.select('line.nv-boxplot-median') + .watchTransition(renderWatch, 'nv-boxplot: boxplots line') + .attr('x1', box_left) + .attr('y1', function(d,i) { return y(d.values.Q2); }) + .attr('x2', box_right) + .attr('y2', function(d,i) { return y(d.values.Q2); }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + }); + + renderWatch.renderEnd('nv-boxplot immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.boxPlotChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var boxplot = nv.models.boxPlot() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + ; + + var margin = {top: 15, right: 10, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.getColor() + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , staggerLabels = false + , tooltip = nv.models.tooltip() + , x + , y + , noData = "No Data Available." + , dispatch = d3.dispatch('beforeUpdate', 'renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(boxplot); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + dispatch.beforeUpdate(); + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + // Display No Data message if there's nothing to show. (quartiles required at minimum) + if (!data || !data.length || + !data.filter(function(d) { return d.values.hasOwnProperty("Q1") && d.values.hasOwnProperty("Q2") && d.values.hasOwnProperty("Q3"); }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = boxplot.xScale(); + y = boxplot.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g'); + var defsEnter = gEnter.append('defs'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + + gEnter.append('g').attr('class', 'nv-barsWrap'); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + boxplot + .width(availableWidth) + .height(availableHeight); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })) + + barsWrap.transition().call(boxplot); + + + defsEnter.append('clipPath') + .attr('id', 'nv-x-label-clip-' + boxplot.id()) + .append('rect'); + + g.select('#nv-x-label-clip-' + boxplot.id() + ' rect') + .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) + .attr('height', 16) + .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + if (staggerLabels) { + xTicks + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1",0) + .attr("x2",availableWidth) + .attr("y1", y(0)) + .attr("y2", y(0)) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + }); + + renderWatch.renderEnd('nv-boxplot chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + boxplot.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); + }); + + boxplot.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.data(evt).hidden(true); + }); + + boxplot.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.boxplot = boxplot; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + boxplot.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + boxplot.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, boxplot); + nv.utils.initOptions(chart); + + return chart; +} + +// Chart design based on the recommendations of Stephen Few. Implementation +// based on the work of Clint Ivy, Jamie Love, and Jason Davies. +// http://projects.instantcognition.com/protovis/bulletchart/ + +nv.models.bullet = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , orient = 'left' // TODO top & bottom + , reverse = false + , ranges = function(d) { return d.ranges } + , markers = function(d) { return d.markers ? d.markers : [] } + , measures = function(d) { return d.measures } + , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] } + , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] } + , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] } + , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) + , width = 380 + , height = 30 + , container = null + , tickFormat = null + , color = nv.utils.getColor(['#1f77b4']) + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove') + ; + + function chart(selection) { + selection.each(function(d, i) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + var rangez = ranges.call(this, d, i).slice().sort(d3.descending), + markerz = markers.call(this, d, i).slice().sort(d3.descending), + measurez = measures.call(this, d, i).slice().sort(d3.descending), + rangeLabelz = rangeLabels.call(this, d, i).slice(), + markerLabelz = markerLabels.call(this, d, i).slice(), + measureLabelz = measureLabels.call(this, d, i).slice(); + + // Setup Scales + // Compute the new x-scale. + var x1 = d3.scale.linear() + .domain( d3.extent(d3.merge([forceX, rangez])) ) + .range(reverse ? [availableWidth, 0] : [0, availableWidth]); + + // Retrieve the old x-scale, if this is an update. + var x0 = this.__chart__ || d3.scale.linear() + .domain([0, Infinity]) + .range(x1.range()); + + // Stash the new scale. + this.__chart__ = x1; + + var rangeMin = d3.min(rangez), //rangez[2] + rangeMax = d3.max(rangez), //rangez[0] + rangeAvg = rangez[1]; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('rect').attr('class', 'nv-range nv-rangeMax'); + gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg'); + gEnter.append('rect').attr('class', 'nv-range nv-rangeMin'); + gEnter.append('rect').attr('class', 'nv-measure'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0) + w1 = function(d) { return Math.abs(x1(d) - x1(0)) }; + var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) }, + xp1 = function(d) { return d < 0 ? x1(d) : x1(0) }; + + g.select('rect.nv-rangeMax') + .attr('height', availableHeight) + .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin)) + .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin)) + .datum(rangeMax > 0 ? rangeMax : rangeMin) + + g.select('rect.nv-rangeAvg') + .attr('height', availableHeight) + .attr('width', w1(rangeAvg)) + .attr('x', xp1(rangeAvg)) + .datum(rangeAvg) + + g.select('rect.nv-rangeMin') + .attr('height', availableHeight) + .attr('width', w1(rangeMax)) + .attr('x', xp1(rangeMax)) + .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax)) + .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax)) + .datum(rangeMax > 0 ? rangeMin : rangeMax) + + g.select('rect.nv-measure') + .style('fill', color) + .attr('height', availableHeight / 3) + .attr('y', availableHeight / 3) + .attr('width', measurez < 0 ? + x1(0) - x1(measurez[0]) + : x1(measurez[0]) - x1(0)) + .attr('x', xp1(measurez)) + .on('mouseover', function() { + dispatch.elementMouseover({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") + }) + }) + .on('mouseout', function() { + dispatch.elementMouseout({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") + }) + }); + + var h3 = availableHeight / 6; + + var markerData = markerz.map( function(marker, index) { + return {value: marker, label: markerLabelz[index]} + }); + gEnter + .selectAll("path.nv-markerTriangle") + .data(markerData) + .enter() + .append('path') + .attr('class', 'nv-markerTriangle') + .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') + .on('mouseover', function(d) { + dispatch.elementMouseover({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill"), + pos: [x1(d.value), availableHeight/2] + }) + + }) + .on('mousemove', function(d) { + dispatch.elementMousemove({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") + }) + }) + .on('mouseout', function(d, i) { + dispatch.elementMouseout({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") + }) + }); + + g.selectAll("path.nv-markerTriangle") + .data(markerData) + .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' }); + + wrap.selectAll('.nv-range') + .on('mouseover', function(d,i) { + var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); + dispatch.elementMouseover({ + value: d, + label: label, + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Previous', + color: d3.select(this).style("fill") + }) + }) + .on('mouseout', function(d,i) { + var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); + dispatch.elementMouseout({ + value: d, + label: label, + color: d3.select(this).style("fill") + }) + }); + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) + markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) + measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom + orient = _; + reverse = orient == 'right' || orient == 'bottom'; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + + + +// Chart design based on the recommendations of Stephen Few. Implementation +// based on the work of Clint Ivy, Jamie Love, and Jason Davies. +// http://projects.instantcognition.com/protovis/bulletchart/ +nv.models.bulletChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var bullet = nv.models.bullet(); + var tooltip = nv.models.tooltip(); + + var orient = 'left' // TODO top & bottom + , reverse = false + , margin = {top: 5, right: 40, bottom: 20, left: 120} + , ranges = function(d) { return d.ranges } + , markers = function(d) { return d.markers ? d.markers : [] } + , measures = function(d) { return d.measures } + , width = null + , height = 55 + , tickFormat = null + , ticks = null + , noData = null + , dispatch = d3.dispatch() + ; + + tooltip + .duration(0) + .headerEnabled(false); + + function chart(selection) { + selection.each(function(d, i) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = height - margin.top - margin.bottom, + that = this; + + chart.update = function() { chart(selection) }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!d || !ranges.call(this, d, i)) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var rangez = ranges.call(this, d, i).slice().sort(d3.descending), + markerz = markers.call(this, d, i).slice().sort(d3.descending), + measurez = measures.call(this, d, i).slice().sort(d3.descending); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-bulletWrap'); + gEnter.append('g').attr('class', 'nv-titles'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Compute the new x-scale. + var x1 = d3.scale.linear() + .domain([0, Math.max(rangez[0], (markerz[0] || 0), measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain + .range(reverse ? [availableWidth, 0] : [0, availableWidth]); + + // Retrieve the old x-scale, if this is an update. + var x0 = this.__chart__ || d3.scale.linear() + .domain([0, Infinity]) + .range(x1.range()); + + // Stash the new scale. + this.__chart__ = x1; + + var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0) + w1 = function(d) { return Math.abs(x1(d) - x1(0)) }; + + var title = gEnter.select('.nv-titles').append('g') + .attr('text-anchor', 'end') + .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')'); + title.append('text') + .attr('class', 'nv-title') + .text(function(d) { return d.title; }); + + title.append('text') + .attr('class', 'nv-subtitle') + .attr('dy', '1em') + .text(function(d) { return d.subtitle; }); + + bullet + .width(availableWidth) + .height(availableHeight) + + var bulletWrap = g.select('.nv-bulletWrap'); + d3.transition(bulletWrap).call(bullet); + + // Compute the tick format. + var format = tickFormat || x1.tickFormat( availableWidth / 100 ); + + // Update the tick groups. + var tick = g.selectAll('g.nv-tick') + .data(x1.ticks( ticks ? ticks : (availableWidth / 50) ), function(d) { + return this.textContent || format(d); + }); + + // Initialize the ticks with the old scale, x0. + var tickEnter = tick.enter().append('g') + .attr('class', 'nv-tick') + .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' }) + .style('opacity', 1e-6); + + tickEnter.append('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickEnter.append('text') + .attr('text-anchor', 'middle') + .attr('dy', '1em') + .attr('y', availableHeight * 7 / 6) + .text(format); + + // Transition the updating ticks to the new scale, x1. + var tickUpdate = d3.transition(tick) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1); + + tickUpdate.select('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickUpdate.select('text') + .attr('y', availableHeight * 7 / 6); + + // Transition the exiting ticks to the new scale, x1. + d3.transition(tick.exit()) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1e-6) + .remove(); + }); + + d3.timer.flush(); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + bullet.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.label, + value: evt.value, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + bullet.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + bullet.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.bullet = bullet; + chart.dispatch = dispatch; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) + markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) + measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, + ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom + orient = _; + reverse = orient == 'right' || orient == 'bottom'; + }} + }); + + nv.utils.inheritOptions(chart, bullet); + nv.utils.initOptions(chart); + + return chart; +}; + + + +nv.models.candlestickBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getOpen = function(d) { return d.open } + , getClose = function(d) { return d.close } + , getHigh = function(d) { return d.high } + , getLow = function(d) { return d.low } + , forceX = [] + , forceY = [] + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , clipEdge = true + , color = nv.utils.defaultColor() + , interactive = false + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + // Width of the candlestick bars. + var barWidth = (availableWidth / data[0].values.length) * .45; + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [5 + barWidth / 2, availableWidth - barWidth / 2 - 5]); + + y.domain(yDomain || [ + d3.min(data[0].values.map(getLow).concat(forceY)), + d3.max(data[0].values.map(getHigh).concat(forceY)) + ] + ).range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-candlestickBar').data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-candlestickBar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-ticks'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick') + .data(function(d) { return d }); + ticks.exit().remove(); + + var tickGroups = ticks.enter().append('g'); + + // The colors are currently controlled by CSS. + ticks + .attr('class', function(d, i, j) { return (getOpen(d, i) > getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i}); + + var lines = tickGroups.append('line') + .attr('class', 'nv-candlestick-lines') + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + var rects = tickGroups.append('rect') + .attr('class', 'nv-candlestick-rects nv-bars') + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); + + ticks.select('.nv-candlestick-lines').transition() + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + ticks.select('.nv-candlestick-rects').transition() + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); + }); + + return chart; + } + + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + chart.clearHighlights(); + container.select(".nv-candlestickBar .nv-tick-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + container.select(".nv-candlestickBar .nv-tick.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}}, + close: {get: function(){return getClose();}, set: function(_){getClose=_;}}, + high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}}, + low: {get: function(){return getLow;}, set: function(_){getLow=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.cumulativeLineChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , controls = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 30, bottom: 50, left: 60} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , showControls = true + , useInteractiveGuideline = false + , rescaleY = true + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , id = lines.id() + , state = nv.utils.state() + , defaultState = null + , noData = null + , average = function(d) { return d.average } + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') + , transitionDuration = 250 + , duration = 250 + , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function. + ; + + state.index = 0; + state.rescaleY = rescaleY; + + xAxis.orient('bottom').tickPadding(7); + yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var dx = d3.scale.linear() + , index = {i: 0, x: 0} + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + index: index.i, + rescaleY: rescaleY + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.index !== undefined) + index.i = state.index; + if (state.rescaleY !== undefined) + rescaleY = state.rescaleY; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(lines); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + container.classed('nv-chart-' + id, true); + var that = this; + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart) + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + var indexDrag = d3.behavior.drag() + .on('dragstart', dragStart) + .on('drag', dragMove) + .on('dragend', dragEnd); + + + function dragStart(d,i) { + d3.select(chart.container) + .style('cursor', 'ew-resize'); + } + + function dragMove(d,i) { + index.x = d3.event.x; + index.i = Math.round(dx.invert(index.x)); + updateZero(); + } + + function dragEnd(d,i) { + d3.select(chart.container) + .style('cursor', 'auto'); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = lines.xScale(); + y = lines.yScale(); + + if (!rescaleY) { + var seriesDomains = data + .filter(function(series) { return !series.disabled }) + .map(function(series,i) { + var initialDomain = d3.extent(series.values, lines.y()); + + //account for series being disabled when losing 95% or more + if (initialDomain[0] < -.95) initialDomain[0] = -.95; + + return [ + (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]), + (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0]) + ]; + }); + + var completeDomain = [ + d3.min(seriesDomains, function(d) { return d[0] }), + d3.max(seriesDomains, function(d) { return d[1] }) + ]; + + lines.yDomain(completeDomain); + } else { + lines.yDomain(null); + } + + dx.domain([0, data[0].values.length - 1]) //Assumes all series have same length + .range([0, availableWidth]) + .clamp(true); + + var data = indexify(index.i, data); + + // Setup containers and skeleton of chart + var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all"; + var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-interactive'); + gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none"); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-background'); + gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents); + gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none"); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + // Controls + if (showControls) { + var controlsData = [ + { key: 'Re-scale y-axis', disabled: !rescaleY } + ]; + + controls + .width(140) + .color(['#444', '#444', '#444']) + .rightAlign(false) + .margin({top: 5, right: 0, bottom: 5, left: 20}) + ; + + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Show error if series goes below 100% + var tempDisabled = data.filter(function(d) { return d.tempDisabled }); + + wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates + if (tempDisabled.length) { + wrap.append('text').attr('class', 'tempDisabled') + .attr('x', availableWidth / 2) + .attr('y', '-.71em') + .style('text-anchor', 'end') + .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.'); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left,top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + gEnter.select('.nv-background') + .append('rect'); + + g.select('.nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + lines + //.x(function(d) { return d.x }) + .y(function(d) { return d.display.y }) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; })); + + var linesWrap = g.select('.nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled })); + + linesWrap.call(lines); + + //Store a series index number in the data array. + data.forEach(function(d,i) { + d.seriesIndex = i; + }); + + var avgLineData = data.filter(function(d) { + return !d.disabled && !!average(d); + }); + + var avgLines = g.select(".nv-avgLinesWrap").selectAll("line") + .data(avgLineData, function(d) { return d.key; }); + + var getAvgLineY = function(d) { + //If average lines go off the svg element, clamp them to the svg bounds. + var yVal = y(average(d)); + if (yVal < 0) return 0; + if (yVal > availableHeight) return availableHeight; + return yVal; + }; + + avgLines.enter() + .append('line') + .style('stroke-width',2) + .style('stroke-dasharray','10,10') + .style('stroke',function (d,i) { + return lines.color()(d,d.seriesIndex); + }) + .attr('x1',0) + .attr('x2',availableWidth) + .attr('y1', getAvgLineY) + .attr('y2', getAvgLineY); + + avgLines + .style('stroke-opacity',function(d){ + //If average lines go offscreen, make them transparent + var yVal = y(average(d)); + if (yVal < 0 || yVal > availableHeight) return 0; + return 1; + }) + .attr('x1',0) + .attr('x2',availableWidth) + .attr('y1', getAvgLineY) + .attr('y2', getAvgLineY); + + avgLines.exit().remove(); + + //Create index line + var indexLine = linesWrap.selectAll('.nv-indexLine') + .data([index]); + indexLine.enter().append('rect').attr('class', 'nv-indexLine') + .attr('width', 3) + .attr('x', -2) + .attr('fill', 'red') + .attr('fill-opacity', .5) + .style("pointer-events","all") + .call(indexDrag); + + indexLine + .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' }) + .attr('height', availableHeight); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/70, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + function updateZero() { + indexLine + .data([index]); + + //When dragging the index line, turn off line transitions. + // Then turn them back on when done dragging. + var oldDuration = chart.duration(); + chart.duration(0); + chart.update(); + chart.duration(oldDuration); + } + + g.select('.nv-background rect') + .on('click', function() { + index.x = d3.mouse(this)[0]; + index.i = Math.round(dx.invert(index.x)); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + + updateZero(); + }); + + lines.dispatch.on('elementClick', function(e) { + index.i = e.pointIndex; + index.x = dx(index.i); + + // update state and send stateChange with new index + state.index = index.i; + dispatch.stateChange(state); + + updateZero(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + d.disabled = !d.disabled; + rescaleY = !d.disabled; + + state.rescaleY = rescaleY; + dispatch.stateChange(state); + chart.update(); + }); + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + lines.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + lines.highlightPoint(i, pointIndex, true); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex) + }); + }); + + //Highlight the tooltip entry based on which point the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); + var threshold = 0.03 * domainExtent; + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold); + if (indexToHighlight !== null) + allData[indexToHighlight].highlight = true; + } + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex); + interactiveLayer.tooltip + .chartContainer(that.parentNode) + .valueFormatter(function(d,i) { + return yAxis.tickFormat()(d); + }) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + lines.clearHighlights(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.index !== 'undefined') { + index.i = e.index; + index.x = dx(index.i); + + state.index = e.index; + + indexLine + .data([index]); + } + + if (typeof e.rescaleY !== 'undefined') { + rescaleY = e.rescaleY; + } + + chart.update(); + }); + + }); + + renderWatch.renderEnd('cumulativeLineChart immediate'); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + var point = { + x: chart.x()(evt.point), + y: chart.y()(evt.point), + color: evt.point.color + }; + evt.point = point; + tooltip.data(evt).hidden(false); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + var indexifyYGetter = null; + /* Normalize the data according to an index point. */ + function indexify(idx, data) { + if (!indexifyYGetter) indexifyYGetter = lines.y(); + return data.map(function(line, i) { + if (!line.values) { + return line; + } + var indexValue = line.values[idx]; + if (indexValue == null) { + return line; + } + var v = indexifyYGetter(indexValue, idx); + + //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue + if (v < -.95 && !noErrorCheck) { + //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100) + + line.tempDisabled = true; + return line; + } + + line.tempDisabled = false; + + line.values = line.values.map(function(point, pointIndex) { + point.display = {'y': (indexifyYGetter(point, pointIndex) - v) / (1 + v) }; + return point; + }); + + return line; + }) + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.lines = lines; + chart.legend = legend; + chart.controls = controls; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + chart.state = state; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + rescaleY: {get: function(){return rescaleY;}, set: function(_){rescaleY=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + average: {get: function(){return average;}, set: function(_){average=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + noErrorCheck: {get: function(){return noErrorCheck;}, set: function(_){noErrorCheck=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (_ === true) { + chart.interactive(false); + chart.useVoronoi(false); + } + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + lines.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + renderWatch.reset(duration); + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; +//TODO: consider deprecating by adding necessary features to multiBar model +nv.models.discreteBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , color = nv.utils.defaultColor() + , showValues = false + , valueFormat = d3.format(',.2f') + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + , rectClass = 'discreteBar' + , duration = 250 + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0 } + }) + }); + + x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableWidth], .1); + y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY))); + + // If showValues, pad the Y axis range to account for label height + if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]); + else y.range(yRange || [availableHeight, 0]); + + //store old scales if they exist + x0 = x0 || x; + y0 = y0 || y.copy().range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit() + .watchTransition(renderWatch, 'discreteBar: exit groups') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6) + .remove(); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }); + groups + .watchTransition(renderWatch, 'discreteBar: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', .75); + + var bars = groups.selectAll('g.nv-bar') + .data(function(d) { return d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('g') + .attr('transform', function(d,i,j) { + return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')' + }) + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('click', function(d,i) { + var element = this; + dispatch.elementClick({ + data: d, + index: i, + color: d3.select(this).style("fill"), + event: d3.event, + element: element + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }); + + barsEnter.append('rect') + .attr('height', 0) + .attr('width', x.rangeBand() * .9 / data.length ) + + if (showValues) { + barsEnter.append('text') + .attr('text-anchor', 'middle') + ; + + bars.select('text') + .text(function(d,i) { return valueFormat(getY(d,i)) }) + .watchTransition(renderWatch, 'discreteBar: bars text') + .attr('x', x.rangeBand() * .9 / 2) + .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 }) + + ; + } else { + bars.selectAll('text').remove(); + } + + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' }) + .style('fill', function(d,i) { return d.color || color(d,i) }) + .style('stroke', function(d,i) { return d.color || color(d,i) }) + .select('rect') + .attr('class', rectClass) + .watchTransition(renderWatch, 'discreteBar: bars rect') + .attr('width', x.rangeBand() * .9 / data.length); + bars.watchTransition(renderWatch, 'discreteBar: bars') + //.delay(function(d,i) { return i * 1200 / data[0].values.length }) + .attr('transform', function(d,i) { + var left = x(getX(d,i)) + x.rangeBand() * .05, + top = getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : //make 1 px positive bars show up above y=0 + y(getY(d,i)); + + return 'translate(' + left + ', ' + top + ')' + }) + .select('rect') + .attr('height', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y(0)), 1) + }); + + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('discreteBar immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.discreteBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var discretebar = nv.models.discreteBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 15, right: 10, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.getColor() + , showLegend = false + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , staggerLabels = false + , wrapLabels = false + , rotateLabels = 0 + , x + , y + , noData = null + , dispatch = d3.dispatch('beforeUpdate','renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .keyFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(discretebar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + dispatch.beforeUpdate(); + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = discretebar.xScale(); + y = discretebar.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g'); + var defsEnter = gEnter.append('defs'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + discretebar + .width(availableWidth) + .height(availableHeight); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + barsWrap.transition().call(discretebar); + + + defsEnter.append('clipPath') + .attr('id', 'nv-x-label-clip-' + discretebar.id()) + .append('rect'); + + g.select('#nv-x-label-clip-' + discretebar.id() + ' rect') + .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) + .attr('height', 16) + .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')'); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + if (staggerLabels) { + xTicks + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + + if (rotateLabels) { + xTicks + .selectAll('.tick text') + .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') + .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); + } + + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) + } + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1",0) + .attr("x2",(rightAlignYAxis) ? -availableWidth : availableWidth) + .attr("y1", y(0)) + .attr("y2", y(0)) + ; + }); + + renderWatch.renderEnd('discreteBar chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + discretebar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + discretebar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + discretebar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.discretebar = discretebar; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + discretebar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + discretebar.color(color); + legend.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, discretebar); + nv.utils.initOptions(chart); + + return chart; +} + +nv.models.distribution = function() { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 400 //technically width or height depending on x or y.... + , size = 8 + , axis = 'x' // 'x' or 'y'... horizontal or vertical + , getData = function(d) { return d[axis] } // defaults d.x or d.y + , color = nv.utils.defaultColor() + , scale = d3.scale.linear() + , domain + , duration = 250 + , dispatch = d3.dispatch('renderEnd') + ; + + //============================================================ + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var scale0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + //============================================================ + + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom), + naxis = axis == 'x' ? 'y' : 'x', + container = d3.select(this); + nv.utils.initSVG(container); + + //------------------------------------------------------------ + // Setup Scales + + scale0 = scale0 || scale; + + //------------------------------------------------------------ + + + //------------------------------------------------------------ + // Setup containers and skeleton of chart + + var wrap = container.selectAll('g.nv-distribution').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') + + //------------------------------------------------------------ + + + var distWrap = g.selectAll('g.nv-dist') + .data(function(d) { return d }, function(d) { return d.key }); + + distWrap.enter().append('g'); + distWrap + .attr('class', function(d,i) { return 'nv-dist nv-series-' + i }) + .style('stroke', function(d,i) { return color(d, i) }); + + var dist = distWrap.selectAll('line.nv-dist' + axis) + .data(function(d) { return d.values }) + dist.enter().append('line') + .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) }) + renderWatch.transition(distWrap.exit().selectAll('line.nv-dist' + axis), 'dist exit') + // .transition() + .attr(axis + '1', function(d,i) { return scale(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale(getData(d,i)) }) + .style('stroke-opacity', 0) + .remove(); + dist + .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i }) + .attr(naxis + '1', 0) + .attr(naxis + '2', size); + renderWatch.transition(dist, 'dist') + // .transition() + .attr(axis + '1', function(d,i) { return scale(getData(d,i)) }) + .attr(axis + '2', function(d,i) { return scale(getData(d,i)) }) + + + scale0 = scale.copy(); + + }); + renderWatch.renderEnd('distribution immediate'); + return chart; + } + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + chart.options = nv.utils.optionsFunc.bind(chart); + chart.dispatch = dispatch; + + chart.margin = function(_) { + if (!arguments.length) return margin; + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.right = typeof _.right != 'undefined' ? _.right : margin.right; + margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + return chart; + }; + + chart.width = function(_) { + if (!arguments.length) return width; + width = _; + return chart; + }; + + chart.axis = function(_) { + if (!arguments.length) return axis; + axis = _; + return chart; + }; + + chart.size = function(_) { + if (!arguments.length) return size; + size = _; + return chart; + }; + + chart.getData = function(_) { + if (!arguments.length) return getData; + getData = d3.functor(_); + return chart; + }; + + chart.scale = function(_) { + if (!arguments.length) return scale; + scale = _; + return chart; + }; + + chart.color = function(_) { + if (!arguments.length) return color; + color = nv.utils.getColor(_); + return chart; + }; + + chart.duration = function(_) { + if (!arguments.length) return duration; + duration = _; + renderWatch.reset(duration); + return chart; + }; + //============================================================ + + + return chart; +} +nv.models.furiousLegend = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 5, right: 0, bottom: 5, left: 0} + , width = 400 + , height = 20 + , getKey = function(d) { return d.key } + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths + , align = true + , padding = 28 //define how much space between legend items. - recommend 32 for furious version + , rightAlign = true + , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. + , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false + , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-legend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var series = g.selectAll('.nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + + var seriesShape; + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + + seriesShape = series.select('rect'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series + .on('mouseover', function(d,i) { + dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects + }) + .on('mouseout', function(d,i) { + dispatch.legendMouseout(d,i); + }) + .on('click', function(d,i) { + dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); + if (updateState) { + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } + } + } + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) + }); + + } + }) + .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; + dispatch.legendDblclick(d,i); + if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); + //the default behavior of NVD3 legends, when double clicking one, + // is to set all other series' to false, and make the double clicked series enabled. + data.forEach(function(series) { + series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; + }); + d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); + series.exit().remove(); + + seriesText + .attr('fill', setTextColor) + .text(getKey); + + //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) + // NEW ALIGNING CODE, TODO: clean up + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if (align) { + + var seriesWidths = []; + series.each(function(d,i) { + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } + var nodeTextLength; + try { + nodeTextLength = legendText.node().getComputedTextLength(); + // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead + if(nodeTextLength <= 0) throw Error(); + } + catch(e) { + nodeTextLength = nv.utils.calcApproxTextWidth(legendText); + } + + seriesWidths.push(nodeTextLength + padding); + }); + + var seriesPerRow = 0; + var legendWidth = 0; + var columnWidths = []; + + while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { + columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; + legendWidth += seriesWidths[seriesPerRow++]; + } + if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row + + while ( legendWidth > availableWidth && seriesPerRow > 1 ) { + columnWidths = []; + seriesPerRow--; + + for (var k = 0; k < seriesWidths.length; k++) { + if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) ) + columnWidths[k % seriesPerRow] = seriesWidths[k]; + } + + legendWidth = columnWidths.reduce(function(prev, cur, index, array) { + return prev + cur; + }); + } + + var xPositions = []; + for (var i = 0, curX = 0; i < seriesPerRow; i++) { + xPositions[i] = curX; + curX += columnWidths[i]; + } + + series + .attr('transform', function(d, i) { + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; + }); + + //position legend as far right as possible within the total width + if (rightAlign) { + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); + } + else { + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); + } + + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); + + } else { + + var ypos = 5, + newxpos = 5, + maxwidth = 0, + xpos; + series + .attr('transform', function(d, i) { + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; + xpos = newxpos; + + if (width < margin.left + margin.right + xpos + length) { + newxpos = xpos = 5; + ypos += versPadding; + } + + newxpos += length; + if (newxpos > maxwidth) maxwidth = newxpos; + + return 'translate(' + xpos + ',' + ypos + ')'; + }); + + //position legend as far right as possible within the total width + g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')'); + + height = margin.top + margin.bottom + ypos + 15; + } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15) + } + + seriesShape + .style('fill', setBGColor) + .style('stroke', function(d,i) { return d.color || color(d, i) }); + }); + + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? color(d,i) : '#fff'; + } else if (!expanded) { + return !!d.disabled ? color(d,i) : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#fff' : color(d,i); + } else { + return !!d.disabled ? '#fff' : color(d,i); + } + } + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + align: {get: function(){return align;}, set: function(_){align=_;}}, + rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; +//TODO: consider deprecating and using multibar with single series for this +nv.models.historicalBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceX = [] + , forceY = [0] + , padData = false + , clipEdge = true + , color = nv.utils.defaultColor() + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + , interactive = true + ; + + var renderWatch = nv.utils.renderWatch(dispatch, 0); + + function chart(selection) { + selection.each(function(data) { + renderWatch.reset(); + + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [0, availableWidth]); + + y.domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) )) + .range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-bars'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var bars = wrap.select('.nv-bars').selectAll('.nv-bar') + .data(function(d) { return d }, function(d,i) {return getX(d,i)}); + bars.exit().remove(); + + bars.enter().append('rect') + .attr('x', 0 ) + .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) }) + .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) }) + .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) + .on('mouseover', function(d,i) { + if (!interactive) return; + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + + }) + .on('mouseout', function(d,i) { + if (!interactive) return; + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + if (!interactive) return; + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('click', function(d,i) { + if (!interactive) return; + dispatch.elementClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + if (!interactive) return; + dispatch.elementDblClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }); + + bars + .attr('fill', function(d,i) { return color(d, i); }) + .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i }) + .watchTransition(renderWatch, 'bars') + .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) + //TODO: better width calculations that don't assume always uniform data spacing;w + .attr('width', (availableWidth / data[0].values.length) * .9 ); + + bars.watchTransition(renderWatch, 'bars') + .attr('y', function(d,i) { + var rval = getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : + y(getY(d,i)); + return nv.utils.NaNtoZero(rval); + }) + .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) }); + + }); + + renderWatch.renderEnd('historicalBar immediate'); + return chart; + } + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + container + .select(".nv-bars .nv-bar-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + container + .select(".nv-bars .nv-bar.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.historicalBarChart = function(bar_model) { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var bars = bar_model || nv.models.historicalBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() + ; + + + var margin = {top: 30, right: 90, bottom: 50, left: 90} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = false + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , x + , y + , state = {} + , defaultState = null + , noData = null + , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , transitionDuration = 250 + ; + + xAxis.orient('bottom').tickPadding(7); + yAxis.orient( (rightAlignYAxis) ? 'right' : 'left'); + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, 0); + + function chart(selection) { + selection.each(function(data) { + renderWatch.reset(); + renderWatch.models(bars); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; + chart.container = this; + + //set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = bars.xScale(); + y = bars.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + bars + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + barsWrap.transition().call(bars); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .transition() + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .transition() + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + bars.clearHighlights(); + + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + bars.highlightPoint(pointIndex,true); + var point = series.values[pointIndex]; + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex), + data: series.values[pointIndex] + }); + }); + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + interactiveLayer.tooltip + .chartContainer(that.parentNode) + .valueFormatter(function(d,i) { + return yAxis.tickFormat()(d); + }) + .data({ + value: xValue, + index: pointIndex, + series: allData + })(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + dispatch.tooltipHide(); + bars.clearHighlights(); + }); + + legend.dispatch.on('legendClick', function(d,i) { + d.disabled = !d.disabled; + + if (!data.filter(function(d) { return !d.disabled }).length) { + data.map(function(d) { + d.disabled = false; + wrap.selectAll('.nv-series').classed('disabled', false); + return d; + }); + } + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + + selection.transition().call(chart); + }); + + legend.dispatch.on('legendDblclick', function(d) { + //Double clicking should always enable current series, and disabled all others. + data.forEach(function(d) { + d.disabled = true; + }); + d.disabled = false; + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + chart.update(); + }); + + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + chart.update(); + }); + }); + + renderWatch.renderEnd('historicalBarChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.bars = bars; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + bars.color(color); + }}, + duration: {get: function(){return transitionDuration;}, set: function(_){ + transitionDuration=_; + renderWatch.reset(transitionDuration); + yAxis.duration(transitionDuration); + xAxis.duration(transitionDuration); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (_ === true) { + chart.interactive(false); + } + }} + }); + + nv.utils.inheritOptions(chart, bars); + nv.utils.initOptions(chart); + + return chart; +}; + + +// ohlcChart is just a historical chart with ohlc bars and some tweaks +nv.models.ohlcBarChart = function() { + var chart = nv.models.historicalBarChart(nv.models.ohlcBar()); + + // special default tooltip since we show multiple values per x + chart.useInteractiveGuideline(true); + chart.interactiveLayer.tooltip.contentGenerator(function(data) { + // we assume only one series exists for this chart + var d = data.series[0].data; + // match line colors as defined in nv.d3.css + var color = d.open < d.close ? "2ca02c" : "d62728"; + return '' + + '

' + data.value + '

' + + '' + + '' + + '' + + '' + + '' + + '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
'; + }); + return chart; +}; + +// candlestickChart is just a historical chart with candlestick bars and some tweaks +nv.models.candlestickBarChart = function() { + var chart = nv.models.historicalBarChart(nv.models.candlestickBar()); + + // special default tooltip since we show multiple values per x + chart.useInteractiveGuideline(true); + chart.interactiveLayer.tooltip.contentGenerator(function(data) { + // we assume only one series exists for this chart + var d = data.series[0].data; + // match line colors as defined in nv.d3.css + var color = d.open < d.close ? "2ca02c" : "d62728"; + return '' + + '

' + data.value + '

' + + '' + + '' + + '' + + '' + + '' + + '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
'; + }); + return chart; +}; +nv.models.legend = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 5, right: 0, bottom: 5, left: 0} + , width = 400 + , height = 20 + , getKey = function(d) { return d.key } + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths + , align = true + , padding = 32 //define how much space between legend items. - recommend 32 for furious version + , rightAlign = true + , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. + , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false + , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-legend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var series = g.selectAll('.nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + + var seriesEnter = series.enter().append('g').attr('class', 'nv-series'); + var seriesShape; + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + seriesShape = series.select('.nv-legend-symbol'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series + .on('mouseover', function(d,i) { + dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects + }) + .on('mouseout', function(d,i) { + dispatch.legendMouseout(d,i); + }) + .on('click', function(d,i) { + dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); + if (updateState) { + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } + } + } + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) + }); + + } + }) + .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; + dispatch.legendDblclick(d,i); + if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); + //the default behavior of NVD3 legends, when double clicking one, + // is to set all other series' to false, and make the double clicked series enabled. + data.forEach(function(series) { + series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; + }); + d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); + series.exit().remove(); + + seriesText + .attr('fill', setTextColor) + .text(getKey); + + //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) + // NEW ALIGNING CODE, TODO: clean up + var legendWidth = 0; + if (align) { + + var seriesWidths = []; + series.each(function(d,i) { + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } + var nodeTextLength; + try { + nodeTextLength = legendText.node().getComputedTextLength(); + // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead + if(nodeTextLength <= 0) throw Error(); + } + catch(e) { + nodeTextLength = nv.utils.calcApproxTextWidth(legendText); + } + + seriesWidths.push(nodeTextLength + padding); + }); + + var seriesPerRow = 0; + var columnWidths = []; + legendWidth = 0; + + while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { + columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; + legendWidth += seriesWidths[seriesPerRow++]; + } + if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row + + while ( legendWidth > availableWidth && seriesPerRow > 1 ) { + columnWidths = []; + seriesPerRow--; + + for (var k = 0; k < seriesWidths.length; k++) { + if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) ) + columnWidths[k % seriesPerRow] = seriesWidths[k]; + } + + legendWidth = columnWidths.reduce(function(prev, cur, index, array) { + return prev + cur; + }); + } + + var xPositions = []; + for (var i = 0, curX = 0; i < seriesPerRow; i++) { + xPositions[i] = curX; + curX += columnWidths[i]; + } + + series + .attr('transform', function(d, i) { + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; + }); + + //position legend as far right as possible within the total width + if (rightAlign) { + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); + } + else { + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); + } + + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); + + } else { + + var ypos = 5, + newxpos = 5, + maxwidth = 0, + xpos; + series + .attr('transform', function(d, i) { + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; + xpos = newxpos; + + if (width < margin.left + margin.right + xpos + length) { + newxpos = xpos = 5; + ypos += versPadding; + } + + newxpos += length; + if (newxpos > maxwidth) maxwidth = newxpos; + + if(legendWidth < xpos + maxwidth) { + legendWidth = xpos + maxwidth; + } + return 'translate(' + xpos + ',' + ypos + ')'; + }); + + //position legend as far right as possible within the total width + g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')'); + + height = margin.top + margin.bottom + ypos + 15; + } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15); + + // The background for the expanded legend (UI) + gEnter.insert('rect',':first-child') + .attr('class', 'nv-legend-bg') + .attr('fill', '#eee') + // .attr('stroke', '#444') + .attr('opacity',0); + + var seriesBG = g.select('.nv-legend-bg'); + + seriesBG + .transition().duration(300) + .attr('x', -versPadding ) + .attr('width', legendWidth + versPadding - 12) + .attr('height', height + 10) + .attr('y', -margin.top - 10) + .attr('opacity', expanded ? 1 : 0); + + + } + + seriesShape + .style('fill', setBGColor) + .style('fill-opacity', setBGOpacity) + .style('stroke', setBGColor); + }); + + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? '#000' : '#fff'; + } else if (!expanded) { + if(!d.color) d.color = color(d,i); + return !!d.disabled ? d.color : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#eee' : d.color || color(d,i); + } else { + return d.color || color(d,i); + } + } + + + function setBGOpacity(d,i) { + if(expanded && vers == 'furious') { + return 1; + } else { + return !!d.disabled ? 0 : 1; + } + } + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + align: {get: function(){return align;}, set: function(_){align=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, + rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.line = function() { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var scatter = nv.models.scatter() + ; + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , container = null + , strokeWidth = 1.5 + , color = nv.utils.defaultColor() // a function that returns a color + , getX = function(d) { return d.x } // accessor to get the x value from a data point + , getY = function(d) { return d.y } // accessor to get the y value from a data point + , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined + , isArea = function(d) { return d.area } // decides if a line is an area or just a line + , clipEdge = false // if true, masks lines within x and y scale + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , interpolate = "linear" // controls the line interpolation + , duration = 250 + , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + scatter + .pointSize(16) // default size + .pointDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor + ; + + //============================================================ + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 //used to store previous scales + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + //============================================================ + + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + nv.utils.initSVG(container); + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + x0 = x0 || x; + y0 = y0 || y; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + scatter + .width(availableWidth) + .height(availableHeight); + + var scatterWrap = wrap.select('.nv-scatterWrap'); + scatterWrap.call(scatter); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + scatter.id()) + .append('rect'); + + wrap.select('#nv-edge-clip-' + scatter.id() + ' rect') + .attr('width', availableWidth) + .attr('height', (availableHeight > 0) ? availableHeight : 0); + + g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); + scatterWrap + .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth }) + .style('fill-opacity', 1e-6); + + groups.exit().remove(); + + groups + .attr('class', function(d,i) { + return (d.classed || '') + ' nv-group nv-series-' + i; + }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i)}); + groups.watchTransition(renderWatch, 'line: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', function(d) { return d.fillOpacity || .5}); + + var areaPaths = groups.selectAll('path.nv-area') + .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area + areaPaths.enter().append('path') + .attr('class', 'nv-area') + .attr('d', function(d) { + return d3.svg.area() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) }) + .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) }) + .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) }) + //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this + .apply(this, [d.values]) + }); + groups.exit().selectAll('path.nv-area') + .remove(); + + areaPaths.watchTransition(renderWatch, 'line: areaPaths') + .attr('d', function(d) { + return d3.svg.area() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) }) + .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) }) + .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) }) + //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this + .apply(this, [d.values]) + }); + + var linePaths = groups.selectAll('path.nv-line') + .data(function(d) { return [d.values] }); + + linePaths.enter().append('path') + .attr('class', 'nv-line') + .attr('d', + d3.svg.line() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) }) + .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) }) + ); + + linePaths.watchTransition(renderWatch, 'line: linePaths') + .attr('d', + d3.svg.line() + .interpolate(interpolate) + .defined(defined) + .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) }) + .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) }) + ); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + }); + renderWatch.renderEnd('line immediate'); + return chart; + } + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.scatter = scatter; + // Pass through events + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + defined: {get: function(){return defined;}, set: function(_){defined=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + }}, + isArea: {get: function(){return isArea;}, set: function(_){ + isArea = d3.functor(_); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + scatter.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + scatter.y(_); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + scatter.color(color); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.lineChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() + , lines2 = nv.models.line() + , x2Axis = nv.models.axis() + , y2Axis = nv.models.axis() + , brush = d3.svg.brush() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , margin2 = {top: 0, right: 20, bottom: 20, left: 60} + , color = nv.utils.defaultColor() + , width = null + , height = null + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , x + , y + , x2 + , y2 + , focusEnable = false + , focusShowAxisY = false + , focusShowAxisX = true + , focusHeight = 50 + , brushExtent = null + , state = nv.utils.state() + , defaultState = null + , noData = null + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState', 'renderEnd') + , duration = 250 + ; + + // set options on sub-objects for this chart + xAxis.orient('bottom').tickPadding(7); + yAxis.orient(rightAlignYAxis ? 'right' : 'left'); + + lines.clipEdge(true).duration(0); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false; }); + + x2Axis.orient('bottom').tickPadding(5); + y2Axis.orient(rightAlignYAxis ? 'right' : 'left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + interactiveLayer.tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled; }) + }; + }; + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + }; + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(lines); + renderWatch.models(lines2); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + if (focusShowAxisX) renderWatch.models(x2Axis); + if (focusShowAxisY) renderWatch.models(y2Axis); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0), + availableHeight2 = focusHeight - margin2.top - margin2.bottom; + + chart.update = function() { + if( duration === 0 ) { + container.call( chart ); + } else { + container.transition().duration(duration).call(chart); + } + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled; }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length; }).length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + + // Setup Scales + x = lines.xScale(); + y = lines.yScale(); + x2 = lines2.xScale(); + y2 = lines2.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-legendWrap'); + + var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); + focusEnter.append('g').attr('class', 'nv-background').append('rect'); + focusEnter.append('g').attr('class', 'nv-x nv-axis'); + focusEnter.append('g').attr('class', 'nv-y nv-axis'); + focusEnter.append('g').attr('class', 'nv-linesWrap'); + focusEnter.append('g').attr('class', 'nv-interactive'); + + var contextEnter = gEnter.append('g').attr('class', 'nv-context'); + contextEnter.append('g').attr('class', 'nv-background').append('rect'); + contextEnter.append('g').attr('class', 'nv-x nv-axis'); + contextEnter.append('g').attr('class', 'nv-y nv-axis'); + contextEnter.append('g').attr('class', 'nv-linesWrap'); + contextEnter.append('g').attr('class', 'nv-brushBackground'); + contextEnter.append('g').attr('class', 'nv-x nv-brush'); + + // Legend + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight1) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + g.select('.nv-focus .nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight1); + + lines + .width(availableWidth) + .height(availableHeight1) + .color(data.map(function(d,i) { + return d.color || color(d, i); + + }).filter(function(d,i) { return !data[i].disabled; })); + + var linesWrap = g.select('.nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled; })); + + + // Setup Main (Focus) Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks(nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight1, 0); + + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize( -availableWidth, 0); + } + + //============================================================ + // Update Axes + //============================================================ + function updateXAxis() { + if(showXAxis) { + g.select('.nv-focus .nv-x.nv-axis') + .transition() + .duration(duration) + .call(xAxis) + ; + } + } + + function updateYAxis() { + if(showYAxis) { + g.select('.nv-focus .nv-y.nv-axis') + .transition() + .duration(duration) + .call(yAxis) + ; + } + } + + g.select('.nv-focus .nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight1 + ')'); + + if( !focusEnable ) + { + linesWrap.call(lines); + updateXAxis(); + updateYAxis(); + } + else + { + lines2 + .defined(lines.defined()) + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled; })); + + g.select('.nv-context') + .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')') + .style('display', focusEnable ? 'initial' : 'none') + ; + + var contextLinesWrap = g.select('.nv-context .nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled; })) + ; + + d3.transition(contextLinesWrap).call(lines2); + + + // Setup Brush + brush + .x(x2) + .on('brush', function() { + onBrush(); + }); + + if (brushExtent) brush.extent(brushExtent); + + var brushBG = g.select('.nv-brushBackground').selectAll('g') + .data([brushExtent || brush.extent()]); + + var brushBGenter = brushBG.enter() + .append('g'); + + brushBGenter.append('rect') + .attr('class', 'left') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + brushBGenter.append('rect') + .attr('class', 'right') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + var gBrush = g.select('.nv-x.nv-brush') + .call(brush); + gBrush.selectAll('rect') + .attr('height', availableHeight2); + gBrush.selectAll('.resize').append('path').attr('d', resizePath); + + onBrush(); + + g.select('.nv-context .nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight2); + + // Setup Secondary (Context) Axes + if (focusShowAxisX) { + x2Axis + .scale(x2) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight2, 0); + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); + d3.transition(g.select('.nv-context .nv-x.nv-axis')) + .call(x2Axis); + } + + if (focusShowAxisY) { + y2Axis + .scale(y2) + ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) + .tickSize( -availableWidth, 0); + + d3.transition(g.select('.nv-context .nv-y.nv-axis')) + .call(y2Axis); + } + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + lines.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled && !series.disableTooltip; + }) + .forEach(function(series,i) { + var extent = focusEnable ? (brush.empty() ? x2.domain() : brush.extent()) : x.domain(); + var currentValues = series.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }); + + pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x()); + var point = currentValues[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue !== null) { + lines.highlightPoint(series.seriesIndex, pointIndex, true); + } + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: pointYValue, + color: color(series,series.seriesIndex), + data: point + }); + }); + //Highlight the tooltip entry based on which point the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); + var threshold = 0.03 * domainExtent; + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value;}),yValue,threshold); + if (indexToHighlight !== null) + allData[indexToHighlight].highlight = true; + } + + interactiveLayer.tooltip + .chartContainer(chart.container.parentNode) + .valueFormatter(function(d,i) { + return d === null ? "N/A" : yAxis.tickFormat()(d); + }) + .data({ + value: chart.x()( singlePoint,pointIndex ), + index: pointIndex, + series: allData + })(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on('elementClick', function(e) { + var pointXLocation, allData = []; + + data.filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }).forEach(function(series) { + var pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + var point = series.values[pointIndex]; + if (typeof point === 'undefined') return; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + var yPos = chart.yScale()(chart.y()(point,pointIndex)); + allData.push({ + point: point, + pointIndex: pointIndex, + pos: [pointXLocation, yPos], + seriesIndex: series.seriesIndex, + series: series + }); + }); + + lines.dispatch.elementClick(allData); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + lines.clearHighlights(); + }); + + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + chart.update(); + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + // Taken from crossfilter (http://square.github.com/crossfilter/) + function resizePath(d) { + var e = +(d == 'e'), + x = e ? 1 : -1, + y = availableHeight2 / 3; + return 'M' + (0.5 * x) + ',' + y + + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + + 'V' + (2 * y - 6) + + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y) + + 'Z' + + 'M' + (2.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8) + + 'M' + (4.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8); + } + + + function updateBrushBG() { + if (!brush.empty()) brush.extent(brushExtent); + brushBG + .data([brush.empty() ? x2.domain() : brushExtent]) + .each(function(d,i) { + var leftWidth = x2(d[0]) - x.range()[0], + rightWidth = availableWidth - x2(d[1]); + d3.select(this).select('.left') + .attr('width', leftWidth < 0 ? 0 : leftWidth); + + d3.select(this).select('.right') + .attr('x', x2(d[1])) + .attr('width', rightWidth < 0 ? 0 : rightWidth); + }); + } + + + function onBrush() { + brushExtent = brush.empty() ? null : brush.extent(); + var extent = brush.empty() ? x2.domain() : brush.extent(); + + //The brush extent cannot be less than one. If it is, don't update the line chart. + if (Math.abs(extent[0] - extent[1]) <= 1) { + return; + } + + dispatch.brush({extent: extent, brush: brush}); + + + updateBrushBG(); + + // Update Main (Focus) + var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') + .datum( + data + .filter(function(d) { return !d.disabled; }) + .map(function(d,i) { + return { + key: d.key, + area: d.area, + classed: d.classed, + values: d.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }), + disableTooltip: d.disableTooltip + }; + }) + ); + focusLinesWrap.transition().duration(duration).call(lines); + + + // Update Main (Focus) Axes + updateXAxis(); + updateYAxis(); + } + + + }); + + renderWatch.renderEnd('lineChart immediate'); + return chart; + } + + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + if(!evt.series.disableTooltip){ + tooltip.data(evt).hidden(false); + } + }); + + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.lines = lines; + chart.lines2 = lines2; + chart.legend = legend; + chart.xAxis = xAxis; + chart.x2Axis = x2Axis; + chart.yAxis = yAxis; + chart.y2Axis = y2Axis; + chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; + chart.state = state; + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, + focusHeight: {get: function(){return height2;}, set: function(_){focusHeight=_;}}, + focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}}, + focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}}, + brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + lines.duration(duration); + xAxis.duration(duration); + x2Axis.duration(duration); + yAxis.duration(duration); + y2Axis.duration(duration); + }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + lines.color(color); + }}, + interpolate: {get: function(){return lines.interpolate();}, set: function(_){ + lines.interpolate(_); + lines2.interpolate(_); + }}, + xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){ + xAxis.tickFormat(_); + x2Axis.tickFormat(_); + }}, + yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){ + yAxis.tickFormat(_); + y2Axis.tickFormat(_); + }}, + x: {get: function(){return lines.x();}, set: function(_){ + lines.x(_); + lines2.x(_); + }}, + y: {get: function(){return lines.y();}, set: function(_){ + lines.y(_); + lines2.y(_); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (useInteractiveGuideline) { + lines.interactive(false); + lines.useVoronoi(false); + } + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.lineWithFocusChart = function() { + return nv.models.lineChart() + .margin({ bottom: 30 }) + .focusEnable( true ); +}; +nv.models.linePlusBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var lines = nv.models.line() + , lines2 = nv.models.line() + , bars = nv.models.historicalBar() + , bars2 = nv.models.historicalBar() + , xAxis = nv.models.axis() + , x2Axis = nv.models.axis() + , y1Axis = nv.models.axis() + , y2Axis = nv.models.axis() + , y3Axis = nv.models.axis() + , y4Axis = nv.models.axis() + , legend = nv.models.legend() + , brush = d3.svg.brush() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 30, bottom: 30, left: 60} + , margin2 = {top: 0, right: 30, bottom: 20, left: 60} + , width = null + , height = null + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.defaultColor() + , showLegend = true + , focusEnable = true + , focusShowAxisY = false + , focusShowAxisX = true + , focusHeight = 50 + , extent + , brushExtent = null + , x + , x2 + , y1 + , y2 + , y3 + , y4 + , noData = null + , dispatch = d3.dispatch('brush', 'stateChange', 'changeState') + , transitionDuration = 0 + , state = nv.utils.state() + , defaultState = null + , legendLeftAxisHint = ' (left axis)' + , legendRightAxisHint = ' (right axis)' + , switchYAxisOrder = false + ; + + lines.clipEdge(true); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false }); + xAxis.orient('bottom').tickPadding(5); + y1Axis.orient('left'); + y2Axis.orient('right'); + x2Axis.orient('bottom').tickPadding(5); + y3Axis.orient('left'); + y4Axis.orient('right'); + + tooltip.headerEnabled(true).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var getBarsAxis = function() { + return switchYAxisOrder + ? { main: y1Axis, focus: y3Axis } + : { main: y2Axis, focus: y4Axis } + } + + var getLinesAxis = function() { + return switchYAxisOrder + ? { main: y2Axis, focus: y4Axis } + : { main: y1Axis, focus: y3Axis } + } + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + var allDisabled = function(data) { + return data.every(function(series) { + return series.disabled; + }); + } + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) + - (focusEnable ? focusHeight : 0), + availableHeight2 = focusHeight - margin2.top - margin2.bottom; + + chart.update = function() { container.transition().duration(transitionDuration).call(chart); }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + var dataBars = data.filter(function(d) { return !d.disabled && d.bar }); + var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240 + + x = bars.xScale(); + x2 = x2Axis.scale(); + + // select the scales and series based on the position of the yAxis + y1 = switchYAxisOrder ? lines.yScale() : bars.yScale(); + y2 = switchYAxisOrder ? bars.yScale() : lines.yScale(); + y3 = switchYAxisOrder ? lines2.yScale() : bars2.yScale(); + y4 = switchYAxisOrder ? bars2.yScale() : lines2.yScale(); + + var series1 = data + .filter(function(d) { return !d.disabled && (switchYAxisOrder ? !d.bar : d.bar) }) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i) } + }) + }); + + var series2 = data + .filter(function(d) { return !d.disabled && (switchYAxisOrder ? d.bar : !d.bar) }) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i) } + }) + }); + + x.range([0, availableWidth]); + + x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } )) + .range([0, availableWidth]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-legendWrap'); + + // this is the main chart + var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); + focusEnter.append('g').attr('class', 'nv-x nv-axis'); + focusEnter.append('g').attr('class', 'nv-y1 nv-axis'); + focusEnter.append('g').attr('class', 'nv-y2 nv-axis'); + focusEnter.append('g').attr('class', 'nv-barsWrap'); + focusEnter.append('g').attr('class', 'nv-linesWrap'); + + // context chart is where you can focus in + var contextEnter = gEnter.append('g').attr('class', 'nv-context'); + contextEnter.append('g').attr('class', 'nv-x nv-axis'); + contextEnter.append('g').attr('class', 'nv-y1 nv-axis'); + contextEnter.append('g').attr('class', 'nv-y2 nv-axis'); + contextEnter.append('g').attr('class', 'nv-barsWrap'); + contextEnter.append('g').attr('class', 'nv-linesWrap'); + contextEnter.append('g').attr('class', 'nv-brushBackground'); + contextEnter.append('g').attr('class', 'nv-x nv-brush'); + + //============================================================ + // Legend + //------------------------------------------------------------ + + if (showLegend) { + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); + + g.select('.nv-legendWrap') + .datum(data.map(function(series) { + series.originalKey = series.originalKey === undefined ? series.key : series.originalKey; + if(switchYAxisOrder) { + series.key = series.originalKey + (series.bar ? legendRightAxisHint : legendLeftAxisHint); + } else { + series.key = series.originalKey + (series.bar ? legendLeftAxisHint : legendRightAxisHint); + } + return series; + })) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"? + availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight; + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + //============================================================ + // Context chart (focus chart) components + //------------------------------------------------------------ + + // hide or show the focus context chart + g.select('.nv-context').style('display', focusEnable ? 'initial' : 'none'); + + bars2 + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function (d, i) { + return d.color || color(d, i); + }).filter(function (d, i) { + return !data[i].disabled && data[i].bar + })); + lines2 + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function (d, i) { + return d.color || color(d, i); + }).filter(function (d, i) { + return !data[i].disabled && !data[i].bar + })); + + var bars2Wrap = g.select('.nv-context .nv-barsWrap') + .datum(dataBars.length ? dataBars : [ + {values: []} + ]); + var lines2Wrap = g.select('.nv-context .nv-linesWrap') + .datum(allDisabled(dataLines) ? + [{values: []}] : + dataLines.filter(function(dataLine) { + return !dataLine.disabled; + })); + + g.select('.nv-context') + .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')'); + + bars2Wrap.transition().call(bars2); + lines2Wrap.transition().call(lines2); + + // context (focus chart) axis controls + if (focusShowAxisX) { + x2Axis + ._ticks( nv.utils.calcTicksX(availableWidth / 100, data)) + .tickSize(-availableHeight2, 0); + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y3.range()[0] + ')'); + g.select('.nv-context .nv-x.nv-axis').transition() + .call(x2Axis); + } + + if (focusShowAxisY) { + y3Axis + .scale(y3) + ._ticks( availableHeight2 / 36 ) + .tickSize( -availableWidth, 0); + y4Axis + .scale(y4) + ._ticks( availableHeight2 / 36 ) + .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none + + g.select('.nv-context .nv-y3.nv-axis') + .style('opacity', dataBars.length ? 1 : 0) + .attr('transform', 'translate(0,' + x2.range()[0] + ')'); + g.select('.nv-context .nv-y2.nv-axis') + .style('opacity', dataLines.length ? 1 : 0) + .attr('transform', 'translate(' + x2.range()[1] + ',0)'); + + g.select('.nv-context .nv-y1.nv-axis').transition() + .call(y3Axis); + g.select('.nv-context .nv-y2.nv-axis').transition() + .call(y4Axis); + } + + // Setup Brush + brush.x(x2).on('brush', onBrush); + + if (brushExtent) brush.extent(brushExtent); + + var brushBG = g.select('.nv-brushBackground').selectAll('g') + .data([brushExtent || brush.extent()]); + + var brushBGenter = brushBG.enter() + .append('g'); + + brushBGenter.append('rect') + .attr('class', 'left') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + brushBGenter.append('rect') + .attr('class', 'right') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + var gBrush = g.select('.nv-x.nv-brush') + .call(brush); + gBrush.selectAll('rect') + //.attr('y', -5) + .attr('height', availableHeight2); + gBrush.selectAll('.resize').append('path').attr('d', resizePath); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + + //============================================================ + // Functions + //------------------------------------------------------------ + + // Taken from crossfilter (http://square.github.com/crossfilter/) + function resizePath(d) { + var e = +(d == 'e'), + x = e ? 1 : -1, + y = availableHeight2 / 3; + return 'M' + (.5 * x) + ',' + y + + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + + 'V' + (2 * y - 6) + + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y) + + 'Z' + + 'M' + (2.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8) + + 'M' + (4.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8); + } + + + function updateBrushBG() { + if (!brush.empty()) brush.extent(brushExtent); + brushBG + .data([brush.empty() ? x2.domain() : brushExtent]) + .each(function(d,i) { + var leftWidth = x2(d[0]) - x2.range()[0], + rightWidth = x2.range()[1] - x2(d[1]); + d3.select(this).select('.left') + .attr('width', leftWidth < 0 ? 0 : leftWidth); + + d3.select(this).select('.right') + .attr('x', x2(d[1])) + .attr('width', rightWidth < 0 ? 0 : rightWidth); + }); + } + + function onBrush() { + brushExtent = brush.empty() ? null : brush.extent(); + extent = brush.empty() ? x2.domain() : brush.extent(); + dispatch.brush({extent: extent, brush: brush}); + updateBrushBG(); + + // Prepare Main (Focus) Bars and Lines + bars + .width(availableWidth) + .height(availableHeight1) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && data[i].bar })); + + lines + .width(availableWidth) + .height(availableHeight1) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled && !data[i].bar })); + + var focusBarsWrap = g.select('.nv-focus .nv-barsWrap') + .datum(!dataBars.length ? [{values:[]}] : + dataBars + .map(function(d,i) { + return { + key: d.key, + values: d.values.filter(function(d,i) { + return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1]; + }) + } + }) + ); + + var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') + .datum(allDisabled(dataLines) ? [{values:[]}] : + dataLines + .filter(function(dataLine) { return !dataLine.disabled; }) + .map(function(d,i) { + return { + area: d.area, + fillOpacity: d.fillOpacity, + key: d.key, + values: d.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }) + } + }) + ); + + // Update Main (Focus) X Axis + if (dataBars.length && !switchYAxisOrder) { + x = bars.xScale(); + } else { + x = lines.xScale(); + } + + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight1, 0); + + xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]); + + g.select('.nv-x.nv-axis').transition().duration(transitionDuration) + .call(xAxis); + + // Update Main (Focus) Bars and Lines + focusBarsWrap.transition().duration(transitionDuration).call(bars); + focusLinesWrap.transition().duration(transitionDuration).call(lines); + + // Setup and Update Main (Focus) Y Axes + g.select('.nv-focus .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y1.range()[0] + ')'); + + y1Axis + .scale(y1) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize(-availableWidth, 0); + y2Axis + .scale(y2) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none + + // Calculate opacity of the axis + var barsOpacity = dataBars.length ? 1 : 0; + var linesOpacity = dataLines.length && !allDisabled(dataLines) ? 1 : 0; + + var y1Opacity = switchYAxisOrder ? linesOpacity : barsOpacity; + var y2Opacity = switchYAxisOrder ? barsOpacity : linesOpacity; + + g.select('.nv-focus .nv-y1.nv-axis') + .style('opacity', y1Opacity); + g.select('.nv-focus .nv-y2.nv-axis') + .style('opacity', y2Opacity) + .attr('transform', 'translate(' + x.range()[1] + ',0)'); + + g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration) + .call(y1Axis); + g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration) + .call(y2Axis); + } + + onBrush(); + + }); + + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return getLinesAxis().main.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + }); + + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + value: chart.y()(evt.data), + color: evt.color + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return getBarsAxis().main.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + }); + + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.legend = legend; + chart.lines = lines; + chart.lines2 = lines2; + chart.bars = bars; + chart.bars2 = bars2; + chart.xAxis = xAxis; + chart.x2Axis = x2Axis; + chart.y1Axis = y1Axis; + chart.y2Axis = y2Axis; + chart.y3Axis = y3Axis; + chart.y4Axis = y4Axis; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, + focusHeight: {get: function(){return focusHeight;}, set: function(_){focusHeight=_;}}, + focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}}, + focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}}, + legendLeftAxisHint: {get: function(){return legendLeftAxisHint;}, set: function(_){legendLeftAxisHint=_;}}, + legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; + }}, + duration: {get: function(){return transitionDuration;}, set: function(_){ + transitionDuration = _; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + lines.x(_); + lines2.x(_); + bars.x(_); + bars2.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + lines.y(_); + lines2.y(_); + bars.y(_); + bars2.y(_); + }}, + switchYAxisOrder: {get: function(){return switchYAxisOrder;}, set: function(_){ + // Switch the tick format for the yAxis + if(switchYAxisOrder !== _) { + var tickFormat = y1Axis.tickFormat(); + y1Axis.tickFormat(y2Axis.tickFormat()); + y2Axis.tickFormat(tickFormat); + } + switchYAxisOrder=_; + }} + }); + + nv.utils.inheritOptions(chart, lines); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , clipEdge = true + , stacked = false + , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function + , color = nv.utils.defaultColor() + , hideable = false + , barColor = null // adding the ability to set the color for each rather than the whole group + , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled + , duration = 500 + , xDomain + , yDomain + , xRange + , yRange + , groupSpacing = 0.1 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 //used to store previous scales + , renderWatch = nv.utils.renderWatch(dispatch, duration) + ; + + var last_datalength = 0; + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + var nonStackableCount = 0; + // This function defines the requirements for render complete + var endFn = function(d, i) { + if (d.series === data.length - 1 && i === data[0].values.length - 1) + return true; + return false; + }; + + if(hideable && data.length) hideable = [{ + values: data[0].values.map(function(d) { + return { + x: d.x, + y: 0, + series: d.series, + size: 0.01 + };} + )}]; + + if (stacked) { + var parsed = d3.layout.stack() + .offset(stackOffset) + .values(function(d){ return d.values }) + .y(getY) + (!data.length && hideable ? hideable : data); + + parsed.forEach(function(series, i){ + // if series is non-stackable, use un-parsed data + if (series.nonStackable) { + data[i].nonStackableSeries = nonStackableCount++; + parsed[i] = data[i]; + } else { + // don't stack this seires on top of the nonStackable seriees + if (i > 0 && parsed[i - 1].nonStackable){ + parsed[i].values.map(function(d,j){ + d.y0 -= parsed[i - 1].values[j].y; + d.y1 = d.y0 + d.y; + }); + } + } + }); + data = parsed; + } + //add series index and key to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + point.key = series.key; + }); + }); + + // HACK for negative value stacking + if (stacked) { + data[0].values.map(function(d,i) { + var posBase = 0, negBase = 0; + data.map(function(d, idx) { + if (!data[idx].nonStackable) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase; + negBase = negBase - f.size; + } else + { + f.y1 = f.size + posBase; + posBase = posBase + f.size; + } + } + + }); + }); + } + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d, idx) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx } + }) + }); + + x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableWidth], groupSpacing); + + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { + var domain = d.y; + // increase the domain range if this series is stackable + if (stacked && !data[d.idx].nonStackable) { + if (d.y > 0){ + domain = d.y1 + } else { + domain = d.y1 + d.y + } + } + return domain; + }).concat(forceY))) + .range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + x0 = x0 || x; + y0 = y0 || y; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d,i) { return i }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + + var exitTransition = renderWatch + .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration)) + .attr('y', function(d, i, j) { + var yVal = y0(0) || 0; + if (stacked) { + if (data[d.series] && !data[d.series].nonStackable) { + yVal = y0(d.y0); + } + } + return yVal; + }) + .attr('height', 0) + .remove(); + if (exitTransition.delay) + exitTransition.delay(function(d,i) { + var delay = i * (duration / (last_datalength + 1)) - i; + return delay; + }); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i) }); + groups + .style('stroke-opacity', 1) + .style('fill-opacity', 0.75); + + var bars = groups.selectAll('rect.nv-bar') + .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('rect') + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + .attr('x', function(d,i,j) { + return stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length ) + }) + .attr('y', function(d,i,j) { return y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0 }) + .attr('height', 0) + .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) }) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) + ; + bars + .style('fill', function(d,i,j){ return color(d, j, i); }) + .style('stroke', function(d,i,j){ return color(d, j, i); }) + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('click', function(d,i) { + var element = this; + dispatch.elementClick({ + data: d, + index: i, + color: d3.select(this).style("fill"), + event: d3.event, + element: element + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }); + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) + + if (barColor) { + if (!disabled) disabled = data.map(function() { return true }); + bars + .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }) + .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }); + } + + var barSelection = + bars.watchTransition(renderWatch, 'multibar', Math.min(250, duration)) + .delay(function(d,i) { + return i * duration / data[0].values.length; + }); + if (stacked){ + barSelection + .attr('y', function(d,i,j) { + var yVal = 0; + // if stackable, stack it on top of the previous series + if (!data[j].nonStackable) { + yVal = y(d.y1); + } else { + if (getY(d,i) < 0){ + yVal = y(0); + } else { + if (y(0) - y(getY(d,i)) < -1){ + yVal = y(0) - 1; + } else { + yVal = y(getY(d, i)) || 0; + } + } + } + return yVal; + }) + .attr('height', function(d,i,j) { + if (!data[j].nonStackable) { + return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 0); + } else { + return Math.max(Math.abs(y(getY(d,i)) - y(0)), 0) || 0; + } + }) + .attr('x', function(d,i,j) { + var width = 0; + if (data[j].nonStackable) { + width = d.series * x.rangeBand() / data.length; + if (data.length !== nonStackableCount){ + width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2); + } + } + return width; + }) + .attr('width', function(d,i,j){ + if (!data[j].nonStackable) { + return x.rangeBand(); + } else { + // if all series are nonStacable, take the full width + var width = (x.rangeBand() / nonStackableCount); + // otherwise, nonStackable graph will be only taking the half-width + // of the x rangeBand + if (data.length !== nonStackableCount) { + width = x.rangeBand()/(nonStackableCount*2); + } + return width; + } + }); + } + else { + barSelection + .attr('x', function(d,i) { + return d.series * x.rangeBand() / data.length; + }) + .attr('width', x.rangeBand() / data.length) + .attr('y', function(d,i) { + return getY(d,i) < 0 ? + y(0) : + y(0) - y(getY(d,i)) < 1 ? + y(0) - 1 : + y(getY(d,i)) || 0; + }) + .attr('height', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0; + }); + } + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + // keep track of the last data value length for transition calculations + if (data[0] && data[0].values) { + last_datalength = data[0].values.length; + } + + }); + + renderWatch.renderEnd('multibar immediate'); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}}, + stackOffset: {get: function(){return stackOffset;}, set: function(_){stackOffset=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + hideable: {get: function(){return hideable;}, set: function(_){hideable=_;}}, + groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + barColor: {get: function(){return barColor;}, set: function(_){ + barColor = _ ? nv.utils.getColor(_) : null; + }} + }); + + nv.utils.initOptions(chart); + + return chart; +};nv.models.multiBarChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var multibar = nv.models.multiBar() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , interactiveLayer = nv.interactiveGuideline() + , legend = nv.models.legend() + , controls = nv.models.legend() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , controlLabels = {} + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , reduceXTicks = true // if false a tick will show for every data point + , staggerLabels = false + , wrapLabels = false + , rotateLabels = 0 + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , state = nv.utils.state() + , defaultState = null + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') + , controlWidth = function() { return showControls ? 180 : 0 } + , duration = 250 + , useInteractiveGuideline = false + ; + + state.stacked = false // DEPRECATED Maintained for backward compatibility + + multibar.stacked(false); + xAxis + .orient('bottom') + .tickPadding(7) + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + var stacked = false; + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + stacked: stacked + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.stacked !== undefined) + stacked = state.stacked; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(multibar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition() + .duration(duration) + .call(chart); + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = multibar.xScale(); + y = multibar.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + // Legend + if (showLegend) { + legend.width(availableWidth - controlWidth()); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() }, + { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() } + ]; + + controls.width(controlWidth()).color(['#444', '#444', '#444']); + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + multibar + .disabled(data.map(function(series) { return series.disabled })) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + barsWrap.call(multibar); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis') + .call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g'); + + xTicks + .selectAll('line, text') + .style('opacity', 1) + + if (staggerLabels) { + var getTranslate = function(x,y) { + return "translate(" + x + "," + y + ")"; + }; + + var staggerUp = 5, staggerDown = 17; //pixels to stagger by + // Issue #140 + xTicks + .selectAll("text") + .attr('transform', function(d,i,j) { + return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown)); + }); + + var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length; + g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text") + .attr("transform", function(d,i) { + return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp); + }); + } + + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) + } + + if (reduceXTicks) + xTicks + .filter(function(d,i) { + return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0; + }) + .selectAll('text, line') + .style('opacity', 0); + + if(rotateLabels) + xTicks + .selectAll('.tick text') + .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') + .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); + + g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text') + .style('opacity', 1); + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + switch (d.key) { + case 'Grouped': + case controlLabels.grouped: + multibar.stacked(false); + break; + case 'Stacked': + case controlLabels.stacked: + multibar.stacked(true); + break; + } + + state.stacked = multibar.stacked(); + dispatch.stateChange(state); + chart.update(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + if (typeof e.stacked !== 'undefined') { + multibar.stacked(e.stacked); + state.stacked = e.stacked; + stacked = e.stacked; + } + chart.update(); + }); + + if (useInteractiveGuideline) { + interactiveLayer.dispatch.on('elementMousemove', function(e) { + if (e.pointXValue == undefined) return; + + var singlePoint, pointIndex, pointXLocation, xValue, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = x.domain().indexOf(e.pointXValue) + + var point = series.values[pointIndex]; + if (point === undefined) return; + + xValue = point.x; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = e.mouseX + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex), + data: series.values[pointIndex] + }); + }); + + interactiveLayer.tooltip + .chartContainer(that.parentNode) + .data({ + value: xValue, + index: pointIndex, + series: allData + })(); + + interactiveLayer.renderGuideLine(pointXLocation); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + interactiveLayer.tooltip.hidden(true); + }); + } + else { + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + } + }); + + renderWatch.renderEnd('multibarchart immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.multibar = multibar; + chart.legend = legend; + chart.controls = controls; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.state = state; + chart.tooltip = tooltip; + chart.interactiveLayer = interactiveLayer; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + multibar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) + }} + }); + + nv.utils.inheritOptions(chart, multibar); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBarHorizontal = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getYerr = function(d) { return d.yErr } + , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove + , color = nv.utils.defaultColor() + , barColor = null // adding the ability to set the color for each rather than the whole group + , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled + , stacked = false + , showValues = false + , showBarLabels = false + , valuePadding = 60 + , groupSpacing = 0.1 + , valueFormat = d3.format(',.2f') + , delay = 1200 + , xDomain + , yDomain + , xRange + , yRange + , duration = 250 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; //used to store previous scales + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + if (stacked) + data = d3.layout.stack() + .offset('zero') + .values(function(d){ return d.values }) + .y(getY) + (data); + + //add series index and key to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + point.key = series.key; + }); + }); + + // HACK for negative value stacking + if (stacked) + data[0].values.map(function(d,i) { + var posBase = 0, negBase = 0; + data.map(function(d) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase - f.size; + negBase = negBase - f.size; + } else + { + f.y1 = posBase; + posBase = posBase + f.size; + } + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 } + }) + }); + + x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) + .rangeBands(xRange || [0, availableHeight], groupSpacing); + + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY))) + + if (showValues && !stacked) + y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]); + else + y.range(yRange || [0, availableWidth]); + + x0 = x0 || x; + y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-groups'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d,i) { return i }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit().watchTransition(renderWatch, 'multibarhorizontal: exit groups') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6) + .remove(); + groups + .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .classed('hover', function(d) { return d.hover }) + .style('fill', function(d,i){ return color(d, i) }) + .style('stroke', function(d,i){ return color(d, i) }); + groups.watchTransition(renderWatch, 'multibarhorizontal: groups') + .style('stroke-opacity', 1) + .style('fill-opacity', .75); + + var bars = groups.selectAll('g.nv-bar') + .data(function(d) { return d.values }); + bars.exit().remove(); + + var barsEnter = bars.enter().append('g') + .attr('transform', function(d,i,j) { + return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')' + }); + + barsEnter.append('rect') + .attr('width', 0) + .attr('height', x.rangeBand() / (stacked ? 1 : data.length) ) + + bars + .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('click', function(d,i) { + dispatch.elementClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }) + .on('dblclick', function(d,i) { + dispatch.elementDblClick({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + d3.event.stopPropagation(); + }); + + if (getYerr(data[0],0)) { + barsEnter.append('polyline'); + + bars.select('polyline') + .attr('fill', 'none') + .attr('points', function(d,i) { + var xerr = getYerr(d,i) + , mid = 0.8 * x.rangeBand() / ((stacked ? 1 : data.length) * 2); + xerr = xerr.length ? xerr : [-Math.abs(xerr), Math.abs(xerr)]; + xerr = xerr.map(function(e) { return y(e) - y(0); }); + var a = [[xerr[0],-mid], [xerr[0],mid], [xerr[0],0], [xerr[1],0], [xerr[1],-mid], [xerr[1],mid]]; + return a.map(function (path) { return path.join(',') }).join(' '); + }) + .attr('transform', function(d,i) { + var mid = x.rangeBand() / ((stacked ? 1 : data.length) * 2); + return 'translate(' + (getY(d,i) < 0 ? 0 : y(getY(d,i)) - y(0)) + ', ' + mid + ')' + }); + } + + barsEnter.append('text'); + + if (showValues && !stacked) { + bars.select('text') + .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' }) + .attr('y', x.rangeBand() / (data.length * 2)) + .attr('dy', '.32em') + .text(function(d,i) { + var t = valueFormat(getY(d,i)) + , yerr = getYerr(d,i); + if (yerr === undefined) + return t; + if (!yerr.length) + return t + '±' + valueFormat(Math.abs(yerr)); + return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0])); + }); + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .select('text') + .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 }) + } else { + bars.selectAll('text').text(''); + } + + if (showBarLabels && !stacked) { + barsEnter.append('text').classed('nv-bar-label',true); + bars.select('text.nv-bar-label') + .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' }) + .attr('y', x.rangeBand() / (data.length * 2)) + .attr('dy', '.32em') + .text(function(d,i) { return getX(d,i) }); + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .select('text.nv-bar-label') + .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 }); + } + else { + bars.selectAll('text.nv-bar-label').text(''); + } + + bars + .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) + + if (barColor) { + if (!disabled) disabled = data.map(function() { return true }); + bars + .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }) + .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); }); + } + + if (stacked) + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .attr('transform', function(d,i) { + return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')' + }) + .select('rect') + .attr('width', function(d,i) { + return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) || 0 + }) + .attr('height', x.rangeBand() ); + else + bars.watchTransition(renderWatch, 'multibarhorizontal: bars') + .attr('transform', function(d,i) { + //TODO: stacked must be all positive or all negative, not both? + return 'translate(' + + (getY(d,i) < 0 ? y(getY(d,i)) : y(0)) + + ',' + + (d.series * x.rangeBand() / data.length + + + x(getX(d,i)) ) + + ')' + }) + .select('rect') + .attr('height', x.rangeBand() / data.length ) + .attr('width', function(d,i) { + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0 + }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('multibarHorizontal immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + yErr: {get: function(){return getYerr;}, set: function(_){getYerr=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + stacked: {get: function(){return stacked;}, set: function(_){stacked=_;}}, + showValues: {get: function(){return showValues;}, set: function(_){showValues=_;}}, + // this shows the group name, seems pointless? + //showBarLabels: {get: function(){return showBarLabels;}, set: function(_){showBarLabels=_;}}, + disabled: {get: function(){return disabled;}, set: function(_){disabled=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}}, + groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + barColor: {get: function(){return barColor;}, set: function(_){ + barColor = _ ? nv.utils.getColor(_) : null; + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.multiBarHorizontalChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var multibar = nv.models.multiBarHorizontal() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend().height(30) + , controls = nv.models.legend().height(30) + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , controlLabels = {} + , showLegend = true + , showXAxis = true + , showYAxis = true + , stacked = false + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , state = nv.utils.state() + , defaultState = null + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + , controlWidth = function() { return showControls ? 180 : 0 } + , duration = 250 + ; + + state.stacked = false; // DEPRECATED Maintained for backward compatibility + + multibar.stacked(stacked); + + xAxis + .orient('left') + .tickPadding(5) + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient('bottom') + .tickFormat(d3.format(',.1f')) + ; + + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + stacked: stacked + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.stacked !== undefined) + stacked = state.stacked; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(multibar); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.transition().duration(duration).call(chart) }; + chart.container = this; + + stacked = multibar.stacked(); + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = multibar.xScale(); + y = multibar.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + + // Legend + if (showLegend) { + legend.width(availableWidth - controlWidth()); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { key: controlLabels.grouped || 'Grouped', disabled: multibar.stacked() }, + { key: controlLabels.stacked || 'Stacked', disabled: !multibar.stacked() } + ]; + + controls.width(controlWidth()).color(['#444', '#444', '#444']); + g.select('.nv-controlsWrap') + .datum(controlsData) + .attr('transform', 'translate(0,' + (-margin.top) +')') + .call(controls); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + multibar + .disabled(data.map(function(series) { return series.disabled })) + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })); + + barsWrap.transition().call(multibar); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksY(availableHeight/24, data) ) + .tickSize(-availableWidth, 0); + + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + + xTicks + .selectAll('line, text'); + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight, 0); + + g.select('.nv-y.nv-axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1", y(0)) + .attr("x2", y(0)) + .attr("y1", 0) + .attr("y2", -availableHeight) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + switch (d.key) { + case 'Grouped': + case controlLabels.grouped: + multibar.stacked(false); + break; + case 'Stacked': + case controlLabels.stacked: + multibar.stacked(true); + break; + } + + state.stacked = multibar.stacked(); + dispatch.stateChange(state); + stacked = multibar.stacked(); + + chart.update(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.stacked !== 'undefined') { + multibar.stacked(e.stacked); + state.stacked = e.stacked; + stacked = e.stacked; + } + + chart.update(); + }); + }); + renderWatch.renderEnd('multibar horizontal chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.multibar = multibar; + chart.legend = legend; + chart.controls = controls; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.state = state; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + multibar.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) + }} + }); + + nv.utils.inheritOptions(chart, multibar); + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.multiChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 30, right: 20, bottom: 50, left: 60}, + color = nv.utils.defaultColor(), + width = null, + height = null, + showLegend = true, + noData = null, + yDomain1, + yDomain2, + getX = function(d) { return d.x }, + getY = function(d) { return d.y}, + interpolate = 'monotone', + useVoronoi = true, + interactiveLayer = nv.interactiveGuideline(), + useInteractiveGuideline = false, + legendRightAxisHint = ' (right axis)' + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x = d3.scale.linear(), + yScale1 = d3.scale.linear(), + yScale2 = d3.scale.linear(), + + lines1 = nv.models.line().yScale(yScale1), + lines2 = nv.models.line().yScale(yScale2), + + scatters1 = nv.models.scatter().yScale(yScale1), + scatters2 = nv.models.scatter().yScale(yScale2), + + bars1 = nv.models.multiBar().stacked(false).yScale(yScale1), + bars2 = nv.models.multiBar().stacked(false).yScale(yScale2), + + stack1 = nv.models.stackedArea().yScale(yScale1), + stack2 = nv.models.stackedArea().yScale(yScale2), + + xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5), + yAxis1 = nv.models.axis().scale(yScale1).orient('left'), + yAxis2 = nv.models.axis().scale(yScale2).orient('right'), + + legend = nv.models.legend().height(30), + tooltip = nv.models.tooltip(), + dispatch = d3.dispatch(); + + var charts = [lines1, lines2, scatters1, scatters2, bars1, bars2, stack1, stack2]; + + function chart(selection) { + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + + chart.update = function() { container.transition().call(chart); }; + chart.container = this; + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1}); + var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2}); + var dataScatters1 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 1}); + var dataScatters2 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 2}); + var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1}); + var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2}); + var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1}); + var dataStack2 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 2}); + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1}) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d), y: getY(d) } + }) + }); + + var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2}) + .map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d), y: getY(d) } + }) + }); + + x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return getX(d) })) + .range([0, availableWidth]); + + var wrap = container.selectAll('g.wrap.multiChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y1 nv-axis'); + gEnter.append('g').attr('class', 'nv-y2 nv-axis'); + gEnter.append('g').attr('class', 'stack1Wrap'); + gEnter.append('g').attr('class', 'stack2Wrap'); + gEnter.append('g').attr('class', 'bars1Wrap'); + gEnter.append('g').attr('class', 'bars2Wrap'); + gEnter.append('g').attr('class', 'scatters1Wrap'); + gEnter.append('g').attr('class', 'scatters2Wrap'); + gEnter.append('g').attr('class', 'lines1Wrap'); + gEnter.append('g').attr('class', 'lines2Wrap'); + gEnter.append('g').attr('class', 'legendWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + var g = wrap.select('g'); + + var color_array = data.map(function(d,i) { + return data[i].color || color(d, i); + }); + + if (showLegend) { + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); + legend.color(color_array); + + g.select('.legendWrap') + .datum(data.map(function(series) { + series.originalKey = series.originalKey === undefined ? series.key : series.originalKey; + series.key = series.originalKey + (series.yAxis == 1 ? '' : legendRightAxisHint); + return series; + })) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.legendWrap') + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); + } + + lines1 + .width(availableWidth) + .height(availableHeight) + .interpolate(interpolate) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'})); + lines2 + .width(availableWidth) + .height(availableHeight) + .interpolate(interpolate) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'})); + scatters1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'scatter'})); + scatters2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'scatter'})); + bars1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'})); + bars2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'})); + stack1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'})); + stack2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'})); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var lines1Wrap = g.select('.lines1Wrap') + .datum(dataLines1.filter(function(d){return !d.disabled})); + var scatters1Wrap = g.select('.scatters1Wrap') + .datum(dataScatters1.filter(function(d){return !d.disabled})); + var bars1Wrap = g.select('.bars1Wrap') + .datum(dataBars1.filter(function(d){return !d.disabled})); + var stack1Wrap = g.select('.stack1Wrap') + .datum(dataStack1.filter(function(d){return !d.disabled})); + var lines2Wrap = g.select('.lines2Wrap') + .datum(dataLines2.filter(function(d){return !d.disabled})); + var scatters2Wrap = g.select('.scatters2Wrap') + .datum(dataScatters2.filter(function(d){return !d.disabled})); + var bars2Wrap = g.select('.bars2Wrap') + .datum(dataBars2.filter(function(d){return !d.disabled})); + var stack2Wrap = g.select('.stack2Wrap') + .datum(dataStack2.filter(function(d){return !d.disabled})); + + var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){ + return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) + }).concat([{x:0, y:0}]) : []; + var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){ + return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) + }).concat([{x:0, y:0}]) : []; + + yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } )) + .range([0, availableHeight]); + + yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } )) + .range([0, availableHeight]); + + lines1.yDomain(yScale1.domain()); + scatters1.yDomain(yScale1.domain()); + bars1.yDomain(yScale1.domain()); + stack1.yDomain(yScale1.domain()); + + lines2.yDomain(yScale2.domain()); + scatters2.yDomain(yScale2.domain()); + bars2.yDomain(yScale2.domain()); + stack2.yDomain(yScale2.domain()); + + if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);} + if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);} + + if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);} + if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);} + + if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);} + if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);} + + if(dataScatters1.length){d3.transition(scatters1Wrap).call(scatters1);} + if(dataScatters2.length){d3.transition(scatters2Wrap).call(scatters2);} + + xAxis + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + d3.transition(g.select('.nv-x.nv-axis')) + .call(xAxis); + + yAxis1 + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + + d3.transition(g.select('.nv-y1.nv-axis')) + .call(yAxis1); + + yAxis2 + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + d3.transition(g.select('.nv-y2.nv-axis')) + .call(yAxis2); + + g.select('.nv-y1.nv-axis') + .classed('nv-disabled', series1.length ? false : true) + .attr('transform', 'translate(' + x.range()[0] + ',0)'); + + g.select('.nv-y2.nv-axis') + .classed('nv-disabled', series2.length ? false : true) + .attr('transform', 'translate(' + x.range()[1] + ',0)'); + + legend.dispatch.on('stateChange', function(newState) { + chart.update(); + }); + + if(useInteractiveGuideline){ + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + //============================================================ + // Event Handling/Dispatching + //------------------------------------------------------------ + + function mouseover_line(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } + + function mouseover_scatter(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } + + function mouseover_stack(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.point['x'] = stack1.x()(evt.point); + evt.point['y'] = stack1.y()(evt.point); + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } + + function mouseover_bar(evt) { + var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1; + + evt.value = bars1.x()(evt.data); + evt['series'] = { + value: bars1.y()(evt.data), + color: evt.color, + key: evt.data.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } + + + + function clearHighlights() { + for(var i=0, il=charts.length; i < il; i++){ + var chart = charts[i]; + try { + chart.clearHighlights(); + } catch(e){} + } + } + + function highlightPoint(serieIndex, pointIndex, b){ + for(var i=0, il=charts.length; i < il; i++){ + var chart = charts[i]; + try { + chart.highlightPoint(serieIndex, pointIndex, b); + } catch(e){} + } + } + + if(useInteractiveGuideline){ + interactiveLayer.dispatch.on('elementMousemove', function(e) { + clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + var extent = x.domain(); + var currentValues = series.values.filter(function(d,i) { + return chart.x()(d,i) >= extent[0] && chart.x()(d,i) <= extent[1]; + }); + + pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, chart.x()); + var point = currentValues[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue !== null) { + highlightPoint(i, pointIndex, true); + } + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = x(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: pointYValue, + color: color(series,series.seriesIndex), + data: point, + yAxis: series.yAxis == 2 ? yAxis2 : yAxis1 + }); + }); + + interactiveLayer.tooltip + .chartContainer(chart.container.parentNode) + .valueFormatter(function(d,i) { + var yAxis = allData[i].yAxis; + return d === null ? "N/A" : yAxis.tickFormat()(d); + }) + .data({ + value: chart.x()( singlePoint,pointIndex ), + index: pointIndex, + series: allData + })(); + + interactiveLayer.renderGuideLine(pointXLocation); + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + clearHighlights(); + }); + } else { + lines1.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines2.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + lines2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + scatters1.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters2.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + scatters2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + stack2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar); + bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar); + + bars1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars1.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + bars2.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + } + }); + + return chart; + } + + //============================================================ + // Global getters and setters + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.legend = legend; + chart.lines1 = lines1; + chart.lines2 = lines2; + chart.scatters1 = scatters1; + chart.scatters2 = scatters2; + chart.bars1 = bars1; + chart.bars2 = bars2; + chart.stack1 = stack1; + chart.stack2 = stack2; + chart.xAxis = xAxis; + chart.yAxis1 = yAxis1; + chart.yAxis2 = yAxis2; + chart.tooltip = tooltip; + chart.interactiveLayer = interactiveLayer; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}}, + yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + legendRightAxisHint: {get: function(){return legendRightAxisHint;}, set: function(_){legendRightAxisHint=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + x: {get: function(){return getX;}, set: function(_){ + getX = _; + lines1.x(_); + lines2.x(_); + scatters1.x(_); + scatters2.x(_); + bars1.x(_); + bars2.x(_); + stack1.x(_); + stack2.x(_); + }}, + y: {get: function(){return getY;}, set: function(_){ + getY = _; + lines1.y(_); + lines2.y(_); + scatters1.y(_); + scatters2.y(_); + stack1.y(_); + stack2.y(_); + bars1.y(_); + bars2.y(_); + }}, + useVoronoi: {get: function(){return useVoronoi;}, set: function(_){ + useVoronoi=_; + lines1.useVoronoi(_); + lines2.useVoronoi(_); + stack1.useVoronoi(_); + stack2.useVoronoi(_); + }}, + + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (useInteractiveGuideline) { + lines1.interactive(false); + lines1.useVoronoi(false); + lines2.interactive(false); + lines2.useVoronoi(false); + stack1.interactive(false); + stack1.useVoronoi(false); + stack2.interactive(false); + stack2.useVoronoi(false); + scatters1.interactive(false); + scatters2.interactive(false); + } + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.ohlcBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getOpen = function(d) { return d.open } + , getClose = function(d) { return d.close } + , getHigh = function(d) { return d.high } + , getLow = function(d) { return d.low } + , forceX = [] + , forceY = [] + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , clipEdge = true + , color = nv.utils.defaultColor() + , interactive = false + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + // ohlc bar width. + var w = (availableWidth / data[0].values.length) * .9; + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]); + + y.domain(yDomain || [ + d3.min(data[0].values.map(getLow).concat(forceY)), + d3.max(data[0].values.map(getHigh).concat(forceY)) + ] + ).range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-ticks'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick') + .data(function(d) { return d }); + ticks.exit().remove(); + + ticks.enter().append('path') + .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i }) + .attr('d', function(d,i) { + return 'm0,0l0,' + + (y(getOpen(d,i)) + - y(getHigh(d,i))) + + 'l' + + (-w/2) + + ',0l' + + (w/2) + + ',0l0,' + + (y(getLow(d,i)) - y(getOpen(d,i))) + + 'l0,' + + (y(getClose(d,i)) + - y(getLow(d,i))) + + 'l' + + (w/2) + + ',0l' + + (-w/2) + + ',0z'; + }) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; }) + .attr('fill', function(d,i) { return color[0]; }) + .attr('stroke', function(d,i) { return color[0]; }) + .attr('x', 0 ) + .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) }) + .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) }); + + // the bar colors are controlled by CSS currently + ticks.attr('class', function(d,i,j) { + return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i; + }); + + d3.transition(ticks) + .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; }) + .attr('d', function(d,i) { + var w = (availableWidth / data[0].values.length) * .9; + return 'm0,0l0,' + + (y(getOpen(d,i)) + - y(getHigh(d,i))) + + 'l' + + (-w/2) + + ',0l' + + (w/2) + + ',0l0,' + + (y(getLow(d,i)) + - y(getOpen(d,i))) + + 'l0,' + + (y(getClose(d,i)) + - y(getLow(d,i))) + + 'l' + + (w/2) + + ',0l' + + (-w/2) + + ',0z'; + }); + }); + + return chart; + } + + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + chart.clearHighlights(); + container.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + container.select(".nv-ohlcBar .nv-tick.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}}, + close: {get: function(){return getClose();}, set: function(_){getClose=_;}}, + high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}}, + low: {get: function(){return getLow;}, set: function(_){getLow=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +// Code adapted from Jason Davies' "Parallel Coordinates" +// http://bl.ocks.org/jasondavies/1341281 +nv.models.parallelCoordinates = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 30, right: 0, bottom: 10, left: 0} + , width = null + , height = null + , x = d3.scale.ordinal() + , y = {} + , dimensionData = [] + , enabledDimensions = [] + , dimensionNames = [] + , displayBrush = true + , color = nv.utils.defaultColor() + , filters = [] + , active = [] + , dragging = [] + , axisWithUndefinedValues = [] + , lineTension = 1 + , foreground + , background + , dimensions + , line = d3.svg.line() + , axis = d3.svg.axis() + , dispatch = d3.dispatch('brushstart', 'brush', 'brushEnd', 'dimensionsOrder', "stateChange", 'elementClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd', 'activeChanged') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + + //Convert old data to new format (name, values) + if (data[0].values === undefined) { + var newData = []; + data.forEach(function (d) { + var val = {}; + var key = Object.keys(d); + key.forEach(function (k) { if (k !== "name") val[k] = d[k] }); + newData.push({ key: d.name, values: val }); + }); + data = newData; + } + + var dataValues = data.map(function (d) {return d.values}); + if (active.length === 0) { + active = data; + }; //set all active before first brush call + + dimensionNames = dimensionData.sort(function (a, b) { return a.currentPosition - b.currentPosition; }).map(function (d) { return d.key }); + enabledDimensions = dimensionData.filter(function (d) { return !d.disabled; }); + + + // Setup Scales + x.rangePoints([0, availableWidth], 1).domain(enabledDimensions.map(function (d) { return d.key; })); + + //Set as true if all values on an axis are missing. + // Extract the list of dimensions and create a scale for each. + var oldDomainMaxValue = {}; + var displayMissingValuesline = false; + + dimensionNames.forEach(function(d) { + var extent = d3.extent(dataValues, function (p) { return +p[d]; }); + var min = extent[0]; + var max = extent[1]; + var onlyUndefinedValues = false; + //If there is no values to display on an axis, set the extent to 0 + if (isNaN(min) || isNaN(max)) { + onlyUndefinedValues = true; + min = 0; + max = 0; + } + //Scale axis if there is only one value + if (min === max) { + min = min - 1; + max = max + 1; + } + var f = filters.filter(function (k) { return k.dimension == d; }); + if (f.length !== 0) { + //If there is only NaN values, keep the existing domain. + if (onlyUndefinedValues) { + min = y[d].domain()[0]; + max = y[d].domain()[1]; + } + //If the brush extent is > max (< min), keep the extent value. + else if (!f[0].hasOnlyNaN && displayBrush) { + min = min > f[0].extent[0] ? f[0].extent[0] : min; + max = max < f[0].extent[1] ? f[0].extent[1] : max; + } + //If there is NaN values brushed be sure the brush extent is on the domain. + else if (f[0].hasNaN) { + max = max < f[0].extent[1] ? f[0].extent[1] : max; + oldDomainMaxValue[d] = y[d].domain()[1]; + displayMissingValuesline = true; + } + } + //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display "undefined values" text. + //The remaining 10% are used to display the missingValue line. + y[d] = d3.scale.linear() + .domain([min, max]) + .range([(availableHeight - 12) * 0.9, 0]); + + axisWithUndefinedValues = []; + + y[d].brush = d3.svg.brush().y(y[d]).on('brushstart', brushstart).on('brush', brush).on('brushend', brushend); + }); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinates').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinates'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-parallelCoordinates background'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + line.interpolate('cardinal').tension(lineTension); + axis.orient('left'); + var axisDrag = d3.behavior.drag() + .on('dragstart', dragStart) + .on('drag', dragMove) + .on('dragend', dragEnd); + + //Add missing value line at the bottom of the chart + var missingValuesline, missingValueslineText; + var step = x.range()[1] - x.range()[0]; + if (!isNaN(step)) { + var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12]; + missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]); + missingValuesline.enter().append('line'); + missingValuesline.exit().remove(); + missingValuesline.attr("x1", function(d) { return d[0]; }) + .attr("y1", function(d) { return d[1]; }) + .attr("x2", function(d) { return d[2]; }) + .attr("y2", function(d) { return d[3]; }); + + //Add the text "undefined values" under the missing value line + missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data(["undefined values"]); + missingValueslineText.append('text').data(["undefined values"]); + missingValueslineText.enter().append('text'); + missingValueslineText.exit().remove(); + missingValueslineText.attr("y", availableHeight) + //To have the text right align with the missingValues line, substract 92 representing the text size. + .attr("x", availableWidth - 92 - step / 2) + .text(function(d) { return d; }); + } + // Add grey background lines for context. + background = wrap.select('.background').selectAll('path').data(data); + background.enter().append('path'); + background.exit().remove(); + background.attr('d', path); + + // Add blue foreground lines for focus. + foreground = wrap.select('.foreground').selectAll('path').data(data); + foreground.enter().append('path') + foreground.exit().remove(); + foreground.attr('d', path) + .style("stroke-width", function (d, i) { + if (isNaN(d.strokeWidth)) { d.strokeWidth = 1;} return d.strokeWidth;}) + .attr('stroke', function (d, i) { return d.color || color(d, i); }); + foreground.on("mouseover", function (d, i) { + d3.select(this).classed('hover', true).style("stroke-width", d.strokeWidth + 2 + "px").style("stroke-opacity", 1); + dispatch.elementMouseover({ + label: d.name, + color: d.color || color(d, i) + }); + + }); + foreground.on("mouseout", function (d, i) { + d3.select(this).classed('hover', false).style("stroke-width", d.strokeWidth + "px").style("stroke-opacity", 0.7); + dispatch.elementMouseout({ + label: d.name, + index: i + }); + }); + foreground.on('mousemove', function (d, i) { + dispatch.elementMousemove(); + }); + foreground.on('click', function (d) { + dispatch.elementClick({ + id: d.id + }); + }); + // Add a group element for each dimension. + dimensions = g.selectAll('.dimension').data(enabledDimensions); + var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension'); + + dimensions.attr('transform', function(d) { return 'translate(' + x(d.key) + ',0)'; }); + dimensionsEnter.append('g').attr('class', 'nv-axis'); + + // Add an axis and title. + dimensionsEnter.append('text') + .attr('class', 'nv-label') + .style("cursor", "move") + .attr('dy', '-1em') + .attr('text-anchor', 'middle') + .on("mouseover", function(d, i) { + dispatch.elementMouseover({ + label: d.tooltip || d.key + }); + }) + .on("mouseout", function(d, i) { + dispatch.elementMouseout({ + label: d.tooltip + }); + }) + .on('mousemove', function (d, i) { + dispatch.elementMousemove(); + }) + .call(axisDrag); + + dimensionsEnter.append('g').attr('class', 'nv-brushBackground'); + dimensions.exit().remove(); + dimensions.select('.nv-label').text(function (d) { return d.key }); + dimensions.select('.nv-axis') + .each(function (d, i) { + d3.select(this).call(axis.scale(y[d.key]).tickFormat(d3.format(d.format))); + }); + + // Add and store a brush for each axis. + restoreBrush(displayBrush); + + var actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); }), + extents = actives.map(function (p) { return y[p].brush.extent(); }); + var formerActive = active.slice(0); + + //Restore active values + active = []; + foreground.style("display", function (d) { + var isActive = actives.every(function (p, i) { + if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) { + return true; + } + return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p])); + }); + if (isActive) + active.push(d); + return !isActive ? "none" : null; + + }); + + if (filters.length > 0 || !nv.utils.arrayEquals(active, formerActive)) { + dispatch.activeChanged(active); + } + + // Returns the path for a given data point. + function path(d) { + return line(enabledDimensions.map(function (p) { + //If value if missing, put the value on the missing value line + if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key])) || displayMissingValuesline) { + var domain = y[p.key].domain(); + var range = y[p.key].range(); + var min = domain[0] - (domain[1] - domain[0]) / 9; + + //If it's not already the case, allow brush to select undefined values + if (axisWithUndefinedValues.indexOf(p.key) < 0) { + + var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]); + y[p.key].brush.y(newscale); + axisWithUndefinedValues.push(p.key); + } + if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key]))) { + return [x(p.key), y[p.key](min)]; + } + } + + //If parallelCoordinate contain missing values show the missing values line otherwise, hide it. + if (missingValuesline !== undefined) { + if (axisWithUndefinedValues.length > 0 || displayMissingValuesline) { + missingValuesline.style("display", "inline"); + missingValueslineText.style("display", "inline"); + } else { + missingValuesline.style("display", "none"); + missingValueslineText.style("display", "none"); + } + } + return [x(p.key), y[p.key](d.values[p.key])]; + })); + } + + function restoreBrush(visible) { + filters.forEach(function (f) { + //If filter brushed NaN values, keep the brush on the bottom of the axis. + var brushDomain = y[f.dimension].brush.y().domain(); + if (f.hasOnlyNaN) { + f.extent[1] = (y[f.dimension].domain()[1] - brushDomain[0]) * (f.extent[1] - f.extent[0]) / (oldDomainMaxValue[f.dimension] - f.extent[0]) + brushDomain[0]; + } + if (f.hasNaN) { + f.extent[0] = brushDomain[0]; + } + if (visible) + y[f.dimension].brush.extent(f.extent); + }); + + dimensions.select('.nv-brushBackground') + .each(function (d) { + d3.select(this).call(y[d.key].brush); + + }) + .selectAll('rect') + .attr('x', -8) + .attr('width', 16); + } + + // Handles a brush event, toggling the display of foreground lines. + function brushstart() { + //If brush aren't visible, show it before brushing again. + if (displayBrush === false) { + restoreBrush(true); + } + } + + // Handles a brush event, toggling the display of foreground lines. + function brush() { + actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); }), + extents = actives.map(function(p) { return y[p].brush.extent(); }); + + filters = []; //erase current filters + actives.forEach(function(d,i) { + filters[i] = { + dimension: d, + extent: extents[i], + hasNaN: false, + hasOnlyNaN: false + } + }); + + active = []; //erase current active list + foreground.style('display', function(d) { + var isActive = actives.every(function(p, i) { + if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) return true; + return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p])); + }); + if (isActive) active.push(d); + return isActive ? null : 'none'; + }); + + dispatch.brush({ + filters: filters, + active: active + }); + } + function brushend() { + var hasActiveBrush = actives.length > 0 ? true : false; + filters.forEach(function (f) { + if (f.extent[0] === y[f.dimension].brush.y().domain()[0] && axisWithUndefinedValues.indexOf(f.dimension) >= 0) + f.hasNaN = true; + if (f.extent[1] < y[f.dimension].domain()[0]) + f.hasOnlyNaN = true; + }); + dispatch.brushEnd(active, hasActiveBrush); + } + function dragStart(d) { + dragging[d.key] = this.parentNode.__origin__ = x(d.key); + background.attr("visibility", "hidden"); + + } + + function dragMove(d) { + dragging[d.key] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x)); + foreground.attr("d", path); + enabledDimensions.sort(function (a, b) { return dimensionPosition(a.key) - dimensionPosition(b.key); }); + enabledDimensions.forEach(function (d, i) { return d.currentPosition = i; }); + x.domain(enabledDimensions.map(function (d) { return d.key; })); + dimensions.attr("transform", function(d) { return "translate(" + dimensionPosition(d.key) + ")"; }); + } + + function dragEnd(d, i) { + delete this.parentNode.__origin__; + delete dragging[d.key]; + d3.select(this.parentNode).attr("transform", "translate(" + x(d.key) + ")"); + foreground + .attr("d", path); + background + .attr("d", path) + .attr("visibility", null); + + dispatch.dimensionsOrder(enabledDimensions); + } + function resetBrush() { + filters = []; + active = []; + dispatch.stateChange(); + } + function resetDrag() { + dimensionName.map(function (d, i) { return d.currentPosition = d.originalPosition; }); + dispatch.stateChange(); + } + + function dimensionPosition(d) { + var v = dragging[d]; + return v == null ? x(d) : v; + } + }); + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width= _;}}, + height: {get: function(){return height;}, set: function(_){height= _;}}, + dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } }, + displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } }, + filters: { get: function () { return filters; }, set: function (_) { filters = _; } }, + active: { get: function () { return active; }, set: function (_) { active = _; } }, + lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}}, + + // deprecated options + dimensions: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensions', 'use dimensionData instead'); + if (dimensionData.length === 0) { + _.forEach(function (k) { dimensionData.push({ key: k }) }) + } else { + _.forEach(function (k, i) { dimensionData[i].key= k }) + } + } + }, + dimensionNames: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensionNames', 'use dimensionData instead'); + dimensionNames = []; + if (dimensionData.length === 0) { + _.forEach(function (k) { dimensionData.push({ key: k }) }) + } else { + _.forEach(function (k, i) { dimensionData[i].key = k }) + } + + }}, + dimensionFormats: {get: function () { return dimensionData.map(function (d) { return d.format }); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensionFormats', 'use dimensionData instead'); + if (dimensionData.length === 0) { + _.forEach(function (f) { dimensionData.push({ format: f }) }) + } else { + _.forEach(function (f, i) { dimensionData[i].format = f }) + } + + }}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.parallelCoordinatesChart = function () { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var parallelCoordinates = nv.models.parallelCoordinates() + var legend = nv.models.legend() + var tooltip = nv.models.tooltip(); + var dimensionTooltip = nv.models.tooltip(); + + var margin = { top: 0, right: 0, bottom: 0, left: 0 } + , width = null + , height = null + , showLegend = true + , color = nv.utils.defaultColor() + , state = nv.utils.state() + , dimensionData = [] + , dimensionNames = [] + , displayBrush = true + , defaultState = null + , noData = null + , dispatch = d3.dispatch('dimensionsOrder', 'brushEnd', 'stateChange', 'changeState', 'renderEnd') + , controlWidth = function () { return showControls ? 180 : 0 } + ; + + //============================================================ + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + var stateGetter = function(data) { + return function() { + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if(state.active !== undefined) { + data.forEach(function(series, i) { + series.disabled = !state.active[i]; + }); + } + } + }; + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(parallelCoordinates); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.call(chart); }; + chart.container = this; + + state.setter(stateSetter(dimensionData), chart.update) + .getter(stateGetter(dimensionData)) + .update(); + + //set state.disabled + state.disabled = dimensionData.map(function (d) { return !!d.disabled }); + + //Keep dimensions position in memory + dimensionData = dimensionData.map(function (d) {d.disabled = !!d.disabled; return d}); + dimensionData.forEach(function (d, i) { + d.originalPosition = isNaN(d.originalPosition) ? i : d.originalPosition; + d.currentPosition = isNaN(d.currentPosition) ? i : d.currentPosition; + }); + + var currentDimensions = dimensionNames.map(function (d) { return d.key; }); + var newDimensions = dimensionData.map(function (d) { return d.key; }); + dimensionData.forEach(function (k, i) { + var idx = currentDimensions.indexOf(k.key); + if (idx < 0) { + dimensionNames.splice(i, 0, k); + } else { + var gap = dimensionNames[idx].currentPosition - dimensionNames[idx].originalPosition; + dimensionNames[idx].originalPosition = k.originalPosition; + dimensionNames[idx].currentPosition = k.originalPosition + gap; + } + }); + //Remove old dimensions + dimensionNames = dimensionNames.filter(function (d) { return newDimensions.indexOf(d.key) >= 0; }); + + if (!defaultState) { + var key; + defaultState = {}; + for(key in state) { + if(state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if(!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + //------------------------------------------------------------ + // Setup containers and skeleton of chart + + var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinatesChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinatesChart').append('g'); + + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + g.select("rect") + .attr("width", availableWidth) + .attr("height", (availableHeight > 0) ? availableHeight : 0); + + // Legend + if (showLegend) { + legend.width(availableWidth) + .color(function (d) { return "rgb(188,190,192)"; }); + + g.select('.nv-legendWrap') + .datum(dimensionNames.sort(function (a, b) { return a.originalPosition - b.originalPosition; })) + .call(legend); + + if (margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + wrap.select('.nv-legendWrap') + .attr('transform', 'translate( 0 ,' + (-margin.top) + ')'); + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + + + + // Main Chart Component(s) + parallelCoordinates + .width(availableWidth) + .height(availableHeight) + .dimensionData(dimensionNames) + .displayBrush(displayBrush); + + var parallelCoordinatesWrap = g.select('.nv-parallelCoordinatesWrap ') + .datum(data); + + parallelCoordinatesWrap.transition().call(parallelCoordinates); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + //Display reset brush button + parallelCoordinates.dispatch.on('brushEnd', function (active, hasActiveBrush) { + if (hasActiveBrush) { + displayBrush = true; + dispatch.brushEnd(active); + } else { + + displayBrush = false; + } + }); + + legend.dispatch.on('stateChange', function(newState) { + for(var key in newState) { + state[key] = newState[key]; + } + dispatch.stateChange(state); + chart.update(); + }); + + //Update dimensions order and display reset sorting button + parallelCoordinates.dispatch.on('dimensionsOrder', function (e) { + dimensionNames.sort(function (a, b) { return a.currentPosition - b.currentPosition; }); + var isSorted = false; + dimensionNames.forEach(function (d, i) { + d.currentPosition = i; + if (d.currentPosition !== d.originalPosition) + isSorted = true; + }); + dispatch.dimensionsOrder(dimensionNames, isSorted); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function (e) { + + if (typeof e.disabled !== 'undefined') { + dimensionNames.forEach(function (series, i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + }); + + renderWatch.renderEnd('parraleleCoordinateChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + parallelCoordinates.dispatch.on('elementMouseover.tooltip', function (evt) { + evt['series'] = { + key: evt.label, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + parallelCoordinates.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + parallelCoordinates.dispatch.on('elementMousemove.tooltip', function () { + tooltip(); + }); + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.parallelCoordinates = parallelCoordinates; + chart.legend = legend; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: { get: function () { return width; }, set: function (_) { width = _; } }, + height: { get: function () { return height; }, set: function (_) { height = _; } }, + showLegend: { get: function () { return showLegend; }, set: function (_) { showLegend = _; } }, + defaultState: { get: function () { return defaultState; }, set: function (_) { defaultState = _; } }, + dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } }, + displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } }, + noData: { get: function () { return noData; }, set: function (_) { noData = _; } }, + + // options that require extra logic in the setter + margin: { + get: function () { return margin; }, + set: function (_) { + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + } + }, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + parallelCoordinates.color(color); + }} + }); + + nv.utils.inheritOptions(chart, parallelCoordinates); + nv.utils.initOptions(chart); + + return chart; + };nv.models.pie = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 500 + , height = 500 + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , color = nv.utils.defaultColor() + , valueFormat = d3.format(',.2f') + , showLabels = true + , labelsOutside = false + , labelType = "key" + , labelThreshold = .02 //if slice percentage is under this, don't show label + , donut = false + , title = false + , growOnHover = true + , titleOffset = 0 + , labelSunbeamLayout = false + , startAngle = false + , padAngle = false + , endAngle = false + , cornerRadius = 0 + , donutRatio = 0.5 + , arcsRadius = [] + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + ; + + var arcs = []; + var arcsOver = []; + + //============================================================ + // chart function + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right + , availableHeight = height - margin.top - margin.bottom + , radius = Math.min(availableWidth, availableHeight) / 2 + , arcsRadiusOuter = [] + , arcsRadiusInner = [] + ; + + container = d3.select(this) + if (arcsRadius.length === 0) { + var outer = radius - radius / 5; + var inner = donutRatio * radius; + for (var i = 0; i < data[0].length; i++) { + arcsRadiusOuter.push(outer); + arcsRadiusInner.push(inner); + } + } else { + arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; }); + arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; }); + donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); })); + } + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('.nv-wrap.nv-pie').data(data); + var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + var g_pie = gEnter.append('g').attr('class', 'nv-pie'); + gEnter.append('g').attr('class', 'nv-pieLabels'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + + // + container.on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + arcs = []; + arcsOver = []; + for (var i = 0; i < data[0].length; i++) { + + var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]); + var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5); + + if (startAngle !== false) { + arc.startAngle(startAngle); + arcOver.startAngle(startAngle); + } + if (endAngle !== false) { + arc.endAngle(endAngle); + arcOver.endAngle(endAngle); + } + if (donut) { + arc.innerRadius(arcsRadiusInner[i]); + arcOver.innerRadius(arcsRadiusInner[i]); + } + + if (arc.cornerRadius && cornerRadius) { + arc.cornerRadius(cornerRadius); + arcOver.cornerRadius(cornerRadius); + } + + arcs.push(arc); + arcsOver.push(arcOver); + } + + // Setup the Pie chart and choose the data element + var pie = d3.layout.pie() + .sort(null) + .value(function(d) { return d.disabled ? 0 : getY(d) }); + + // padAngle added in d3 3.5 + if (pie.padAngle && padAngle) { + pie.padAngle(padAngle); + } + + // if title is specified and donut, put it in the middle + if (donut && title) { + g_pie.append("text").attr('class', 'nv-pie-title'); + + wrap.select('.nv-pie-title') + .style("text-anchor", "middle") + .text(function (d) { + return title; + }) + .style("font-size", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + "px") + .attr("dy", "0.35em") // trick to vertically center text + .attr('transform', function(d, i) { + return 'translate(0, '+ titleOffset + ')'; + }); + } + + var slices = wrap.select('.nv-pie').selectAll('.nv-slice').data(pie); + var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label').data(pie); + + slices.exit().remove(); + pieLabels.exit().remove(); + + var ae = slices.enter().append('g'); + ae.attr('class', 'nv-slice'); + ae.on('mouseover', function(d, i) { + d3.select(this).classed('hover', true); + if (growOnHover) { + d3.select(this).select("path").transition() + .duration(70) + .attr("d", arcsOver[i]); + } + dispatch.elementMouseover({ + data: d.data, + index: i, + color: d3.select(this).style("fill") + }); + }); + ae.on('mouseout', function(d, i) { + d3.select(this).classed('hover', false); + if (growOnHover) { + d3.select(this).select("path").transition() + .duration(50) + .attr("d", arcs[i]); + } + dispatch.elementMouseout({data: d.data, index: i}); + }); + ae.on('mousemove', function(d, i) { + dispatch.elementMousemove({data: d.data, index: i}); + }); + ae.on('click', function(d, i) { + var element = this; + dispatch.elementClick({ + data: d.data, + index: i, + color: d3.select(this).style("fill"), + event: d3.event, + element: element + }); + }); + ae.on('dblclick', function(d, i) { + dispatch.elementDblClick({ + data: d.data, + index: i, + color: d3.select(this).style("fill") + }); + }); + + slices.attr('fill', function(d,i) { return color(d.data, i); }); + slices.attr('stroke', function(d,i) { return color(d.data, i); }); + + var paths = ae.append('path').each(function(d) { + this._current = d; + }); + + slices.select('path') + .transition() + .attr('d', function (d, i) { return arcs[i](d); }) + .attrTween('d', arcTween); + + if (showLabels) { + // This does the normal label + var labelsArc = []; + for (var i = 0; i < data[0].length; i++) { + labelsArc.push(arcs[i]); + + if (labelsOutside) { + if (donut) { + labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius()); + if (startAngle !== false) labelsArc[i].startAngle(startAngle); + if (endAngle !== false) labelsArc[i].endAngle(endAngle); + } + } else if (!donut) { + labelsArc[i].innerRadius(0); + } + } + + pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) { + var group = d3.select(this); + + group.attr('transform', function (d, i) { + if (labelSunbeamLayout) { + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate + var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { + rotateAngle -= 90; + } else { + rotateAngle += 90; + } + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; + } else { + d.outerRadius = radius + 10; // Set Outer Coordinate + d.innerRadius = radius + 15; // Set Inner Coordinate + return 'translate(' + labelsArc[i].centroid(d) + ')' + } + }); + + group.append('rect') + .style('stroke', '#fff') + .style('fill', '#fff') + .attr("rx", 3) + .attr("ry", 3); + + group.append('text') + .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned + .style('fill', '#000') + }); + + var labelLocationHash = {}; + var avgHeight = 14; + var avgWidth = 140; + var createHashKey = function(coordinates) { + return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight; + }; + var getSlicePercentage = function(d) { + return (d.endAngle - d.startAngle) / (2 * Math.PI); + }; + + pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) { + if (labelSunbeamLayout) { + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate + var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { + rotateAngle -= 90; + } else { + rotateAngle += 90; + } + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; + } else { + d.outerRadius = radius + 10; // Set Outer Coordinate + d.innerRadius = radius + 15; // Set Inner Coordinate + + /* + Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. + Each label location is hashed, and if a hash collision occurs, we assume an overlap. + Adjust the label's y-position to remove the overlap. + */ + var center = labelsArc[i].centroid(d); + var percent = getSlicePercentage(d); + if (d.value && percent >= labelThreshold) { + var hashKey = createHashKey(center); + if (labelLocationHash[hashKey]) { + center[1] -= avgHeight; + } + labelLocationHash[createHashKey(center)] = true; + } + return 'translate(' + center + ')' + } + }); + + pieLabels.select(".nv-label text") + .style('text-anchor', function(d,i) { + //center the text on it's origin or begin/end if orthogonal aligned + return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle'; + }) + .text(function(d, i) { + var percent = getSlicePercentage(d); + var label = ''; + if (!d.value || percent < labelThreshold) return ''; + + if(typeof labelType === 'function') { + label = labelType(d, i, { + 'key': getX(d.data), + 'value': getY(d.data), + 'percent': valueFormat(percent) + }); + } else { + switch (labelType) { + case 'key': + label = getX(d.data); + break; + case 'value': + label = valueFormat(getY(d.data)); + break; + case 'percent': + label = d3.format('%')(percent); + break; + } + } + return label; + }) + ; + } + + + // Computes the angle of an arc, converting from radians to degrees. + function angle(d) { + var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90; + return a > 90 ? a - 180 : a; + } + + function arcTween(a, idx) { + a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle; + a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle; + if (!donut) a.innerRadius = 0; + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function (t) { + return arcs[idx](i(t)); + }; + } + }); + + renderWatch.renderEnd('pie immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } }, + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}}, + title: {get: function(){return title;}, set: function(_){title=_;}}, + titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}}, + labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}}, + valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + endAngle: {get: function(){return endAngle;}, set: function(_){endAngle=_;}}, + startAngle: {get: function(){return startAngle;}, set: function(_){startAngle=_;}}, + padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}}, + cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}}, + donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}}, + labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}}, + labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}}, + donut: {get: function(){return donut;}, set: function(_){donut=_;}}, + growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}}, + + // depreciated after 1.7.1 + pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('pieLabelsOutside', 'use labelsOutside instead'); + }}, + // depreciated after 1.7.1 + donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('donutLabelsOutside', 'use labelsOutside instead'); + }}, + // deprecated after 1.7.1 + labelFormat: {get: function(){ return valueFormat;}, set: function(_) { + valueFormat=_; + nv.deprecated('labelFormat','use valueFormat instead'); + }}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.right = typeof _.right != 'undefined' ? _.right : margin.right; + margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + }}, + y: {get: function(){return getY;}, set: function(_){ + getY=d3.functor(_); + }}, + color: {get: function(){return color;}, set: function(_){ + color=nv.utils.getColor(_); + }}, + labelType: {get: function(){return labelType;}, set: function(_){ + labelType= _ || 'key'; + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.pieChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var pie = nv.models.pie(); + var legend = nv.models.legend(); + var tooltip = nv.models.tooltip(); + + var margin = {top: 30, right: 20, bottom: 20, left: 20} + , width = null + , height = null + , showLegend = true + , legendPosition = "top" + , color = nv.utils.defaultColor() + , state = nv.utils.state() + , defaultState = null + , noData = null + , duration = 250 + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + ; + + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return pie.valueFormat()(d, i); + }); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) { + data.forEach(function (series, i) { + series.disabled = !state.active[i]; + }); + } + } + }; + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(pie); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.transition().call(chart); }; + chart.container = this; + + state.setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + //set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-pieWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + // Legend + if (showLegend) { + if (legendPosition === "top") { + legend.width( availableWidth ).key(pie.x()); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } else if (legendPosition === "right") { + var legendWidth = nv.models.legend().width(); + if (availableWidth / 2 < legendWidth) { + legendWidth = (availableWidth / 2) + } + legend.height(availableHeight).key(pie.x()); + legend.width(legendWidth); + availableWidth -= legend.width(); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend) + .attr('transform', 'translate(' + (availableWidth) +',0)'); + } + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + pie.width(availableWidth).height(availableHeight); + var pieWrap = g.select('.nv-pieWrap').datum([data]); + d3.transition(pieWrap).call(pie); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) { + state[key] = newState[key]; + } + dispatch.stateChange(state); + chart.update(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + }); + + renderWatch.renderEnd('pieChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + pie.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + pie.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + pie.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.legend = legend; + chart.dispatch = dispatch; + chart.pie = pie; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); + + // use Object get/set functionality to map between vars and chart functions + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + + // options that require extra logic in the setter + color: {get: function(){return color;}, set: function(_){ + color = _; + legend.color(color); + pie.color(color); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + nv.utils.inheritOptions(chart, pie); + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.scatter = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , color = nv.utils.defaultColor() // chooses color + , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one + , container = null + , x = d3.scale.linear() + , y = d3.scale.linear() + , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area + , getX = function(d) { return d.x } // accessor to get the x value + , getY = function(d) { return d.y } // accessor to get the y value + , getSize = function(d) { return d.size || 1} // accessor to get the point size + , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape + , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) + , forceY = [] // List of numbers to Force into the Y scale + , forceSize = [] // List of numbers to Force into the Size scale + , interactive = true // If true, plots a voronoi overlay for advanced point intersection + , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding + , clipEdge = false // if true, masks points within x and y scale + , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance + , showVoronoi = false // display the voronoi areas + , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips + , xDomain = null // Override x domain (skips the calculation from data) + , yDomain = null // Override y domain + , xRange = null // Override x range + , yRange = null // Override y range + , sizeDomain = null // Override point size domain + , sizeRange = null + , singlePoint = false + , dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , useVoronoi = true + , duration = 250 + , interactiveUpdateDelay = 300 + ; + + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0, z0 // used to store previous scales + , timeoutID + , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips + , renderWatch = nv.utils.renderWatch(dispatch, duration) + , _sizeRange_def = [16, 256] + ; + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + //add series index to each data point for reference + data.forEach(function(series, i) { + series.values.forEach(function(point) { + point.series = i; + }); + }); + + // Setup Scales + // remap and flatten the data for use in calculating the scales' domains + var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance + d3.merge( + data.map(function(d) { + return d.values.map(function(d,i) { + return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) } + }) + }) + ); + + x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX))) + + if (padData && data[0]) + x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]); + //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [0, availableWidth]); + + if (chart.yScale().name === "o") { + var min = d3.min(seriesData.map(function(d) { if (d.y !== 0) return d.y; })); + y.clamp(true) + .domain(yDomain || d3.extent(seriesData.map(function(d) { + if (d.y !== 0) return d.y; + else return min * 0.1; + }).concat(forceY))) + .range(yRange || [availableHeight, 0]); + } else { + y.domain(yDomain || d3.extent(seriesData.map(function (d) { return d.y;}).concat(forceY))) + .range(yRange || [availableHeight, 0]); + } + + z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize))) + .range(sizeRange || _sizeRange_def); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]; + + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + if ( isNaN(x.domain()[0])) { + x.domain([-1,1]); + } + + if ( isNaN(y.domain()[0])) { + y.domain([-1,1]); + } + + x0 = x0 || x; + y0 = y0 || y; + z0 = z0 || z; + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + wrap.classed('nv-single-point', singlePoint); + gEnter.append('g').attr('class', 'nv-groups'); + gEnter.append('g').attr('class', 'nv-point-paths'); + wrapEnter.append('g').attr('class', 'nv-point-clips'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', (availableHeight > 0) ? availableHeight : 0); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + function updateInteractiveLayer() { + // Always clear needs-update flag regardless of whether or not + // we will actually do anything (avoids needless invocations). + needsUpdate = false; + + if (!interactive) return false; + + // inject series and point index for reference into voronoi + if (useVoronoi === true) { + var vertices = d3.merge(data.map(function(group, groupIndex) { + return group.values + .map(function(point, pointIndex) { + // *Adding noise to make duplicates very unlikely + // *Injecting series and point index for reference + /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. + */ + var pX = getX(point,pointIndex); + var pY = getY(point,pointIndex); + + return [x(pX)+ Math.random() * 1e-4, + y(pY)+ Math.random() * 1e-4, + groupIndex, + pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates + }) + .filter(function(pointArray, pointIndex) { + return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! + }) + }) + ); + + if (vertices.length == 0) return false; // No active points, we're done + if (vertices.length < 3) { + // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work + vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]); + vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]); + vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]); + vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]); + } + + // keep voronoi sections from going more than 10 outside of graph + // to avoid overlap with other things like legend etc + var bounds = d3.geom.polygon([ + [-10,-10], + [-10,height + 10], + [width + 10,height + 10], + [width + 10,-10] + ]); + + var voronoi = d3.geom.voronoi(vertices).map(function(d, i) { + return { + 'data': bounds.clip(d), + 'series': vertices[i][2], + 'point': vertices[i][3] + } + }); + + // nuke all voronoi paths on reload and recreate them + wrap.select('.nv-point-paths').selectAll('path').remove(); + var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi); + var vPointPaths = pointPaths + .enter().append("svg:path") + .attr("d", function(d) { + if (!d || !d.data || d.data.length === 0) + return 'M 0 0'; + else + return "M" + d.data.join(",") + "Z"; + }) + .attr("id", function(d,i) { + return "nv-path-"+i; }) + .attr("clip-path", function(d,i) { return "url(#nv-clip-"+id+"-"+i+")"; }) + ; + + // good for debugging point hover issues + if (showVoronoi) { + vPointPaths.style("fill", d3.rgb(230, 230, 230)) + .style('fill-opacity', 0.4) + .style('stroke-opacity', 1) + .style("stroke", d3.rgb(200,200,200)); + } + + if (clipVoronoi) { + // voronoi sections are already set to clip, + // just create the circles with the IDs they expect + wrap.select('.nv-point-clips').selectAll('*').remove(); // must do * since it has sub-dom + var pointClips = wrap.select('.nv-point-clips').selectAll('clipPath').data(vertices); + var vPointClips = pointClips + .enter().append("svg:clipPath") + .attr("id", function(d, i) { return "nv-clip-"+id+"-"+i;}) + .append("svg:circle") + .attr('cx', function(d) { return d[0]; }) + .attr('cy', function(d) { return d[1]; }) + .attr('r', clipRadius); + } + + var mouseEventCallback = function(d, mDispatch) { + if (needsUpdate) return 0; + var series = data[d.series]; + if (series === undefined) return; + var point = series.values[d.point]; + point['color'] = color(series, d.series); + + // standardize attributes for tooltip. + point['x'] = getX(point); + point['y'] = getY(point); + + // can't just get box of event node since it's actually a voronoi polygon + var box = container.node().getBoundingClientRect(); + var scrollTop = window.pageYOffset || document.documentElement.scrollTop; + var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; + + var pos = { + left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10, + top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10 + }; + + mDispatch({ + point: point, + series: series, + pos: pos, + relativePos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], + seriesIndex: d.series, + pointIndex: d.point + }); + }; + + pointPaths + .on('click', function(d) { + mouseEventCallback(d, dispatch.elementClick); + }) + .on('dblclick', function(d) { + mouseEventCallback(d, dispatch.elementDblClick); + }) + .on('mouseover', function(d) { + mouseEventCallback(d, dispatch.elementMouseover); + }) + .on('mouseout', function(d, i) { + mouseEventCallback(d, dispatch.elementMouseout); + }); + + } else { + // add event handlers to points instead voronoi paths + wrap.select('.nv-groups').selectAll('.nv-group') + .selectAll('.nv-point') + //.data(dataWithPoints) + //.style('pointer-events', 'auto') // recativate events, disabled by css + .on('click', function(d,i) { + //nv.log('test', d, i); + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementClick({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('dblclick', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementDblClick({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('mouseover', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementMouseover({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i, + color: color(d, i) + }); + }) + .on('mouseout', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementMouseout({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i, + color: color(d, i) + }); + }); + } + } + + needsUpdate = true; + var groups = wrap.select('.nv-groups').selectAll('.nv-group') + .data(function(d) { return d }, function(d) { return d.key }); + groups.enter().append('g') + .style('stroke-opacity', 1e-6) + .style('fill-opacity', 1e-6); + groups.exit() + .remove(); + groups + .attr('class', function(d,i) { + return (d.classed || '') + ' nv-group nv-series-' + i; + }) + .classed('hover', function(d) { return d.hover }); + groups.watchTransition(renderWatch, 'scatter: groups') + .style('fill', function(d,i) { return color(d, i) }) + .style('stroke', function(d,i) { return color(d, i) }) + .style('stroke-opacity', 1) + .style('fill-opacity', .5); + + // create the points, maintaining their IDs from the original data set + var points = groups.selectAll('path.nv-point') + .data(function(d) { + return d.values.map( + function (point, pointIndex) { + return [point, pointIndex] + }).filter( + function(pointArray, pointIndex) { + return pointActive(pointArray[0], pointIndex) + }) + }); + points.enter().append('path') + .style('fill', function (d) { return d.color }) + .style('stroke', function (d) { return d.color }) + .attr('transform', function(d) { + return 'translate(' + nv.utils.NaNtoZero(x0(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y0(getY(d[0],d[1]))) + ')' + }) + .attr('d', + nv.utils.symbol() + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) + ); + points.exit().remove(); + groups.exit().selectAll('path.nv-point') + .watchTransition(renderWatch, 'scatter exit') + .attr('transform', function(d) { + return 'translate(' + nv.utils.NaNtoZero(x(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')' + }) + .remove(); + points.each(function(d) { + d3.select(this) + .classed('nv-point', true) + .classed('nv-point-' + d[1], true) + .classed('nv-noninteractive', !interactive) + .classed('hover',false) + ; + }); + points + .watchTransition(renderWatch, 'scatter points') + .attr('transform', function(d) { + //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1]))); + return 'translate(' + nv.utils.NaNtoZero(x(getX(d[0],d[1]))) + ',' + nv.utils.NaNtoZero(y(getY(d[0],d[1]))) + ')' + }) + .attr('d', + nv.utils.symbol() + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) + ); + + // Delay updating the invisible interactive layer for smoother animation + if( interactiveUpdateDelay ) + { + clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer + timeoutID = setTimeout(updateInteractiveLayer, interactiveUpdateDelay ); + } + else + { + updateInteractiveLayer(); + } + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + z0 = z.copy(); + + }); + renderWatch.renderEnd('scatter immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + // utility function calls provided by this chart + chart._calls = new function() { + this.clearHighlights = function () { + nv.dom.write(function() { + container.selectAll(".nv-point.hover").classed("hover", false); + }); + return null; + }; + this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) { + nv.dom.write(function() { + container.select('.nv-groups') + .selectAll(".nv-series-" + seriesIndex) + .selectAll(".nv-point-" + pointIndex) + .classed("hover", isHoverOver); + }); + }; + }; + + // trigger calls from events too + dispatch.on('elementMouseover.point', function(d) { + if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,true); + }); + + dispatch.on('elementMouseout.point', function(d) { + if (interactive) chart._calls.highlightPoint(d.seriesIndex,d.pointIndex,false); + }); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + pointScale: {get: function(){return z;}, set: function(_){z=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + pointDomain: {get: function(){return sizeDomain;}, set: function(_){sizeDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + pointRange: {get: function(){return sizeRange;}, set: function(_){sizeRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + forcePoint: {get: function(){return forceSize;}, set: function(_){forceSize=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + pointActive: {get: function(){return pointActive;}, set: function(_){pointActive=_;}}, + padDataOuter: {get: function(){return padDataOuter;}, set: function(_){padDataOuter=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}}, + clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}}, + showVoronoi: {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactiveUpdateDelay: {get:function(){return interactiveUpdateDelay;}, set: function(_){interactiveUpdateDelay=_;}}, + + + // simple functor options + x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}}, + pointSize: {get: function(){return getSize;}, set: function(_){getSize = d3.functor(_);}}, + pointShape: {get: function(){return getShape;}, set: function(_){getShape = d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + useVoronoi: {get: function(){return useVoronoi;}, set: function(_){ + useVoronoi = _; + if (useVoronoi === false) { + clipVoronoi = false; + } + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.scatterChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var scatter = nv.models.scatter() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , distX = nv.models.distribution() + , distY = nv.models.distribution() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 20, bottom: 50, left: 75} + , width = null + , height = null + , container = null + , color = nv.utils.defaultColor() + , x = scatter.xScale() + , y = scatter.yScale() + , showDistX = false + , showDistY = false + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , state = nv.utils.state() + , defaultState = null + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') + , noData = null + , duration = 250 + ; + + scatter.xScale(x).yScale(y); + xAxis.orient('bottom').tickPadding(10); + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickPadding(10) + ; + distX.axis('x'); + distY.axis('y'); + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0 + , renderWatch = nv.utils.renderWatch(dispatch, duration); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + if (showDistX) renderWatch.models(distX); + if (showDistY) renderWatch.models(distY); + + selection.each(function(data) { + var that = this; + + container = d3.select(this); + nv.utils.initSVG(container); + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disableddisabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display noData message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container); + renderWatch.renderEnd('scatter immediate'); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id()); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + // background for pointer events + gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none"); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + gEnter.append('g').attr('class', 'nv-regressionLinesWrap'); + gEnter.append('g').attr('class', 'nv-distWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Legend + if (showLegend) { + var legendWidth = availableWidth; + legend.width(legendWidth); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0' + ',' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + scatter + .width(availableWidth) + .height(availableHeight) + .color(data.map(function(d,i) { + d.color = d.color || color(d, i); + return d.color; + }).filter(function(d,i) { return !data[i].disabled })); + + wrap.select('.nv-scatterWrap') + .datum(data.filter(function(d) { return !d.disabled })) + .call(scatter); + + + wrap.select('.nv-regressionLinesWrap') + .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')'); + + var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines') + .data(function (d) { + return d; + }); + + regWrap.enter().append('g').attr('class', 'nv-regLines'); + + var regLine = regWrap.selectAll('.nv-regLine') + .data(function (d) { + return [d] + }); + + regLine.enter() + .append('line').attr('class', 'nv-regLine') + .style('stroke-opacity', 0); + + // don't add lines unless we have slope and intercept to use + regLine.filter(function(d) { + return d.intercept && d.slope; + }) + .watchTransition(renderWatch, 'scatterPlusLineChart: regline') + .attr('x1', x.range()[0]) + .attr('x2', x.range()[1]) + .attr('y1', function (d, i) { + return y(x.domain()[0] * d.slope + d.intercept) + }) + .attr('y2', function (d, i) { + return y(x.domain()[1] * d.slope + d.intercept) + }) + .style('stroke', function (d, i, j) { + return color(d, j) + }) + .style('stroke-opacity', function (d, i) { + return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1 + }); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight , 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + y.range()[0] + ')') + .call(xAxis); + } + + if (showYAxis) { + yAxis + .scale(y) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis') + .call(yAxis); + } + + // Setup Distribution + if (showDistX) { + distX + .getData(scatter.x()) + .scale(x) + .width(availableWidth) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + gEnter.select('.nv-distWrap').append('g') + .attr('class', 'nv-distributionX'); + g.select('.nv-distributionX') + .attr('transform', 'translate(0,' + y.range()[0] + ')') + .datum(data.filter(function(d) { return !d.disabled })) + .call(distX); + } + + if (showDistY) { + distY + .getData(scatter.y()) + .scale(y) + .width(availableHeight) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled })); + gEnter.select('.nv-distWrap').append('g') + .attr('class', 'nv-distributionY'); + g.select('.nv-distributionY') + .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)') + .datum(data.filter(function(d) { return !d.disabled })) + .call(distY); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + if (typeof e.disabled !== 'undefined') { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + + // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block + scatter.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', 0); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', distY.size()); + }); + + scatter.dispatch.on('elementMouseover.tooltip', function(evt) { + container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', evt.relativePos[1] - availableHeight); + container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', evt.relativePos[0] + distX.size()); + tooltip.data(evt).hidden(false); + }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + + }); + + renderWatch.renderEnd('scatter with line immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.scatter = scatter; + chart.legend = legend; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.distX = distX; + chart.distY = distY; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + container: {get: function(){return container;}, set: function(_){container=_;}}, + showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}}, + showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + distX.color(color); + distY.color(color); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.sparkline = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 2, right: 0, bottom: 2, left: 0} + , width = 400 + , height = 32 + , container = null + , animate = true + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.getColor(['#000']) + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x .domain(xDomain || d3.extent(data, getX )) + .range(xRange || [0, availableWidth]); + + y .domain(yDomain || d3.extent(data, getY )) + .range(yRange || [availableHeight, 0]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') + + var paths = wrap.selectAll('path') + .data(function(d) { return [d] }); + paths.enter().append('path'); + paths.exit().remove(); + paths + .style('stroke', function(d,i) { return d.color || color(d, i) }) + .attr('d', d3.svg.line() + .x(function(d,i) { return x(getX(d,i)) }) + .y(function(d,i) { return y(getY(d,i)) }) + ); + + // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent) + var points = wrap.selectAll('circle.nv-point') + .data(function(data) { + var yValues = data.map(function(d, i) { return getY(d,i); }); + function pointIndex(index) { + if (index != -1) { + var result = data[index]; + result.pointIndex = index; + return result; + } else { + return null; + } + } + var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])), + minPoint = pointIndex(yValues.indexOf(y.domain()[0])), + currentPoint = pointIndex(yValues.length - 1); + return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;}); + }); + points.enter().append('circle'); + points.exit().remove(); + points + .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) }) + .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) }) + .attr('r', 2) + .attr('class', function(d,i) { + return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' : + getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue' + }); + }); + + renderWatch.renderEnd('sparkline immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + animate: {get: function(){return animate;}, set: function(_){animate=_;}}, + + //functor options + x: {get: function(){return getX;}, set: function(_){getX=d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY=d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + chart.dispatch = dispatch; + nv.utils.initOptions(chart); + return chart; +}; + +nv.models.sparklinePlus = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var sparkline = nv.models.sparkline(); + + var margin = {top: 15, right: 100, bottom: 10, left: 50} + , width = null + , height = null + , x + , y + , index = [] + , paused = false + , xTickFormat = d3.format(',r') + , yTickFormat = d3.format(',.2f') + , showLastValue = true + , alignValue = true + , rightAlignValue = false + , noData = null + , dispatch = d3.dispatch('renderEnd') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(sparkline); + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.call(chart); }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + var currentValue = sparkline.y()(data[data.length-1], data.length-1); + + // Setup Scales + x = sparkline.xScale(); + y = sparkline.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-sparklineWrap'); + gEnter.append('g').attr('class', 'nv-valueWrap'); + gEnter.append('g').attr('class', 'nv-hoverArea'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + var sparklineWrap = g.select('.nv-sparklineWrap'); + + sparkline.width(availableWidth).height(availableHeight); + sparklineWrap.call(sparkline); + + if (showLastValue) { + var valueWrap = g.select('.nv-valueWrap'); + var value = valueWrap.selectAll('.nv-currentValue') + .data([currentValue]); + + value.enter().append('text').attr('class', 'nv-currentValue') + .attr('dx', rightAlignValue ? -8 : 8) + .attr('dy', '.9em') + .style('text-anchor', rightAlignValue ? 'end' : 'start'); + + value + .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) + .attr('y', alignValue ? function (d) { + return y(d) + } : 0) + .style('fill', sparkline.color()(data[data.length - 1], data.length - 1)) + .text(yTickFormat(currentValue)); + } + + gEnter.select('.nv-hoverArea').append('rect') + .on('mousemove', sparklineHover) + .on('click', function() { paused = !paused }) + .on('mouseout', function() { index = []; updateValueLine(); }); + + g.select('.nv-hoverArea rect') + .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' }) + .attr('width', availableWidth + margin.left + margin.right) + .attr('height', availableHeight + margin.top); + + //index is currently global (within the chart), may or may not keep it that way + function updateValueLine() { + if (paused) return; + + var hoverValue = g.selectAll('.nv-hoverValue').data(index); + + var hoverEnter = hoverValue.enter() + .append('g').attr('class', 'nv-hoverValue') + .style('stroke-opacity', 0) + .style('fill-opacity', 0); + + hoverValue.exit() + .transition().duration(250) + .style('stroke-opacity', 0) + .style('fill-opacity', 0) + .remove(); + + hoverValue + .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' }) + .transition().duration(250) + .style('stroke-opacity', 1) + .style('fill-opacity', 1); + + if (!index.length) return; + + hoverEnter.append('line') + .attr('x1', 0) + .attr('y1', -margin.top) + .attr('x2', 0) + .attr('y2', availableHeight); + + hoverEnter.append('text').attr('class', 'nv-xValue') + .attr('x', -6) + .attr('y', -margin.top) + .attr('text-anchor', 'end') + .attr('dy', '.9em'); + + g.select('.nv-hoverValue .nv-xValue') + .text(xTickFormat(sparkline.x()(data[index[0]], index[0]))); + + hoverEnter.append('text').attr('class', 'nv-yValue') + .attr('x', 6) + .attr('y', -margin.top) + .attr('text-anchor', 'start') + .attr('dy', '.9em'); + + g.select('.nv-hoverValue .nv-yValue') + .text(yTickFormat(sparkline.y()(data[index[0]], index[0]))); + } + + function sparklineHover() { + if (paused) return; + + var pos = d3.mouse(this)[0] - margin.left; + + function getClosestIndex(data, x) { + var distance = Math.abs(sparkline.x()(data[0], 0) - x); + var closestIndex = 0; + for (var i = 0; i < data.length; i++){ + if (Math.abs(sparkline.x()(data[i], i) - x) < distance) { + distance = Math.abs(sparkline.x()(data[i], i) - x); + closestIndex = i; + } + } + return closestIndex; + } + + index = [getClosestIndex(data, Math.round(x.invert(pos)))]; + updateValueLine(); + } + + }); + renderWatch.renderEnd('sparklinePlus immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.sparkline = sparkline; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}}, + yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}}, + showLastValue: {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}}, + alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}}, + rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + + nv.utils.inheritOptions(chart, sparkline); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.stackedArea = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , color = nv.utils.defaultColor() // a function that computes the color + , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one + , container = null + , getX = function(d) { return d.x } // accessor to get the x value from a data point + , getY = function(d) { return d.y } // accessor to get the y value from a data point + , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined + , style = 'stack' + , offset = 'zero' + , order = 'default' + , interpolate = 'linear' // controls the line interpolation + , clipEdge = false // if true, masks lines within x and y scale + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , scatter = nv.models.scatter() + , duration = 250 + , dispatch = d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout') + ; + + scatter + .pointSize(2.2) // default size + .pointDomain([2.2, 2.2]) // all the same size by default + ; + + /************************************ + * offset: + * 'wiggle' (stream) + * 'zero' (stacked) + * 'expand' (normalize to 100%) + * 'silhouette' (simple centered) + * + * order: + * 'inside-out' (stream) + * 'default' (input order) + ************************************/ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(scatter); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x = scatter.xScale(); + y = scatter.yScale(); + + var dataRaw = data; + // Injecting point index into each point because d3.layout.stack().out does not give index + data.forEach(function(aseries, i) { + aseries.seriesIndex = i; + aseries.values = aseries.values.map(function(d, j) { + d.index = j; + d.seriesIndex = i; + return d; + }); + }); + + var dataFiltered = data.filter(function(series) { + return !series.disabled; + }); + + data = d3.layout.stack() + .order(order) + .offset(offset) + .values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion + .x(getX) + .y(getY) + .out(function(d, y0, y) { + d.display = { + y: y, + y0: y0 + }; + }) + (dataFiltered); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-areaWrap'); + gEnter.append('g').attr('class', 'nv-scatterWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // If the user has not specified forceY, make sure 0 is included in the domain + // Otherwise, use user-specified values for forceY + if (scatter.forceY().length == 0) { + scatter.forceY().push(0); + } + + scatter + .width(availableWidth) + .height(availableHeight) + .x(getX) + .y(function(d) { + if (d.display !== undefined) { return d.display.y + d.display.y0; } + }) + .forceY([0]) + .color(data.map(function(d,i) { + d.color = d.color || color(d, d.seriesIndex); + return d.color; + })); + + var scatterWrap = g.select('.nv-scatterWrap') + .datum(data); + + scatterWrap.call(scatter); + + defsEnter.append('clipPath') + .attr('id', 'nv-edge-clip-' + id) + .append('rect'); + + wrap.select('#nv-edge-clip-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); + + var area = d3.svg.area() + .defined(defined) + .x(function(d,i) { return x(getX(d,i)) }) + .y0(function(d) { + return y(d.display.y0) + }) + .y1(function(d) { + return y(d.display.y + d.display.y0) + }) + .interpolate(interpolate); + + var zeroArea = d3.svg.area() + .defined(defined) + .x(function(d,i) { return x(getX(d,i)) }) + .y0(function(d) { return y(d.display.y0) }) + .y1(function(d) { return y(d.display.y0) }); + + var path = g.select('.nv-areaWrap').selectAll('path.nv-area') + .data(function(d) { return d }); + + path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i }) + .attr('d', function(d,i){ + return zeroArea(d.values, d.seriesIndex); + }) + .on('mouseover', function(d,i) { + d3.select(this).classed('hover', true); + dispatch.areaMouseover({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.areaMouseout({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }) + .on('click', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.areaClick({ + point: d, + series: d.key, + pos: [d3.event.pageX, d3.event.pageY], + seriesIndex: d.seriesIndex + }); + }); + + path.exit().remove(); + path.style('fill', function(d,i){ + return d.color || color(d, d.seriesIndex) + }) + .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) }); + path.watchTransition(renderWatch,'stackedArea path') + .attr('d', function(d,i) { + return area(d.values,i) + }); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + scatter.dispatch.on('elementMouseover.area', function(e) { + g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true); + }); + scatter.dispatch.on('elementMouseout.area', function(e) { + g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false); + }); + + //Special offset functions + chart.d3_stackedOffset_stackPercent = function(stackData) { + var n = stackData.length, //How many series + m = stackData[0].length, //how many points per series + i, + j, + o, + y0 = []; + + for (j = 0; j < m; ++j) { //Looping through all points + for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series + o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time. + } + + if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0 + stackData[i][j][1] /= o; + } else { //(total y value of all series at point in time i) == 0 + for (i = 0; i < n; i++) { + stackData[i][j][1] = 0; + } + } + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }; + + }); + + renderWatch.renderEnd('stackedArea immediate'); + return chart; + } + + //============================================================ + // Global getters and setters + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.scatter = scatter; + + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); + + chart.interpolate = function(_) { + if (!arguments.length) return interpolate; + interpolate = _; + return chart; + }; + + chart.duration = function(_) { + if (!arguments.length) return duration; + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + return chart; + }; + + chart.dispatch = dispatch; + chart.scatter = scatter; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + defined: {get: function(){return defined;}, set: function(_){defined=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + offset: {get: function(){return offset;}, set: function(_){offset=_;}}, + order: {get: function(){return order;}, set: function(_){order=_;}}, + interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, + + // simple functor options + x: {get: function(){return getX;}, set: function(_){getX = d3.functor(_);}}, + y: {get: function(){return getY;}, set: function(_){getY = d3.functor(_);}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + style: {get: function(){return style;}, set: function(_){ + style = _; + switch (style) { + case 'stack': + chart.offset('zero'); + chart.order('default'); + break; + case 'stream': + chart.offset('wiggle'); + chart.order('inside-out'); + break; + case 'stream-center': + chart.offset('silhouette'); + chart.order('inside-out'); + break; + case 'expand': + chart.offset('expand'); + chart.order('default'); + break; + case 'stack_percent': + chart.offset(chart.d3_stackedOffset_stackPercent); + chart.order('default'); + break; + } + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + scatter.duration(duration); + }} + }); + + nv.utils.inheritOptions(chart, scatter); + nv.utils.initOptions(chart); + + return chart; +}; + +nv.models.stackedAreaChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var stacked = nv.models.stackedArea() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + , legend = nv.models.legend() + , controls = nv.models.legend() + , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() + ; + + var margin = {top: 30, right: 25, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.defaultColor() + , showControls = true + , showLegend = true + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , useInteractiveGuideline = false + , showTotalInTooltip = true + , totalLabel = 'TOTAL' + , x //can be accessed via chart.xScale() + , y //can be accessed via chart.yScale() + , state = nv.utils.state() + , defaultState = null + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + , controlWidth = 250 + , controlOptions = ['Stacked','Stream','Expanded'] + , controlLabels = {} + , duration = 250 + ; + + state.style = stacked.style(); + xAxis.orient('bottom').tickPadding(7); + yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + interactiveLayer.tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + var oldYTickFormat = null, + oldValueFormatter = null; + + controls.updateState(false); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + var style = stacked.style(); + + var stateGetter = function(data) { + return function(){ + return { + active: data.map(function(d) { return !d.disabled }), + style: stacked.style() + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if (state.style !== undefined) + style = state.style; + if (state.active !== undefined) + data.forEach(function(series,i) { + series.disabled = !state.active[i]; + }); + } + }; + + var percentFormatter = d3.format('%'); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(stacked); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.transition().duration(duration).call(chart); }; + chart.container = this; + + state + .setter(stateSetter(data), chart.update) + .getter(stateGetter(data)) + .update(); + + // DEPRECATED set state.disabled + state.disabled = data.map(function(d) { return !!d.disabled }); + + if (!defaultState) { + var key; + defaultState = {}; + for (key in state) { + if (state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = stacked.xScale(); + y = stacked.yScale(); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g'); + var g = wrap.select('g'); + + gEnter.append("rect").style("opacity",0); + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis'); + gEnter.append('g').attr('class', 'nv-stackedWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + gEnter.append('g').attr('class', 'nv-controlsWrap'); + gEnter.append('g').attr('class', 'nv-interactive'); + + g.select("rect").attr("width",availableWidth).attr("height",availableHeight); + + // Legend + if (showLegend) { + var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth; + + legend.width(legendWidth); + g.select('.nv-legendWrap').datum(data).call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.nv-legendWrap') + .attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')'); + } + + // Controls + if (showControls) { + var controlsData = [ + { + key: controlLabels.stacked || 'Stacked', + metaKey: 'Stacked', + disabled: stacked.style() != 'stack', + style: 'stack' + }, + { + key: controlLabels.stream || 'Stream', + metaKey: 'Stream', + disabled: stacked.style() != 'stream', + style: 'stream' + }, + { + key: controlLabels.expanded || 'Expanded', + metaKey: 'Expanded', + disabled: stacked.style() != 'expand', + style: 'expand' + }, + { + key: controlLabels.stack_percent || 'Stack %', + metaKey: 'Stack_Percent', + disabled: stacked.style() != 'stack_percent', + style: 'stack_percent' + } + ]; + + controlWidth = (controlOptions.length/3) * 260; + controlsData = controlsData.filter(function(d) { + return controlOptions.indexOf(d.metaKey) !== -1; + }); + + controls + .width( controlWidth ) + .color(['#444', '#444', '#444']); + + g.select('.nv-controlsWrap') + .datum(controlsData) + .call(controls); + + if ( margin.top != Math.max(controls.height(), legend.height()) ) { + margin.top = Math.max(controls.height(), legend.height()); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + g.select('.nv-controlsWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left: margin.left, top: margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + + stacked + .width(availableWidth) + .height(availableHeight); + + var stackedWrap = g.select('.nv-stackedWrap') + .datum(data); + + stackedWrap.transition().call(stacked); + + // Setup Axes + if (showXAxis) { + xAxis.scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize( -availableHeight, 0); + + g.select('.nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight + ')'); + + g.select('.nv-x.nv-axis') + .transition().duration(0) + .call(xAxis); + } + + if (showYAxis) { + var ticks; + if (stacked.offset() === 'wiggle') { + ticks = 0; + } + else { + ticks = nv.utils.calcTicksY(availableHeight/36, data); + } + yAxis.scale(y) + ._ticks(ticks) + .tickSize(-availableWidth, 0); + + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + var currentFormat = yAxis.tickFormat(); + + if ( !oldYTickFormat || currentFormat !== percentFormatter ) + oldYTickFormat = currentFormat; + + //Forces the yAxis to use percentage in 'expand' mode. + yAxis.tickFormat(percentFormatter); + } + else { + if (oldYTickFormat) { + yAxis.tickFormat(oldYTickFormat); + oldYTickFormat = null; + } + } + + g.select('.nv-y.nv-axis') + .transition().duration(0) + .call(yAxis); + } + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + + stacked.dispatch.on('areaClick.toggle', function(e) { + if (data.filter(function(d) { return !d.disabled }).length === 1) + data.forEach(function(d) { + d.disabled = false; + }); + else + data.forEach(function(d,i) { + d.disabled = (i != e.seriesIndex); + }); + + state.disabled = data.map(function(d) { return !!d.disabled }); + dispatch.stateChange(state); + + chart.update(); + }); + + legend.dispatch.on('stateChange', function(newState) { + for (var key in newState) + state[key] = newState[key]; + dispatch.stateChange(state); + chart.update(); + }); + + controls.dispatch.on('legendClick', function(d,i) { + if (!d.disabled) return; + + controlsData = controlsData.map(function(s) { + s.disabled = true; + return s; + }); + d.disabled = false; + + stacked.style(d.style); + + + state.style = stacked.style(); + dispatch.stateChange(state); + + chart.update(); + }); + + interactiveLayer.dispatch.on('elementMousemove', function(e) { + stacked.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); + var point = series.values[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue != null) { + stacked.highlightPoint(i, pointIndex, true); + } + if (typeof point === 'undefined') return; + if (typeof singlePoint === 'undefined') singlePoint = point; + if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + + //If we are in 'expand' mode, use the stacked percent value instead of raw value. + var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex); + allData.push({ + key: series.key, + value: tooltipValue, + color: color(series,series.seriesIndex), + stackedValue: point.display + }); + + if (showTotalInTooltip && stacked.style() != 'expand') { + valueSum += tooltipValue; + }; + }); + + allData.reverse(); + + //Highlight the tooltip entry based on which stack the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var yDistMax = Infinity, indexToHighlight = null; + allData.forEach(function(series,i) { + + //To handle situation where the stacked area chart is negative, we need to use absolute values + //when checking if the mouse Y value is within the stack area. + yValue = Math.abs(yValue); + var stackedY0 = Math.abs(series.stackedValue.y0); + var stackedY = Math.abs(series.stackedValue.y); + if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0)) + { + indexToHighlight = i; + return; + } + }); + if (indexToHighlight != null) + allData[indexToHighlight].highlight = true; + } + + //If we are not in 'expand' mode, add a 'Total' row to the tooltip. + if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2) { + allData.push({ + key: totalLabel, + value: valueSum, + total: true + }); + } + + var xValue = chart.x()(singlePoint,pointIndex); + + var valueFormatter = interactiveLayer.tooltip.valueFormatter(); + // Keeps track of the tooltip valueFormatter if the chart changes to expanded view + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + if ( !oldValueFormatter ) { + oldValueFormatter = valueFormatter; + } + //Forces the tooltip to use percentage in 'expand' mode. + valueFormatter = d3.format(".1%"); + } + else { + if (oldValueFormatter) { + valueFormatter = oldValueFormatter; + oldValueFormatter = null; + } + } + + interactiveLayer.tooltip + .chartContainer(that.parentNode) + .valueFormatter(valueFormatter) + .data( + { + value: xValue, + series: allData + } + )(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + stacked.clearHighlights(); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function(e) { + + if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { + data.forEach(function(series,i) { + series.disabled = e.disabled[i]; + }); + + state.disabled = e.disabled; + } + + if (typeof e.style !== 'undefined') { + stacked.style(e.style); + style = e.style; + } + + chart.update(); + }); + + }); + + renderWatch.renderEnd('stacked Area chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + stacked.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.point['x'] = stacked.x()(evt.point); + evt.point['y'] = stacked.y()(evt.point); + tooltip.data(evt).hidden(false); + }); + + stacked.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.stacked = stacked; + chart.legend = legend; + chart.controls = controls; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, + controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, + controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}}, + showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}}, + totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + stacked.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + stacked.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = !!_; + chart.interactive(!_); + chart.useVoronoi(!_); + stacked.scatter.interactive(!_); + }} + }); + + nv.utils.inheritOptions(chart, stacked); + nv.utils.initOptions(chart); + + return chart; +}; +// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad +nv.models.sunburst = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , mode = "count" + , modes = {count: function(d) { return 1; }, size: function(d) { return d.size }} + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , color = nv.utils.defaultColor() + , groupColorByParent = true + , duration = 500 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + var x = d3.scale.linear().range([0, 2 * Math.PI]); + var y = d3.scale.sqrt(); + + var partition = d3.layout.partition() + .sort(null) + .value(function(d) { return 1; }); + + var arc = d3.svg.arc() + .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); }) + .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); }) + .innerRadius(function(d) { return Math.max(0, y(d.y)); }) + .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); }); + + // Keep track of the current and previous node being displayed as the root. + var node, prevNode; + // Keep track of the root node + var rootNode; + + //============================================================ + // chart function + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin); + var availableHeight = nv.utils.availableHeight(height, container, margin); + var radius = Math.min(availableWidth, availableHeight) / 2; + var path; + + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('.nv-wrap.nv-sunburst').data(data); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id); + + var g = wrapEnter.selectAll('nv-sunburst'); + + chart.update = function() { + if ( duration === 0 ) { + container.call(chart); + } else { + container.transition().duration(duration).call(chart); + } + }; + chart.container = this; + + + wrap.attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + + container.on('click', function (d, i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + y.range([0, radius]); + + node = node || data; + rootNode = data[0]; + partition.value(modes[mode] || modes["count"]); + path = g.data(partition.nodes).enter() + .append("path") + .attr("d", arc) + .style("fill", function (d) { + if (d.color) { + return d.color; + } + else if (groupColorByParent) { + return color((d.children ? d : d.parent).name); + } + else { + return color(d.name); + } + }) + .style("stroke", "#FFF") + .on("click", function(d) { + if (prevNode !== node && node !== d) prevNode = node; + node = d; + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(d)); + }) + .each(stash) + .on("dblclick", function(d) { + if (prevNode.parent == d) { + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(rootNode)); + } + }) + .each(stash) + .on('mouseover', function(d,i){ + d3.select(this).classed('hover', true).style('opacity', 0.8); + dispatch.elementMouseover({ + data: d, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i){ + d3.select(this).classed('hover', false).style('opacity', 1); + dispatch.elementMouseout({ + data: d + }); + }) + .on('mousemove', function(d,i){ + dispatch.elementMousemove({ + data: d + }); + }); + + + + // Setup for switching data: stash the old values for transition. + function stash(d) { + d.x0 = d.x; + d.dx0 = d.dx; + } + + // When switching data: interpolate the arcs in data space. + function arcTweenData(a, i) { + var oi = d3.interpolate({x: a.x0, dx: a.dx0}, a); + + function tween(t) { + var b = oi(t); + a.x0 = b.x; + a.dx0 = b.dx; + return arc(b); + } + + if (i == 0) { + // If we are on the first arc, adjust the x domain to match the root node + // at the current zoom level. (We only need to do this once.) + var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]); + return function (t) { + x.domain(xd(t)); + return tween(t); + }; + } else { + return tween; + } + } + + // When zooming: interpolate the scales. + function arcTweenZoom(d) { + var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]), + yd = d3.interpolate(y.domain(), [d.y, 1]), + yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]); + return function (d, i) { + return i + ? function (t) { + return arc(d); + } + : function (t) { + x.domain(xd(t)); + y.domain(yd(t)).range(yr(t)); + return arc(d); + }; + }; + } + + }); + + renderWatch.renderEnd('sunburst immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + mode: {get: function(){return mode;}, set: function(_){mode=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + groupColorByParent: {get: function(){return groupColorByParent;}, set: function(_){groupColorByParent=!!_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color=nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.sunburstChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var sunburst = nv.models.sunburst(); + var tooltip = nv.models.tooltip(); + + var margin = {top: 30, right: 20, bottom: 20, left: 20} + , width = null + , height = null + , color = nv.utils.defaultColor() + , id = Math.round(Math.random() * 100000) + , defaultState = null + , noData = null + , duration = 250 + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + tooltip + .headerEnabled(false) + .valueFormatter(function(d, i) { + return d; + }); + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(sunburst); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) { + container.call(chart); + } else { + container.transition().duration(duration).call(chart); + } + }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sunburstChart').data(data); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburstChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-sunburstWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + sunburst.width(availableWidth).height(availableHeight); + var sunWrap = g.select('.nv-sunburstWrap').datum(data); + d3.transition(sunWrap).call(sunburst); + + }); + + renderWatch.renderEnd('sunburstChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + sunburst.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.data.name, + value: evt.data.size, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + sunburst.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + sunburst.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.sunburst = sunburst; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); + + // use Object get/set functionality to map between vars and chart functions + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + + // options that require extra logic in the setter + color: {get: function(){return color;}, set: function(_){ + color = _; + sunburst.color(color); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + sunburst.duration(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + nv.utils.inheritOptions(chart, sunburst); + nv.utils.initOptions(chart); + return chart; +}; + +nv.version = "1.8.2"; +})(); \ No newline at end of file diff --git a/dist/js/widgets/employer-form/employer-form.js b/dist/js/widgets/employer-form/employer-form.js new file mode 100644 index 0000000..564625e --- /dev/null +++ b/dist/js/widgets/employer-form/employer-form.js @@ -0,0 +1,13 @@ +'use strict'; + +{ + (function () { + var checkbox = document.querySelector('.employer-form .form__action .mdl-checkbox__input'), + button = document.querySelector('.employer-form .form__action .mdl-button'); + button.disabled = !checkbox.checked; + + checkbox.addEventListener('change', function () { + button.disabled = !checkbox.checked; + }); + })(); +} \ No newline at end of file diff --git a/dist/js/widgets/line-chart/line-chart-nvd3.js b/dist/js/widgets/line-chart/line-chart-nvd3.js new file mode 100644 index 0000000..e69156a --- /dev/null +++ b/dist/js/widgets/line-chart/line-chart-nvd3.js @@ -0,0 +1,242 @@ +'use strict'; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +{ + (function () { + var LineChart = (function () { + function LineChart(columns, color, margin, data, nv) { + _classCallCheck(this, LineChart); + + this.columns = columns; + this.color = color; + this.margin = margin; + this.data = data; + this.nv = nv; + this.maxX = 130; + this.drawStep = 6; // It shows how many points will be drawn in one step + this.durationResizeAnimation = 500; + } + + _createClass(LineChart, [{ + key: '_addSvgContainer', + value: function _addSvgContainer() { + this.svg = d3.select('.line-chart__container').append('div').append('svg'); + } + }, { + key: '_getSvgSizes', + value: function _getSvgSizes() { + var svgWidth = getComputedStyle(this.svg[0][0]).width, + svgHeight = getComputedStyle(this.svg[0][0]).height; + this.svgWidth = svgWidth.slice(0, svgWidth.length - 2); + this.svgHeight = svgHeight.slice(0, svgHeight.length - 2) - this.margin; + } + }, { + key: '_addAxisLabels', + value: function _addAxisLabels() { + d3.selectAll('.line-chart__container svg .y-axis-label').remove(); + d3.select('.line-chart__container svg').append('text').attr('class', 'y-axis-label').attr('x', '-72').attr('y', '12').attr('transform', 'rotate(-90)').text('REVENUE'); + d3.select('.line-chart__container svg').append('text').attr('class', 'x-axis-label').text('TIME'); + } + }, { + key: '_buildBackground', + value: function _buildBackground() { + this._addSvgContainer(); + this._getSvgSizes(); + + var bars = []; + for (var i = 0; i < this.columns; i++) { + bars.push(this.svgHeight); + } + + this.barsLayout = this.svg.append('g').attr('class', 'bars').attr('transform', 'translate(' + this.margin + ', 0)').selectAll('rect').data(bars).enter().append('rect'); + + this._addAxisLabels(); + + this._setBackgroundSizes(); + } + }, { + key: '_setBackgroundSizes', + value: function _setBackgroundSizes() { + var availableBarWidth = (this.svgWidth - 2 * this.margin) / this.columns, + barWidth = availableBarWidth / 2; + this.barsLayout.attr('fill', this.color).attr('y', this.margin).attr('height', function (d, i) { + return d; + }).transition().duration(this.durationResizeAnimation).attr('width', barWidth).attr('x', function (d, i) { + return i * availableBarWidth; + }); + d3.select('.line-chart__container svg .x-axis-label').transition().duration(this.durationResizeAnimation).attr('x', this.svgWidth - this.margin - 30).attr('y', this.svgHeight - this.svgHeight / 4 + this.margin + 14); + } + }, { + key: 'drawChart', + value: function drawChart() { + this._buildBackground(); + this._buildLegend(); + this._buildNvGraph(); + this._animateGraphs(); + } + }, { + key: '_buildNvGraph', + value: function _buildNvGraph() { + var _this = this; + + this._tuneNvGraph(); + + nv.addGraph(function () { + _this.svg.datum(_this.data).transition().duration(0).call(_this.lineChart); + nv.utils.windowResize(_this.resizeBackground.bind(_this)); + nv.utils.windowResize(_this.lineChart.update); + return _this.lineChart; + }); + } + }, { + key: '_tuneNvGraph', + value: function _tuneNvGraph() { + this.lineChart = nv.models.lineChart().margin({ top: this.margin, right: this.margin, bottom: 0, left: this.margin }).useInteractiveGuideline(true).xDomain([0, 13.6]).yDomain([-1.01, 3]).showLegend(false).showYAxis(true).showXAxis(true).pointSize(5); + + this.lineChart.tooltip.enabled(false); + this.lineChart.interactiveLayer.tooltip.enabled(false); + + this.lineChart.xAxis.showMaxMin(false).tickValues([0]).tickFormat(d3.format('c')); + + this.lineChart.yAxis.showMaxMin(false).ticks(10).tickFormat(d3.format('c')); + } + }, { + key: '_buildLegend', + value: function _buildLegend() { + var legend = d3.select('.line-chart__container').append('div').attr('class', 'legend').selectAll('.legend__item').data(this.data).enter().append('div').attr('class', 'legend__item'); + + legend.append('div').attr('class', 'legend__mark pull-left').style('background-color', function (d) { + return d.color; + }); + + legend.append('div').attr('class', 'legend__text').text(function (d) { + return d.key; + }); + } + }, { + key: 'resizeBackground', + value: function resizeBackground() { + this._getSvgSizes(); + this._setBackgroundSizes(); + } + }, { + key: '_animateGraphs', + value: function _animateGraphs() { + var _this2 = this; + + var i = 1; + this.timer = setInterval(function () { + _this2._calcAllGraphs(i); + _this2._drawNextStep(i); + i++; + _this2._checkEndOfAnimation(i); + }, 15); + } + }, { + key: '_drawNextStep', + value: function _drawNextStep(i) { + if (i % this.drawStep == 0 || i == this.maxX) { + this.lineChart.update(); + } + } + }, { + key: '_checkEndOfAnimation', + value: function _checkEndOfAnimation(i) { + if (i == this.maxX + 1) { + this.lineChart.duration(this.durationResizeAnimation); + this.data[1].fillOpacity = 0.11; + this.lineChart.update(); + clearInterval(this.timer); + } + } + }, { + key: '_calcAllGraphs', + value: function _calcAllGraphs(i) { + this._calcFirstGraph(i); + this._calcSecondGraph(i); + this._calcThirdGraph(i); + } + }, { + key: '_calcFirstGraph', + value: function _calcFirstGraph(i) { + var INTERVAL_1 = 28, + INTERVAL_2 = 71, + INTERVAL_3 = 110; + var graphAwesome = this.data[0].values; + + if (i < INTERVAL_1) { + graphAwesome.push({ x: i / 10, y: (.0343 * i * i - .67 * i) / 14 }); + } else { + if (i < INTERVAL_2) { + graphAwesome.push({ x: i / 10, y: -(i - 71) * (i - 71) / 1026 + 2.378 }); + } else { + if (i < INTERVAL_3) { + graphAwesome.push({ x: i / 10, y: -4 / (i - 43) + 2.53 }); + } else { + graphAwesome.push({ x: i / 10, y: (i - 114) * (i - 114) * (i - 114) / 13000 + 2.476 }); + } + } + } + } + }, { + key: '_calcSecondGraph', + value: function _calcSecondGraph(i) { + var INTERVAL_1 = 30, + INTERVAL_2 = 82; + var graphGood = this.data[1].values; + + if (i < INTERVAL_1) { + graphGood.push({ x: i / 10, y: (.03255 * i * i - .96 * i) / 16 }); + } else { + if (i < INTERVAL_2) { + graphGood.push({ x: i / 10, y: (-.01055 * (i - 80.3) * (i - 80.3) + 27) / 15 }); + } else { + graphGood.push({ x: i / 10, y: (i / 2 - 45) * (i / 2 - 45) * (i / 2 - 45) / 15000 + 1.805 }); + } + } + } + }, { + key: '_calcThirdGraph', + value: function _calcThirdGraph(i) { + var INTERVAL_1 = 31, + INTERVAL_2 = 103; + var graphFail = this.data[2].values; + + if (i < INTERVAL_1) { + graphFail.push({ x: i / 10, y: (.02255 * i * i - .91 * i) / 13 }); + } else { + if (i < INTERVAL_2) { + graphFail.push({ x: i / 10, y: .82 * Math.sin((i - 45) / 21) }); + } else { + graphFail.push({ x: i / 10, y: -(i - 130) * (i - 130) * (i - 130) / 64000 }); + } + } + } + }]); + + return LineChart; + })(); + + var data = [{ + values: [{ x: 0, y: 0 }], + key: 'Awesome', + color: 'rgb(80, 150, 215)' + }, { + values: [{ x: 0, y: 0 }], + key: 'Good', + color: 'rgb(0, 188, 212)', + fillOpacity: 0.00001, + area: true + }, { + values: [{ x: 0, y: 0 }], + key: 'Fail', + color: 'rgb(255, 82, 82)' + }]; + + var lineChart = new LineChart(7, '#4a4a4a', 20, data, nv); + lineChart.drawChart(); + })(); +} \ No newline at end of file diff --git a/dist/js/widgets/pie-chart/pie-chart-nvd3.js b/dist/js/widgets/pie-chart/pie-chart-nvd3.js new file mode 100644 index 0000000..f61fb37 --- /dev/null +++ b/dist/js/widgets/pie-chart/pie-chart-nvd3.js @@ -0,0 +1,93 @@ +'use strict'; + +{ + var colors = ['rgba(96, 196, 150, 1)', 'rgba(80, 150, 215, 1)', 'rgba(0, 188, 212, 1)', 'rgba(116, 199, 209, 1)', 'rgba(255, 82, 82, 1)', 'rgba(0, 0, 0, 0)']; + + var data = [{ + 'key': 'Coding', + 'y': 0, + 'end': 9 + }, { + 'key': 'Eating', + 'y': 0, + 'end': 3 + }, { + 'key': 'Sleeping', + 'y': 0, + 'end': 3 + }, { + 'key': 'Meditation', + 'y': 0, + 'end': 3 + }, { + 'key': 'The fight against evil', + 'y': 0, + 'end': 6 + }, { + 'key': 'Pending', + 'y': 23.9 + }]; + + nv.addGraph(function () { + var innerRadius = 0.86, + outerRadius = 1.02; + + var pieChart = nv.models.pieChart().x(function (d) { + return d.key; + }).y(function (d) { + return d.y; + }).showLabels(false).donut(true).growOnHover(true).padAngle(.04).cornerRadius(0).margin({ 'left': -10, 'right': -10, 'top': -10, 'bottom': -10 }).color(colors).arcsRadius([{ 'inner': innerRadius, 'outer': outerRadius }, { 'inner': innerRadius, 'outer': outerRadius }, { 'inner': innerRadius, 'outer': outerRadius }, { 'inner': innerRadius, 'outer': outerRadius }, { 'inner': innerRadius, 'outer': outerRadius }]).showLegend(false).title('0 hours').titleOffset(10); + + pieChart.tooltip.enabled(true).hideDelay(0).headerEnabled(false).contentGenerator(function (d) { + if (d === null) { + return ''; + } + d3.selectAll('.nvtooltip').classed('mdl-tooltip', true); + return d.data.y + ' hours'; + }); + + var container = d3.select('.pie-chart__container').append('div').append('svg').datum(data).transition().duration(1200).call(pieChart); + + var h = 0, + i = 0; + var timer = setInterval(animatePie, 70, data); + + function animatePie(data) { + if (i < data.length - 1) { + if (data[i].y < data[i].end) { + data[i].y++; + data[data.length - 1].y--; + pieChart.title(h + 1 + ' hours'); + h++; + } else { + i++; + } + } else { + data.splice(data.length - 1, 1); + clearInterval(timer); + return; + } + if (container[0][0]) { + pieChart.update(); + } else { + clearInterval(timer); + } + } + + d3.select('.nv-pie .nv-pie').append('image').attr('width', '30').attr('height', '30').attr('xlink:href', 'images/watch_white.svg').attr('transform', 'translate(-15,-35)'); + + var color = d3.scale.ordinal().range(colors); + + var legend = d3.select('.pie-chart__container').append('div').attr('class', 'legend').selectAll('.legend__item').data(data.slice(0, data.length - 1)).enter().append('div').attr('class', 'legend__item'); + + legend.append('div').attr('class', 'legend__mark pull-left').style('background-color', function (d) { + return color(d.key); + }); + + legend.append('div').attr('class', 'legend__text').text(function (d) { + return d.key; + }); + + return pieChart; + }); +} \ No newline at end of file diff --git a/dist/js/widgets/table/table.js b/dist/js/widgets/table/table.js new file mode 100644 index 0000000..3322188 --- /dev/null +++ b/dist/js/widgets/table/table.js @@ -0,0 +1,24 @@ +'use strict'; + +{ + (function () { + var task1 = document.querySelector('#task1'), + task2 = document.querySelector('#task2'), + task4 = document.querySelector('#task4'); + + task1.addEventListener('mdl-componentupgraded', function () { + task1.MaterialProgress.setProgress(44); + }); + task2.addEventListener('mdl-componentupgraded', function () { + task2.MaterialProgress.setProgress(14); + }); + task4.addEventListener('mdl-componentupgraded', function () { + task4.MaterialProgress.setProgress(31); + }); + + setTimeout(function () { + document.querySelector('.projects-table .is-selected td > label').classList.add('is-checked'); + componentHandler.upgradeDom(); + }, 100); + })(); +} \ No newline at end of file diff --git a/dist/js/widgets/todo/todo.js b/dist/js/widgets/todo/todo.js new file mode 100644 index 0000000..e158ac0 --- /dev/null +++ b/dist/js/widgets/todo/todo.js @@ -0,0 +1,248 @@ +'use strict'; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +{ + (function () { + 'use strict'; + + /*==========MODEL==========*/ + + var Model = (function () { + function Model(database) { + _classCallCheck(this, Model); + + this.database = database || [{ + title: 'Fix bugs', + id: 1651644545, + completed: '' + }, { + title: 'Implement 30% of my feature', + id: 1651646545, + completed: '' + }, { + title: 'Fencing', + id: 5451646545, + completed: 'checked' + }, { + title: 'Read an article about Test-Driven Development', + id: 5428646545, + completed: '' + }]; + } + + /*==========VIEW==========*/ + + _createClass(Model, [{ + key: 'createItem', + value: function createItem(title) { + var newItem = { + title: title, + id: new Date().getTime(), + completed: '' + }; + this.database.push(newItem); + return newItem; + } + }, { + key: 'checkItem', + value: function checkItem(id) { + for (var i = 0; i < this.database.length; i++) { + if (id == this.database[i].id) { + this.database[i].completed = this.database[i].completed ? '' : 'checked'; + return; + } + } + } + }, { + key: 'deleteItem', + value: function deleteItem(id) { + for (var i = 0; i < this.database.length; i++) { + if (id == this.database[i].id) { + this.database.splice(i, 1); + return; + } + } + } + }, { + key: 'deleteCompletedItems', + value: function deleteCompletedItems() { + for (var i = 0; i < this.database.length; i++) { + if (this.database[i].completed === 'checked') { + this.database.splice(i, 1); + i--; + } + } + } + }]); + + return Model; + })(); + + var View = (function () { + function View() { + _classCallCheck(this, View); + + this.$todoList = document.querySelector('.todo .mdl-list'); + this.inputTemplate = '
\n \n \n
'; + } + + /*==========CONTROLLER==========*/ + + _createClass(View, [{ + key: 'insertInput', + value: function insertInput() { + var newLi = document.createElement('li'); + newLi.classList.add('mdl-list__item'); + newLi.innerHTML = this._prepareTemplate({}); + this.$todoList.appendChild(newLi); + View.upgradeNewMdlComponents(); + var inputSpan = document.querySelector('.todo .mdl-list li:last-child .mdl-checkbox__label'); + inputSpan.innerHTML = this.inputTemplate; + View.upgradeNewMdlComponents(); + document.querySelector('.todo .mdl-list__item:last-child .mdl-textfield__input').focus(); + } + }, { + key: '_prepareTemplate', + value: function _prepareTemplate(data) { + return '\n \n \n
\n \n
'; + } + }, { + key: 'showAll', + value: function showAll(database) { + var _this = this; + + this.$todoList.innerHTML = ''; + database.forEach(function (data) { + var newLi = document.createElement('li'); + newLi.classList.add('mdl-list__item'); + newLi.innerHTML = _this._prepareTemplate(data); + _this.$todoList.appendChild(newLi); + }); + View.upgradeNewMdlComponents(); + } + }, { + key: 'show', + value: function show(data) { + var newLi = document.createElement('li'); + newLi.classList.add('mdl-list__item'); + newLi.innerHTML = this._prepareTemplate(data); + this.$todoList.appendChild(newLi); + View.upgradeNewMdlComponents(); + } + }], [{ + key: 'upgradeNewMdlComponents', + value: function upgradeNewMdlComponents() { + componentHandler.upgradeDom(); + } + }]); + + return View; + })(); + + var Controller = (function () { + function Controller(model, view) { + var _this2 = this; + + _classCallCheck(this, Controller); + + this.$addItemButton = document.querySelector('.todo .mdl-button--fab'); + this.$removeCompletedButton = document.querySelector('.todo .mdl-card__actions .mdl-button'); + this.model = model; + this.view = view; + + this.view.$todoList.addEventListener('mouseup', function (event) { + var clickTarget = event.path[1]; + if (clickTarget.hasAttribute('deleteItem')) { + var id = clickTarget.getAttribute('for'); + _this2.model.deleteItem(id); + _this2.removeItem(event); + } else if (clickTarget.hasAttribute('checkboxItem')) { + _this2.check(clickTarget); + } else { + clickTarget = event.target; + if (clickTarget.hasAttribute('checkboxItem')) { + _this2.check(clickTarget); + } + } + }); + + this.$addItemButton.addEventListener('click', function () { + _this2.$addItemButton.setAttribute('disabled', 'true'); + _this2.$removeCompletedButton.setAttribute('disabled', 'true'); + _this2.view.insertInput(); + + var inputTextArea = document.querySelector('.todo .mdl-list__item:last-child .mdl-textfield__input'); + inputTextArea.addEventListener('keydown', function (event) { + if (event.keyCode === 27) { + _this2.removeItem(event); + } else { + if (event.keyCode === 13) { + _this2.addItem(inputTextArea.value); + _this2.removeItem(event); + } + } + }); + }); + + this.$removeCompletedButton.addEventListener('click', function () { + _this2.removeCompletedItems(); + }); + + if (this.model.database != []) { + this.view.showAll(this.model.database); + } + } + + /*==========INITIALIZE==========*/ + + _createClass(Controller, [{ + key: 'addItem', + value: function addItem(title) { + if (title.trim() === '') { + return; + } + this.view.show(this.model.createItem(title)); + } + }, { + key: 'removeItem', + value: function removeItem(clickTarget) { + for (var i = 0; i < clickTarget.path.length; i++) { + if (clickTarget.path[i].className == 'mdl-list__item') { + clickTarget.path[i].remove(); + break; + } + } + this.$addItemButton.removeAttribute('disabled'); + this.$removeCompletedButton.removeAttribute('disabled'); + } + }, { + key: 'removeCompletedItems', + value: function removeCompletedItems() { + this.model.deleteCompletedItems(); + this.view.showAll(this.model.database); + } + }, { + key: 'check', + value: function check(checkbox) { + var id = checkbox.getAttribute('for'); + this.model.checkItem(id); + } + }]); + + return Controller; + })(); + + var Todo = function Todo() { + _classCallCheck(this, Todo); + + this.model = new Model(); + this.view = new View(); + this.controller = new Controller(this.model, this.view); + }; + + var todo = new Todo(); + })(); +} \ No newline at end of file