├── .gitattributes ├── .gitignore ├── .jslintrc ├── .tern-project ├── .travis.yml ├── Content ├── bootstrap-datepicker.css ├── bootstrap-datepicker3.css ├── bootstrap-theme.css ├── bootstrap-theme.css.map ├── bootstrap-theme.min.css ├── bootstrap.css ├── bootstrap.css.map ├── bootstrap.min.css └── qunit-1.18.0.css ├── Licence.md ├── README.md ├── Tests ├── Tests.html └── tests.js ├── build ├── koextensions.js └── koextensions.min.js ├── gulpfile.js ├── package.json ├── references ├── bootstrap-datepicker.js ├── bootstrap-datepicker.min.js ├── bootstrap.js ├── bootstrap.min.js ├── d3.js ├── d3.min.js ├── jquery-3.1.0-vsdoc.js ├── jquery-3.1.0.js ├── jquery-3.1.0.min.js ├── jquery-3.1.0.min.map ├── jquery-3.1.0.slim.js ├── jquery-3.1.0.slim.min.js ├── jquery-3.1.0.slim.min.map ├── knockout-3.4.0.debug.js ├── knockout-3.4.0.js ├── locales │ ├── bootstrap-datepicker.ar.js │ ├── bootstrap-datepicker.az.js │ ├── bootstrap-datepicker.bg.js │ ├── bootstrap-datepicker.ca.js │ ├── bootstrap-datepicker.cs.js │ ├── bootstrap-datepicker.cy.js │ ├── bootstrap-datepicker.da.js │ ├── bootstrap-datepicker.de.js │ ├── bootstrap-datepicker.el.js │ ├── bootstrap-datepicker.es.js │ ├── bootstrap-datepicker.et.js │ ├── bootstrap-datepicker.fa.js │ ├── bootstrap-datepicker.fi.js │ ├── bootstrap-datepicker.fr.js │ ├── bootstrap-datepicker.gl.js │ ├── bootstrap-datepicker.he.js │ ├── bootstrap-datepicker.hr.js │ ├── bootstrap-datepicker.hu.js │ ├── bootstrap-datepicker.id.js │ ├── bootstrap-datepicker.is.js │ ├── bootstrap-datepicker.it.js │ ├── bootstrap-datepicker.ja.js │ ├── bootstrap-datepicker.ka.js │ ├── bootstrap-datepicker.kk.js │ ├── bootstrap-datepicker.kr.js │ ├── bootstrap-datepicker.lt.js │ ├── bootstrap-datepicker.lv.js │ ├── bootstrap-datepicker.mk.js │ ├── bootstrap-datepicker.ms.js │ ├── bootstrap-datepicker.nb.js │ ├── bootstrap-datepicker.nl-BE.js │ ├── bootstrap-datepicker.nl.js │ ├── bootstrap-datepicker.no.js │ ├── bootstrap-datepicker.pl.js │ ├── bootstrap-datepicker.pt-BR.js │ ├── bootstrap-datepicker.pt.js │ ├── bootstrap-datepicker.ro.js │ ├── bootstrap-datepicker.rs-latin.js │ ├── bootstrap-datepicker.rs.js │ ├── bootstrap-datepicker.ru.js │ ├── bootstrap-datepicker.sk.js │ ├── bootstrap-datepicker.sl.js │ ├── bootstrap-datepicker.sq.js │ ├── bootstrap-datepicker.sv.js │ ├── bootstrap-datepicker.sw.js │ ├── bootstrap-datepicker.th.js │ ├── bootstrap-datepicker.tr.js │ ├── bootstrap-datepicker.ua.js │ ├── bootstrap-datepicker.vi.js │ ├── bootstrap-datepicker.zh-CN.js │ └── bootstrap-datepicker.zh-TW.js └── qunit-1.18.0.js ├── src ├── charting.js ├── charts │ ├── barchart.js │ ├── bubblechart.js │ ├── chordchart.js │ ├── histogramchart.js │ ├── linechart.js │ └── piechart.js ├── koextensions.js └── kotools.js └── testpages ├── BubbleChart.html ├── CashFlowExample.html ├── ChordChart.html ├── DateBindingTests.html ├── HistogramExample.html ├── LineChartSlidder.html ├── UtilsTests.html ├── WithoutKnockout.html ├── barcharttests-uglified.html ├── barcharttests.html ├── index.html ├── linetests.html └── piecharts.html /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.jslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ass": false, 3 | "bitwise": false, 4 | "browser": false, 5 | "closure": false, 6 | "continue": false, 7 | "couch": false, 8 | "debug": false, 9 | "devel": false, 10 | "eqeq": false, 11 | "evil": false, 12 | "forin": false, 13 | "indent": 4, 14 | "maxerr": 50, 15 | "maxlen": false, 16 | "newcap": false, 17 | "node": true, 18 | "nomen": false, 19 | "passfail": false, 20 | "plusplus": true, 21 | "predef": [ 22 | "define", 23 | "angular", 24 | "$" 25 | ], 26 | "regexp": false, 27 | "rhino": false, 28 | "sloppy": false, 29 | "stupid": false, 30 | "sub": false, 31 | "todo": false, 32 | "unparam": true, 33 | "vars": true, 34 | "unused": true, 35 | "white": true, 36 | "multivar":false 37 | } 38 | -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaVersion": 5, 3 | "libs": [ 4 | "jquery" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_script: 3 | - npm install gulp 4 | script: gulp test 5 | -------------------------------------------------------------------------------- /Content/bootstrap-datepicker.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Datepicker for Bootstrap 3 | * 4 | * Copyright 2012 Stefan Petre 5 | * Improvements by Andrew Rowls 6 | * Licensed under the Apache License v2.0 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | */ 10 | .datepicker { 11 | padding: 4px; 12 | -webkit-border-radius: 4px; 13 | -moz-border-radius: 4px; 14 | border-radius: 4px; 15 | direction: ltr; 16 | /*.dow { 17 | border-top: 1px solid #ddd !important; 18 | }*/ 19 | } 20 | .datepicker-inline { 21 | width: 220px; 22 | } 23 | .datepicker.datepicker-rtl { 24 | direction: rtl; 25 | } 26 | .datepicker.datepicker-rtl table tr td span { 27 | float: right; 28 | } 29 | .datepicker-dropdown { 30 | top: 0; 31 | left: 0; 32 | } 33 | .datepicker-dropdown:before { 34 | content: ''; 35 | display: inline-block; 36 | border-left: 7px solid transparent; 37 | border-right: 7px solid transparent; 38 | border-bottom: 7px solid #ccc; 39 | border-top: 0; 40 | border-bottom-color: rgba(0, 0, 0, 0.2); 41 | position: absolute; 42 | } 43 | .datepicker-dropdown:after { 44 | content: ''; 45 | display: inline-block; 46 | border-left: 6px solid transparent; 47 | border-right: 6px solid transparent; 48 | border-bottom: 6px solid #ffffff; 49 | border-top: 0; 50 | position: absolute; 51 | } 52 | .datepicker-dropdown.datepicker-orient-left:before { 53 | left: 6px; 54 | } 55 | .datepicker-dropdown.datepicker-orient-left:after { 56 | left: 7px; 57 | } 58 | .datepicker-dropdown.datepicker-orient-right:before { 59 | right: 6px; 60 | } 61 | .datepicker-dropdown.datepicker-orient-right:after { 62 | right: 7px; 63 | } 64 | .datepicker-dropdown.datepicker-orient-top:before { 65 | top: -7px; 66 | } 67 | .datepicker-dropdown.datepicker-orient-top:after { 68 | top: -6px; 69 | } 70 | .datepicker-dropdown.datepicker-orient-bottom:before { 71 | bottom: -7px; 72 | border-bottom: 0; 73 | border-top: 7px solid #999; 74 | } 75 | .datepicker-dropdown.datepicker-orient-bottom:after { 76 | bottom: -6px; 77 | border-bottom: 0; 78 | border-top: 6px solid #ffffff; 79 | } 80 | .datepicker > div { 81 | display: none; 82 | } 83 | .datepicker.days div.datepicker-days { 84 | display: block; 85 | } 86 | .datepicker.months div.datepicker-months { 87 | display: block; 88 | } 89 | .datepicker.years div.datepicker-years { 90 | display: block; 91 | } 92 | .datepicker table { 93 | margin: 0; 94 | -webkit-touch-callout: none; 95 | -webkit-user-select: none; 96 | -khtml-user-select: none; 97 | -moz-user-select: none; 98 | -ms-user-select: none; 99 | user-select: none; 100 | } 101 | .datepicker td, 102 | .datepicker th { 103 | text-align: center; 104 | width: 20px; 105 | height: 20px; 106 | -webkit-border-radius: 4px; 107 | -moz-border-radius: 4px; 108 | border-radius: 4px; 109 | border: none; 110 | } 111 | .table-striped .datepicker table tr td, 112 | .table-striped .datepicker table tr th { 113 | background-color: transparent; 114 | } 115 | .datepicker table tr td.day:hover, 116 | .datepicker table tr td.day.focused { 117 | background: #eeeeee; 118 | cursor: pointer; 119 | } 120 | .datepicker table tr td.old, 121 | .datepicker table tr td.new { 122 | color: #999999; 123 | } 124 | .datepicker table tr td.disabled, 125 | .datepicker table tr td.disabled:hover { 126 | background: none; 127 | color: #999999; 128 | cursor: default; 129 | } 130 | .datepicker table tr td.today, 131 | .datepicker table tr td.today:hover, 132 | .datepicker table tr td.today.disabled, 133 | .datepicker table tr td.today.disabled:hover { 134 | background-color: #fde19a; 135 | background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); 136 | background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); 137 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); 138 | background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); 139 | background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); 140 | background-image: linear-gradient(top, #fdd49a, #fdf59a); 141 | background-repeat: repeat-x; 142 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); 143 | border-color: #fdf59a #fdf59a #fbed50; 144 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 145 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 146 | color: #000; 147 | } 148 | .datepicker table tr td.today:hover, 149 | .datepicker table tr td.today:hover:hover, 150 | .datepicker table tr td.today.disabled:hover, 151 | .datepicker table tr td.today.disabled:hover:hover, 152 | .datepicker table tr td.today:active, 153 | .datepicker table tr td.today:hover:active, 154 | .datepicker table tr td.today.disabled:active, 155 | .datepicker table tr td.today.disabled:hover:active, 156 | .datepicker table tr td.today.active, 157 | .datepicker table tr td.today:hover.active, 158 | .datepicker table tr td.today.disabled.active, 159 | .datepicker table tr td.today.disabled:hover.active, 160 | .datepicker table tr td.today.disabled, 161 | .datepicker table tr td.today:hover.disabled, 162 | .datepicker table tr td.today.disabled.disabled, 163 | .datepicker table tr td.today.disabled:hover.disabled, 164 | .datepicker table tr td.today[disabled], 165 | .datepicker table tr td.today:hover[disabled], 166 | .datepicker table tr td.today.disabled[disabled], 167 | .datepicker table tr td.today.disabled:hover[disabled] { 168 | background-color: #fdf59a; 169 | } 170 | .datepicker table tr td.today:active, 171 | .datepicker table tr td.today:hover:active, 172 | .datepicker table tr td.today.disabled:active, 173 | .datepicker table tr td.today.disabled:hover:active, 174 | .datepicker table tr td.today.active, 175 | .datepicker table tr td.today:hover.active, 176 | .datepicker table tr td.today.disabled.active, 177 | .datepicker table tr td.today.disabled:hover.active { 178 | background-color: #fbf069 \9; 179 | } 180 | .datepicker table tr td.today:hover:hover { 181 | color: #000; 182 | } 183 | .datepicker table tr td.today.active:hover { 184 | color: #fff; 185 | } 186 | .datepicker table tr td.range, 187 | .datepicker table tr td.range:hover, 188 | .datepicker table tr td.range.disabled, 189 | .datepicker table tr td.range.disabled:hover { 190 | background: #eeeeee; 191 | -webkit-border-radius: 0; 192 | -moz-border-radius: 0; 193 | border-radius: 0; 194 | } 195 | .datepicker table tr td.range.today, 196 | .datepicker table tr td.range.today:hover, 197 | .datepicker table tr td.range.today.disabled, 198 | .datepicker table tr td.range.today.disabled:hover { 199 | background-color: #f3d17a; 200 | background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a); 201 | background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a); 202 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a)); 203 | background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a); 204 | background-image: -o-linear-gradient(top, #f3c17a, #f3e97a); 205 | background-image: linear-gradient(top, #f3c17a, #f3e97a); 206 | background-repeat: repeat-x; 207 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0); 208 | border-color: #f3e97a #f3e97a #edde34; 209 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 210 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 211 | -webkit-border-radius: 0; 212 | -moz-border-radius: 0; 213 | border-radius: 0; 214 | } 215 | .datepicker table tr td.range.today:hover, 216 | .datepicker table tr td.range.today:hover:hover, 217 | .datepicker table tr td.range.today.disabled:hover, 218 | .datepicker table tr td.range.today.disabled:hover:hover, 219 | .datepicker table tr td.range.today:active, 220 | .datepicker table tr td.range.today:hover:active, 221 | .datepicker table tr td.range.today.disabled:active, 222 | .datepicker table tr td.range.today.disabled:hover:active, 223 | .datepicker table tr td.range.today.active, 224 | .datepicker table tr td.range.today:hover.active, 225 | .datepicker table tr td.range.today.disabled.active, 226 | .datepicker table tr td.range.today.disabled:hover.active, 227 | .datepicker table tr td.range.today.disabled, 228 | .datepicker table tr td.range.today:hover.disabled, 229 | .datepicker table tr td.range.today.disabled.disabled, 230 | .datepicker table tr td.range.today.disabled:hover.disabled, 231 | .datepicker table tr td.range.today[disabled], 232 | .datepicker table tr td.range.today:hover[disabled], 233 | .datepicker table tr td.range.today.disabled[disabled], 234 | .datepicker table tr td.range.today.disabled:hover[disabled] { 235 | background-color: #f3e97a; 236 | } 237 | .datepicker table tr td.range.today:active, 238 | .datepicker table tr td.range.today:hover:active, 239 | .datepicker table tr td.range.today.disabled:active, 240 | .datepicker table tr td.range.today.disabled:hover:active, 241 | .datepicker table tr td.range.today.active, 242 | .datepicker table tr td.range.today:hover.active, 243 | .datepicker table tr td.range.today.disabled.active, 244 | .datepicker table tr td.range.today.disabled:hover.active { 245 | background-color: #efe24b \9; 246 | } 247 | .datepicker table tr td.selected, 248 | .datepicker table tr td.selected:hover, 249 | .datepicker table tr td.selected.disabled, 250 | .datepicker table tr td.selected.disabled:hover { 251 | background-color: #9e9e9e; 252 | background-image: -moz-linear-gradient(top, #b3b3b3, #808080); 253 | background-image: -ms-linear-gradient(top, #b3b3b3, #808080); 254 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080)); 255 | background-image: -webkit-linear-gradient(top, #b3b3b3, #808080); 256 | background-image: -o-linear-gradient(top, #b3b3b3, #808080); 257 | background-image: linear-gradient(top, #b3b3b3, #808080); 258 | background-repeat: repeat-x; 259 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0); 260 | border-color: #808080 #808080 #595959; 261 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 262 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 263 | color: #fff; 264 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 265 | } 266 | .datepicker table tr td.selected:hover, 267 | .datepicker table tr td.selected:hover:hover, 268 | .datepicker table tr td.selected.disabled:hover, 269 | .datepicker table tr td.selected.disabled:hover:hover, 270 | .datepicker table tr td.selected:active, 271 | .datepicker table tr td.selected:hover:active, 272 | .datepicker table tr td.selected.disabled:active, 273 | .datepicker table tr td.selected.disabled:hover:active, 274 | .datepicker table tr td.selected.active, 275 | .datepicker table tr td.selected:hover.active, 276 | .datepicker table tr td.selected.disabled.active, 277 | .datepicker table tr td.selected.disabled:hover.active, 278 | .datepicker table tr td.selected.disabled, 279 | .datepicker table tr td.selected:hover.disabled, 280 | .datepicker table tr td.selected.disabled.disabled, 281 | .datepicker table tr td.selected.disabled:hover.disabled, 282 | .datepicker table tr td.selected[disabled], 283 | .datepicker table tr td.selected:hover[disabled], 284 | .datepicker table tr td.selected.disabled[disabled], 285 | .datepicker table tr td.selected.disabled:hover[disabled] { 286 | background-color: #808080; 287 | } 288 | .datepicker table tr td.selected:active, 289 | .datepicker table tr td.selected:hover:active, 290 | .datepicker table tr td.selected.disabled:active, 291 | .datepicker table tr td.selected.disabled:hover:active, 292 | .datepicker table tr td.selected.active, 293 | .datepicker table tr td.selected:hover.active, 294 | .datepicker table tr td.selected.disabled.active, 295 | .datepicker table tr td.selected.disabled:hover.active { 296 | background-color: #666666 \9; 297 | } 298 | .datepicker table tr td.active, 299 | .datepicker table tr td.active:hover, 300 | .datepicker table tr td.active.disabled, 301 | .datepicker table tr td.active.disabled:hover { 302 | background-color: #006dcc; 303 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc); 304 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc); 305 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); 306 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); 307 | background-image: -o-linear-gradient(top, #0088cc, #0044cc); 308 | background-image: linear-gradient(top, #0088cc, #0044cc); 309 | background-repeat: repeat-x; 310 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); 311 | border-color: #0044cc #0044cc #002a80; 312 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 313 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 314 | color: #fff; 315 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 316 | } 317 | .datepicker table tr td.active:hover, 318 | .datepicker table tr td.active:hover:hover, 319 | .datepicker table tr td.active.disabled:hover, 320 | .datepicker table tr td.active.disabled:hover:hover, 321 | .datepicker table tr td.active:active, 322 | .datepicker table tr td.active:hover:active, 323 | .datepicker table tr td.active.disabled:active, 324 | .datepicker table tr td.active.disabled:hover:active, 325 | .datepicker table tr td.active.active, 326 | .datepicker table tr td.active:hover.active, 327 | .datepicker table tr td.active.disabled.active, 328 | .datepicker table tr td.active.disabled:hover.active, 329 | .datepicker table tr td.active.disabled, 330 | .datepicker table tr td.active:hover.disabled, 331 | .datepicker table tr td.active.disabled.disabled, 332 | .datepicker table tr td.active.disabled:hover.disabled, 333 | .datepicker table tr td.active[disabled], 334 | .datepicker table tr td.active:hover[disabled], 335 | .datepicker table tr td.active.disabled[disabled], 336 | .datepicker table tr td.active.disabled:hover[disabled] { 337 | background-color: #0044cc; 338 | } 339 | .datepicker table tr td.active:active, 340 | .datepicker table tr td.active:hover:active, 341 | .datepicker table tr td.active.disabled:active, 342 | .datepicker table tr td.active.disabled:hover:active, 343 | .datepicker table tr td.active.active, 344 | .datepicker table tr td.active:hover.active, 345 | .datepicker table tr td.active.disabled.active, 346 | .datepicker table tr td.active.disabled:hover.active { 347 | background-color: #003399 \9; 348 | } 349 | .datepicker table tr td span { 350 | display: block; 351 | width: 23%; 352 | height: 54px; 353 | line-height: 54px; 354 | float: left; 355 | margin: 1%; 356 | cursor: pointer; 357 | -webkit-border-radius: 4px; 358 | -moz-border-radius: 4px; 359 | border-radius: 4px; 360 | } 361 | .datepicker table tr td span:hover { 362 | background: #eeeeee; 363 | } 364 | .datepicker table tr td span.disabled, 365 | .datepicker table tr td span.disabled:hover { 366 | background: none; 367 | color: #999999; 368 | cursor: default; 369 | } 370 | .datepicker table tr td span.active, 371 | .datepicker table tr td span.active:hover, 372 | .datepicker table tr td span.active.disabled, 373 | .datepicker table tr td span.active.disabled:hover { 374 | background-color: #006dcc; 375 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc); 376 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc); 377 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); 378 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); 379 | background-image: -o-linear-gradient(top, #0088cc, #0044cc); 380 | background-image: linear-gradient(top, #0088cc, #0044cc); 381 | background-repeat: repeat-x; 382 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); 383 | border-color: #0044cc #0044cc #002a80; 384 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 385 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 386 | color: #fff; 387 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 388 | } 389 | .datepicker table tr td span.active:hover, 390 | .datepicker table tr td span.active:hover:hover, 391 | .datepicker table tr td span.active.disabled:hover, 392 | .datepicker table tr td span.active.disabled:hover:hover, 393 | .datepicker table tr td span.active:active, 394 | .datepicker table tr td span.active:hover:active, 395 | .datepicker table tr td span.active.disabled:active, 396 | .datepicker table tr td span.active.disabled:hover:active, 397 | .datepicker table tr td span.active.active, 398 | .datepicker table tr td span.active:hover.active, 399 | .datepicker table tr td span.active.disabled.active, 400 | .datepicker table tr td span.active.disabled:hover.active, 401 | .datepicker table tr td span.active.disabled, 402 | .datepicker table tr td span.active:hover.disabled, 403 | .datepicker table tr td span.active.disabled.disabled, 404 | .datepicker table tr td span.active.disabled:hover.disabled, 405 | .datepicker table tr td span.active[disabled], 406 | .datepicker table tr td span.active:hover[disabled], 407 | .datepicker table tr td span.active.disabled[disabled], 408 | .datepicker table tr td span.active.disabled:hover[disabled] { 409 | background-color: #0044cc; 410 | } 411 | .datepicker table tr td span.active:active, 412 | .datepicker table tr td span.active:hover:active, 413 | .datepicker table tr td span.active.disabled:active, 414 | .datepicker table tr td span.active.disabled:hover:active, 415 | .datepicker table tr td span.active.active, 416 | .datepicker table tr td span.active:hover.active, 417 | .datepicker table tr td span.active.disabled.active, 418 | .datepicker table tr td span.active.disabled:hover.active { 419 | background-color: #003399 \9; 420 | } 421 | .datepicker table tr td span.old, 422 | .datepicker table tr td span.new { 423 | color: #999999; 424 | } 425 | .datepicker th.datepicker-switch { 426 | width: 145px; 427 | } 428 | .datepicker thead tr:first-child th, 429 | .datepicker tfoot tr th { 430 | cursor: pointer; 431 | } 432 | .datepicker thead tr:first-child th:hover, 433 | .datepicker tfoot tr th:hover { 434 | background: #eeeeee; 435 | } 436 | .datepicker .cw { 437 | font-size: 10px; 438 | width: 12px; 439 | padding: 0 2px 0 5px; 440 | vertical-align: middle; 441 | } 442 | .datepicker thead tr:first-child th.cw { 443 | cursor: default; 444 | background-color: transparent; 445 | } 446 | .input-append.date .add-on i, 447 | .input-prepend.date .add-on i { 448 | cursor: pointer; 449 | width: 16px; 450 | height: 16px; 451 | } 452 | .input-daterange input { 453 | text-align: center; 454 | } 455 | .input-daterange input:first-child { 456 | -webkit-border-radius: 3px 0 0 3px; 457 | -moz-border-radius: 3px 0 0 3px; 458 | border-radius: 3px 0 0 3px; 459 | } 460 | .input-daterange input:last-child { 461 | -webkit-border-radius: 0 3px 3px 0; 462 | -moz-border-radius: 0 3px 3px 0; 463 | border-radius: 0 3px 3px 0; 464 | } 465 | .input-daterange .add-on { 466 | display: inline-block; 467 | width: auto; 468 | min-width: 16px; 469 | height: 20px; 470 | padding: 4px 5px; 471 | font-weight: normal; 472 | line-height: 20px; 473 | text-align: center; 474 | text-shadow: 0 1px 0 #ffffff; 475 | vertical-align: middle; 476 | background-color: #eeeeee; 477 | border: 1px solid #ccc; 478 | margin-left: -5px; 479 | margin-right: -5px; 480 | } 481 | .datepicker.dropdown-menu { 482 | position: absolute; 483 | top: 100%; 484 | left: 0; 485 | z-index: 1000; 486 | float: left; 487 | display: none; 488 | min-width: 160px; 489 | list-style: none; 490 | background-color: #ffffff; 491 | border: 1px solid #ccc; 492 | border: 1px solid rgba(0, 0, 0, 0.2); 493 | -webkit-border-radius: 5px; 494 | -moz-border-radius: 5px; 495 | border-radius: 5px; 496 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 497 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 498 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 499 | -webkit-background-clip: padding-box; 500 | -moz-background-clip: padding; 501 | background-clip: padding-box; 502 | *border-right-width: 2px; 503 | *border-bottom-width: 2px; 504 | color: #333333; 505 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 506 | font-size: 13px; 507 | line-height: 20px; 508 | } 509 | .datepicker.dropdown-menu th, 510 | .datepicker.dropdown-menu td { 511 | padding: 4px 5px; 512 | } 513 | -------------------------------------------------------------------------------- /Content/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /Content/qunit-1.18.0.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.18.0 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2015-04-03T10:23Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 1em 0.5em 1em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 1em 0.5em 1em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | padding: 0.2em; 81 | } 82 | 83 | .qunit-url-config { 84 | display: inline-block; 85 | padding: 0.1em; 86 | } 87 | 88 | .qunit-filter { 89 | display: block; 90 | float: right; 91 | margin-left: 1em; 92 | } 93 | 94 | /** Tests: Pass/Fail */ 95 | 96 | #qunit-tests { 97 | list-style-position: inside; 98 | } 99 | 100 | #qunit-tests li { 101 | padding: 0.4em 1em 0.4em 1em; 102 | border-bottom: 1px solid #FFF; 103 | list-style-position: inside; 104 | } 105 | 106 | #qunit-tests > li { 107 | display: none; 108 | } 109 | 110 | #qunit-tests li.running, 111 | #qunit-tests li.pass, 112 | #qunit-tests li.fail, 113 | #qunit-tests li.skipped { 114 | display: list-item; 115 | } 116 | 117 | #qunit-tests.hidepass li.running, 118 | #qunit-tests.hidepass li.pass { 119 | visibility: hidden; 120 | position: absolute; 121 | width: 0px; 122 | height: 0px; 123 | padding: 0; 124 | border: 0; 125 | margin: 0; 126 | } 127 | 128 | #qunit-tests li strong { 129 | cursor: pointer; 130 | } 131 | 132 | #qunit-tests li.skipped strong { 133 | cursor: default; 134 | } 135 | 136 | #qunit-tests li a { 137 | padding: 0.5em; 138 | color: #C2CCD1; 139 | text-decoration: none; 140 | } 141 | 142 | #qunit-tests li p a { 143 | padding: 0.25em; 144 | color: #6B6464; 145 | } 146 | #qunit-tests li a:hover, 147 | #qunit-tests li a:focus { 148 | color: #000; 149 | } 150 | 151 | #qunit-tests li .runtime { 152 | float: right; 153 | font-size: smaller; 154 | } 155 | 156 | .qunit-assert-list { 157 | margin-top: 0.5em; 158 | padding: 0.5em; 159 | 160 | background-color: #FFF; 161 | 162 | border-radius: 5px; 163 | } 164 | 165 | .qunit-collapsed { 166 | display: none; 167 | } 168 | 169 | #qunit-tests table { 170 | border-collapse: collapse; 171 | margin-top: 0.2em; 172 | } 173 | 174 | #qunit-tests th { 175 | text-align: right; 176 | vertical-align: top; 177 | padding: 0 0.5em 0 0; 178 | } 179 | 180 | #qunit-tests td { 181 | vertical-align: top; 182 | } 183 | 184 | #qunit-tests pre { 185 | margin: 0; 186 | white-space: pre-wrap; 187 | word-wrap: break-word; 188 | } 189 | 190 | #qunit-tests del { 191 | background-color: #E0F2BE; 192 | color: #374E0C; 193 | text-decoration: none; 194 | } 195 | 196 | #qunit-tests ins { 197 | background-color: #FFCACA; 198 | color: #500; 199 | text-decoration: none; 200 | } 201 | 202 | /*** Test Counts */ 203 | 204 | #qunit-tests b.counts { color: #000; } 205 | #qunit-tests b.passed { color: #5E740B; } 206 | #qunit-tests b.failed { color: #710909; } 207 | 208 | #qunit-tests li li { 209 | padding: 5px; 210 | background-color: #FFF; 211 | border-bottom: none; 212 | list-style-position: inside; 213 | } 214 | 215 | /*** Passing Styles */ 216 | 217 | #qunit-tests li li.pass { 218 | color: #3C510C; 219 | background-color: #FFF; 220 | border-left: 10px solid #C6E746; 221 | } 222 | 223 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 224 | #qunit-tests .pass .test-name { color: #366097; } 225 | 226 | #qunit-tests .pass .test-actual, 227 | #qunit-tests .pass .test-expected { color: #999; } 228 | 229 | #qunit-banner.qunit-pass { background-color: #C6E746; } 230 | 231 | /*** Failing Styles */ 232 | 233 | #qunit-tests li li.fail { 234 | color: #710909; 235 | background-color: #FFF; 236 | border-left: 10px solid #EE5757; 237 | white-space: pre; 238 | } 239 | 240 | #qunit-tests > li:last-child { 241 | border-radius: 0 0 5px 5px; 242 | } 243 | 244 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 245 | #qunit-tests .fail .test-name, 246 | #qunit-tests .fail .module-name { color: #000; } 247 | 248 | #qunit-tests .fail .test-actual { color: #EE5757; } 249 | #qunit-tests .fail .test-expected { color: #008000; } 250 | 251 | #qunit-banner.qunit-fail { background-color: #EE5757; } 252 | 253 | /*** Skipped tests */ 254 | 255 | #qunit-tests .skipped { 256 | background-color: #EBECE9; 257 | } 258 | 259 | #qunit-tests .qunit-skipped-label { 260 | background-color: #F4FF77; 261 | display: inline-block; 262 | font-style: normal; 263 | color: #366097; 264 | line-height: 1.8em; 265 | padding: 0 0.5em; 266 | margin: -0.4em 0.4em -0.4em 0; 267 | } 268 | 269 | /** Result */ 270 | 271 | #qunit-testresult { 272 | padding: 0.5em 1em 0.5em 1em; 273 | 274 | color: #2B81AF; 275 | background-color: #D2E0E6; 276 | 277 | border-bottom: 1px solid #FFF; 278 | } 279 | #qunit-testresult .module-name { 280 | font-weight: 700; 281 | } 282 | 283 | /** Fixture */ 284 | 285 | #qunit-fixture { 286 | position: absolute; 287 | top: -10000px; 288 | left: -10000px; 289 | width: 1000px; 290 | height: 1000px; 291 | } 292 | -------------------------------------------------------------------------------- /Licence.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | KoExtensions 2 | ============ 3 | [![Build Status](https://travis-ci.org/hoonzis/KoExtensions.svg?branch=master)](https://travis-ci.org/hoonzis/KoExtensions) 4 | 5 | KoExtensions can be used as standalone JavaScript charting library based on D3JS or plug-in for KnockoutJS. Besides charting, when used with Knockout it provides other useful bindings. Available charts: 6 | 7 | [piechart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/piechart.PNG 8 | [cashflow]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/cashflow.PNG 9 | [linechart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/linechart.PNG 10 | [chordchart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/chordchart.PNG 11 | [bubblechart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/bubblechart.PNG 12 | [histochart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/histogram.PNG 13 | [mapbinding]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/mapbinding.PNG 14 | [linechartslidder]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/small/horizontalslidder.PNG 15 | 16 | [piechartex]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/piecharts.html 17 | [cashFlowEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/CashFlowExample.html 18 | [lineSlidder]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/LineChartSlidder.html 19 | [chordEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/ChordChart.html 20 | [bubbleEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/BubbleChart.html 21 | [histoEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/HistogramExample.html 22 | [datepickerEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/DateBindingTests.html 23 | [formattingEx]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/UtilsTests.html 24 | [linechartex]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/linetests.html 25 | [barchartex]: https://github.com/hoonzis/KoExtensions/blob/master/testpages/barcharttests.html 26 | 27 | 28 | | Pie Chart | Bar Chart | Line Chart | 29 | | ------------------------|:---------------------:| ----------------------:| 30 | | ![alt text][piechart] | ![alt text][cashflow] | ![alt text][linechartslidder] | 31 | | [Example][piechartex] | [Example1][barchartex] [Example2][cashFlowEx] | [Example1][linechartex][With Slidder][lineSlidder]| 32 | 33 | | Chord Chart | Bubble Chart | Histogram | 34 | | ------------------------|:-------------------:| ---------------------:| 35 | | ![alt text][chordchart] | ![alt text][bubblechart] | ![alt text][histochart] | 36 | | [Example][chordEx] | [Example][bubbleEx] | [Example][histoEx] | 37 | 38 | Fiddle to play around: 39 | https://jsfiddle.net/u4sL2x67/4/ 40 | 41 | **Other bindings useful for Knockout:** 42 | 43 | * Bootstrap DateTime picker binding [Example] [datepickerEx] 44 | * FormattedValue binding - showing data values in the UI with applied formatting (currencies, rounding). [Example][formattingEx] 45 | 46 | All charts are created with [D3JS](http://d3js.org/) and based on multiple examples provided in the documentation. 47 | 48 | #### Using KoExtensions 49 | KoExtensions can be used either together with Knockout or as a separate charting library. 50 | 51 | ```javascript 52 | // As separate charting library 53 | 54 | 55 | koext.charting.lineChart(testData, el, {width:"100px"}); 56 | ``` 57 | 58 | ```javascript 59 | // Together with knockout 60 | 61 | 62 | 63 |
81 |
82 |

83 |
84 |
85 | 86 | ``` 87 | 88 | - Interesting usage of barchart can be "cashflow chart" which shows a single line, going through the bars being the addition of the bars values. This can be achieved as follows: 89 | 90 | [cashflowchart]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/cashflowchart.png 91 | ![alt text][cashflowchart] 92 | 93 | ```html 94 |
95 | ``` 96 | ```javascript 97 | function TestViewModels (expenses){ 98 | self = this; 99 | self.lifeExpenses = ko.observableArray([]); 100 | self.expensesPerMonth = ko.observableArray([]); 101 | var totalPerMonth = expenses.map(function(item){ 102 | var keys = Object.keys(item).filter(function(key){return key != 'month';}); 103 | var monthTotal = { x : item['month'], y : d3.sum(keys, function(key) { return item[key];}) }; 104 | return monthTotal; 105 | }); 106 | self.lifeExpenses(expenses); 107 | self.expensesPerMonth(totalPerMonth); 108 | } 109 | ``` 110 | - Histogram chart has some additional properties which can be used to visualize the statistical distribution, using either Mean or Median and standard variance or MAD (Median absolute deviation) 111 | 112 | [histogram]: https://raw.githubusercontent.com/hoonzis/KoExtensions/gh-pages/img/histogram.PNG 113 | ![alt text][histogram] 114 | 115 | ```html 116 |
122 | ``` 123 | -------------------------------------------------------------------------------- /Tests/Tests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QUnit Example 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Tests/tests.js: -------------------------------------------------------------------------------- 1 | var koTools = koextensions.tools; 2 | 3 | QUnit.test("isValidDate returns true if object is date and has meaningful value", function(assert) { 4 | var res = koTools.isValidDate(new Date("12/12/2012")); 5 | assert.ok(res); 6 | }); 7 | 8 | QUnit.test("convertSeriesToXYPairs, will convert if series is just array of numbers", function(assert) { 9 | var data = [1000, 500, 100]; 10 | var res = koTools.convertSeriesToXYPairs(data); 11 | 12 | assert.equal(res[0].y, 1000); 13 | assert.equal(res[2].x,2); 14 | }); 15 | 16 | QUnit.test("convertAllSeriesToXYPairs, will ignore if no values property is available", function(assert) { 17 | var data = [ 18 | [1000, 500, 100] , 19 | { x:"test" } 20 | ]; 21 | var res = koTools.convertAllSeriesToXYPairs(data); 22 | 23 | assert.equal(res[0][0], 1000); 24 | assert.equal(res[1].x, "test"); 25 | }); 26 | 27 | QUnit.test("Enlarge text by copying", function(assert) { 28 | var value = koTools.toLength("test", 8); 29 | assert.equal(value, "testtest", "Should be 8 characters!"); 30 | }); 31 | 32 | QUnit.test("String is string", function(assert) { 33 | var v = "0.05"; 34 | assert.equal(koTools.isString(v), true, 'Is string'); 35 | }); 36 | 37 | QUnit.test("Int is not string", function(assert) { 38 | var v = 0.05; 39 | assert.equal(koTools.isString(v), false, 'Is not string'); 40 | }); 41 | 42 | QUnit.test("default options setter sets all values specified in default options", function(assert) { 43 | var defaultOptions = { 44 | start: 10, 45 | mapper: function (x) { return x*2;} 46 | } 47 | 48 | var testOptions = { 49 | hello: 5 50 | } 51 | 52 | var res = koTools.setDefaultOptions(defaultOptions, testOptions); 53 | 54 | assert.equal(res.start, 10); 55 | assert.equal(res.hello, 5); 56 | assert.equal(res.mapper(2), 4); 57 | }); 58 | 59 | 60 | QUnit.test("compare different mileniums", function(assert) { 61 | var comparer = koTools.monthsComparer; 62 | var res = comparer("20121", "19991"); 63 | assert.equal(res, 1); 64 | }); 65 | 66 | QUnit.test("compare different years", function(assert) { 67 | var comparer = koTools.monthsComparer; 68 | var res = comparer("20111", "20121"); 69 | assert.equal(res, -1); 70 | }); 71 | 72 | QUnit.test("adding values to empty matrix", function(assert) { 73 | var matrix = []; 74 | matrix.setOrAdd(1, 2, 3); 75 | matrix.setOrAdd(1, 2, 3); 76 | assert.equal(matrix[1][2], 6); 77 | }); 78 | 79 | QUnit.test("set values two times", function(assert) { 80 | var matrix = []; 81 | matrix.set(1, 2, 2); 82 | matrix.set(1, 2, 3); 83 | assert.equal(matrix[1][2], 3); 84 | }); 85 | 86 | QUnit.test("densifying a sparse matrix", function(assert) { 87 | var matrix = []; 88 | matrix.set(1, 2, 2); 89 | matrix.set(1, 2, 3); 90 | assert.equal(matrix[1][2], 3); 91 | }); 92 | 93 | QUnit.test("adding days", function(assert) { 94 | var dat = new Date(2015, 12, 30); 95 | var newDate = dat.addDays(10); 96 | assert.equal(newDate.getDate(), 9); 97 | }); 98 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var gulp = require('gulp'); 4 | var uglify = require('gulp-uglifyjs'); 5 | var watch = require('gulp-watch'); 6 | var plumber = require('gulp-plumber'); 7 | var browserify = require('gulp-browserify'); 8 | var qunit = require('gulp-qunit'); 9 | 10 | gulp.task('scripts', function() { 11 | // Single entry point to browserify 12 | gulp.src('src/koextensions.js') 13 | .pipe(browserify({ 14 | standalone: 'koextensions' 15 | })) 16 | .pipe(gulp.dest('./build')); 17 | }); 18 | 19 | gulp.task('uglify', function() { 20 | gulp.src('build/koextensions.js') 21 | .pipe(uglify('koextensions.min.js')) 22 | .pipe(gulp.dest('build')); 23 | }); 24 | 25 | gulp.task('test', ['scripts', 'uglify'], function() { 26 | return gulp.src('./tests/tests.html') 27 | .pipe(qunit()); 28 | }); 29 | 30 | gulp.task('build', ['scripts','uglify'], function () { 31 | console.log("Default task"); 32 | }); 33 | 34 | gulp.task("default", ["build"], function () { 35 | gulp.watch('src/*.js', ['build']); 36 | }); 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koextensions", 3 | "version": "1.0.0", 4 | "description": "Charts & Tools for Knockout", 5 | "author": "Jan Fajfr", 6 | "devDependencies": { 7 | "browserify": "^13.0.0", 8 | "gulp": "^3.9.0", 9 | "gulp-browserify": "^0.5.1", 10 | "gulp-plumber": "^1.1.0", 11 | "gulp-qunit": "^1.4.0", 12 | "gulp-uglifyjs": "^0.6.2", 13 | "gulp-watch": "^4.3.9", 14 | "watchify": "^3.7.0" 15 | }, 16 | "main": "gulpfile.js", 17 | "directories": { 18 | "test": "tests" 19 | }, 20 | "dependencies": { 21 | "gulp-browserify": "^0.5.1", 22 | "browserify": "^13.1.0", 23 | "gulp": "^3.9.1", 24 | "watchify": "^3.7.0" 25 | }, 26 | "scripts": { 27 | "test": "gulp test" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "git+https://github.com/hoonzis/KoExtensions.git" 32 | }, 33 | "keywords": [ 34 | "knockout", 35 | "charts" 36 | ], 37 | "license": "ISC", 38 | "bugs": { 39 | "url": "https://github.com/hoonzis/KoExtensions/issues" 40 | }, 41 | "homepage": "https://github.com/hoonzis/KoExtensions#readme" 42 | } 43 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arabic translation for bootstrap-datepicker 3 | * Mohammed Alshehri 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ar'] = { 7 | days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"], 8 | daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"], 9 | daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"], 10 | months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 11 | monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 12 | today: "هذا اليوم", 13 | rtl: true 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.az.js: -------------------------------------------------------------------------------- 1 | // Azerbaijani 2 | ;(function($){ 3 | $.fn.datepicker.dates['az'] = { 4 | days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"], 5 | daysShort: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."], 6 | daysMin: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."], 7 | months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"], 8 | monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"], 9 | today: "Bu gün", 10 | weekStart: 1 11 | }; 12 | }(jQuery)); 13 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.bg.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bulgarian translation for bootstrap-datepicker 3 | * Apostol Apostolov 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['bg'] = { 7 | days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"], 8 | daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"], 9 | daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"], 10 | months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"], 11 | monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"], 12 | today: "днес" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ca.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Catalan translation for bootstrap-datepicker 3 | * J. Garcia 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ca'] = { 7 | days: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte", "Diumenge"], 8 | daysShort: ["Diu", "Dil", "Dmt", "Dmc", "Dij", "Div", "Dis", "Diu"], 9 | daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds", "dg"], 10 | months: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"], 12 | today: "Avui" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.cs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Czech translation for bootstrap-datepicker 3 | * Matěj Koubík 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['cs'] = { 8 | days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"], 9 | daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So", "Ne"], 11 | months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], 12 | monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"], 13 | today: "Dnes" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.cy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welsh translation for bootstrap-datepicker 3 | * S. Morris 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['cy'] = { 7 | days: ["Sul", "Llun", "Mawrth", "Mercher", "Iau", "Gwener", "Sadwrn", "Sul"], 8 | daysShort: ["Sul", "Llu", "Maw", "Mer", "Iau", "Gwe", "Sad", "Sul"], 9 | daysMin: ["Su", "Ll", "Ma", "Me", "Ia", "Gwe", "Sa", "Su"], 10 | months: ["Ionawr", "Chewfror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorfennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"], 11 | monthsShort: ["Ion", "Chw", "Maw", "Ebr", "Mai", "Meh", "Gor", "Aws", "Med", "Hyd", "Tach", "Rha"], 12 | today: "Heddiw" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.da.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Danish translation for bootstrap-datepicker 3 | * Christian Pedersen 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['da'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "I Dag", 13 | clear: "Nulstil" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.de.js: -------------------------------------------------------------------------------- 1 | /** 2 | * German translation for bootstrap-datepicker 3 | * Sam Zurcher 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['de'] = { 7 | days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], 8 | daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"], 9 | daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], 10 | months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 11 | monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], 12 | today: "Heute", 13 | clear: "Löschen", 14 | weekStart: 1, 15 | format: "dd.mm.yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.el.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Greek translation for bootstrap-datepicker 3 | */ 4 | ;(function($){ 5 | $.fn.datepicker.dates['el'] = { 6 | days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο", "Κυριακή"], 7 | daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"], 8 | daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα", "Κυ"], 9 | months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"], 10 | monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"], 11 | today: "Σήμερα" 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Spanish translation for bootstrap-datepicker 3 | * Bruno Bonamin 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['es'] = { 7 | days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"], 10 | months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], 11 | monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], 12 | today: "Hoy" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.et.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Estonian translation for bootstrap-datepicker 3 | * Ando Roots 4 | * Fixes by Illimar Tambek < 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['et'] = { 8 | days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev", "Pühapäev"], 9 | daysShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup", "Pühap"], 10 | daysMin: ["P", "E", "T", "K", "N", "R", "L", "P"], 11 | months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"], 12 | monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"], 13 | today: "Täna", 14 | clear: "Tühjenda", 15 | weekStart: 1, 16 | format: "dd.mm.yyyy" 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.fa.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Persian translation for bootstrap-datepicker 3 | * Mostafa Rokooie 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fa'] = { 7 | days: ["یک‌شنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنج‌شنبه", "جمعه", "شنبه", "یک‌شنبه"], 8 | daysShort: ["یک", "دو", "سه", "چهار", "پنج", "جمعه", "شنبه", "یک"], 9 | daysMin: ["ی", "د", "س", "چ", "پ", "ج", "ش", "ی"], 10 | months: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"], 11 | monthsShort: ["ژان", "فور", "مار", "آور", "مه", "ژون", "ژوی", "اوت", "سپت", "اکت", "نوا", "دسا"], 12 | today: "امروز", 13 | clear: "پاک کن", 14 | weekStart: 1, 15 | format: "yyyy/mm/dd" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.fi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finnish translation for bootstrap-datepicker 3 | * Jaakko Salonen 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fi'] = { 7 | days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"], 8 | daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"], 9 | daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"], 10 | months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], 11 | monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"], 12 | today: "tänään", 13 | weekStart: 1, 14 | format: "d.m.yyyy" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.fr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * French translation for bootstrap-datepicker 3 | * Nico Mollet 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fr'] = { 7 | days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"], 8 | daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"], 9 | daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"], 10 | months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], 11 | monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Déc"], 12 | today: "Aujourd'hui", 13 | clear: "Effacer", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.gl.js: -------------------------------------------------------------------------------- 1 | ;(function($){ 2 | $.fn.datepicker.dates['gl'] = { 3 | days: ["Domingo", "Luns", "Martes", "Mércores", "Xoves", "Venres", "Sábado", "Domingo"], 4 | daysShort: ["Dom", "Lun", "Mar", "Mér", "Xov", "Ven", "Sáb", "Dom"], 5 | daysMin: ["Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa", "Do"], 6 | months: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"], 7 | monthsShort: ["Xan", "Feb", "Mar", "Abr", "Mai", "Xun", "Xul", "Ago", "Sep", "Out", "Nov", "Dec"], 8 | today: "Hoxe", 9 | clear: "Limpar" 10 | }; 11 | }(jQuery)); 12 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.he.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hebrew translation for bootstrap-datepicker 3 | * Sagie Maoz 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['he'] = { 7 | days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"], 8 | daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 9 | daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 10 | months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], 11 | monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"], 12 | today: "היום", 13 | rtl: true 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.hr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Croatian localisation 3 | */ 4 | ;(function($){ 5 | $.fn.datepicker.dates['hr'] = { 6 | days: ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota", "Nedjelja"], 7 | daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub", "Ned"], 8 | daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su", "Ne"], 9 | months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"], 10 | monthsShort: ["Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro"], 11 | today: "Danas" 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.hu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hungarian translation for bootstrap-datepicker 3 | * Sotus László 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['hu'] = { 7 | days: ["Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap"], 8 | daysShort: ["Vas", "Hét", "Ked", "Sze", "Csü", "Pén", "Szo", "Vas"], 9 | daysMin: ["Va", "Hé", "Ke", "Sz", "Cs", "Pé", "Sz", "Va"], 10 | months: ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Sze", "Okt", "Nov", "Dec"], 12 | today: "Ma", 13 | weekStart: 1, 14 | format: "yyyy.mm.dd" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bahasa translation for bootstrap-datepicker 3 | * Azwar Akbar 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['id'] = { 7 | days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"], 8 | daysShort: ["Mgu", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mgu"], 9 | daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"], 10 | months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"], 12 | today: "Hari Ini", 13 | clear: "Kosongkan" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.is.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Icelandic translation for bootstrap-datepicker 3 | * Hinrik Örn Sigurðsson 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['is'] = { 7 | days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur", "Sunnudagur"], 8 | daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau", "Sun"], 9 | daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La", "Su"], 10 | months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"], 12 | today: "Í Dag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.it.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Italian translation for bootstrap-datepicker 3 | * Enrico Rubboli 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['it'] = { 7 | days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato", "Domenica"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"], 10 | months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], 12 | today: "Oggi", 13 | clear: "Cancella", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ja.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Japanese translation for bootstrap-datepicker 3 | * Norio Suzuki 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ja'] = { 7 | days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "日曜"], 8 | daysShort: ["日", "月", "火", "水", "木", "金", "土", "日"], 9 | daysMin: ["日", "月", "火", "水", "木", "金", "土", "日"], 10 | months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 11 | monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 12 | today: "今日", 13 | format: "yyyy/mm/dd" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ka.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Georgian translation for bootstrap-datepicker 3 | * Levan Melikishvili 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ka'] = { 7 | days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი", "კვირა"], 8 | daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ", "კვი"], 9 | daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა", "კვ"], 10 | months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომები", "ნოემბერი", "დეკემბერი"], 11 | monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"], 12 | today: "დღეს", 13 | clear: "გასუფთავება", 14 | weekStart: 1, 15 | format: "dd.mm.yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.kk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Kazakh translation for bootstrap-datepicker 3 | * Yerzhan Tolekov 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['kk'] = { 7 | days: ["Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі", "Жексенбі"], 8 | daysShort: ["Жек", "Дүй", "Сей", "Сәр", "Бей", "Жұм", "Сен", "Жек"], 9 | daysMin: ["Жк", "Дс", "Сс", "Ср", "Бс", "Жм", "Сн", "Жк"], 10 | months: ["Қаңтар", "Ақпан", "Наурыз", "Сәуір", "Мамыр", "Маусым", "Шілде", "Тамыз", "Қыркүйек", "Қазан", "Қараша", "Желтоқсан"], 11 | monthsShort: ["Қаң", "Ақп", "Нау", "Сәу", "Мамыр", "Мау", "Шлд", "Тмз", "Қыр", "Қзн", "Қар", "Жел"], 12 | today: "Бүгін", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.kr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Korean translation for bootstrap-datepicker 3 | * Gu Youn 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['kr'] = { 7 | days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"], 8 | daysShort: ["일", "월", "화", "수", "목", "금", "토", "일"], 9 | daysMin: ["일", "월", "화", "수", "목", "금", "토", "일"], 10 | months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], 11 | monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"] 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Lithuanian translation for bootstrap-datepicker 3 | * Šarūnas Gliebus 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datepicker.dates['lt'] = { 8 | days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis", "Sekmadienis"], 9 | daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š", "S"], 10 | daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št", "Sk"], 11 | months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"], 12 | monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"], 13 | today: "Šiandien", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.lv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Latvian translation for bootstrap-datepicker 3 | * Artis Avotins 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datepicker.dates['lv'] = { 8 | days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena", "Svētdiena"], 9 | daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"], 10 | daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "Se", "Sv"], 11 | months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec"], 13 | today: "Šodien", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.mk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Macedonian translation for bootstrap-datepicker 3 | * Marko Aleksic 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['mk'] = { 7 | days: ["Недела", "Понеделник", "Вторник", "Среда", "Четврток", "Петок", "Сабота", "Недела"], 8 | daysShort: ["Нед", "Пон", "Вто", "Сре", "Чет", "Пет", "Саб", "Нед"], 9 | daysMin: ["Не", "По", "Вт", "Ср", "Че", "Пе", "Са", "Не"], 10 | months: ["Јануари", "Февруари", "Март", "Април", "Мај", "Јуни", "Јули", "Август", "Септември", "Октомври", "Ноември", "Декември"], 11 | monthsShort: ["Јан", "Фев", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"], 12 | today: "Денес", 13 | format: "dd.mm.yyyy" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Malay translation for bootstrap-datepicker 3 | * Ateman Faiz 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ms'] = { 7 | days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"], 8 | daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"], 9 | daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"], 10 | months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"], 12 | today: "Hari Ini" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.nb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian (bokmål) translation for bootstrap-datepicker 3 | * Fredrik Sundmyhr 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nb'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], 12 | today: "I Dag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.nl-BE.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Belgium-Dutch translation for bootstrap-datepicker 3 | * Julien Poulin 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nl-BE'] = { 7 | days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], 8 | daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 9 | daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 10 | months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Vandaag", 13 | clear: "Leegmaken", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.nl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dutch translation for bootstrap-datepicker 3 | * Reinier Goltstein 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nl'] = { 7 | days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], 8 | daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 9 | daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 10 | months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Vandaag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.no.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian translation for bootstrap-datepicker 3 | **/ 4 | ;(function($){ 5 | $.fn.datepicker.dates['no'] = { 6 | days: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'], 7 | daysShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'], 8 | daysMin: ['Sø','Ma','Ti','On','To','Fr','Lø'], 9 | months: ['Januar','Februar','Mars','April','Mai','Juni','Juli','August','September','Oktober','November','Desember'], 10 | monthsShort: ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Des'], 11 | today: 'I dag', 12 | clear: 'Nullstill', 13 | weekStart: 1, 14 | format: 'dd.mm.yyyy' 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.pl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Polish translation for bootstrap-datepicker 3 | * Robert 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['pl'] = { 7 | days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Niedziela"], 8 | daysShort: ["Nie", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nie"], 9 | daysMin: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So", "N"], 10 | months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], 11 | monthsShort: ["Sty", "Lu", "Mar", "Kw", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa", "Lis", "Gru"], 12 | today: "Dzisiaj", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.pt-BR.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Brazilian translation for bootstrap-datepicker 3 | * Cauan Cabral 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['pt-BR'] = { 7 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 8 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 9 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 10 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 11 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 12 | today: "Hoje", 13 | clear: "Limpar" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.pt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Portuguese translation for bootstrap-datepicker 3 | * Original code: Cauan Cabral 4 | * Tiago Melo 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['pt'] = { 8 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 9 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 10 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 11 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 12 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 13 | today: "Hoje", 14 | clear: "Limpar" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ro.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Romanian translation for bootstrap-datepicker 3 | * Cristian Vasile 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ro'] = { 7 | days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă", "Duminică"], 8 | daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"], 9 | daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"], 10 | months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"], 11 | monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"], 12 | today: "Astăzi", 13 | clear: "Șterge", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.rs-latin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian latin translation for bootstrap-datepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['rs-latin'] = { 7 | days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub", "Ned"], 9 | daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su", "N"], 10 | months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danas" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.rs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian cyrillic translation for bootstrap-datepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['rs'] = { 7 | days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота", "Недеља"], 8 | daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", "Нед"], 9 | daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су", "Н"], 10 | months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"], 11 | monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"], 12 | today: "Данас" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ru.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Russian translation for bootstrap-datepicker 3 | * Victor Taranenko 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ru'] = { 7 | days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"], 8 | daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Вск"], 9 | daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"], 10 | months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"], 11 | monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"], 12 | today: "Сегодня", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.sk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovak translation for bootstrap-datepicker 3 | * Marek Lichtner 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates["sk"] = { 8 | days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota", "Nedeľa"], 9 | daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pia", "So", "Ne"], 11 | months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"], 13 | today: "Dnes" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.sl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovene translation for bootstrap-datepicker 3 | * Gregor Rudolf 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sl'] = { 7 | days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"], 9 | daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So", "Ne"], 10 | months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danes" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.sq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Albanian translation for bootstrap-datepicker 3 | * Tomor Pupovci 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sq'] = { 7 | days: ["E Diel", "E Hënë", "E martē", "E mërkurë", "E Enjte", "E Premte", "E Shtunë", "E Diel"], 8 | daysShort: ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Shtu", "Die"], 9 | daysMin: ["Di", "Hë", "Ma", "Më", "En", "Pr", "Sht", "Di"], 10 | months: ["Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor"], 11 | monthsShort: ["Jan", "Shk", "Mar", "Pri", "Maj", "Qer", "Korr", "Gu", "Sht", "Tet", "Nën", "Dhjet"], 12 | today: "Sot" 13 | }; 14 | }(jQuery)); 15 | 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.sv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swedish translation for bootstrap-datepicker 3 | * Patrik Ragnarsson 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sv'] = { 7 | days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"], 8 | daysShort: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"], 9 | daysMin: ["Sö", "Må", "Ti", "On", "To", "Fr", "Lö", "Sö"], 10 | months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Idag", 13 | format: "yyyy-mm-dd", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.sw.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swahili translation for bootstrap-datepicker 3 | * Edwin Mugendi 4 | * Source: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['sw'] = { 8 | days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi", "Jumapili"], 9 | daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1", "J2"], 10 | daysMin: ["2", "3", "4", "5", "A", "I", "1", "2"], 11 | months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"], 12 | monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"], 13 | today: "Leo" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.th.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Thai translation for bootstrap-datepicker 3 | * Suchau Jiraprapot 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['th'] = { 7 | days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"], 8 | daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 9 | daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 10 | months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"], 11 | monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], 12 | today: "วันนี้" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.tr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Turkish translation for bootstrap-datepicker 3 | * Serkan Algur 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['tr'] = { 7 | days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi", "Pazar"], 8 | daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts", "Pz"], 9 | daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct", "Pz"], 10 | months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"], 11 | monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"], 12 | today: "Bugün", 13 | format: "dd.mm.yyyy" 14 | }; 15 | }(jQuery)); 16 | 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.ua.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ukrainian translation for bootstrap-datepicker 3 | * Igor Polynets 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ua'] = { 7 | days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятница", "Субота", "Неділя"], 8 | daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"], 9 | daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"], 10 | months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], 11 | monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"], 12 | today: "Сьогодні", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.vi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vietnamese translation for bootstrap-datepicker 3 | * An Vo 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['vi'] = { 7 | days: ["Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy", "Chủ nhật"], 8 | daysShort: ["CN", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7", "CN"], 9 | daysMin: ["CN", "T2", "T3", "T4", "T5", "T6", "T7", "CN"], 10 | months: ["Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"], 11 | monthsShort: ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"], 12 | today: "Hôm nay", 13 | clear: "Xóa", 14 | format: "dd/mm/yyyy" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplified Chinese translation for bootstrap-datepicker 3 | * Yuan Cheung 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['zh-CN'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今日", 13 | format: "yyyy年mm月dd日", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /references/locales/bootstrap-datepicker.zh-TW.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Traditional Chinese translation for bootstrap-datepicker 3 | * Rung-Sheng Jang 4 | * FrankWu Fix more appropriate use of Traditional Chinese habit 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['zh-TW'] = { 8 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 9 | daysShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六", "週日"], 10 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 11 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 13 | today: "今天", 14 | format: "yyyy年mm月dd日", 15 | weekStart: 1 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /src/charting.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require('./kotools'); 4 | 5 | var charting = {}; 6 | 7 | charting.colors = d3.scale.ordinal().range(["#1f77b4", "#2ca02c", "#d62728", "#393b79", "#ff7f0e", "#8c564b", "#843c39"]); 8 | 9 | charting.getElementAndCheckData = function (element, data) { 10 | var el = d3.select(element); 11 | if (data === null || data === undefined || data.length === 0) { 12 | element.innerHTML = "No data available"; 13 | return null; 14 | } 15 | element.innerHTML = ""; 16 | return el; 17 | }; 18 | 19 | charting.legendFont = function(longest){ 20 | if (longest > 20) { 21 | return 8; 22 | } 23 | if(longest > 15) { 24 | return 10; 25 | } 26 | if(longest > 10) { 27 | return 12; 28 | } 29 | return 13; 30 | } 31 | 32 | charting.getLegendWidthAndFontSize = function (data) { 33 | //when there is no legend, just return 0 pixels 34 | if (!data || data.length === 0) { 35 | return 0; 36 | } 37 | var longest = d3.max(data, function (el) { 38 | return el.length; 39 | }); 40 | // we determine the optimal font size and from it calculate the rest (rectangle size and legend width) 41 | var fontSize = charting.legendFont(longest); 42 | var rectangleSize = fontSize + 2; 43 | return { 44 | fontSize: fontSize + "px", 45 | width: rectangleSize + (fontSize - 3) * longest, 46 | rectangle: rectangleSize 47 | }; 48 | }; 49 | 50 | charting.showStandardLegend = function (parent, data, color, showLegend, height) { 51 | if (showLegend) { 52 | var legendDims = charting.getLegendWidthAndFontSize(data); 53 | 54 | var legend = parent 55 | .append("svg") 56 | .attr("width", legendDims.width) 57 | .selectAll("g") 58 | .data(data) 59 | .enter().append("g") 60 | .attr("transform", function (d, i) { return "translate(0," + i * (legendDims.rectangle + 4) + ")"; }); 61 | 62 | legend.append("rect") 63 | .attr("width", legendDims.rectangle) 64 | .attr("height", legendDims.rectangle) 65 | .style("fill", function(i) { return color(i); }); 66 | 67 | 68 | legend.append("text") 69 | .attr("x", legendDims.rectangle + 4) 70 | .attr("y", legendDims.rectangle / 2) 71 | .attr("font-size", legendDims.fontSize) 72 | .attr("dy", ".35em") 73 | .text(function (t) { return t; }); 74 | } 75 | }; 76 | 77 | charting.headerStyle = function (el) { 78 | el 79 | .style("text-align", "left") 80 | .style("font-size", "12px") 81 | .style("font-family", "sans-serif") 82 | .style("margin-bottom", "4px") 83 | .style("color", "#FFFFFF") 84 | .style("font-weight", "bold") 85 | .style("clear", "both") 86 | .style("float", "left"); 87 | }; 88 | 89 | charting.valueStyle = function (el) { 90 | el 91 | .style("text-align", "left") 92 | .style("font-size", "12px") 93 | .style("font-family", "sans-serif") 94 | // botom marging is 4 so that the padding of the tooltip on bottom is 6, gives 10 as the padding 95 | // on top of the tooltip 96 | .style("margin-bottom", "4px") 97 | .style("margin-left", "6px") 98 | .style("color", "#FFFFFF") 99 | .style("float", "left"); 100 | }; 101 | 102 | charting.showTooltip = function (info) { 103 | if(d3.select("#toolTipBorder")[0]){ 104 | charting.createTooltip(); 105 | } 106 | 107 | var tooltip = d3.select("#toolTipBorder"); 108 | var tooltipContent = d3.select("#toolTip"); 109 | var key; 110 | var value; 111 | 112 | tooltipContent.html(""); 113 | for (key in info) { 114 | if (info.hasOwnProperty(key)) { 115 | value = info[key]; 116 | charting.headerStyle(tooltipContent.append("div").text(key)); 117 | 118 | if (value) { 119 | if (koTools.isDate(value)) { 120 | charting.valueStyle(tooltipContent.append("div").text(value.toFormattedString())); 121 | } else { 122 | charting.valueStyle(tooltipContent.append("div").text(value)); 123 | } 124 | } 125 | } 126 | } 127 | 128 | tooltip.transition() 129 | .duration(200) 130 | .style("opacity", ".83"); 131 | 132 | tooltip.style("left", (d3.event.pageX + 15) + "px") 133 | .style("top", (d3.event.pageY - 75) + "px"); 134 | }; 135 | 136 | charting.hideTooltip = function () { 137 | var toolTip = d3.select("#toolTipBorder"); 138 | toolTip.transition() 139 | .duration(300) 140 | .style("opacity", "0"); 141 | }; 142 | 143 | charting.createTooltip = function () { 144 | var tooltip = d3.select("body") 145 | .append("div"); 146 | 147 | tooltip 148 | .attr("id", "toolTipBorder") 149 | .style("position", "absolute") 150 | .style("opacity", 0) 151 | .style("background-color", "#111111") 152 | .style("border-radius", "6px") 153 | .style("padding", "10px") 154 | .style("padding-bottom", "6px") 155 | .append("div") 156 | .attr("id", "toolTip") 157 | .style("z-index", 100000); 158 | }; 159 | 160 | charting.getDimensions = function (options, el) { 161 | var dims = {}; 162 | dims.margin = { top: options.top || 20, right: options.right || 50, bottom: options.bottom || 30 , left: options.left || 50 }; 163 | dims.width = options.width || 200; 164 | dims.height = options.height || 100; 165 | dims.yAxisWidth = 40; 166 | if(options.yAxisLabel) { 167 | dims.yAxisWidth = 80; 168 | } 169 | if (options.xAxisTextAngle) { 170 | dims.margin.bottom = options.xAxisTextAngle*50/90 + dims.margin.bottom; 171 | } 172 | 173 | dims.legendWidth = 0; 174 | 175 | // TODO: would be good to have the real width of the leged here 176 | if(options.legend){ 177 | dims.legendWidth = 150; 178 | } 179 | 180 | if(options.xAxisLabel) { 181 | dims.margin.bottom+= 15; 182 | } 183 | dims.containerHeight = dims.height + dims.margin.top + dims.margin.bottom; 184 | dims.containerWidth = dims.width + dims.yAxisWidth + dims.margin.left + dims.margin.right; 185 | 186 | if (options.fillParentController) { 187 | dims.containerWidth = koTools.getWidth(el) - dims.legendWidth - 20; 188 | dims.containerHeight = d3.max([koTools.getHeight(el), options.height]) - 30; 189 | 190 | dims.height = dims.containerHeight - (dims.margin.top + dims.margin.bottom); 191 | dims.width = dims.containerWidth - (dims.yAxisWidth + dims.margin.left + dims.margin.right); 192 | dims.fillParentController = true; 193 | } 194 | 195 | if (options.horizontalSlider) { 196 | var sliderSpace = 30; 197 | var afterSlider = 60; 198 | 199 | if (options.xAxisTextAngle) { 200 | sliderSpace = 60; 201 | afterSlider = 80; 202 | } 203 | 204 | dims.sliderHeight = 20; 205 | dims.containerHeight = dims.height + dims.sliderHeight + sliderSpace + afterSlider; 206 | dims.sliderOffset = dims.height + sliderSpace; 207 | } 208 | return dims; 209 | }; 210 | 211 | charting.appendContainer = function (el, dims) { 212 | var svg = el.append("svg") 213 | .attr("width", dims.containerWidth) 214 | .attr("height", dims.containerHeight) 215 | .append("g") 216 | .attr("transform", "translate(" + dims.margin.left + "," + dims.margin.top + ")"); 217 | 218 | return svg; 219 | }; 220 | 221 | charting.createXAxis = function (svg,options,x,dims) { 222 | var xAxis = d3.svg.axis() 223 | .scale(x) 224 | .orient("bottom"); 225 | 226 | if (options.xFormat){ 227 | xAxis.tickFormat(options.xFormat); 228 | } 229 | 230 | if (options.tickValues){ 231 | xAxis.tickValues(options.tickValues); 232 | } 233 | 234 | var axis = svg.append("g") 235 | .attr("class", "x axis") 236 | .attr("transform", "translate(0," + dims.height + ")") 237 | .call(xAxis); 238 | 239 | charting.xAxisStyle(axis); 240 | charting.rotateAxisText(axis, options); 241 | 242 | if (options.xAxisLabel){ 243 | svg.append("text") 244 | .style("font-size", "13") 245 | .style("font-family", "sans-serif") 246 | .style("font-weight","bold") 247 | .attr("class", "x label") 248 | .attr("text-anchor", "end") 249 | .attr("x", (dims.width / 2) + 35 ) 250 | .attr("y", dims.height + dims.margin.bottom) 251 | .text(options.xAxisLabel); 252 | } 253 | return xAxis; 254 | }; 255 | 256 | charting.rotateAxisText = function (axis, options) { 257 | if (options.xAxisTextAngle) { 258 | axis.selectAll("text") 259 | .attr("y", 0) 260 | .attr("x", 9) 261 | .attr("dy", ".35em") 262 | .attr("transform", "rotate(" + options.xAxisTextAngle + ")") 263 | .style("text-anchor", "start"); 264 | } 265 | }; 266 | 267 | charting.yAxisStyle = function(el) 268 | { 269 | el.select("path").style("display","none"); 270 | el.selectAll("line").style("shape-rendering","crispEdges").style("stroke","#000"); 271 | el.selectAll("line").style("stroke","#777").style("stroke-dasharray","2.2"); 272 | el.style("font-family", "sans-serif"); 273 | el.style("font-size", "13"); 274 | }; 275 | 276 | charting.xAxisStyle = function(el){ 277 | el.select("path").style("display","none"); 278 | el.select("line").style("shape-rendering","crispEdges").style("stroke","#000"); 279 | el.selectAll("line").style("stroke","#000"); 280 | el.style("font-family", "sans-serif"); 281 | el.style("font-size", "13"); 282 | return el; 283 | }; 284 | 285 | charting.createYAxis = function (svg, options, yScale, dims) { 286 | var yAxis = d3.svg.axis().scale(yScale).tickSize(dims.width).orient("right"); 287 | 288 | if (options.yFormat){ 289 | yAxis.tickFormat(options.yFormat); 290 | } 291 | 292 | var axis = svg.append("g") 293 | .attr("class", "y axis") 294 | .call(yAxis); 295 | 296 | charting.yAxisStyle(axis); 297 | 298 | if (options.yAxisLabel) { 299 | svg.append("text") 300 | .attr("class", "y label") 301 | .attr("text-anchor", "end") 302 | .attr("y", 0) 303 | .attr("dy", ".75em") 304 | .style("font-size", "13") 305 | .style("font-family", "sans-serif") 306 | .style("font-weight","bold") 307 | .text(options.yAxisLabel) 308 | .attr("transform", "translate(" + (dims.width+dims.yAxisWidth) + "," + (dims.height/2) + ")rotate(-90)"); 309 | } 310 | return yAxis; 311 | }; 312 | 313 | charting.determineXScale = function (data, def,options) { 314 | if (!def) { 315 | def = { 316 | allNumbers: true, 317 | allDates: true, 318 | min: Number.MAX_VALUE, 319 | max: Number.MIN_VALUE, 320 | xKeys:[] 321 | }; 322 | } 323 | 324 | var newKeys = data.map(function (v) { 325 | if (!koTools.isNumber(v)){ 326 | def.allNumbers = false; 327 | } 328 | if (!koTools.isDate(v)){ 329 | def.allDates = false; 330 | } 331 | if (v < def.min){ 332 | def.min = v; 333 | } 334 | if (v > def.max){ 335 | def.max = v; 336 | } 337 | return v; 338 | }); 339 | 340 | if(def.xKeys){ 341 | def.xKeys = def.xKeys.concat(newKeys); 342 | }else{ 343 | def.xKeys = newKeys; 344 | } 345 | def.scaleType = def.allNumbers ? 'linear' : def.allDates ? 'date' : 'ordinal'; 346 | def.xFormat = def.allDates ? koTools.getIdealDateFormat([def.min,def.max]) : null; 347 | if(!options.xFormat){ 348 | options.xFormat = def.xFormat; 349 | } 350 | 351 | return def; 352 | }; 353 | 354 | charting.getXScaleForMultiLines = function (data,options) { 355 | var def = null; 356 | data.forEach(function(i) { 357 | def = charting.determineXScale(i.values.map(function(v) { 358 | return v.x; 359 | }), def,options); 360 | }); 361 | return def; 362 | }; 363 | 364 | charting.getYScaleDefForMultiline = function (data,options,filteredDomain){ 365 | var def = null; 366 | data.forEach(function(i) { 367 | var filteredData = i.values; 368 | if(filteredDomain){ 369 | filteredData = i.values.filter(function(d){ 370 | return d.x >= filteredDomain[0] && d.x <= filteredDomain[1]; 371 | }); 372 | } 373 | def = charting.determineYScale(filteredData.map(function(v) { 374 | return v.y; 375 | }), def,options); 376 | }); 377 | return def; 378 | }; 379 | 380 | charting.determineYScale = function (data, def,options) { 381 | if (!def) { 382 | def = { 383 | min: Number.MAX_VALUE, 384 | max: Number.MIN_VALUE 385 | }; 386 | } 387 | 388 | data.forEach(function(v) { 389 | if (v < def.min){ 390 | def.min = v; 391 | } 392 | if (v > def.max){ 393 | def.max = v; 394 | } 395 | }); 396 | 397 | //setting up margings. how much more on the bottom and on the top of the chart should be shown 398 | //bellow or above the max and minimum value - carefull to handle negative max values 399 | if(options.marginCoef){ 400 | var reversedCoef = - options.marginCoef; 401 | def.max = def.max > 0 ? def.max * options.marginCoef : def.max * reversedCoef; 402 | def.min = def.min < 0 ? def.min * options.marginCoef : def.min * reversedCoef; 403 | } 404 | 405 | //the min and max can also be specified in the options directly 406 | def.min = options.yMin || def.min; 407 | def.max = options.yMax || def.max; 408 | return def; 409 | }; 410 | 411 | //takes the result of determineXScale and creates D3 scale 412 | charting.getXScaleFromConfig = function (def,dims) { 413 | var x; 414 | 415 | if (def.scaleType === 'linear') { 416 | x = d3.scale.linear().range([0, dims.width], 0.1); 417 | x.domain([def.min, def.max]); 418 | } else if (def.scaleType === 'ordinal') { 419 | x = d3.scale.ordinal() 420 | .rangeRoundBands([0, dims.width], 0.1); 421 | x.domain(def.xKeys); 422 | } else if (def.scaleType === 'date') { 423 | x = d3.time.scale().range([0, dims.width], 0.1); 424 | x.domain([def.min, def.max]); 425 | x.ticks(10); 426 | } else { 427 | throw "invalid scale type"; 428 | } 429 | return x; 430 | }; 431 | 432 | charting.xGetter = function (scaleDef, x) { 433 | return function(d) { 434 | if (scaleDef.scaleType === 'ordinal'){ 435 | return x(d) + x.rangeBand() / 2; 436 | } 437 | if (scaleDef.scaleType === 'date' || scaleDef.scaleType === 'linear'){ 438 | return x(d); 439 | } 440 | throw "invalid Scale Type"; 441 | }; 442 | }; 443 | 444 | charting.createVerticalLine = function (svg,x,y){ 445 | return svg.append("line") 446 | .attr("x1",x) 447 | .attr("y1", 0) 448 | .attr("x2", x) 449 | .attr("y2", y) 450 | .attr("stroke-width", 2) 451 | .attr("stroke", "black"); 452 | }; 453 | 454 | charting.mouseCoordinates = function (context,x,y){ 455 | var coordinates = d3.mouse(context); 456 | return { 457 | x : coordinates[0], 458 | y : coordinates[1], 459 | rY: y.invert(coordinates[1]), 460 | rX: x.invert(coordinates[0]) 461 | }; 462 | }; 463 | 464 | charting.moveLine = function(line, x){ 465 | var current = line.attr("x1"); 466 | var trans = x - current; 467 | line.attr("transform", "translate(" + trans + ",0)"); 468 | }; 469 | 470 | charting.createMouseMoveListener = function(svg,dims,callback){ 471 | svg.append("rect") 472 | .attr("class", "overlay") 473 | .attr("width", dims.width) 474 | .attr("height", dims.height) 475 | .style("fill","none") 476 | .style("pointer-events","all") 477 | .on("mousemove", callback); 478 | }; 479 | 480 | charting.createOrMoveVerticalLine = function(line,svg,dims,x){ 481 | if (!line) { 482 | return charting.createVerticalLine(svg,x,dims.height); 483 | } 484 | 485 | charting.moveLine(line,x); 486 | return line; 487 | }; 488 | 489 | charting.passOptions = function (func, options){ 490 | return function(d) { 491 | func(options, d); 492 | }; 493 | }; 494 | 495 | charting.singlePointOver = function (element, options, d) { 496 | var info = {}; 497 | var xValue = options.xFormat ? options.xFormat(d.x) : d.x; 498 | info[xValue] = ""; 499 | var valueName = d.linename || "value"; 500 | info[valueName] = d.y; 501 | charting.showTooltip(info); 502 | d3.select(element).style("fill", "black"); 503 | }; 504 | 505 | charting.singlePointOut = function (element) { 506 | d3.select(element).style("fill", "white"); 507 | charting.hideTooltip(); 508 | }; 509 | 510 | 511 | module.exports = charting; 512 | -------------------------------------------------------------------------------- /src/charts/barchart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require('./../kotools'); 4 | var charting = require('./../charting'); 5 | 6 | //accepts and array of objects. one property of each object is used as the x-coordinate 7 | //(determined by the xcoord option, which by default is set to 'x') 8 | //the rest of the properties is stacked to the chart 9 | charting.barChart = function (data, element, options, lineData) { 10 | var el = charting.getElementAndCheckData(element, data); 11 | if (!el){ 12 | return; 13 | } 14 | 15 | var defaultOptions = { 16 | legend: true, 17 | width: 600, 18 | height: 200, 19 | xUnitName: 'x', 20 | itemName: 'Item', 21 | xcoord: 'x' 22 | }; 23 | 24 | options = koTools.setDefaultOptions(defaultOptions, options); 25 | var xcoord = options.xcoord; 26 | 27 | // not all the items do have the same set of properties, therefor scan them all and concatenate the result 28 | var keys = []; 29 | data.map(function (i) { 30 | var itemKeys = d3.keys(i).filter(function (key) { return key !== xcoord && keys.indexOf(key) < 0; }); 31 | keys = keys.concat(itemKeys); 32 | }); 33 | 34 | //we need color for each possible variable 35 | var color = charting.colors.domain(keys); 36 | 37 | var dims = charting.getDimensions(options, el); 38 | 39 | var xKeys = data.map(function(d){return d[xcoord];}); 40 | 41 | // for bar chart the x-scale is always ordinary with range bounds 42 | // but we run the determining X Scale method anyway 43 | // because it can help determine the xFormat 44 | charting.determineXScale(xKeys, null, options); 45 | 46 | var x = d3.scale.ordinal() 47 | .rangeRoundBands([0, dims.width], 0.3); 48 | 49 | var y = d3.scale.linear() 50 | .rangeRound([dims.height, 0]); 51 | 52 | //runs overs all the data. copies the result to a new array. 53 | //for each item we need y0 and y1 - are the y coordinates of the rectangle 54 | //it is bit tricky to have a something that works for stacked and grouped chart 55 | var arranged = []; 56 | var arrangedByX = {}; 57 | data.forEach(function (d) { 58 | var newD = { x: d[xcoord] }; 59 | var y0Neg = 0; 60 | var y0Pos = 0; 61 | 62 | 63 | var values = []; 64 | color.domain().forEach(function (m) { 65 | if (!koTools.isNumber(d[m]) || d[m] === 0 || d[m] === null){ 66 | return; 67 | } 68 | var xLabel = newD.x; 69 | if (options.xFormat){ 70 | xLabel = options.xFormat(newD.x); 71 | } 72 | var formattedValue = d[m]; 73 | if (options.yFormat){ 74 | formattedValue = options.yFormat(d[m]); 75 | } 76 | 77 | var value = { 78 | name:m, 79 | val: d[m], 80 | x: newD.x, 81 | xLabel: xLabel, 82 | xUnitName: options.xUnitName, 83 | formattedValue: formattedValue 84 | }; 85 | 86 | if (d[m] > 0 && options.style === "stack") { 87 | value.y0 = y0Pos; 88 | y0Pos += d[m]; 89 | value.y1 = y0Pos; 90 | } else if (d[m] < 0 && options.style === "stack"){ 91 | var y1 = y0Neg; 92 | y0Neg += d[m]; 93 | value.y0 = y0Neg; 94 | value.y1 = y1; 95 | } else if (d[m] > 0 && options.style !== "stack"){ 96 | value.y0 = 0; 97 | value.y1 = d[m]; 98 | } else if(d[m] < 0 && options.style !== "stack"){ 99 | value.y0 = d[m]; 100 | value.y1 = 0; 101 | } 102 | values.push(value); 103 | }); 104 | 105 | newD.values = values; 106 | newD.totalPositive = d3.max(newD.values, function (v) { return v.y1; }); 107 | newD.totalNegative = d3.min(newD.values, function (v) { return v.y0; }); 108 | arranged.push(newD); 109 | arrangedByX[newD.x] = newD; 110 | }); 111 | 112 | charting.showStandardLegend(el, keys,color, options, dims); 113 | 114 | var svg = charting.appendContainer(el, dims); 115 | 116 | x.domain(xKeys); 117 | if (options.style === "stack") { 118 | y.domain([ 119 | d3.min(arranged, function (d) { 120 | return d.totalNegative; 121 | }), d3.max(arranged, function (d) { 122 | if (!d){ 123 | return 0; 124 | } 125 | return d.totalPositive; 126 | }) 127 | ]); 128 | } else { 129 | y.domain( 130 | [ 131 | d3.min(arranged, function (d) { 132 | return d3.min(d.values, 133 | function (i) { 134 | if (i.val < 0){ 135 | return i.val; 136 | } 137 | return 0; 138 | }); 139 | }), 140 | d3.max(arranged, function (d) { 141 | return d3.max(d.values, 142 | function (i) { return i.val; }); 143 | }) 144 | ]); 145 | } 146 | 147 | //for the groupped chart 148 | var x1 = d3.scale.ordinal(); 149 | x1.domain(keys).rangeRoundBands([0, x.rangeBand()]); 150 | 151 | charting.createXAxis(svg, options, x, dims); 152 | charting.createYAxis(svg, options, y, dims); 153 | 154 | 155 | var onBarOver = function (d) { 156 | var column = arrangedByX[d.x]; 157 | d3.select(this).style("opacity", 1); 158 | var info = {}; 159 | info[d.xLabel] = ""; 160 | info[d.name] = d.formattedValue; 161 | if (column.totalNegative === 0 && options.style === "stack"){ 162 | info[d.name] += " (" + koTools.toPercent(d.val / column.totalPositive) + ")"; 163 | } 164 | charting.showTooltip(info); 165 | }; 166 | 167 | var onBarOut = function () { 168 | d3.select(this).style("stroke", 'none'); 169 | d3.select(this).style("opacity", 0.9); 170 | charting.hideTooltip(); 171 | }; 172 | 173 | var group = svg.selectAll(".xVal") 174 | .data(arranged) 175 | .enter().append("g") 176 | .attr("class", "g") 177 | .attr("transform", function (d) { return "translate(" + x(d.x) + ",0)"; }); 178 | 179 | var rectangles = group.selectAll("rect") 180 | .data(function (d) { return d.values; }) 181 | .enter().append("rect"); 182 | 183 | if (options.style === "stack") { 184 | rectangles.attr("width", x.rangeBand()); 185 | } else { 186 | rectangles.attr("width", x1.rangeBand()) 187 | .attr("x", function (d) { 188 | return x1(d.name); 189 | }); 190 | } 191 | 192 | rectangles.attr("y", function (d) { 193 | return y(d.y1); 194 | }) 195 | .attr("height", function (d) { 196 | var height = Math.abs(y(d.y0) - y(d.y1)); 197 | return height; 198 | }) 199 | .on("mouseover", onBarOver) 200 | .on("mouseout", onBarOut) 201 | .style("opacity", 0.9) 202 | .style("cursor", "pointer") 203 | .style("fill", function (d) { 204 | return color(d.name); 205 | }); 206 | 207 | //Add the single line for the cashflow like charts 208 | if (!lineData || lineData.length === 0){ 209 | return; 210 | } 211 | 212 | var lineY = d3.scale.linear() 213 | .range([dims.height, 0]); 214 | 215 | var line = d3.svg.line() 216 | .interpolate("linear") 217 | .x(function (d) { 218 | return x(d.x) + x.rangeBand() / 2; 219 | }) 220 | .y(function (d) { 221 | return lineY(d.y); 222 | }); 223 | 224 | //in some cases it makes sense to use the same scale for both 225 | //typically the cash-flow chart 226 | //for other cases (line volumne / units correlations a separate scale should be used for each) 227 | if (!options.sameScaleLinesAndBars) { 228 | lineY.domain([ 229 | 0, 230 | d3.max(lineData, function (v) { return v.y; }) 231 | ]); 232 | } else { 233 | lineY.domain(y.domain()); 234 | } 235 | 236 | var yAxisLeft = d3.svg.axis() 237 | .scale(lineY) 238 | .orient("left"); 239 | 240 | var leftAxis = svg.append("g") 241 | .call(yAxisLeft); 242 | 243 | charting.yAxisStyle(leftAxis); 244 | 245 | svg.append("path") 246 | .attr("d", line(lineData)) 247 | .style("stroke", "blue") 248 | .style("stroke-width", 2) 249 | .style("fill", "none"); 250 | 251 | var circles = svg.selectAll("circle") 252 | .data(lineData) 253 | .enter() 254 | .append("circle"); 255 | 256 | circles.attr("cx", function (d) { return x(d.x) + x.rangeBand() / 2; }) 257 | .attr("cy", function (d) { return lineY(d.y); }) 258 | .attr("r", function () { return 4; }) 259 | .style("fill", "white") 260 | .attr("r", function () { return 3; }) 261 | .style("fill", "white") 262 | .style("stroke-width", "1") 263 | .style("stroke", "black") 264 | .style("cursor", "pointer") 265 | .on("mouseover", function(d) { charting.singlePointOver(this, options, d);}) 266 | .on("click", function(d) { charting.singlePointOver(this, options, d);}) 267 | .on("mouseout", function(d) { charting.singlePointOut(this);}); 268 | }; 269 | -------------------------------------------------------------------------------- /src/charts/bubblechart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var koTools = require('./../kotools'); 3 | var charting = require('./../charting'); 4 | 5 | charting.bubbleChart = function (data, element, options) { 6 | var el = charting.getElementAndCheckData(element, data); 7 | if (!el) { 8 | return; 9 | } 10 | 11 | var defaultOptions = { 12 | legend: true, 13 | width: 500, 14 | height: 200, 15 | maxBubbleSize: 50, 16 | bubbleHorizontal: function(d) { return d.x; }, 17 | bubbleVertical: function(d) { return d.y; }, 18 | bubbleSize: function(d) { return d.size; }, 19 | bubbleColor: function(d) { return d.color; }, 20 | horizontalLabel: 'x', 21 | verticalLabel: 'y', 22 | sizeLabel: 'size', 23 | typeLabel: 'type', 24 | xAxisLabel: false, 25 | yAxisLabel: false, 26 | xAxisTextAngle: null 27 | }; 28 | 29 | options = koTools.setDefaultOptions(defaultOptions, options); 30 | 31 | var dims = charting.getDimensions(options, el); 32 | var horizontalValues = data.map(options.bubbleHorizontal); 33 | var verticalValues = data.map(options.bubbleVertical); 34 | 35 | var bubbleSizes = data.map(options.bubbleSize); 36 | bubbleSizes.sort(d3.ascending); 37 | 38 | var maxBubbleSize = d3.max(bubbleSizes); 39 | var minBubbleSize = d3.min(bubbleSizes); 40 | 41 | var xScaleDef = charting.determineXScale(horizontalValues, null, options); 42 | var xScale = charting.getXScaleFromConfig(xScaleDef,dims); 43 | var yScaleDef = charting.determineYScale(verticalValues, null, options); 44 | var yScale = d3.scale.linear().domain([yScaleDef.min, yScaleDef.max]).range([dims.height, 0]); 45 | var radiusScale = d3.scale.pow().exponent(0.4).domain([minBubbleSize, maxBubbleSize]).range([1, options.maxBubbleSize]).clamp(true); 46 | 47 | var colors = koTools.distinct(data, options.bubbleColor); 48 | var colorScale = charting.colors.domain(colors); 49 | 50 | charting.showStandardLegend(el, colors, colorScale, options, dims); 51 | var svg = charting.appendContainer(el, dims); 52 | 53 | charting.createXAxis(svg, options, xScale, dims); 54 | charting.createYAxis(svg, options, yScale, dims); 55 | 56 | var bubblenodeMouseout = function () { 57 | d3.select(this).style("opacity", 0.8); 58 | charting.hideTooltip(); 59 | }; 60 | 61 | var bubblenodeMouseover = function (d) { 62 | d3.select(this).style("opacity", 1); 63 | var info = {}; 64 | info[options.typeLabel] = options.bubbleColor(d); 65 | info[options.sizeLabel] = options.bubbleSize(d); 66 | info[options.verticalLabel] = options.bubbleVertical(d); 67 | info[options.horizontalLabel] = options.bubbleHorizontal(d); 68 | 69 | charting.showTooltip(info); 70 | }; 71 | 72 | var xGetter = charting.xGetter(xScaleDef, xScale); 73 | 74 | svg.append("g") 75 | .attr("class", "dots") 76 | .selectAll(".dot") 77 | .data(data) 78 | .enter().append("circle") 79 | .attr("class", "dot") 80 | .style("fill", function (d) { return colorScale(options.bubbleColor(d)); }) 81 | .style("opacity", 0.8) 82 | .attr("cx", function (d) { return xGetter(options.bubbleHorizontal(d)); }) 83 | .attr("cy", function (d) { return yScale(options.bubbleVertical(d)); }) 84 | .attr("r", function (d) { return radiusScale(options.bubbleSize(d)); }) 85 | .style("cursor", "pointer") 86 | .on("mouseover", bubblenodeMouseover) 87 | .on("click", bubblenodeMouseover) 88 | .on("mouseout", bubblenodeMouseout); 89 | }; 90 | -------------------------------------------------------------------------------- /src/charts/chordchart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require ('./../kotools'); 4 | var charting = require('./../charting'); 5 | 6 | charting.chordChart = function(data, element, options) { 7 | 8 | var el = charting.getElementAndCheckData(element, data); 9 | if (!el){ 10 | return; 11 | } 12 | 13 | var defaultOptions = { 14 | width: 800, 15 | height: 800, 16 | fillParentController:false, 17 | chordMouseOver: null 18 | }; 19 | 20 | options = koTools.setDefaultOptions(defaultOptions, options); 21 | var dims = charting.getDimensions(options, el); 22 | var outerRadius = Math.min(dims.width, dims.height) / 2 - 100; 23 | var innerRadius = outerRadius - 24; 24 | 25 | //get the name of the item by id 26 | var descGetter = function (item) { 27 | if(options.hideNames){ 28 | return item.index + 1; 29 | } 30 | return data.names[item.index]; 31 | }; 32 | 33 | var color = charting.colors; 34 | 35 | var arc = d3.svg.arc() 36 | .innerRadius(innerRadius) 37 | .outerRadius(outerRadius); 38 | 39 | var layout = d3.layout.chord() 40 | .padding(0.04); 41 | 42 | var path = d3.svg.chord() 43 | .radius(innerRadius); 44 | 45 | var svg = el.append("svg") 46 | .attr("width", dims.width) 47 | .attr("height", dims.height) 48 | .append("g") 49 | .attr("id", "circle") 50 | .attr("transform", "translate(" + dims.width / 2 + "," + dims.height / 2 + ")"); 51 | 52 | var formatValue = function(value){ 53 | if(options.chordFormat){ 54 | value = options.chordFormat(value); 55 | } 56 | return value; 57 | }; 58 | 59 | var chordMouseOver = function (g, i) { 60 | var a1 = data.names[g.source.index]; 61 | var a2 = data.names[g.source.subindex]; 62 | var title = a1 + " - " + a2; 63 | var info = {}; 64 | var value = formatValue(g.source.value); 65 | info[title] = value; 66 | 67 | //get all except this chord and put it in background 68 | svg.selectAll(".chord") 69 | .filter(function (d, index) { 70 | return i !== index; 71 | }) 72 | .transition() 73 | .style("opacity", 0.1); 74 | 75 | charting.showTooltip(info); 76 | }; 77 | 78 | var chordMouseOut = function (g, i) { 79 | svg.selectAll(".chord") 80 | .transition() 81 | .style("opacity", 1); 82 | 83 | charting.hideTooltip(); 84 | }; 85 | 86 | var mouseOverArc = function(opacity) { 87 | return function (g, i) { 88 | svg.selectAll(".chord") 89 | .filter(function (d) { 90 | return d.target.index !== i && d.source.index !== i; 91 | }) 92 | .transition() 93 | .style("opacity", opacity); 94 | 95 | var info = {}; 96 | var value = formatValue(g.value); 97 | info[descGetter(g)] = value; 98 | charting.showTooltip(info); 99 | }; 100 | }; 101 | 102 | layout.matrix(data.matrix); 103 | var group = svg.selectAll(".group") 104 | .data(layout.groups) 105 | .enter().append("g") 106 | .attr("class", "group"); 107 | 108 | 109 | group.append("path") 110 | .attr("id", function(d, i) { return "group" + i; }) 111 | .attr("d", arc) 112 | .style("fill", function(d, i) { return color(i); }) 113 | .on("mouseover", mouseOverArc(0.1)) 114 | .on("mouseout", mouseOverArc(1)); 115 | 116 | group.append("text") 117 | .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) 118 | .attr("dy", ".35em") 119 | .attr("transform", function(d) { 120 | return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + 121 | "translate(" + (innerRadius + 26) + ")" + 122 | (d.angle > Math.PI ? "rotate(180)" : ""); 123 | }) 124 | .style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) 125 | .attr("font-family", "Open Sans, sans-serif") 126 | .style("font-size", "13px") 127 | .text(descGetter); 128 | 129 | // Add the chords. 130 | svg.selectAll(".chord") 131 | .data(layout.chords) 132 | .enter().append("path") 133 | .attr("class", "chord") 134 | .style("fill", function(d) { return color(d.source.index); }) 135 | .style("cursor","pointer") 136 | .attr("d", path) 137 | .on("mouseover", chordMouseOver) 138 | .on("mouseout", chordMouseOut) 139 | .on("click", chordMouseOver); 140 | }; 141 | -------------------------------------------------------------------------------- /src/charts/histogramchart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require ('./../kotools'); 4 | var charting = require('./../charting'); 5 | 6 | charting.histogram = function(data, element, options) { 7 | var defaultOptions = { 8 | bins: 80, 9 | width: 500, 10 | fillParentController:false, 11 | histogramType: 'frequency', 12 | rangeRounding: 2 13 | }; 14 | 15 | var el = charting.getElementAndCheckData(element,data); 16 | if (el === null) { 17 | return; 18 | } 19 | 20 | options = koTools.setDefaultOptions(defaultOptions, options); 21 | var dims = charting.getDimensions(options,el); 22 | 23 | var histogramData = d3.layout.histogram() 24 | .frequency(options.histogramType === 'frequency') 25 | .bins(options.bins)(data); 26 | 27 | var minX = koTools.isValidNumber(options.min) ? options.min : d3.min(histogramData, function (d) { return d.x; }); 28 | 29 | var x = d3.scale.linear() 30 | .domain([ 31 | minX, 32 | d3.max(histogramData, function(d) { return d.x; }) 33 | ]) 34 | .range([0, dims.width-10]); 35 | var columnWidth = x(minX + histogramData[0].dx) - 1; 36 | 37 | var y = d3.scale.linear() 38 | .domain([0, d3.max(histogramData, function(d) { return d.y; })]) 39 | .range([dims.height, 0]); 40 | 41 | var svg = charting.appendContainer(el, dims); 42 | 43 | var bar = svg.selectAll(".bar") 44 | .data(histogramData) 45 | .enter().append("g") 46 | .attr("class", "bar") 47 | .attr("transform", function (d) { 48 | return "translate(" + x(d.x) + "," + y(d.y) + ")"; 49 | }); 50 | 51 | 52 | var onBarOver = function (d) { 53 | d3.select(this).style("opacity", 1); 54 | var header = options.histogramType == "frequency" ? "count": "probability"; 55 | var info = {}; 56 | info[header] = d.y; 57 | info["range"] = d.x.toFixed(options.rangeRounding) + " - " + (d.x+d.dx).toFixed(options.rangeRounding); 58 | charting.showTooltip(info); 59 | }; 60 | 61 | var onBarOut = function () { 62 | charting.hideTooltip(); 63 | d3.select(this).style("opacity", 0.8); 64 | }; 65 | 66 | bar.append("rect") 67 | .attr("x", 1) 68 | .attr("width",columnWidth) 69 | .attr("height", function(d) { 70 | return dims.height - y(d.y); 71 | }) 72 | .attr("fill","#1f77b4") 73 | .attr("opacity",0.8) 74 | .style("cursor", "pointer") 75 | .on("mouseover",onBarOver) 76 | .on("mouseout",onBarOut); 77 | 78 | charting.createXAxis(svg,options,x,dims); 79 | charting.createYAxis(svg, options, y, dims); 80 | 81 | var line = d3.svg.line() 82 | .interpolate("linear") 83 | .x(function (d) { return x(d.x) + x.rangeBand() / 2; }) 84 | .y(function (d) { return y(d.y); }); 85 | 86 | if(options.showProbabilityDistribution){ 87 | 88 | var min = koTools.isValidNumber(options.min) ? options.min : d3.min(data); 89 | var max = koTools.isValidNumber(options.max) ? options.max : d3.max(data); 90 | var total = d3.sum(data); 91 | 92 | var step = (max - min)/500; 93 | var expected = total / data.length; 94 | if(options.expected == 'median'){ 95 | expected = d3.median(data); 96 | } 97 | 98 | var variance = 0; 99 | var distances = []; 100 | data.forEach(function(val){ 101 | var dist = val - expected; 102 | distances.push(Math.abs(dist)); 103 | variance+= dist*dist; 104 | }); 105 | 106 | 107 | if(options.useMAD){ 108 | variance = d3.median(distances); 109 | }else{ 110 | variance= variance / data.length-1; 111 | } 112 | 113 | var i = 0; 114 | var probData = []; 115 | for (i = min;i variance * options.tolerance) { 158 | svg.append("circle") 159 | .attr("cx", x(el) + 2) 160 | .attr("cy", dims.height) 161 | .attr("r", 4) 162 | .attr("fill", "green") 163 | .attr("opacity", 0.8); 164 | } 165 | }); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/charts/linechart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require ('./../kotools'); 4 | var charting = require('./../charting'); 5 | 6 | //Takes as input collection of items [data]. Each item has two values [x] and [y]. 7 | //[{x:1, receivedEtf:123, tradedEtf:100},{x:2, receivedEtf:200, tradedEtf:100}] 8 | //[{linename:receivedEtf, values:[x:q1, y:200]}] 9 | charting.lineChart = function (data, element, options) { 10 | var el = charting.getElementAndCheckData(element, data); 11 | if (!el) { 12 | return; 13 | } 14 | 15 | var defaultOptions = { 16 | legend: true, 17 | width: 200, 18 | height: 200, 19 | horizontalLabel: 'x', 20 | verticalLabel: 'y', 21 | showDataPoints: true, 22 | verticalCursorLine: false, 23 | xAxisLabel: false, 24 | yAxisLabel: false, 25 | xAxisTextAngle: null 26 | }; 27 | 28 | options = koTools.setDefaultOptions(defaultOptions, options); 29 | 30 | data.forEach(function (singleLine) { 31 | if (!singleLine.values) { 32 | throw "Each line needs to have values property containing tuples of x and y values"; 33 | } 34 | 35 | //sort each line using the x coordinate 36 | singleLine.values.sort(function (a, b) { 37 | return d3.ascending(a.x, b.x); 38 | }); 39 | 40 | singleLine.values.forEach(function (d) { 41 | d.linename = singleLine.linename; 42 | }); 43 | }); 44 | 45 | // define all the linenames to compute thed legen width approximation 46 | var linenames = data.map(function (item) { return item.linename; }); 47 | 48 | // points collection will be initilized only if the users wants to see the line points 49 | var points = null; 50 | 51 | //we need also one color per linename 52 | var color = d3.scale.category20(); 53 | color.domain(linenames); 54 | 55 | //and helper function to get the color 56 | var getColor = function (l) { 57 | return l.color || color(l.linename); 58 | }; 59 | 60 | var dims = charting.getDimensions(options, el, linenames); 61 | 62 | var y = d3.scale.linear() 63 | .range([dims.height, 0]); 64 | 65 | var scaleDef = charting.getXScaleForMultiLines(data, options); 66 | var x = charting.getXScaleFromConfig(scaleDef, dims); 67 | var getX = function (d) { 68 | return charting.xGetter(scaleDef, x)(d.x); 69 | }; 70 | 71 | var yScaleDef = charting.getYScaleDefForMultiline(data, options); 72 | 73 | y.domain([yScaleDef.min, yScaleDef.max]); 74 | 75 | var line = d3.svg.line() 76 | .interpolate("linear") 77 | .x(getX) 78 | .y(function (d) { return y(d.y); }); 79 | 80 | var svg = charting.appendContainer(el, dims); 81 | 82 | charting.showStandardLegend(el, linenames, color, options, dims); 83 | 84 | if (options.xTick) { 85 | var xValues = scaleDef.xKeys.filter(function (k) { 86 | return k % options.xTick === 0; 87 | }); 88 | options.tickValues = xValues; 89 | } 90 | var xAxis = charting.createXAxis(svg, options, x, dims); 91 | var yAxis = charting.createYAxis(svg, options, y, dims); 92 | 93 | //howering over a line will just show a tooltip with line name 94 | var lineMouseOver = function (d) { 95 | var info = {}; 96 | // TODO: would be good to have the y value here 97 | info[d.linename] = ""; 98 | charting.showTooltip(info); 99 | }; 100 | 101 | var lines = svg.selectAll(".lines") 102 | .data(data) 103 | .enter() 104 | .append("path") 105 | .attr("class", "line") 106 | .attr("d", function (d) { 107 | return line(d.values); 108 | }) 109 | .style("stroke-width", function (d) { 110 | return d.width || 2; 111 | }) 112 | .style("stroke", function (d) { 113 | return getColor(d); 114 | }) 115 | .style("fill", "none") 116 | .on("mouseover", lineMouseOver) 117 | .on("mouseout", charting.hideTooltip) 118 | .attr("clip-path", "url(#clip)"); 119 | 120 | if (options.showDataPoints) { 121 | 122 | var allPoints = data.length === 1 ? data[0].values : data.reduce(function(a, b) { 123 | if (a.values) { 124 | return a.values.concat(b.values); 125 | } 126 | return a.concat(b.values); 127 | }); 128 | 129 | points = svg.selectAll(".point") 130 | .data(allPoints) 131 | .enter() 132 | .append("circle") 133 | .attr("cx", getX) 134 | .attr("cy", function (d) { return y(d.y); }) 135 | .attr("r", function () { return 3; }) 136 | .style("fill", "white") 137 | .style("stroke-width", "1") 138 | .style("stroke", "black") 139 | .style("cursor", "pointer") 140 | .on("mouseover", function(d) { charting.singlePointOver(this, options, d);}) 141 | .on("click", function(d) { charting.singlePointOver(this, options, d);}) 142 | .on("mouseout", function() { charting.singlePointOut(this);}) 143 | .attr("clip-path", "url(#clip)"); 144 | } 145 | 146 | if (options.horizontalSlider) { 147 | var context = svg.append("g") 148 | .attr("transform", "translate(" + "0" + "," + dims.sliderOffset + ")") 149 | .attr("class", "context"); 150 | 151 | var slidderScale = charting.getXScaleFromConfig(scaleDef, dims); 152 | 153 | var allTicks = x.ticks(); 154 | var startMin = allTicks[2]; 155 | var startMax = allTicks[7]; 156 | 157 | var brush = d3.svg.brush() 158 | .x(slidderScale) 159 | .extent([startMin, startMax]); 160 | 161 | var brushed = function () { 162 | var filteredDomain = brush.empty() ? slidderScale.domain() : brush.extent(); 163 | x.domain(filteredDomain); 164 | 165 | var axis = svg.select(".x.axis"); 166 | axis.transition().call(xAxis); 167 | charting.rotateAxisText(axis, options); 168 | charting.xAxisStyle(axis); 169 | 170 | yScaleDef = charting.getYScaleDefForMultiline(data, options, filteredDomain); 171 | y.domain([yScaleDef.min, yScaleDef.max]); 172 | 173 | axis = svg.select(".y.axis"); 174 | axis.transition().call(yAxis); 175 | charting.yAxisStyle(axis); 176 | 177 | lines.transition() 178 | .attr("d", function (d) { 179 | return line(d.values); 180 | }); 181 | 182 | if (points) { 183 | points.transition() 184 | .attr("cx", getX) 185 | .attr("cy", function (d) { return y(d.y); }); 186 | } 187 | }; 188 | 189 | brush.on("brush", brushed); 190 | 191 | var sliderAxis = d3.svg.axis() 192 | .scale(slidderScale) 193 | .tickFormat(options.xFormat) 194 | .orient("bottom"); 195 | 196 | var sliderAxisElement = context.append("g") 197 | .attr("class", "x sliderAxis") 198 | .attr("transform", "translate(0," + dims.sliderHeight + ")") 199 | .call(sliderAxis); 200 | charting.xAxisStyle(sliderAxisElement); 201 | charting.rotateAxisText(sliderAxisElement, options); 202 | 203 | svg.append("defs") 204 | .append("clipPath") 205 | .attr("id", "clip") 206 | .append("rect") 207 | .attr("width", dims.width) 208 | .attr("height", dims.height); 209 | 210 | var contextArea = d3.svg.area() 211 | .interpolate("monotone") 212 | .x(function (d) { return slidderScale(d.x); }) 213 | .y0(dims.sliderHeight) 214 | .y1(0); 215 | 216 | context.append("path") 217 | .attr("class", "area") 218 | .attr("d", contextArea(data[0].values)) 219 | .attr("fill", "#F1F1F2"); 220 | 221 | context.append("g") 222 | .attr("class", "x brush") 223 | .call(brush) 224 | .selectAll("rect") 225 | .attr("height", dims.sliderHeight) 226 | .attr("fill", "#1f77b4") 227 | .attr("rx", "5"); 228 | } 229 | }; 230 | -------------------------------------------------------------------------------- /src/charts/piechart.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var koTools = require ('./../kotools'); 4 | var charting = require('./../charting'); 5 | 6 | charting.pieChart = function(data, element,options) { 7 | var el = charting.getElementAndCheckData(element, data); 8 | if (!el) { 9 | return; 10 | } 11 | 12 | var defaultOptions = { 13 | legend: true, 14 | width: 200, 15 | height: 150, 16 | left: 3, 17 | right:3 18 | }; 19 | 20 | options = koTools.setDefaultOptions(defaultOptions, options); 21 | 22 | //for a piechart only positive values make sense 23 | data = data.filter(function (i) { 24 | return i.y > 0; 25 | }); 26 | 27 | if (data.length === 0){ 28 | return; 29 | } 30 | 31 | var color = options.colors || charting.colors; 32 | var xKeys = data.map(function (i) { return i.x; }); 33 | 34 | //the color scale can be passed from outside... 35 | if(!options.colors){ 36 | color.domain(xKeys); 37 | } 38 | var dims = charting.getDimensions(options, el); 39 | 40 | var outerRadius = Math.min(dims.width, dims.height) / 2 - 3; 41 | var donut = d3.layout.pie(); 42 | var arc = d3.svg.arc().outerRadius(outerRadius); 43 | var labelRadius = outerRadius-30; 44 | var labelArc = d3.svg.arc().outerRadius(labelRadius).innerRadius(labelRadius); 45 | 46 | donut.value(function (d) { return d.y; }); 47 | var sum = d3.sum(data, function (item) { return item.y; }); 48 | 49 | //piechart shows the values in the legend as well 50 | //that's why it passes the whole data collection and both, description and value function provider 51 | charting.showStandardLegend(el, xKeys, color, options, dims); 52 | var svg = charting.appendContainer(el, dims); 53 | svg.data([data]); 54 | 55 | var arcs = svg.selectAll("g.arc") 56 | .data(donut) 57 | .enter().append("g") 58 | .attr("class", "arc") 59 | .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")"); 60 | 61 | var arcMouseOver = function(d) { 62 | d3.select(this).style("stroke", 'white'); 63 | d3.select(this).style("opacity", 1); 64 | var info = {}; 65 | var value = d.formatted + " (" + koTools.toPercent(d.percentage) + ")"; 66 | info[d.data.x] = value; 67 | charting.showTooltip(info); 68 | }; 69 | 70 | var arcMouseOut = function() { 71 | d3.select(this).style("opacity", 0.9); 72 | charting.hideTooltip(); 73 | }; 74 | 75 | arcs.append("path") 76 | .attr("d", arc) 77 | .style("fill", function(d) { return color(d.data.x); }) 78 | .style("stroke-width", 2) 79 | .style("stroke", "white") 80 | .on("mouseover", arcMouseOver) 81 | .on("mouseout", arcMouseOut) 82 | .style("cursor", "pointer") 83 | .style("opacity",0.9) 84 | .each(function(d) { 85 | d.percentage = d.data.y / sum; 86 | d.formatted = options.yFormat ? options.yFormat(d.data.y) : d.data.y; 87 | }); 88 | 89 | arcs.append("text") 90 | .attr("transform", function(d) { 91 | return "translate(" + labelArc.centroid(d) + ")"; 92 | }) 93 | .style("font-family", "sans-serif") 94 | .style("font-size", 12) 95 | .style("fill", "#FFFFFF") 96 | .style("font-weight", "bold") 97 | .style("text-anchor", "middle") 98 | //.attr("dy", ".35em") 99 | .text(function(d) { 100 | return (d.percentage*100).toCurrencyString("%",1); 101 | }); 102 | }; 103 | -------------------------------------------------------------------------------- /src/koextensions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var kotools = require ('./kotools'); 4 | var charting = require('./charting'); 5 | require('./charts/piechart'); 6 | require('./charts/barchart'); 7 | require('./charts/linechart'); 8 | require('./charts/chordchart'); 9 | require('./charts/bubblechart'); 10 | require('./charts/histogramchart'); 11 | 12 | function koextensions() { 13 | var self = this; 14 | 15 | //let tools and charting be accesible globaly 16 | self.tools = kotools; 17 | self.charting = charting; 18 | 19 | self.registerExtensions = function () { 20 | if (typeof(ko) === 'undefined') { 21 | console.log("Knockout was not found, using standalon KoExtensions for charting"); 22 | return; 23 | } 24 | 25 | ko.bindingHandlers.datepicker = { 26 | init: function(element, valueAccessor, allBindingsAccessor) { 27 | //initialize datepicker with some optional options 28 | var options = allBindingsAccessor().datepickerOptions || {}; 29 | $(element).datepicker(options); 30 | 31 | //when a user changes the date, update the view model 32 | ko.utils.registerEventHandler(element, "changeDate", function(event) { 33 | var value = valueAccessor(); 34 | if (ko.isObservable(value)) { 35 | value(event.date); 36 | } 37 | }); 38 | }, 39 | update: function(element, valueAccessor) { 40 | var widget = $(element).data("datepicker"); 41 | 42 | if (widget != null) { 43 | var vmValue = ko.utils.unwrapObservable(valueAccessor()); 44 | 45 | //if we have a string value - convert it first 46 | if (kotools.isString(vmValue)) { 47 | vmValue = new Date(vmValue); 48 | } 49 | 50 | //if the date is not valid - don't visualize it, or we would have a "NaN/NaN/NaN" 51 | if (!kotools.isValidDate(vmValue)) { 52 | return; 53 | } 54 | 55 | widget.setDates(vmValue); 56 | } 57 | } 58 | }; 59 | 60 | ko.bindingHandlers.linechart = { 61 | update: function(element, valueAccessor, allBindingsAccessor) { 62 | var options = allBindingsAccessor().chartOptions; 63 | var data = allBindingsAccessor().linechart(); 64 | charting.lineChart(data, element, options); 65 | } 66 | }; 67 | 68 | ko.bindingHandlers.piechart = { 69 | update: function(element, valueAccessor, allBindingsAccessor) { 70 | var data = allBindingsAccessor().piechart(); 71 | var options = allBindingsAccessor().chartOptions; 72 | charting.pieChart(data, element, options); 73 | } 74 | }; 75 | 76 | ko.bindingHandlers.barchart = { 77 | update: function(element, valueAccessor, allBindingsAccessor) { 78 | var data = ko.unwrap(valueAccessor()); 79 | var options = ko.unwrap(allBindingsAccessor().chartOptions); 80 | var line = ko.unwrap(allBindingsAccessor().line); 81 | charting.barChart(data, element, options, line); 82 | } 83 | }; 84 | 85 | ko.bindingHandlers.chordChart = { 86 | update: function (element, valueAccessor, allBindingsAccessor) { 87 | var data = allBindingsAccessor().chordChart(); 88 | var options = allBindingsAccessor().chartOptions; 89 | charting.chordChart(data, element, options); 90 | } 91 | }; 92 | 93 | ko.bindingHandlers.histogram = { 94 | update: function(element, valueAccessor, allBindingsAccessor) { 95 | var data = ko.unwrap(valueAccessor()); 96 | var options = ko.unwrap(allBindingsAccessor().chartOptions); 97 | charting.histogram(data, element, options); 98 | } 99 | }; 100 | 101 | ko.bindingHandlers.scatterplot = { 102 | update: function(element, valueAccessor, allBindingsAccessor) { 103 | var data = ko.unwrap(valueAccessor()); 104 | var options = ko.unwrap(allBindingsAccessor().chartOptions); 105 | charting.scatterPlot(data, element, options); 106 | } 107 | }; 108 | 109 | ko.bindingHandlers.bubblechart = { 110 | update: function(element, valueAccessor, allBindingsAccessor) { 111 | var data = ko.unwrap(valueAccessor()); 112 | var options = ko.unwrap(allBindingsAccessor().chartOptions); 113 | charting.bubbleChart(data, element, options); 114 | } 115 | }; 116 | 117 | ko.bindingHandlers.formattedValue = { 118 | update: function (element, valueAccessor, allBindingsAccessor) { 119 | var fValue = getFormattedValueFromAccessor(allBindingsAccessor()); 120 | applyFormattedValue(fValue, element); 121 | } 122 | } 123 | 124 | ko.bindingHandlers.progress = { 125 | init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 126 | var value = valueAccessor()(); 127 | if (value == null) 128 | value = 0; 129 | element.style.width = value + "%"; 130 | element.style.display = 'none'; 131 | element.style.display = 'block'; 132 | }, 133 | update: function (element, valueAccessor, allBindingsAccessor) { 134 | var value = valueAccessor()(); 135 | if (value == null) 136 | value = 0; 137 | element.style.width = value + "%"; 138 | } 139 | }; 140 | }; 141 | 142 | function applyFormattedValue(fValue, element) { 143 | //TODO: test if val is function => observable then evaluate, test if it is a number before calling toCurrencyString 144 | if (fValue.val != null) { 145 | if (fValue.transf != null) 146 | fValue.val = fValue.transf(fValue.val); 147 | if (kotools.isNumber(fValue.val)) { 148 | element.innerHTML = fValue.val.toCurrencyString(fValue.currency, fValue.rounding); 149 | } else if (kotools.isDate(fValue.val)) { 150 | element.innerHTML = fValue.val.toFormattedString(); 151 | } else { 152 | element.innerHTML = fValue.val; 153 | } 154 | } 155 | }; 156 | 157 | function getFormattedValueFromAccessor(accessor) { 158 | var fValue = { 159 | currency: getValue(accessor.currency), 160 | val: getValue(accessor.formattedValue), 161 | transf: accessor.transformation, 162 | rounding: getValue(accessor.rounding) 163 | }; 164 | return fValue; 165 | } 166 | 167 | 168 | 169 | function getValue(val) { 170 | if (val != null && typeof (val) == 'function') 171 | val = val(); 172 | return val; 173 | }; 174 | }; 175 | 176 | var koext = new koextensions(); 177 | koext.registerExtensions(); 178 | 179 | module.exports = koext; 180 | -------------------------------------------------------------------------------- /src/kotools.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function kotools() { 4 | 5 | var self = this; 6 | var today = new Date(); 7 | 8 | self.currentYear = today.getFullYear(); 9 | self.currentMonth = today.getMonth(); 10 | self.isEmpty = function (str) { 11 | return (!str || 0 === str.length); 12 | }; 13 | 14 | Date.prototype.toFormattedString = function () { 15 | var cDate = this.getDate(); 16 | var cMonth = this.getMonth() + 1; //Months are zero based 17 | var cYear = this.getFullYear(); 18 | return cDate + "/" + cMonth + "/" + cYear; 19 | }; 20 | 21 | Array.prototype.setOrAdd = function (x, y, value) { 22 | if (this[x] === null || this[x] === undefined) { 23 | this[x] = []; 24 | } 25 | if (this[x][y] === null || isNaN(this[x][y])){ 26 | this[x][y] = value; 27 | } 28 | else{ 29 | this[x][y] += value; 30 | } 31 | }; 32 | 33 | Array.prototype.set = function (x, y, value) { 34 | if (!this[x]){ 35 | this[x] = []; 36 | } 37 | this[x][y] = value; 38 | }; 39 | 40 | Date.prototype.addDays = function (days) { 41 | var dat = new Date(this.valueOf()); 42 | dat.setDate(dat.getDate() + days); 43 | return dat; 44 | }; 45 | 46 | self.getQuarter = function(item) { 47 | if (item.Year !== null && item.Quarter !== null) { 48 | return "Q" + item.Quarter + item.Year; 49 | } 50 | return null; 51 | }; 52 | 53 | self.paddy = function (n, p, c) { 54 | var pad_char = c !== 'undefined' ? c : '0'; 55 | var pad = [1 + p].join(pad_char); 56 | return (pad + n).slice(-pad.length); 57 | }; 58 | 59 | self.getMonth = function(item) { 60 | if (item.Year !== null && item.Month !== null) { 61 | return String(item.Year) + self.paddy(item.Month, 2).toString(); 62 | } 63 | return null; 64 | }; 65 | 66 | self.monthsComparer = function(item1, item2) { 67 | if (self.isString(item1)) { 68 | var year1 = parseInt(item1.substring(0, 4), 10); 69 | var month1 = parseInt(item1.substring(4, item1.length), 10); 70 | 71 | var year2 = parseInt(item2.substring(0, 4), 10); 72 | var month2 = parseInt(item2.substring(4, item2.length), 10); 73 | 74 | if (year1 === year2) { 75 | return d3.ascending(month1, month2); 76 | } 77 | 78 | return d3.ascending(year1, year2); 79 | } 80 | return d3.ascending(item1, item2); 81 | }; 82 | 83 | self.monthsIncrementer = function(item) { 84 | var year = parseInt(item.substring(0, 4), 10); 85 | var month = parseInt(item.substring(4, item.length), 10); 86 | 87 | if (month === 12) { 88 | month = 1; 89 | year++; 90 | } else { 91 | month++; 92 | } 93 | var yyyy = year.toString(); 94 | var mm = month.toString(); 95 | return yyyy + (mm[1] ? mm : "0" + mm[0]); 96 | }; 97 | 98 | self.quartersComparer = function(item1, item2) { 99 | var q1 = item1.substring(1, 2); 100 | var year1 = item1.substring(2, 6); 101 | 102 | var q2 = item2.substring(1, 2); 103 | var year2 = item2.substring(2, 6); 104 | 105 | if (year1 === year2) { 106 | return d3.ascending(q1, q2); 107 | } 108 | 109 | return d3.ascending(year1, year2); 110 | }; 111 | 112 | var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; 113 | 114 | self.getYearAndMonthLabel = function(i) { 115 | if (!self.isString(i)) { 116 | return ""; 117 | } 118 | var month = monthNames[parseInt(i.substring(4, i.length), 10) - 1]; 119 | return month; 120 | }; 121 | 122 | self.getProperty = function(key, d) { 123 | if (typeof key === "function") { 124 | return key(d); 125 | } 126 | return d[key]; 127 | }; 128 | 129 | self.getWidth = function(el) 130 | { 131 | if (el.clientWidth){ 132 | return el.clientWidth; 133 | } 134 | 135 | if (Array.isArray(el) && el.length > 0) { 136 | return self.getWidth(el[0]); 137 | } 138 | return null; 139 | }; 140 | 141 | 142 | self.getHeight = function(el) 143 | { 144 | if (el.clientHeight && el.clientHeight !== 0){ 145 | return el.clientHeight; 146 | } 147 | 148 | if (Array.isArray(el) && el.length > 0) { 149 | return self.getHeight(el[0]); 150 | } 151 | 152 | if (el.parentElement !== null) { 153 | return self.getHeight(el.parentElement); 154 | } 155 | 156 | return null; 157 | }; 158 | 159 | self.find = function(data, predicate) { 160 | var i = 0; 161 | for (i = 0; i < data.length; i++) { 162 | if (predicate(data[i])) { 163 | return data[i]; 164 | } 165 | } 166 | return null; 167 | }; 168 | 169 | self.isString = function(x) { 170 | return typeof x === 'string'; 171 | }; 172 | 173 | self.isNumber = function(n) { 174 | return !isNaN(parseFloat(n)) && isFinite(n); 175 | }; 176 | 177 | self.isValidNumber = function(n) { 178 | return n !== null && !isNaN(n); 179 | }; 180 | 181 | self.isDate = function(d) { 182 | return Object.prototype.toString.call(d) === "[object Date]"; 183 | 184 | }; 185 | 186 | Number.prototype.formatMoney = function(c, d, t) { 187 | var n = this; 188 | c = isNaN(c = Math.abs(c)) ? 2 : c; 189 | d = d === undefined ? "." : d; 190 | t = t === undefined ? "," : t; 191 | var s = n < 0 ? "-" : "", 192 | i = parseInt(n = Math.abs(+n || 0).toFixed(c), 10) + "", 193 | j = (j = i.length) > 3 ? j % 3 : 0; 194 | return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); 195 | }; 196 | 197 | self.parseDate = function(input) { 198 | if (input instanceof Date) { 199 | return input; 200 | } 201 | 202 | //first get rid of the hour & etc... 203 | var firstSpace = input.indexOf(" "); 204 | 205 | if (firstSpace !== -1) { 206 | input = input.substring(0, firstSpace); 207 | var separator = "/"; 208 | var parts = []; 209 | if (input.indexOf("-") !== -1) { 210 | separator = "-"; 211 | parts = input.split(separator); 212 | if (parts.length === 3) { 213 | return new Date(parts[0], parts[1] - 1, parts[2]); 214 | } else if (input.indexOf("/") !== -1) { 215 | return new Date(parts[2], parts[0] - 1, parts[1]); 216 | } 217 | } 218 | } 219 | return new Date(Date.parse(input)); 220 | }; 221 | 222 | //verify that the date is valid => object is date-time and there is a meaningful value 223 | self.isValidDate = function(d) { 224 | if (!self.isDate(d)) { 225 | return false; 226 | } 227 | return !isNaN(d.getTime()); 228 | }; 229 | 230 | self.compare = function(x, y) { 231 | for (var propertyName in x) { 232 | if (x[propertyName] !== y[propertyName]) { 233 | return false; 234 | } 235 | } 236 | return true; 237 | }; 238 | 239 | self.toLength = function(val, length) { 240 | if (val.length >= length) { 241 | return val.substring(0, length); 242 | } 243 | 244 | var returnVal = ""; 245 | for (var i = 0; i < length; i++) { 246 | returnVal += val[i % val.length]; 247 | } 248 | return returnVal; 249 | }; 250 | 251 | Number.prototype.toCurrencyString = function(cur, decSpaces) { 252 | var formatted = this.toFixed(decSpaces).replace(/(\d)(?=(\d{3})+\b)/g, '$1 '); 253 | if (cur != null) 254 | formatted += ' ' + cur; 255 | return formatted; 256 | }; 257 | 258 | self.toPercent = function(val) { 259 | if (val === null) 260 | return 0; 261 | return (val * 100).toFixed(1) + " %"; 262 | }; 263 | 264 | //Size of the object - equivalent of array length 265 | Object.size = function(obj) { 266 | var size = 0, key; 267 | for (key in obj) { 268 | if (obj.hasOwnProperty(key)) size++; 269 | } 270 | return size; 271 | }; 272 | 273 | 274 | var objToString = Object.prototype.toString; 275 | 276 | function isString(obj) { 277 | return objToString.call(obj) == '[object String]'; 278 | } 279 | 280 | String.prototype.endsWith = function(suffix) { 281 | return this.indexOf(suffix, this.length - suffix.length) !== -1; 282 | }; 283 | 284 | //difference in 2 arrays 285 | self.diff = function(a1, a2) { 286 | return a1.filter(function(i) { return a2.indexOf(i) < 0; }); 287 | }; 288 | 289 | self.tryConvertToNumber = function(orgValue) { 290 | var intValue = parseInt(orgValue); 291 | var decimalValue = parseFloat(orgValue); 292 | var value = intValue != null ? intValue : (decimalValue != null ? decimalValue : orgValue); 293 | return value; 294 | }; 295 | 296 | self.toBoolean = function(string) { 297 | if (string == null) 298 | return false; 299 | switch (string.toLowerCase()) { 300 | case "true": 301 | case "yes": 302 | case "1": 303 | return true; 304 | case "false": 305 | case "no": 306 | case "0": 307 | case null: 308 | return false; 309 | default: 310 | return Boolean(string); 311 | } 312 | }; 313 | 314 | self.dateToFrenchString = function(date) { 315 | var month = date.getMonth() + 1; 316 | return date.getDate() + "/" + month + "/" + date.getFullYear(); 317 | }; 318 | 319 | self.dateToUSString = function(date) { 320 | var month = date.getMonth() + 1; 321 | return month + "/" + date.getDate() + "/" + date.getFullYear(); 322 | }; 323 | 324 | self.getYearAndMonth = function(date) { 325 | var yyyy = date.getFullYear().toString(); 326 | var mm = (date.getMonth() + 1).toString(); 327 | return yyyy + (mm[1] ? mm : "0" + mm[0]); 328 | }; 329 | 330 | self.splitMonthAndYear = function(monthAndYear) { 331 | return { 332 | year: self.tryConvertToNumber(monthAndYear.substring(0, 4)), 333 | month: self.tryConvertToNumber(monthAndYear.substring(4, 6)) 334 | }; 335 | }; 336 | 337 | self.distinct = function(data, mapper) { 338 | var mapped = data.map(mapper); 339 | return mapped.filter(function(v, i) { return mapped.indexOf(v) == i; }); 340 | }; 341 | 342 | self.convertSeriesToXYPairs = function(data) { 343 | var converted = []; 344 | for (var i = 0; i < data.length; i++) { 345 | converted.push({ x: i, y: data[i] }); 346 | } 347 | return converted; 348 | }; 349 | 350 | self.convertAllSeriesToXYPairs = function (data) { 351 | if (data == null) { 352 | return null; 353 | } 354 | for (var i = 0; i < data.length; i++) { 355 | if (data[i] != null && data[i].values != null) { 356 | if (self.isNumber(data[i].values[0])) { 357 | data[i].values = self.convertSeriesToXYPairs(data[i].values); 358 | } 359 | } 360 | } 361 | return data; 362 | }; 363 | 364 | self.setDefaultOptions = function (defaultConfig, config) { 365 | config = config || {}; 366 | for (var key in defaultConfig) { 367 | config[key] = config[key] != null ? config[key] : defaultConfig[key]; 368 | } 369 | return config; 370 | }; 371 | 372 | self.getIdealDateFormat = function(range) { 373 | var min = range[0]; 374 | var max = range[1]; 375 | var oneDay = 24*60*60*1000; 376 | var diffDays = Math.round(Math.abs((max.getTime() - min.getTime())/(oneDay))); 377 | 378 | if(diffDays > 5){ 379 | return function(d){ 380 | var val = d.toFormattedString(); 381 | return val; 382 | }; 383 | }else { 384 | var diffHours = Math.abs(max - min) / 36e5; 385 | if(diffHours > 2){ 386 | return function(d){ 387 | return d.getHours() + ":" + d.getMinutes(); 388 | }; 389 | }else{ 390 | return function(d) { return d.getMinutes() + ":" + d.getSeconds();}; 391 | } 392 | } 393 | } 394 | } 395 | 396 | module.exports = new kotools(); 397 | -------------------------------------------------------------------------------- /testpages/BubbleChart.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | BubbleChart Chart 6 | 7 | 8 | 9 | 10 | 11 |

Bubble Chart Example

12 |
13 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /testpages/CashFlowExample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Chashflow example 6 | 7 | 8 | 9 | 10 | 11 |

Cash-Flow Chart:

12 |

Monthly Sales

13 |
14 |
15 | 16 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /testpages/ChordChart.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Chord Chart 6 | 7 | 8 | 9 | 10 | 11 |
12 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /testpages/DateBindingTests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Datepicker binding tests 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 |
33 | 34 |
35 | 36 | 37 |
38 | 39 |
40 | 41 | 42 |
43 |
44 |
45 |
46 |
47 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /testpages/HistogramExample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Histogram example 5 | 6 | 7 | 8 | 9 | 10 |

Detecting the outliers

11 |

Data:

12 | 13 | Show probability distribution 14 |

Tolerance

15 | 16 |

Use MAD

17 | 18 |

Minimum:

19 | 20 |

Expected:

21 | Median 22 | Mean 23 |

Show outliers

24 | 25 |
26 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /testpages/LineChartSlidder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 | 11 |

3 Normalized non-linked data series

12 | 13 |
14 |
15 | 16 |
17 |
18 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /testpages/UtilsTests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Map Test Page 7 | 8 | 9 | 10 | 11 | 12 | Price: 13 | 14 |
Power: 15 | 16 |
Efficiency: 17 | 18 |
Consumption: 19 | 20 |
Distance: 21 | 22 |
Total consumption: 23 | 24 |
Test date: 25 | 26 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /testpages/WithoutKnockout.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 |

3 Normalized non-linked data series

11 |
12 |
13 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /testpages/barcharttests-uglified.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 | 11 |

Stacked bar chart

12 |
13 |
14 | 15 |

Stacked bar chart - with datetime x axis

16 |
17 |
18 | 19 |

Grouped barchart

20 |
21 |
22 | 23 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /testpages/barcharttests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 | 11 |

Stacked bar chart

12 |
13 |
14 | 15 |

Stacked bar chart - with datetime x axis

16 |
17 |
18 | 19 |

Grouped barchart

20 |
21 |
22 | 23 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /testpages/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | KoExtensions 5 | 6 | 7 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /testpages/linetests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /testpages/piecharts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Charting Test Page 6 | 7 | 8 | 9 | 10 | 11 |

Simple piechart:

12 |
13 |
14 | 15 |

Chart in a foreach binding

16 | 17 |
18 |

19 |
20 | 21 |
22 |
23 | 24 | 96 | 97 | 98 | --------------------------------------------------------------------------------