Merge pull request #185 from christianesperar/master
Manage assets and packages
@ -74,5 +74,9 @@
|
||||
"echarts": "^3.1.7",
|
||||
"malihu-custom-scrollbar-plugin": "^3.1.3",
|
||||
"animate.css": "^3.5.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"jquery": "^2.2.3",
|
||||
"fastclick": "^1.0.6"
|
||||
}
|
||||
}
|
||||
|
@ -1072,8 +1072,7 @@ table.jambo_table tbody tr.selected td {
|
||||
.dataTables_wrapper {
|
||||
position: relative;
|
||||
clear: both;
|
||||
zoom: 1;
|
||||
/* Feeling sorry for IE */ }
|
||||
zoom: 1; }
|
||||
|
||||
.dataTables_processing {
|
||||
position: absolute;
|
||||
@ -1112,47 +1111,6 @@ table.dataTable td.focus {
|
||||
outline: 2px solid #1ABB9C !important;
|
||||
outline-offset: -1px; }
|
||||
|
||||
/* Pagination nested */
|
||||
.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
|
||||
height: 19px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
color: #111 !important; }
|
||||
|
||||
.paginate_disabled_previous:hover, .paginate_enabled_previous:hover, .paginate_disabled_next:hover, .paginate_enabled_next:hover {
|
||||
text-decoration: none !important; }
|
||||
|
||||
.paginate_disabled_previous:active, .paginate_enabled_previous:active, .paginate_disabled_next:active, .paginate_enabled_next:active {
|
||||
outline: none; }
|
||||
|
||||
.paginate_disabled_previous, .paginate_disabled_next {
|
||||
color: #666 !important; }
|
||||
|
||||
.paginate_disabled_previous, .paginate_enabled_previous {
|
||||
padding-left: 23px; }
|
||||
|
||||
.paginate_disabled_next, .paginate_enabled_next {
|
||||
padding-right: 23px;
|
||||
margin-left: 10px; }
|
||||
|
||||
.paginate_disabled_previous {
|
||||
background: url("../images/back_disabled.png") no-repeat top left; }
|
||||
|
||||
.paginate_enabled_previous {
|
||||
background: url("../images/back_enabled.png") no-repeat top left; }
|
||||
|
||||
.paginate_enabled_previous:hover {
|
||||
background: url("../images/back_enabled_hover.png") no-repeat top left; }
|
||||
|
||||
.paginate_disabled_next {
|
||||
background: url("../images/forward_disabled.png") no-repeat top right; }
|
||||
|
||||
.paginate_enabled_next {
|
||||
background: url("../images/forward_enabled.png") no-repeat top right; }
|
||||
|
||||
.paginate_enabled_next:hover {
|
||||
background: url("../images/forward_enabled_hover.png") no-repeat top right; }
|
||||
|
||||
table.display {
|
||||
margin: 0 auto;
|
||||
clear: both;
|
||||
@ -1259,7 +1217,7 @@ div.box {
|
||||
border: 1px solid #8080FF;
|
||||
background-color: #E5E5FF; }
|
||||
|
||||
/* ********* /tables styleing ****************************** */
|
||||
/* ********* /tables styling ****************************** */
|
||||
/* ********* /dashboard widget **************************** */
|
||||
/* ********* widgets *************************************** */
|
||||
ul.msg_list li {
|
||||
@ -3069,100 +3027,6 @@ ul.project_files li a i {
|
||||
transform: rotate(-90deg); }
|
||||
|
||||
/* ********* /verticle tabs **************************** */
|
||||
.avatar-view {
|
||||
display: block;
|
||||
border: 3px solid #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
|
||||
cursor: pointer;
|
||||
overflow: hidden; }
|
||||
|
||||
.avatar-body {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px; }
|
||||
|
||||
.avatar-upload {
|
||||
overflow: hidden; }
|
||||
|
||||
.avatar-upload label {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 100px; }
|
||||
|
||||
.avatar-upload input {
|
||||
display: block;
|
||||
margin-left: 110px; }
|
||||
|
||||
.avater-alert {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.avatar-wrapper {
|
||||
height: 364px;
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.25);
|
||||
background-color: #fcfcfc;
|
||||
overflow: hidden; }
|
||||
|
||||
.avatar-wrapper img {
|
||||
display: block;
|
||||
height: auto;
|
||||
max-width: 100%; }
|
||||
|
||||
.avatar-preview {
|
||||
float: left;
|
||||
margin-top: 15px;
|
||||
margin-right: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
overflow: hidden; }
|
||||
|
||||
.avatar-preview:hover {
|
||||
border-color: #ccf;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.15); }
|
||||
|
||||
.avatar-preview img {
|
||||
width: 100%; }
|
||||
|
||||
.preview-lg {
|
||||
height: 184px;
|
||||
width: 184px;
|
||||
margin-top: 15px; }
|
||||
|
||||
.preview-md {
|
||||
height: 100px;
|
||||
width: 100px; }
|
||||
|
||||
.preview-sm {
|
||||
height: 50px;
|
||||
width: 50px; }
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.avatar-preview {
|
||||
float: none; } }
|
||||
.avatar-btns {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px; }
|
||||
|
||||
.avatar-btns .btn-group {
|
||||
margin-right: 5px; }
|
||||
|
||||
.loading {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #fff url("../images/loading.gif") no-repeat center center;
|
||||
opacity: .75;
|
||||
filter: alpha(opacity=75);
|
||||
z-index: 20140628; }
|
||||
|
||||
/* ********* /image cropping **************************** */
|
||||
/* ********* moris **************************** */
|
||||
.morris-hover {
|
||||
position: absolute;
|
||||
|
4
build/css/custom.min.css
vendored
@ -314,20 +314,20 @@
|
||||
|
||||
<div class="col-md-7 col-sm-7 col-xs-12">
|
||||
<div class="product-image">
|
||||
<img src="images/prod1.jpg" alt="..." />
|
||||
<img src="images/prod-1.jpg" alt="..." />
|
||||
</div>
|
||||
<div class="product_gallery">
|
||||
<a>
|
||||
<img src="images/prod2.jpg" alt="..." />
|
||||
<img src="images/prod-2.jpg" alt="..." />
|
||||
</a>
|
||||
<a>
|
||||
<img src="images/prod3.jpg" alt="..." />
|
||||
<img src="images/prod-3.jpg" alt="..." />
|
||||
</a>
|
||||
<a>
|
||||
<img src="images/prod4.jpg" alt="..." />
|
||||
<img src="images/prod-4.jpg" alt="..." />
|
||||
</a>
|
||||
<a>
|
||||
<img src="images/prod5.jpg" alt="..." />
|
||||
<img src="images/prod-5.jpg" alt="..." />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1406,13 +1406,11 @@
|
||||
<div class="container cropper">
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<!-- <h3 class="page-header">Demo:</h3> -->
|
||||
<div class="img-container">
|
||||
<img id="image" src="images/picture2.jpg" alt="Picture">
|
||||
<img id="image" src="images/cropper.jpg" alt="Picture">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<!-- <h3 class="page-header">Preview:</h3> -->
|
||||
<div class="docs-preview clearfix">
|
||||
<div class="img-preview preview-lg"></div>
|
||||
<div class="img-preview preview-md"></div>
|
||||
@ -1420,7 +1418,6 @@
|
||||
<div class="img-preview preview-xs"></div>
|
||||
</div>
|
||||
|
||||
<!-- <h3 class="page-header">Data:</h3> -->
|
||||
<div class="docs-data">
|
||||
<div class="input-group input-group-sm">
|
||||
<label class="input-group-addon" for="dataX">X</label>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 8.6 KiB |
0
production/images/picture2.jpg → production/images/cropper.jpg
Executable file → Normal file
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 894 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.8 KiB |
0
production/images/1.png → production/images/inbox.png
Executable file → Normal file
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 30 KiB |
0
production/images/4.jpg → production/images/media.jpg
Executable file → Normal file
Before Width: | Height: | Size: 284 KiB After Width: | Height: | Size: 284 KiB |
0
production/images/paypal2.png → production/images/paypal.png
Executable file → Normal file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 50 KiB |
0
production/images/prod1.jpg → production/images/prod-1.jpg
Executable file → Normal file
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
0
production/images/prod2.jpg → production/images/prod-2.jpg
Executable file → Normal file
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
0
production/images/prod3.jpg → production/images/prod-3.jpg
Executable file → Normal file
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
0
production/images/prod4.jpg → production/images/prod-4.jpg
Executable file → Normal file
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
0
production/images/prod5.jpg → production/images/prod-5.jpg
Executable file → Normal file
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 304 B |
Before Width: | Height: | Size: 505 B |
Before Width: | Height: | Size: 694 B |
Before Width: | Height: | Size: 358 B |
@ -452,7 +452,7 @@
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#" class="atch-thumb">
|
||||
<img src="images/1.png" alt="img" />
|
||||
<img src="images/inbox.png" alt="img" />
|
||||
</a>
|
||||
|
||||
<div class="file-name">
|
||||
@ -469,7 +469,7 @@
|
||||
|
||||
<li>
|
||||
<a href="#" class="atch-thumb">
|
||||
<img src="images/1.png" alt="img" />
|
||||
<img src="images/inbox.png" alt="img" />
|
||||
</a>
|
||||
|
||||
<div class="file-name">
|
||||
@ -484,7 +484,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="atch-thumb">
|
||||
<img src="images/1.png" alt="img" />
|
||||
<img src="images/inbox.png" alt="img" />
|
||||
</a>
|
||||
|
||||
<div class="file-name">
|
||||
|
@ -988,7 +988,7 @@
|
||||
<!-- Chart.js -->
|
||||
<script src="../vendors/Chart.js/dist/Chart.min.js"></script>
|
||||
<!-- gauge.js -->
|
||||
<script src="../vendors/bernii/gauge.js/dist/gauge.min.js"></script>
|
||||
<script src="../vendors/gauge.js/dist/gauge.min.js"></script>
|
||||
<!-- bootstrap-progressbar -->
|
||||
<script src="../vendors/bootstrap-progressbar/bootstrap-progressbar.min.js"></script>
|
||||
<!-- iCheck -->
|
||||
|
@ -856,7 +856,7 @@
|
||||
<script src="../vendors/raphael/raphael.min.js"></script>
|
||||
<script src="../vendors/morris.js/morris.min.js"></script>
|
||||
<!-- gauge.js -->
|
||||
<script src="../vendors/bernii/gauge.js/dist/gauge.min.js"></script>
|
||||
<script src="../vendors/gauge.js/dist/gauge.min.js"></script>
|
||||
<!-- bootstrap-progressbar -->
|
||||
<script src="../vendors/bootstrap-progressbar/bootstrap-progressbar.min.js"></script>
|
||||
<!-- Skycons -->
|
||||
|
@ -415,7 +415,7 @@
|
||||
<img src="images/visa.png" alt="Visa">
|
||||
<img src="images/mastercard.png" alt="Mastercard">
|
||||
<img src="images/american-express.png" alt="American Express">
|
||||
<img src="images/paypal2.png" alt="Paypal">
|
||||
<img src="images/paypal.png" alt="Paypal">
|
||||
<p class="text-muted well well-sm no-shadow" style="margin-top: 10px;">
|
||||
Etsy doostang zoodles disqus groupon greplin oooj voxy zoodles, weebly ning heekya handango imeem plugg dopplr jibjab, movity jajah plickers sifteo edmodo ifttt zimbra.
|
||||
</p>
|
||||
|
@ -317,7 +317,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask">
|
||||
<p>Your Text</p>
|
||||
<div class="tools tools-bottom">
|
||||
@ -335,7 +335,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask">
|
||||
<p>Your Text</p>
|
||||
<div class="tools tools-bottom">
|
||||
@ -353,7 +353,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask">
|
||||
<p>Your Text</p>
|
||||
<div class="tools tools-bottom">
|
||||
@ -371,7 +371,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask">
|
||||
<p>Your Text</p>
|
||||
<div class="tools tools-bottom">
|
||||
@ -389,7 +389,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask">
|
||||
<p>Your Text</p>
|
||||
<div class="tools tools-bottom">
|
||||
@ -409,7 +409,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask no-caption">
|
||||
<div class="tools tools-bottom">
|
||||
<a href="#"><i class="fa fa-link"></i></a>
|
||||
@ -428,7 +428,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask no-caption">
|
||||
<div class="tools tools-bottom">
|
||||
<a href="#"><i class="fa fa-link"></i></a>
|
||||
@ -447,7 +447,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask no-caption">
|
||||
<div class="tools tools-bottom">
|
||||
<a href="#"><i class="fa fa-link"></i></a>
|
||||
@ -466,7 +466,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask no-caption">
|
||||
<div class="tools tools-bottom">
|
||||
<a href="#"><i class="fa fa-link"></i></a>
|
||||
@ -485,7 +485,7 @@
|
||||
<div class="col-md-55">
|
||||
<div class="thumbnail">
|
||||
<div class="image view view-first">
|
||||
<img style="width: 100%; display: block;" src="images/4.jpg" alt="image" />
|
||||
<img style="width: 100%; display: block;" src="images/media.jpg" alt="image" />
|
||||
<div class="mask no-caption">
|
||||
<div class="tools tools-bottom">
|
||||
<a href="#"><i class="fa fa-link"></i></a>
|
||||
|
@ -308,83 +308,12 @@
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="x_content">
|
||||
|
||||
<div class="col-md-3 col-sm-3 col-xs-12 profile_left">
|
||||
|
||||
<div class="profile_img">
|
||||
|
||||
<!-- end of image cropping -->
|
||||
<div id="crop-avatar">
|
||||
<!-- Current avatar -->
|
||||
<img class="img-responsive avatar-view" src="images/picture.jpg" alt="Avatar" title="Change the avatar">
|
||||
|
||||
<!-- Cropping modal -->
|
||||
<div class="modal fade" id="avatar-modal" aria-hidden="true" aria-labelledby="avatar-modal-label" role="dialog" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<form class="avatar-form" action="crop.php" enctype="multipart/form-data" method="post">
|
||||
<div class="modal-header">
|
||||
<button class="close" data-dismiss="modal" type="button">×</button>
|
||||
<h4 class="modal-title" id="avatar-modal-label">Change Avatar</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="avatar-body">
|
||||
|
||||
<!-- Upload image and data -->
|
||||
<div class="avatar-upload">
|
||||
<input class="avatar-src" name="avatar_src" type="hidden">
|
||||
<input class="avatar-data" name="avatar_data" type="hidden">
|
||||
<label for="avatarInput">Local upload</label>
|
||||
<input class="avatar-input" id="avatarInput" name="avatar_file" type="file">
|
||||
</div>
|
||||
|
||||
<!-- Crop and preview -->
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div class="avatar-wrapper"></div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="avatar-preview preview-lg"></div>
|
||||
<div class="avatar-preview preview-md"></div>
|
||||
<div class="avatar-preview preview-sm"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row avatar-btns">
|
||||
<div class="col-md-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="-90" type="button" title="Rotate -90 degrees">Rotate Left</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="-15" type="button">-15deg</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="-30" type="button">-30deg</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="-45" type="button">-45deg</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="90" type="button" title="Rotate 90 degrees">Rotate Right</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="15" type="button">15deg</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="30" type="button">30deg</button>
|
||||
<button class="btn btn-primary" data-method="rotate" data-option="45" type="button">45deg</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-primary btn-block avatar-save" type="submit">Done</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal" type="button">Close</button>
|
||||
</div> -->
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal -->
|
||||
|
||||
<!-- Loading state -->
|
||||
<div class="loading" aria-label="Loading" role="img" tabindex="-1"></div>
|
||||
</div>
|
||||
<!-- end of image cropping -->
|
||||
|
||||
</div>
|
||||
<h3>Samuel Doe</h3>
|
||||
|
||||
|
@ -1088,56 +1088,68 @@ h3.degrees {
|
||||
.bulk-actions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table.countries_list {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.countries_list td {
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
border-top: 1px solid #eeeeee;
|
||||
}
|
||||
|
||||
.dataTables_paginate a {
|
||||
padding: 6px 9px !important;
|
||||
background: #ddd !important;
|
||||
border-color: #ddd !important;
|
||||
}
|
||||
|
||||
.paging_full_numbers a.paginate_active {
|
||||
background-color: rgba(38, 185, 154, 0.59) !important;
|
||||
border-color: rgba(38, 185, 154, 0.59) !important;
|
||||
}
|
||||
|
||||
button.DTTT_button, div.DTTT_button, a.DTTT_button {
|
||||
border: 1px solid #E7E7E7 !important;
|
||||
background: #E7E7E7 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
table.jambo_table {
|
||||
border: 1px solid rgba(221, 221, 221, 0.78);
|
||||
}
|
||||
|
||||
table.jambo_table thead {
|
||||
background: rgba(52, 73, 94, 0.94);
|
||||
color: #ECF0F1;
|
||||
}
|
||||
|
||||
table.jambo_table tbody tr:hover td {
|
||||
background: rgba(38, 185, 154, 0.07);
|
||||
border-top: 1px solid rgba(38, 185, 154, 0.11);
|
||||
border-bottom: 1px solid rgba(38, 185, 154, 0.11);
|
||||
}
|
||||
|
||||
table.jambo_table tbody tr.selected {
|
||||
background: rgba(38, 185, 154, 0.16);
|
||||
}
|
||||
|
||||
table.jambo_table tbody tr.selected td {
|
||||
border-top: 1px solid rgba(38, 185, 154, 0.40);
|
||||
border-bottom: 1px solid rgba(38, 185, 154, 0.40);
|
||||
}
|
||||
|
||||
.dataTables_paginate a {
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
.dataTables_wrapper {
|
||||
position: relative;
|
||||
clear: both;
|
||||
zoom: 1;
|
||||
/* Feeling sorry for IE */
|
||||
}
|
||||
|
||||
.dataTables_processing {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@ -1153,147 +1165,130 @@ table.jambo_table tbody tr.selected td {
|
||||
font-size: 14px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.dataTables_length {
|
||||
width: 40%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dataTables_filter {
|
||||
width: 50%;
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dataTables_info {
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dataTables_paginate {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.dataTable th.focus,
|
||||
table.dataTable td.focus {
|
||||
outline: 2px solid #1ABB9C !important;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
/* Pagination nested */
|
||||
|
||||
.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
|
||||
height: 19px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
color: #111 !important;
|
||||
}
|
||||
.paginate_disabled_previous:hover, .paginate_enabled_previous:hover, .paginate_disabled_next:hover, .paginate_enabled_next:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.paginate_disabled_previous:active, .paginate_enabled_previous:active, .paginate_disabled_next:active, .paginate_enabled_next:active {
|
||||
outline: none;
|
||||
}
|
||||
.paginate_disabled_previous, .paginate_disabled_next {
|
||||
color: #666 !important;
|
||||
}
|
||||
.paginate_disabled_previous, .paginate_enabled_previous {
|
||||
padding-left: 23px;
|
||||
}
|
||||
.paginate_disabled_next, .paginate_enabled_next {
|
||||
padding-right: 23px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.paginate_disabled_previous {
|
||||
background: url('../images/back_disabled.png') no-repeat top left;
|
||||
}
|
||||
.paginate_enabled_previous {
|
||||
background: url('../images/back_enabled.png') no-repeat top left;
|
||||
}
|
||||
.paginate_enabled_previous:hover {
|
||||
background: url('../images/back_enabled_hover.png') no-repeat top left;
|
||||
}
|
||||
.paginate_disabled_next {
|
||||
background: url('../images/forward_disabled.png') no-repeat top right;
|
||||
}
|
||||
.paginate_enabled_next {
|
||||
background: url('../images/forward_enabled.png') no-repeat top right;
|
||||
}
|
||||
.paginate_enabled_next:hover {
|
||||
background: url('../images/forward_enabled_hover.png') no-repeat top right;
|
||||
}
|
||||
table.display {
|
||||
margin: 0 auto;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.display thead th {
|
||||
padding: 8px 18px 8px 10px;
|
||||
border-bottom: 1px solid black;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.display tfoot th {
|
||||
padding: 3px 18px 3px 10px;
|
||||
border-top: 1px solid black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.display tr.heading2 td {
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.display td {
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
table.display td.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.display thead th:active, table.display thead td:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dataTables_scroll {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.dataTables_scrollBody {
|
||||
*margin-top: -1px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.top, .bottom {}
|
||||
.top .dataTables_info {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.dataTables_empty {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tfoot input {
|
||||
margin: 0.5em 0;
|
||||
width: 100%;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
tfoot input.search_init {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
td.group {
|
||||
background-color: #d1cfd0;
|
||||
border-bottom: 2px solid #A19B9E;
|
||||
border-top: 2px solid #A19B9E;
|
||||
}
|
||||
|
||||
td.details {
|
||||
background-color: #d1cfd0;
|
||||
border: 2px solid #A19B9E;
|
||||
}
|
||||
|
||||
.example_alt_pagination div.dataTables_info {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.paging_full_numbers {
|
||||
width: 400px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.paging_full_numbers a:active {
|
||||
outline: none
|
||||
}
|
||||
|
||||
.paging_full_numbers a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.paging_full_numbers a.paginate_button, .paging_full_numbers a.paginate_active {
|
||||
border: 1px solid #aaa;
|
||||
-webkit-border-radius: 5px;
|
||||
@ -1302,22 +1297,28 @@ td.details {
|
||||
margin: 0 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.paging_full_numbers a.paginate_button {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.paging_full_numbers a.paginate_button:hover {
|
||||
background-color: #ccc;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.paging_full_numbers a.paginate_active {
|
||||
background-color: #99B3FF;
|
||||
}
|
||||
|
||||
table.display tr.even.row_selected td {
|
||||
background-color: #B0BED9;
|
||||
}
|
||||
|
||||
table.display tr.odd.row_selected td {
|
||||
background-color: #9FAFD1;
|
||||
}
|
||||
|
||||
div.box {
|
||||
height: 100px;
|
||||
padding: 10px;
|
||||
@ -1325,8 +1326,7 @@ div.box {
|
||||
border: 1px solid #8080FF;
|
||||
background-color: #E5E5FF;
|
||||
}
|
||||
|
||||
/* ********* /tables styleing ****************************** */
|
||||
/* ********* /tables styling ****************************** */
|
||||
|
||||
|
||||
/* ********* /dashboard widget **************************** */
|
||||
@ -3300,104 +3300,6 @@ ul.project_files li a i {
|
||||
|
||||
/* ********* /verticle tabs **************************** */
|
||||
|
||||
.avatar-view {
|
||||
display: block;
|
||||
border: 3px solid #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .15);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-body {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.avatar-upload {
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-upload label {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 100px;
|
||||
}
|
||||
.avatar-upload input {
|
||||
display: block;
|
||||
margin-left: 110px;
|
||||
}
|
||||
.avater-alert {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.avatar-wrapper {
|
||||
height: 364px;
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, .25);
|
||||
background-color: #fcfcfc;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-wrapper img {
|
||||
display: block;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
.avatar-preview {
|
||||
float: left;
|
||||
margin-top: 15px;
|
||||
margin-right: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-preview:hover {
|
||||
border-color: #ccf;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .15);
|
||||
}
|
||||
.avatar-preview img {
|
||||
width: 100%;
|
||||
}
|
||||
.preview-lg {
|
||||
height: 184px;
|
||||
width: 184px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.preview-md {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
}
|
||||
.preview-sm {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.avatar-preview {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
.avatar-btns {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.avatar-btns .btn-group {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.loading {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #fff url("../images/loading.gif") no-repeat center center;
|
||||
opacity: .75;
|
||||
filter: alpha(opacity=75);
|
||||
z-index: 20140628;
|
||||
}
|
||||
|
||||
/* ********* /image cropping **************************** */
|
||||
|
||||
|
||||
/* ********* moris **************************** */
|
||||
|
||||
|
10
vendors/Chart.js/.bower.json
vendored
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "Chart.js",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.4",
|
||||
"description": "Simple HTML5 Charts using the canvas element",
|
||||
"homepage": "https://github.com/nnnick/Chart.js",
|
||||
"homepage": "https://github.com/chartjs/Chart.js",
|
||||
"author": "nnnick",
|
||||
"license": "MIT",
|
||||
"main": [
|
||||
@ -11,11 +11,11 @@
|
||||
"devDependencies": {
|
||||
"jquery": "~2.1.4"
|
||||
},
|
||||
"_release": "2.1.0",
|
||||
"_release": "2.1.4",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "2.1.0",
|
||||
"commit": "2ee37e12e379ca9b8ad3be7105715bf8c543ead0"
|
||||
"tag": "v2.1.4",
|
||||
"commit": "40d76b6a7ba14aeac69b05ad15d713c3402867b2"
|
||||
},
|
||||
"_source": "https://github.com/nnnick/Chart.js.git",
|
||||
"_target": "^2.0.2",
|
||||
|
10
vendors/Chart.js/.editorconfig
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
2
vendors/Chart.js/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
- [ ] I have read the [guidelines for contributing](https://github.com/chartjs/Chart.js/blob/master/CONTRIBUTING.md)
|
||||
- [ ] I have included an example of my issue on a website such as [JS Bin](http://jsbin.com/), [JS Fiddle](http://jsfiddle.net/), or [Codepen](http://codepen.io/pen/). ([Template](http://codepen.io/pen?template=JXVYzq))
|
2
vendors/Chart.js/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
- [ ] I have read the [guidelines for contributing](https://github.com/chartjs/Chart.js/blob/master/CONTRIBUTING.md)
|
||||
- [ ] I have included an example of my changes on a website such as [JS Bin](http://jsbin.com/), [JS Fiddle](http://jsfiddle.net/), or [Codepen](http://codepen.io/pen/). ([Template](http://codepen.io/pen?template=JXVYzq))
|
2
vendors/Chart.js/.gitignore
vendored
@ -9,5 +9,5 @@ docs/index.md
|
||||
bower_components/
|
||||
|
||||
coverage/*
|
||||
|
||||
.idea
|
||||
nbproject/*
|
||||
|
4
vendors/Chart.js/README.md
vendored
@ -16,7 +16,7 @@ To install via npm / bower:
|
||||
npm install chart.js --save
|
||||
bower install Chart.js --save
|
||||
```
|
||||
CDN: https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.0/Chart.js
|
||||
CDN: https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js
|
||||
|
||||
## Documentation
|
||||
|
||||
@ -31,6 +31,8 @@ For support using Chart.js, please post questions with the [`chartjs` tag on Sta
|
||||
## Building and Testing
|
||||
`gulp build`, `gulp test`
|
||||
|
||||
Thanks to [BrowserStack](https://browserstack.com) for allowing our team to test on thousands of browsers.
|
||||
|
||||
## License
|
||||
|
||||
Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT).
|
||||
|
6
vendors/Chart.js/bower.json
vendored
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "Chart.js",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.4",
|
||||
"description": "Simple HTML5 Charts using the canvas element",
|
||||
"homepage": "https://github.com/nnnick/Chart.js",
|
||||
"homepage": "https://github.com/chartjs/Chart.js",
|
||||
"author": "nnnick",
|
||||
"license": "MIT",
|
||||
"main": [
|
||||
@ -11,4 +11,4 @@
|
||||
"devDependencies": {
|
||||
"jquery": "~2.1.4"
|
||||
}
|
||||
}
|
||||
}
|
19109
vendors/Chart.js/dist/Chart.bundle.js
vendored
21
vendors/Chart.js/dist/Chart.bundle.min.js
vendored
17496
vendors/Chart.js/dist/Chart.js
vendored
13
vendors/Chart.js/dist/Chart.min.js
vendored
207
vendors/Chart.js/docs/00-Getting-Started.md
vendored
@ -6,8 +6,8 @@ anchor: getting-started
|
||||
### Download Chart.js
|
||||
|
||||
To download a zip, go to [Chart.js on Github](https://github.com/chartjs/Chart.js) and choose the version that is right for your application.
|
||||
* [Standard build](https://raw.githubusercontent.com/chartjs/Chart.js/v2.0-dev/dist/Chart.js) (~31kB gzipped)
|
||||
* [Bundled with Moment.js](https://raw.githubusercontent.com/chartjs/Chart.js/v2.0-dev/dist/Chart.bundle.js) (~45kB gzipped)
|
||||
* [Standard build](https://raw.githubusercontent.com/chartjs/Chart.js/master/dist/Chart.js) (~31kB gzipped)
|
||||
* [Bundled with Moment.js](https://raw.githubusercontent.com/chartjs/Chart.js/master/dist/Chart.bundle.js) (~45kB gzipped)
|
||||
* [CDN Versions](https://cdnjs.com/libraries/Chart.js)
|
||||
|
||||
To install via npm / bower:
|
||||
@ -19,6 +19,12 @@ npm install chart.js --save
|
||||
bower install Chart.js --save
|
||||
```
|
||||
|
||||
### Selecting the Correct Build
|
||||
|
||||
Chart.js provides two different builds that are available for your use. The `Chart.js` and `Chart.min.js` files include Chart.js and the accompanying color parsing library. If this version is used and you require the use of the time axis, [Moment.js](http://momentjs.com/) will need to be included before Chart.js.
|
||||
|
||||
The `Chart.bundle.js` and `Chart.bundle.min.js` builds include Moment.js in a single file. This version should be used if you require time axes and want a single file to include, select this version. Do not use this build if your application already includes Moment.js. If you do, Moment.js will be included twice, increasing the page load time and potentially introducing version issues.
|
||||
|
||||
### Installation
|
||||
|
||||
To import Chart.js using an old-school script tag:
|
||||
@ -78,7 +84,24 @@ var myChart = new Chart(ctx, {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3]
|
||||
data: [12, 19, 3, 5, 2, 3],
|
||||
backgroundColor: [
|
||||
'rgba(255, 99, 132, 0.2)',
|
||||
'rgba(54, 162, 235, 0.2)',
|
||||
'rgba(255, 206, 86, 0.2)',
|
||||
'rgba(75, 192, 192, 0.2)',
|
||||
'rgba(153, 102, 255, 0.2)',
|
||||
'rgba(255, 159, 64, 0.2)'
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(255,99,132,1)',
|
||||
'rgba(54, 162, 235, 1)',
|
||||
'rgba(255, 206, 86, 1)',
|
||||
'rgba(75, 192, 192, 1)',
|
||||
'rgba(153, 102, 255, 1)',
|
||||
'rgba(255, 159, 64, 1)'
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
@ -95,181 +118,3 @@ var myChart = new Chart(ctx, {
|
||||
```
|
||||
|
||||
It's that easy to get started using Chart.js! From here you can explore the many options that can help you customise your charts with scales, tooltips, labels, colors, custom actions, and much more.
|
||||
|
||||
### Global chart configuration
|
||||
|
||||
This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.
|
||||
|
||||
Chart.js merges configurations and options in a few places with the global defaults using chart type defaults and scales defaults. This way you can be as specific as you want in your individual chart configs, or change the defaults for Chart.js as a whole.
|
||||
|
||||
The global options are defined in `Chart.defaults.global`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
responsive | Boolean | true | Resizes when the canvas container does.
|
||||
responsiveAnimationDuration | Number | 0 | Duration in milliseconds it takes to animate to new size after a resize event.
|
||||
maintainAspectRatio | Boolean | true | Maintain the original canvas aspect ratio `(width / height)` when resizing
|
||||
events | Array[String] | `["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"]` | Events that the chart should listen to for tooltips and hovering
|
||||
hover |Object|-|-
|
||||
*hover*.onHover | Function | null | Called when any of the events fire. Called in the context of the chart and passed an array of active elements (bars, points, etc)
|
||||
*hover*.mode | String | 'single' | Sets which elements hover. Acceptable options are `'single'`, `'label'`, or `'dataset'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value. `dataset` highlights the closest dataset.
|
||||
*hover*.animationDuration | Number | 400 | Duration in milliseconds it takes to animate hover style changes
|
||||
onClick | Function | null | Called if the event is of type 'mouseup' or 'click'. Called in the context of the chart and passed an array of active elements
|
||||
defaultColor | Color | 'rgba(0,0,0,0.1)' |
|
||||
defaultFontColor | Color | '#666' | Default font color for all text
|
||||
defaultFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Default font family for all text
|
||||
defaultFontSize | Number | 12 | Default font size (in px) for text. Does not apply to radialLinear scale point labels
|
||||
defaultFontStyle | String | 'normal' | Default font style. Does not apply to tooltip title or footer. Does not apply to chart title
|
||||
legendCallback | Function | ` function (chart) { }` | Function to generate a legend. Receives the chart object to generate a legend from. Default implementation returns an HTML string.
|
||||
|
||||
The global options for the chart title is defined in `Chart.defaults.global.title`
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | false | Show the title block
|
||||
position | String | 'top' | Position of the title. 'top' or 'bottom' are allowed
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
fontColor | Color | '#666' | Text color
|
||||
fontFamily | String | 'Helvetica Neue' |
|
||||
fontSize | Number | 12 |
|
||||
fontStyle | String | 'bold' |
|
||||
padding | Number | 10 | Number of pixels to add above and below the title text
|
||||
text | String | '' | Title text
|
||||
|
||||
The global options for the chart legend is defined in `Chart.defaults.global.legend`
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true | Is the legend displayed
|
||||
position | String | 'top' | Position of the legend. Options are 'top' or 'bottom'
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
onClick | Function | `function(event, legendItem) {}` | A callback that is called when a click is registered on top of a label item
|
||||
labels |Object|-|-
|
||||
*labels*.boxWidth | Number | 40 | Width of coloured box
|
||||
*labels*.fontSize | Number | 12 | Font size
|
||||
*labels*.fontStyle | String | "normal" |
|
||||
*labels*.fontColor | Color | "#666" |
|
||||
*labels*.fontFamily | String | "Helvetica Neue" |
|
||||
*labels*.padding | Number | 10 | Padding between rows of colored boxes
|
||||
*labels*.generateLabels: | Function | `function(data) { }` | Generates legend items for each thing in the legend. Default implementation returns the text + styling for the color box. Styles that can be returned are `fillStyle`, `strokeStyle`, `lineCap`, `lineDash`, `lineDashOffset`, `lineWidth`, `lineJoin`. Return a `hidden` attribute to indicate that the label refers to something that is not visible. A strikethrough style will be given to the text in this case.
|
||||
|
||||
The global options for tooltips are defined in `Chart.defaults.global.tooltips`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
enabled | Boolean | true |
|
||||
custom | | null |
|
||||
mode | String | 'single' | Sets which elements appear in the tooltip. Acceptable options are `'single'` or `'label'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value.
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.8)' | Background color of the tooltip
|
||||
| | |
|
||||
Label | | | There are three labels you can control. `title`, `body`, `footer` the star (\*) represents one of these three. *(i.e. titleFontFamily, footerSpacing)*
|
||||
\*FontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" |
|
||||
\*FontSize | Number | 12 |
|
||||
\*FontStyle | String | title - "bold", body - "normal", footer - "bold" |
|
||||
\*Spacing | Number | 2 |
|
||||
\*Color | Color | "#fff" |
|
||||
\*Align | String | "left" | text alignment. See [MDN Canvas Documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign)
|
||||
titleMarginBottom | Number | 6 | Margin to add on bottom of title section
|
||||
footerMarginTop | Number | 6 | Margin to add before drawing the footer
|
||||
xPadding | Number | 6 | Padding to add on left and right of tooltip
|
||||
yPadding | Number | 6 | Padding to add on top and bottom of tooltip
|
||||
caretSize | Number | 5 | Size, in px, of the tooltip arrow
|
||||
cornerRadius | Number | 6 | Radius of tooltip corner curves
|
||||
multiKeyBackground | Color | "#fff" | Color to draw behind the colored boxes when multiple items are in the tooltip
|
||||
| | |
|
||||
callbacks | Object | - | V2.0 introduces callback functions as a replacement for the template engine in v1. The tooltip has the following callbacks for providing text. For all functions, 'this' will be the tooltip object create from the Chart.Tooltip constructor
|
||||
**Callback Functions** | | | All functions are called with the same arguments
|
||||
xLabel | String or Array[Strings] | | This is the xDataValue for each item to be displayed in the tooltip
|
||||
yLabel | String or Array[Strings] | | This is the yDataValue for each item to be displayed in the tooltip
|
||||
index | Number | | Data index.
|
||||
data | Object | | Data object passed to chart.
|
||||
`return`| String or Array[Strings] | | All functions must return either a string or an array of strings. Arrays of strings are treated as multiple lines of text.
|
||||
| | |
|
||||
*callbacks*.beforeTitle | Function | none | Text to render before the title
|
||||
*callbacks*.title | Function | `function(tooltipItems, data) { //Pick first xLabel }` | Text to render as the title
|
||||
*callbacks*.afterTitle | Function | none | Text to render after the ttiel
|
||||
*callbacks*.beforeBody | Function | none | Text to render before the body section
|
||||
*callbacks*.beforeLabel | Function | none | Text to render before an individual label
|
||||
*callbacks*.label | Function | `function(tooltipItem, data) { // Returns "datasetLabel: tooltipItem.yLabel" }` | Text to render as label
|
||||
*callbacks*.afterLabel | Function | none | Text to render after an individual label
|
||||
*callbacks*.afterBody | Function | none | Text to render after the body section
|
||||
*callbacks*.beforeFooter | Function | none | Text to render before the footer section
|
||||
*callbacks*.footer | Function | none | Text to render as the footer
|
||||
*callbacks*.afterFooter | Function | none | Text to render after the footer section
|
||||
|
||||
The global options for animations are defined in `Chart.defaults.global.animation`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
duration | Number | 1000 | The number of milliseconds an animation takes.
|
||||
easing | String | "easeOutQuart" | Easing function to use.
|
||||
onProgress | Function | none | Callback called on each step of an animation. Passed a single argument, an object, containing the chart instance and an object with details of the animation.
|
||||
onComplete | Function | none | Callback called at the end of an animation. Passed the same arguments as `onProgress`
|
||||
|
||||
The global options for elements are defined in `Chart.defaults.global.elements`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
arc | Object | - | -
|
||||
*arc*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default fill color for arcs
|
||||
*arc*.borderColor | Color | "#fff" | Default stroke color for arcs
|
||||
*arc*.borderWidth | Number | 2 | Default stroke width for arcs
|
||||
line | Object | - | -
|
||||
*line*.lineTension | Number | 0.4 | Default bezier curve tension. Set to `0` for no bezier curves.
|
||||
*line*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default line fill color
|
||||
*line*.borderWidth | Number | 3 | Default line stroke width
|
||||
*line*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default line stroke color
|
||||
*line*.borderCapStyle | String | 'butt' | Default line cap style. See [MDN](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap)
|
||||
*line*.borderDash | Array | `[]` | Default line dash. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)
|
||||
*line*.borderDashOffset | Number | 0.0 | Default line dash offset. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
||||
*line*.borderJoinStyle | String | 'miter' | Default line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin)
|
||||
*line*.fill | Boolean | true |
|
||||
point | Object | - | -
|
||||
*point*.radius | Number | 3 | Default point radius
|
||||
*point*.pointStyle | String | 'circle' | Default point style
|
||||
*point*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default point fill color
|
||||
*point*.borderWidth | Number | 1 | Default point stroke width
|
||||
*point*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default point stroke color
|
||||
*point*.hitRadius | Number | 1 | Extra radius added to point radius for hit detection
|
||||
*point*.hoverRadius | Number | 4 | Default point radius when hovered
|
||||
*point*.hoverBorderWidth | Number | 1 | Default stroke width when hovered
|
||||
rectangle | Object | - | -
|
||||
*rectangle*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default bar fill color
|
||||
*rectangle*.borderWidth | Number | 0 | Default bar stroke width
|
||||
*rectangle*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default bar stroke color
|
||||
*rectangle*.borderSkipped | String | 'bottom' | Default skipped (excluded) border for rectangle. Can be one of `bottom`, `left`, `top`, `right`
|
||||
|
||||
If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:
|
||||
|
||||
```javascript
|
||||
Chart.defaults.global.responsive = true;
|
||||
```
|
||||
|
||||
Now, every time we create a chart, `options.responsive` will be `true`.
|
||||
|
||||
### Colors
|
||||
When supplying colors to Chart options, you can use a number of formats. You can specify the color as a string in hexadecimal, RGB, or HSL notations.
|
||||
|
||||
You can also pass a [CanvasGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient) object. You will need to create this before passing to the chart, but using it you can achieve some interesting effects.
|
||||
|
||||
The final option is to pass a [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) object. For example, if you wanted to fill a dataset with a pattern from an image you could do the following.
|
||||
|
||||
```javascript
|
||||
var img = new Image();
|
||||
img.src = 'https://example.com/my_image.png';
|
||||
img.onload = function() {
|
||||
var ctx = document.getElementById('canvas').getContext('2d');
|
||||
var fillPattern = ctx.CreatePattern(img, 'repeat');
|
||||
|
||||
var chart = new Chart(ctx, {
|
||||
data: {
|
||||
labels: ['Item 1', 'Item 2', 'Item 3'],
|
||||
datasets: [{
|
||||
data: [10, 20, 30],
|
||||
backgroundColor: fillPattern
|
||||
}]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
```
|
||||
|
408
vendors/Chart.js/docs/01-Chart-Configuration.md
vendored
Normal file
@ -0,0 +1,408 @@
|
||||
---
|
||||
title: Chart Configuration
|
||||
anchor: chart-configuration
|
||||
---
|
||||
|
||||
Chart.js provides a number of options for changing the behaviour of created charts. These configuration options can be changed on a per chart basis by passing in an options object when creating the chart. Alternatively, the global configuration can be changed which will be used by all charts created after that point.
|
||||
|
||||
### Creating a Chart with Options
|
||||
|
||||
To create a chart with configuration options, simply pass an object containing your configuration to the constructor. In the example below, a line chart is created and configured to not be responsive.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
responsive: false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Global Configuration
|
||||
|
||||
This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.
|
||||
|
||||
Chart.js merges the options object passed to the chart with the global configuration using chart type defaults and scales defaults appropriately. This way you can be as specific as you would like in your individual chart configuration, while still changing the defaults for all chart types where applicable. The global general options are defined in `Chart.defaults.global`. The defaults for each chart type are discussed in the documentation for that chart type.
|
||||
|
||||
The following example would set the hover mode to 'single' for all charts where this was not overridden by the chart type defaults or the options passed to the constructor on creation.
|
||||
|
||||
```javascript
|
||||
Chart.defaults.global.hover.mode = 'single';
|
||||
|
||||
// Hover mode is set to single because it was not overridden here
|
||||
var chartInstanceHoverModeSingle = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
});
|
||||
|
||||
// This chart would have the hover mode that was passed in
|
||||
var chartInstanceDifferentHoverMode = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
hover: {
|
||||
// Overrides the global setting
|
||||
mode: 'label'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Global Font Settings
|
||||
|
||||
There are 4 special global settings that can change all of the fonts on the chart. These options are in `Chart.defaults.global`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
defaultFontColor | Color | '#666' | Default font color for all text
|
||||
defaultFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Default font family for all text
|
||||
defaultFontSize | Number | 12 | Default font size (in px) for text. Does not apply to radialLinear scale point labels
|
||||
defaultFontStyle | String | 'normal' | Default font style. Does not apply to tooltip title or footer. Does not apply to chart title
|
||||
|
||||
### Common Chart Configuration
|
||||
|
||||
The following options are applicable to all charts. The can be set on the [global configuration](#chart-configuration-global-configuration), or they can be passed to the chart constructor.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
responsive | Boolean | true | Resizes when the canvas container does.
|
||||
responsiveAnimationDuration | Number | 0 | Duration in milliseconds it takes to animate to new size after a resize event.
|
||||
maintainAspectRatio | Boolean | true | Maintain the original canvas aspect ratio `(width / height)` when resizing
|
||||
events | Array[String] | `["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"]` | Events that the chart should listen to for tooltips and hovering
|
||||
onClick | Function | null | Called if the event is of type 'mouseup' or 'click'. Called in the context of the chart and passed an array of active elements
|
||||
legendCallback | Function | ` function (chart) { }` | Function to generate a legend. Receives the chart object to generate a legend from. Default implementation returns an HTML string.
|
||||
|
||||
### Title Configuration
|
||||
|
||||
The title configuration is passed into the `options.title` namespace. The global options for the chart title is defined in `Chart.defaults.global.title`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | false | Display the title block
|
||||
position | String | 'top' | Position of the title. Only 'top' or 'bottom' are currently allowed
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
fontSize | Number | 12 | Font size inherited from global configuration
|
||||
fontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family inherited from global configuration
|
||||
fontColor | Color | "#666" | Font color inherited from global configuration
|
||||
fontStyle | String | 'bold' | Font styling of the title.
|
||||
padding | Number | 10 | Number of pixels to add above and below the title text
|
||||
text | String | '' | Title text
|
||||
|
||||
#### Example Usage
|
||||
|
||||
The example below would enable a title of 'Custom Chart Title' on the chart that is created.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Custom Chart Title'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Legend Configuration
|
||||
|
||||
The legend configuration is passed into the `options.legend` namespace. The global options for the chart legend is defined in `Chart.defaults.global.legend`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true | Is the legend displayed
|
||||
position | String | 'top' | Position of the legend. Options are 'top' or 'bottom'
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
onClick | Function | `function(event, legendItem) {}` | A callback that is called when a click is registered on top of a label item
|
||||
labels |Object|-| See the [Legend Label Configuration](#chart-configuration-legend-label-configuration) section below.
|
||||
|
||||
#### Legend Label Configuration
|
||||
|
||||
The legend label configuration is nested below the legend configuration using the `labels` key.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
boxWidth | Number | 40 | Width of coloured box
|
||||
fontSize | Number | 12 | Font size inherited from global configuration
|
||||
fontStyle | String | "normal" | Font style inherited from global configuration
|
||||
fontColor | Color | "#666" | Font color inherited from global configuration
|
||||
fontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family inherited from global configuration
|
||||
padding | Number | 10 | Padding between rows of colored boxes
|
||||
generateLabels: | Function | `function(chart) { }` | Generates legend items for each thing in the legend. Default implementation returns the text + styling for the color box. See [Legend Item](#chart-configuration-legend-item-interface) for details.
|
||||
|
||||
#### Legend Item Interface
|
||||
|
||||
Items passed to the legend `onClick` function are the ones returned from `labels.generateLabels`. These items must implement the following interface.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Label that will be displayed
|
||||
text: String,
|
||||
|
||||
// Fill style of the legend box
|
||||
fillStyle: Color,
|
||||
|
||||
// If true, this item represents a hidden dataset. Label will be rendered with a strike-through effect
|
||||
hidden: Boolean,
|
||||
|
||||
// For box border. See https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap
|
||||
lineCap: String,
|
||||
|
||||
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
|
||||
lineDash: Array[Number],
|
||||
|
||||
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
|
||||
lineDashOffset: Number,
|
||||
|
||||
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
|
||||
lineJoin: String,
|
||||
|
||||
// Width of box border
|
||||
lineWidth: Number,
|
||||
|
||||
// Stroke style of the legend box
|
||||
strokeStyle: Color
|
||||
}
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
The following example will create a chart with the legend enabled and turn all of the text red in color.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: {
|
||||
legend: {
|
||||
display: true,
|
||||
labels: {
|
||||
fontColor: 'rgb(255, 99, 132)'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Tooltip Configuration
|
||||
|
||||
The title configuration is passed into the `options.tooltips` namespace. The global options for the chart tooltips is defined in `Chart.defaults.global.title`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
enabled | Boolean | true | Are tooltips
|
||||
custom | Function | null | See [section](#chart-configuration-custom-tooltips) below
|
||||
mode | String | 'single' | Sets which elements appear in the tooltip. Acceptable options are `'single'` or `'label'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value.
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.8)' | Background color of the tooltip
|
||||
titleFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for tooltip title inherited from global font family
|
||||
titleFontSize | Number | 12 | Font size for tooltip title inherited from global font size
|
||||
titleFontStyle | String | "bold" |
|
||||
titleFontColor | Color | "#fff" | Font color for tooltip title
|
||||
titleSpacing | Number | 2 | Spacing to add to top and bottom of each title line.
|
||||
titleMarginBottom | Number | 6 | Margin to add on bottom of title section
|
||||
bodyFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for tooltip items inherited from global font family
|
||||
bodyFontSize | Number | 12 | Font size for tooltip items inherited from global font size
|
||||
bodyFontStyle | String | "normal" |
|
||||
bodyFontColor | Color | "#fff" | Font color for tooltip items.
|
||||
bodySpacing | Number | 2 | Spacing to add to top and bottom of each tooltip item
|
||||
footerFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for tooltip footer inherited from global font family.
|
||||
footerFontSize | Number | 12 | Font size for tooltip footer inherited from global font size.
|
||||
footerFontStyle | String | "bold" | Font style for tooltip footer.
|
||||
footerFontColor | Color | "#fff" | Font color for tooltip footer.
|
||||
footerSpacing | Number | 2 | Spacing to add to top and bottom of each footer line.
|
||||
footerMarginTop | Number | 6 | Margin to add before drawing the footer
|
||||
xPadding | Number | 6 | Padding to add on left and right of tooltip
|
||||
yPadding | Number | 6 | Padding to add on top and bottom of tooltip
|
||||
caretSize | Number | 5 | Size, in px, of the tooltip arrow
|
||||
cornerRadius | Number | 6 | Radius of tooltip corner curves
|
||||
multiKeyBackground | Color | "#fff" | Color to draw behind the colored boxes when multiple items are in the tooltip
|
||||
callbacks | Object | | See the [callbacks section](#chart-configuration-tooltip-callbacks) below
|
||||
|
||||
#### Tooltip Callbacks
|
||||
|
||||
The tooltip label configuration is nested below the tooltip configuration using the `callbacks` key. The tooltip has the following callbacks for providing text. For all functions, 'this' will be the tooltip object created from the Chart.Tooltip constructor.
|
||||
|
||||
All functions are called with the same arguments: a [tooltip item](#chart-configuration-tooltip-item-interface) and the data object passed to the chart. All functions must return either a string or an array of strings. Arrays of strings are treated as multiple lines of text.
|
||||
|
||||
Callback | Arguments | Description
|
||||
--- | --- | ---
|
||||
beforeTitle | `Array[tooltipItem], data` | Text to render before the title
|
||||
title | `Array[tooltipItem], data` | Text to render as the title
|
||||
afterTitle | `Array[tooltipItem], data` | Text to render after the title
|
||||
beforeBody | `Array[tooltipItem], data` | Text to render before the body section
|
||||
beforeLabel | `tooltipItem, data` | Text to render before an individual label
|
||||
label | `tooltipItem, data` | Text to render for an individual item in the tooltip
|
||||
afterLabel | `tooltipItem, data` | Text to render after an individual label
|
||||
afterBody | `Array[tooltipItem], data` | Text to render after the body section
|
||||
beforeFooter | `Array[tooltipItem], data` | Text to render before the footer section
|
||||
footer | `Array[tooltipItem], data` | Text to render as the footer
|
||||
afterFooter | `Array[tooltipItem], data` | Text to render after the footer section
|
||||
|
||||
#### Tooltip Item Interface
|
||||
|
||||
The tooltip items passed to the tooltip callbacks implement the following interface.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// X Value of the tooltip as a string
|
||||
xLabel: String,
|
||||
|
||||
// Y value of the tooltip as a string
|
||||
yLabel: String,
|
||||
|
||||
// Index of the dataset the item comes from
|
||||
datasetIndex: Number,
|
||||
|
||||
// Index of this data item in the dataset
|
||||
index: Number
|
||||
}
|
||||
```
|
||||
|
||||
### Hover Configuration
|
||||
|
||||
The hover configuration is passed into the `options.hover` namespace. The global hover configuration is at `Chart.defaults.global.hover`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
mode | String | 'single' | Sets which elements hover. Acceptable options are `'single'`, `'label'`, or `'dataset'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value. `dataset` highlights the closest dataset.
|
||||
animationDuration | Number | 400 | Duration in milliseconds it takes to animate hover style changes
|
||||
onHover | Function | null | Called when any of the events fire. Called in the context of the chart and passed an array of active elements (bars, points, etc)
|
||||
|
||||
### Animation Configuration
|
||||
|
||||
The following animation options are available. The global options for are defined in `Chart.defaults.global.animation`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
duration | Number | 1000 | The number of milliseconds an animation takes.
|
||||
easing | String | "easeOutQuart" | Easing function to use.
|
||||
onProgress | Function | none | Callback called on each step of an animation. Passed a single argument, an object, containing the chart instance and an object with details of the animation.
|
||||
onComplete | Function | none | Callback called at the end of an animation. Passed the same arguments as `onProgress`
|
||||
|
||||
#### Animation Callbacks
|
||||
|
||||
The `onProgress` and `onComplete` callbacks are useful for synchronizing an external draw to the chart animation. The callback is passed an object that implements the following interface. An example usage of these callbacks can be found on [Github](https://github.com/chartjs/Chart.js/blob/master/samples/AnimationCallbacks/progress-bar.html). This sample displays a progress bar showing how far along the animation is.
|
||||
|
||||
```javscript
|
||||
{
|
||||
// Chart object
|
||||
chartInstance,
|
||||
|
||||
// Contains details of the on-going animation
|
||||
animationObject,
|
||||
}
|
||||
```
|
||||
|
||||
#### Animation Object
|
||||
|
||||
The animation object passed to the callbacks is of type `Chart.Animation`. The object has the following parameters.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Current Animation frame number
|
||||
currentStep: Number,
|
||||
|
||||
// Number of animation frames
|
||||
numSteps: Number,
|
||||
|
||||
// Animation easing to use
|
||||
easing: String,
|
||||
|
||||
// Function that renders the chart
|
||||
render: Function,
|
||||
|
||||
// User callback
|
||||
onAnimationProgress: Function,
|
||||
|
||||
// User callback
|
||||
onAnimationComplete: Function
|
||||
}
|
||||
```
|
||||
|
||||
### Element Configuration
|
||||
|
||||
The global options for elements are defined in `Chart.defaults.global.elements`.
|
||||
|
||||
Options can be configured for four different types of elements; arc, lines, points, and rectangles. When set, these options apply to all objects of that type unless specifically overridden by the configuration attached to a dataset.
|
||||
|
||||
#### Arc Configuration
|
||||
|
||||
Arcs are used in the polar area, doughnut and pie charts. They can be configured with the following options. The global arc options are stored in `Chart.defaults.global.elements.arc`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.1)' | Default fill color for arcs. Inherited from the global default
|
||||
borderColor | Color | '#fff' | Default stroke color for arcs
|
||||
borderWidth | Number | 2 | Default stroke width for arcs
|
||||
|
||||
#### Line Configuration
|
||||
|
||||
Line elements are used to represent the line in a line chart. The global line options are stored in `Chart.defaults.global.elements.line`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
tension | Number | 0.4 | Default bezier curve tension. Set to `0` for no bezier curves.
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.1)' | Default line fill color
|
||||
borderWidth | Number | 3 | Default line stroke width
|
||||
borderColor | Color | 'rgba(0,0,0,0.1)' | Default line stroke color
|
||||
borderCapStyle | String | 'butt' | Default line cap style. See [MDN](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap)
|
||||
borderDash | Array | `[]` | Default line dash. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)
|
||||
borderDashOffset | Number | 0.0 | Default line dash offset. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
||||
borderJoinStyle | String | 'miter' | Default line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin)
|
||||
fill | Boolean | true | If true, the line is filled.
|
||||
|
||||
#### Point Configuration
|
||||
|
||||
Point elements are used to represent the points in a line chart or a bubble chart. The global point options are stored in `Chart.defaults.global.elements.point`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
radius | Number | 3 | Default point radius
|
||||
pointStyle | String | 'circle' | Default point style
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.1)' | Default point fill color
|
||||
borderWidth | Number | 1 | Default point stroke width
|
||||
borderColor | Color | 'rgba(0,0,0,0.1)' | Default point stroke color
|
||||
hitRadius | Number | 1 | Extra radius added to point radius for hit detection
|
||||
hoverRadius | Number | 4 | Default point radius when hovered
|
||||
hoverBorderWidth | Number | 1 | Default stroke width when hovered
|
||||
|
||||
#### Rectangle Configuration
|
||||
|
||||
Rectangle elements are used to represent the bars in a bar chart. The global rectangle options are stored in `Chart.defaults.global.elements.rectange`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.1)' | Default bar fill color
|
||||
borderWidth | Number | 0 | Default bar stroke width
|
||||
borderColor | Color | 'rgba(0,0,0,0.1)' | Default bar stroke color
|
||||
borderSkipped | String | 'bottom' | Default skipped (excluded) border for rectangle. Can be one of `bottom`, `left`, `top`, `right`
|
||||
|
||||
### Colors
|
||||
|
||||
When supplying colors to Chart options, you can use a number of formats. You can specify the color as a string in hexadecimal, RGB, or HSL notations. If a color is needed, but not specified, Chart.js will use the global default color. This color is stored at `Chart.defaults.global.defaultColor`. It is initially set to 'rgb(0, 0, 0, 0.1)';
|
||||
|
||||
You can also pass a [CanvasGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient) object. You will need to create this before passing to the chart, but using it you can achieve some interesting effects.
|
||||
|
||||
The final option is to pass a [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) object. For example, if you wanted to fill a dataset with a pattern from an image you could do the following.
|
||||
|
||||
```javascript
|
||||
var img = new Image();
|
||||
img.src = 'https://example.com/my_image.png';
|
||||
img.onload = function() {
|
||||
var ctx = document.getElementById('canvas').getContext('2d');
|
||||
var fillPattern = ctx.createPattern(img, 'repeat');
|
||||
|
||||
var chart = new Chart(ctx, {
|
||||
data: {
|
||||
labels: ['Item 1', 'Item 2', 'Item 3'],
|
||||
datasets: [{
|
||||
data: [10, 20, 30],
|
||||
backgroundColor: fillPattern
|
||||
}]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
```
|
301
vendors/Chart.js/docs/01-Scales.md
vendored
@ -1,301 +0,0 @@
|
||||
---
|
||||
title: Scales
|
||||
anchor: scales
|
||||
---
|
||||
|
||||
Scales in v2.0 of Chart.js are significantly more powerful, but also different than those of v1.0.
|
||||
* Multiple x & y axes are now supported.
|
||||
* A built-in label auto-skip feature now detects would-be overlapping ticks and labels and removes every nth label to keep things displaying normally.
|
||||
* Scale titles are now supported
|
||||
* New scale types can be extended without writing an entirely new chart type
|
||||
|
||||
Every scale extends a core scale class with the following options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
type | String | Chart specific. | Type of scale being employed. Custom scales can be created and registered with a string key. Options: ["category"](#scales-category-scale), ["linear"](#scales-linear-scale), ["logarithmic"](#scales-logarithmic-scale), ["time"](#scales-time-scale), ["radialLinear"](#scales-radial-linear-scale)
|
||||
display | Boolean | true | If true, show the scale including gridlines, ticks, and labels. Overrides *gridLines.display*, *scaleLabel.display*, and *ticks.display*.
|
||||
position | String | "left" | Position of the scale. Possible values are top, left, bottom and right.
|
||||
beforeUpdate | Function | undefined | Callback called before the update process starts. Passed a single argument, the scale instance.
|
||||
beforeSetDimensions | Function | undefined | Callback that runs before dimensions are set. Passed a single argument, the scale instance.
|
||||
afterSetDimensions | Function | undefined | Callback that runs after dimensions are set. Passed a single argument, the scale instance.
|
||||
beforeDataLimits | Function | undefined | Callback that runs before data limits are determined. Passed a single argument, the scale instance.
|
||||
afterDataLimits | Function | undefined | Callback that runs after data limits are determined. Passed a single argument, the scale instance.
|
||||
beforeBuildTicks | Function | undefined | Callback that runs before ticks are created. Passed a single argument, the scale instance.
|
||||
afterBuildTicks | Function | undefined | Callback that runs after ticks are created. Useful for filtering ticks. Passed a single argument, the scale instance.
|
||||
beforeTickToLabelConversion | Function | undefined | Callback that runs before ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
afterTickToLabelConversion | Function | undefined | Callback that runs after ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
beforeCalculateTickRotation | Function | undefined | Callback that runs before tick rotation is determined. Passed a single argument, the scale instance.
|
||||
afterCalculateTickRotation | Function | undefined | Callback that runs after tick rotation is determined. Passed a single argument, the scale instance.
|
||||
beforeFit | Function | undefined | Callback that runs before the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterFit | Function | undefined | Callback that runs after the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterUpdate | Function | undefined | Callback that runs at the end of the update process. Passed a single argument, the scale instance.
|
||||
**gridLines** | Object | - | Options for the grid lines that run perpendicular to the axis.
|
||||
*gridLines*.display | Boolean | true |
|
||||
*gridLines*.color | Color | "rgba(0, 0, 0, 0.1)" | Color of the grid lines.
|
||||
*gridLines*.lineWidth | Number | 1 | Stroke width of grid lines
|
||||
*gridLines*.drawOnChartArea | Boolean | true | If true, draw lines on the chart area inside the axis lines. This is useful when there are multiple axes and you need to control which grid lines are drawn
|
||||
*gridLines*.drawTicks | Boolean | true | If true, draw lines beside the ticks in the axis area beside the chart.
|
||||
*gridLines*.tickMarkLength | Number | 10 | Length in pixels that the grid lines will draw into the axis area.
|
||||
*gridLines*.zeroLineWidth | Number | 1 | Stroke width of the grid line for the first index (index 0).
|
||||
*gridLines*.zeroLineColor | Color | "rgba(0, 0, 0, 0.25)" | Stroke color of the grid line for the first index (index 0).
|
||||
*gridLines*.offsetGridLines | Boolean | false | If true, offset labels from grid lines.
|
||||
**scaleLabel** | Object | | Title for the entire axis.
|
||||
*scaleLabel*.display | Boolean | false |
|
||||
*scaleLabel*.labelString | String | "" | The text for the title. (i.e. "# of People", "Response Choices")
|
||||
*scaleLabel*.fontColor | Color | "#666" | Font color for the scale title.
|
||||
*scaleLabel*.fontFamily| String | "Helvetica Neue" | Font family for the scale title, follows CSS font-family options.
|
||||
*scaleLabel*.fontSize | Number | 12 | Font size for the scale title.
|
||||
*scaleLabel*.fontStyle | String | "normal" | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
**ticks** | Object | | Settings for the labels that run along the axis.
|
||||
*ticks*.beginAtZero | Boolean | false | If true the scale will be begin at 0, if false the ticks will begin at your smallest data value.
|
||||
*ticks*.fontColor | Color | "#666" | Font color for the tick labels.
|
||||
*ticks*.fontFamily | String | "Helvetica Neue" | Font family for the tick labels, follows CSS font-family options.
|
||||
*ticks*.fontSize | Number | 12 | Font size for the tick labels.
|
||||
*ticks*.fontStyle | String | "normal" | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
*ticks*.maxRotation | Number | 90 | Maximum rotation for tick labels when rotating to condense labels. Note: Rotation doesn't occur until necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.minRotation | Number | 20 | *currently not-implemented* Minimum rotation for tick labels when condensing is necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.maxTicksLimit | Number | 11 | Maximum number of ticks and gridlines to show. If not defined, it will limit to 11 ticks but will show all gridlines.
|
||||
*ticks*.padding | Number | 10 | Padding between the tick label and the axis. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.mirror | Boolean | false | Flips tick labels around axis, displaying the labels inside the chart instead of outside. *Note: Only applicable to vertical scales.*
|
||||
*ticks*.reverse | Boolean | false | Reverses order of tick labels.
|
||||
*ticks*.display | Boolean | true | If true, show the ticks.
|
||||
*ticks*.suggestedMin | Number | - | User defined minimum number for the scale, overrides minimum value *except for if* it is higher than the minimum value.
|
||||
*ticks*.suggestedMax | Number | - | User defined maximum number for the scale, overrides maximum value *except for if* it is lower than the maximum value.
|
||||
*ticks*.min | Number | - | User defined minimum number for the scale, overrides minimum value.
|
||||
*ticks*.max | Number | - | User defined minimum number for the scale, overrides maximum value
|
||||
*ticks*.autoSkip | Boolean | true | If true, automatically calculates how many labels that can be shown and hides labels accordingly. Turn it off to show all labels no matter what
|
||||
*ticks*.callback | Function | `function(value) { return '' + value; } ` | Returns the string representation of the tick value as it should be displayed on the chart.
|
||||
|
||||
The `callback` method may be used for advanced tick customization. The following callback would display every label in scientific notation
|
||||
```javascript
|
||||
{
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
// Return an empty string to draw the tick line but hide the tick label
|
||||
// Return `null` or `undefined` to hide the tick line entirely
|
||||
userCallback: function(value, index, values) {
|
||||
return value.toExponential();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Category Scale
|
||||
The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data.
|
||||
|
||||
The category scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
}
|
||||
```
|
||||
|
||||
The `ticks.min` and `ticks.max` attributes may be used with the category scale. Unlike other scales, the value of these attributes must simply be something that can be found in the `labels` array of the data object.
|
||||
|
||||
### Linear Scale
|
||||
The linear scale can be used to display numerical data. It can be placed on either the x or y axis. The scatter chart type automatically configures a line chart to use one of these scales for the x axis.
|
||||
|
||||
The linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(tickValue, index, ticks) {
|
||||
var delta = ticks[1] - ticks[0];
|
||||
|
||||
// If we have a number like 2.5 as the delta, figure out how many decimal places we need
|
||||
if (Math.abs(delta) > 1) {
|
||||
if (tickValue !== Math.floor(tickValue)) {
|
||||
// not an integer
|
||||
delta = tickValue - Math.floor(tickValue);
|
||||
}
|
||||
}
|
||||
|
||||
var logDelta = helpers.log10(Math.abs(delta));
|
||||
var tickString = '';
|
||||
|
||||
if (tickValue !== 0) {
|
||||
var numDecimal = -1 * Math.floor(logDelta);
|
||||
numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
|
||||
tickString = tickValue.toFixed(numDecimal);
|
||||
} else {
|
||||
tickString = '0'; // never show decimal places for 0
|
||||
}
|
||||
|
||||
return tickString;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It also provides additional configuration options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
*ticks*.stepSize | Number | - | User defined fixed step size for the scale. If set, the scale ticks will be enumerated by multiple of stepSize, having one tick per increment. If not set, the ticks are labeled automatically using the nice numbers algorithm.
|
||||
|
||||
### Logarithmic Scale
|
||||
The logarithmic scale is used to display logarithmic data of course. It can be placed on either the x or y axis.
|
||||
|
||||
The log scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));
|
||||
|
||||
if (remain === 1 || remain === 2 || remain === 5) {
|
||||
return value.toExponential();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Time Scale
|
||||
The time scale is used to display times and dates. It can be placed on the x axis. When building its ticks, it will automatically calculate the most comfortable unit base on the size of the scale.
|
||||
|
||||
The time scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
time: {
|
||||
// string/callback - By default, date objects are expected. You may use a pattern string from http://momentjs.com/docs/#/parsing/string-format/ to parse a time string format, or use a callback function that is passed the label, and must return a moment() instance.
|
||||
parser: false,
|
||||
// string - By default, unit will automatically be detected. Override with 'week', 'month', 'year', etc. (see supported time measurements)
|
||||
unit: false,
|
||||
|
||||
// Number - The number of steps of the above unit between ticks
|
||||
unitStepSize: 1
|
||||
|
||||
// string - By default, no rounding is applied. To round, set to a supported time unit eg. 'week', 'month', 'year', etc.
|
||||
round: false,
|
||||
|
||||
// Moment js for each of the units. Replaces `displayFormat`
|
||||
// To override, use a pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormats: {
|
||||
'millisecond': 'SSS [ms]',
|
||||
'second': 'h:mm:ss a', // 11:20:01 AM
|
||||
'minute': 'h:mm:ss a', // 11:20:01 AM
|
||||
'hour': 'MMM D, hA', // Sept 4, 5PM
|
||||
'day': 'll', // Sep 4 2015
|
||||
'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
'month': 'MMM YYYY', // Sept 2015
|
||||
'quarter': '[Q]Q - YYYY', // Q3
|
||||
'year': 'YYYY', // 2015
|
||||
},
|
||||
// Sets the display format used in tooltip generation
|
||||
tooltipFormat: ''
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following time measurements are supported:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'millisecond': {
|
||||
display: 'SSS [ms]', // 002 ms
|
||||
maxStep: 1000,
|
||||
},
|
||||
'second': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'minute': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'hour': {
|
||||
display: 'MMM D, hA', // Sept 4, 5PM
|
||||
maxStep: 24,
|
||||
},
|
||||
'day': {
|
||||
display: 'll', // Sep 4 2015
|
||||
maxStep: 7,
|
||||
},
|
||||
'week': {
|
||||
display: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
maxStep: 4.3333,
|
||||
},
|
||||
'month': {
|
||||
display: 'MMM YYYY', // Sept 2015
|
||||
maxStep: 12,
|
||||
},
|
||||
'quarter': {
|
||||
display: '[Q]Q - YYYY', // Q3
|
||||
maxStep: 4,
|
||||
},
|
||||
'year': {
|
||||
display: 'YYYY', // 2015
|
||||
maxStep: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Radial Linear Scale
|
||||
The radial linear scale is used specifically for the radar chart type.
|
||||
|
||||
The radial linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
animate: true,
|
||||
lineArc: false,
|
||||
position: "chartArea",
|
||||
|
||||
angleLines: {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
|
||||
//Number - Limit the maximum number of ticks and gridlines
|
||||
maxTicksLimit: 11,
|
||||
},
|
||||
|
||||
pointLabels: {
|
||||
//String - Point label font declaration
|
||||
fontFamily: "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
fontStyle: "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
fontSize: 10,
|
||||
|
||||
//String - Point label font colour
|
||||
fontColor: "#666",
|
||||
|
||||
//Function - Used to determine point labels to show in scale
|
||||
callback: function(pointLabel) {
|
||||
return pointLabel;
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
357
vendors/Chart.js/docs/02-Scales.md
vendored
Normal file
@ -0,0 +1,357 @@
|
||||
---
|
||||
title: Scales
|
||||
anchor: scales
|
||||
---
|
||||
|
||||
Scales in v2.0 of Chart.js are significantly more powerful, but also different than those of v1.0.
|
||||
* Multiple X & Y axes are supported.
|
||||
* A built-in label auto-skip feature detects would-be overlapping ticks and labels and removes every nth label to keep things displaying normally.
|
||||
* Scale titles are supported
|
||||
* New scale types can be extended without writing an entirely new chart type
|
||||
|
||||
|
||||
### Common Configuration
|
||||
|
||||
Every scale extends a core scale class with the following options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
type | String | Chart specific. | Type of scale being employed. Custom scales can be created and registered with a string key. Options: ["category"](#scales-category-scale), ["linear"](#scales-linear-scale), ["logarithmic"](#scales-logarithmic-scale), ["time"](#scales-time-scale), ["radialLinear"](#scales-radial-linear-scale)
|
||||
display | Boolean | true | If true, show the scale including gridlines, ticks, and labels. Overrides *gridLines.display*, *scaleLabel.display*, and *ticks.display*.
|
||||
position | String | "left" | Position of the scale. Possible values are 'top', 'left', 'bottom' and 'right'.
|
||||
beforeUpdate | Function | undefined | Callback called before the update process starts. Passed a single argument, the scale instance.
|
||||
beforeSetDimensions | Function | undefined | Callback that runs before dimensions are set. Passed a single argument, the scale instance.
|
||||
afterSetDimensions | Function | undefined | Callback that runs after dimensions are set. Passed a single argument, the scale instance.
|
||||
beforeDataLimits | Function | undefined | Callback that runs before data limits are determined. Passed a single argument, the scale instance.
|
||||
afterDataLimits | Function | undefined | Callback that runs after data limits are determined. Passed a single argument, the scale instance.
|
||||
beforeBuildTicks | Function | undefined | Callback that runs before ticks are created. Passed a single argument, the scale instance.
|
||||
afterBuildTicks | Function | undefined | Callback that runs after ticks are created. Useful for filtering ticks. Passed a single argument, the scale instance.
|
||||
beforeTickToLabelConversion | Function | undefined | Callback that runs before ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
afterTickToLabelConversion | Function | undefined | Callback that runs after ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
beforeCalculateTickRotation | Function | undefined | Callback that runs before tick rotation is determined. Passed a single argument, the scale instance.
|
||||
afterCalculateTickRotation | Function | undefined | Callback that runs after tick rotation is determined. Passed a single argument, the scale instance.
|
||||
beforeFit | Function | undefined | Callback that runs before the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterFit | Function | undefined | Callback that runs after the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterUpdate | Function | undefined | Callback that runs at the end of the update process. Passed a single argument, the scale instance.
|
||||
**gridLines** | Object | - | See [grid line configuration](#scales-grid-line-configuration) section.
|
||||
**scaleLabel** | Object | | See [scale title configuration](#scales-scale-title-configuration) section.
|
||||
**ticks** | Object | | See [ticks configuration](#scales-ticks-configuration) section.
|
||||
|
||||
#### Grid Line Configuration
|
||||
|
||||
The grid line configuration is nested under the scale configuration in the `gridLines` key. It defines options for the grid lines that run perpendicular to the axis.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true |
|
||||
color | Color | "rgba(0, 0, 0, 0.1)" | Color of the grid lines.
|
||||
lineWidth | Number | 1 | Stroke width of grid lines
|
||||
drawBorder | Boolean | true | If true draw border on the edge of the chart
|
||||
drawOnChartArea | Boolean | true | If true, draw lines on the chart area inside the axis lines. This is useful when there are multiple axes and you need to control which grid lines are drawn
|
||||
drawTicks | Boolean | true | If true, draw lines beside the ticks in the axis area beside the chart.
|
||||
tickMarkLength | Number | 10 | Length in pixels that the grid lines will draw into the axis area.
|
||||
zeroLineWidth | Number | 1 | Stroke width of the grid line for the first index (index 0).
|
||||
zeroLineColor | Color | "rgba(0, 0, 0, 0.25)" | Stroke color of the grid line for the first index (index 0).
|
||||
offsetGridLines | Boolean | false | If true, offset labels from grid lines.
|
||||
|
||||
#### Scale Title Configuration
|
||||
|
||||
The grid line configuration is nested under the scale configuration in the `scaleLabel` key. It defines options for the scale title.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | false |
|
||||
labelString | String | "" | The text for the title. (i.e. "# of People", "Response Choices")
|
||||
fontColor | Color | "#666" | Font color for the scale title.
|
||||
fontFamily| String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for the scale title, follows CSS font-family options.
|
||||
fontSize | Number | 12 | Font size for the scale title.
|
||||
fontStyle | String | "normal" | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
|
||||
#### Tick Configuration
|
||||
|
||||
The grid line configuration is nested under the scale configuration in the `ticks` key. It defines options for the tick marks that are generated by the axis.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
autoSkip | Boolean | true | If true, automatically calculates how many labels that can be shown and hides labels accordingly. Turn it off to show all labels no matter what
|
||||
callback | Function | `function(value) { return '' + value; } ` | Returns the string representation of the tick value as it should be displayed on the chart. See [callback](#scales-creating-custom-tick-formats) section below.
|
||||
display | Boolean | true | If true, show the ticks.
|
||||
fontColor | Color | "#666" | Font color for the tick labels.
|
||||
fontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for the tick labels, follows CSS font-family options.
|
||||
fontSize | Number | 12 | Font size for the tick labels.
|
||||
fontStyle | String | "normal" | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
labelOffset | Number | 0 | Distance in pixels to offset the label from the centre point of the tick (in the y direction for the x axis, and the x direction for the y axis). *Note: this can cause labels at the edges to be cropped by the edge of the canvas*
|
||||
maxRotation | Number | 90 | Maximum rotation for tick labels when rotating to condense labels. Note: Rotation doesn't occur until necessary. *Note: Only applicable to horizontal scales.*
|
||||
minRotation | Number | 0 | Minimum rotation for tick labels. *Note: Only applicable to horizontal scales.*
|
||||
mirror | Boolean | false | Flips tick labels around axis, displaying the labels inside the chart instead of outside. *Note: Only applicable to vertical scales.*
|
||||
padding | Number | 10 | Padding between the tick label and the axis. *Note: Only applicable to horizontal scales.*
|
||||
reverse | Boolean | false | Reverses order of tick labels.
|
||||
|
||||
#### Creating Custom Tick Formats
|
||||
|
||||
The `callback` method may be used for advanced tick customization. In the following example, every label of the Y axis would be displayed in scientific notation.
|
||||
|
||||
If the callback returns `null` or `undefined` the associated grid line will be hidden.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
// Create scientific notation labels
|
||||
callback: function(value, index, values) {
|
||||
return value.toExponential();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Category Scale
|
||||
|
||||
The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data.
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
The category scale has the following additional options that can be set.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
ticks.min | String | - | The minimum item to display. Must be a value in the `labels` array
|
||||
ticks.max | String | - | The maximum item to display. Must be a value in the `labels` array
|
||||
gridLines.offsetGridLines | Boolean | - | If true, labels are shifted to be between grid lines. This is used in the bar chart.
|
||||
|
||||
|
||||
### Linear Scale
|
||||
|
||||
The linear scale is use to chart numerical data. It can be placed on either the x or y axis. The scatter chart type automatically configures a line chart to use one of these scales for the x axis. As the name suggests, linear interpolation is used to determine where a value lies on the axis.
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
The following options are provided by the linear scale. They are all located in the `ticks` sub options.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
beginAtZero | Boolean | - | if true, scale will inclulde 0 if it is not already included.
|
||||
min | Number | - | User defined minimum number for the scale, overrides minimum value from data.
|
||||
max | Number | - | User defined maximum number for the scale, overrides maximum value from data.
|
||||
maxTicksLimit | Number | 11 | Maximum number of ticks and gridlines to show. If not defined, it will limit to 11 ticks but will show all gridlines.
|
||||
stepSize | Number | - | User defined fixed step size for the scale. If set, the scale ticks will be enumerated by multiple of stepSize, having one tick per increment. If not set, the ticks are labeled automatically using the nice numbers algorithm.
|
||||
stepSize | Number | - | if defined, it can be used along with the min and the max to give a custom number of steps. See the example below.
|
||||
suggestedMax | Number | - | User defined maximum number for the scale, overrides maximum value *except for if* it is lower than the maximum value.
|
||||
suggestedMin | Number | - | User defined minimum number for the scale, overrides minimum value *except for if* it is higher than the minimum value.
|
||||
|
||||
#### Example Configuration
|
||||
|
||||
The following example creates a line chart with a vertical axis that goes from 0 to 5 in 0.5 sized steps.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
max: 5,
|
||||
min: 0,
|
||||
stepSize: 0.5
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Logarithmic Scale
|
||||
|
||||
The logarithmic scale is use to chart numerical data. It can be placed on either the x or y axis. As the name suggests, logarithmic interpolation is used to determine where a value lies on the axis.
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
The following options are provided by the logarithmic scale. They are all located in the `ticks` sub options.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
min | Number | - | User defined minimum number for the scale, overrides minimum value from data.
|
||||
max | Number | - | User defined maximum number for the scale, overrides maximum value from data.
|
||||
|
||||
#### Example Configuration
|
||||
|
||||
The following example creates a chart with a logarithmic X axis that ranges from 1 to 1000.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
xAxes: [{
|
||||
type: 'logarithmic',
|
||||
position: 'bottom',
|
||||
ticks: {
|
||||
min: 1,
|
||||
max: 1000
|
||||
}
|
||||
}]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Time Scale
|
||||
|
||||
The time scale is used to display times and dates. It can only be placed on the X axis. When building its ticks, it will automatically calculate the most comfortable unit base on the size of the scale.
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
The following options are provided by the logarithmic scale. They are all located in the `time` sub options.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
displayFormats | Object | - | See [Display Formats](#scales-display-formats) section below.
|
||||
isoWeekday | Boolean | false | If true and the unit is set to 'week', iso weekdays will be used.
|
||||
max | [Time](#scales-date-formats) | - | If defined, this will override the data maximum
|
||||
min | [Time](#scales-date-formats) | - | If defined, this will override the data minimum
|
||||
parser | String or Function | - | If defined as a string, it is interpreted as a custom format to be used by moment to parse the date. If this is a function, it must return a moment.js object given the appropriate data value.
|
||||
round | String | - | If defined, dates will be rounded to the start of this unit. See [Time Units](#scales-time-units) below for the allowed units.
|
||||
tooltipFormat | String | '' | The moment js format string to use for the tooltip.
|
||||
unit | String | - | If defined, will force the unit to be a certain type. See [Time Units](#scales-time-units) section below for details.
|
||||
unitStepSize | Number | 1 | The number of units between grid lines.
|
||||
|
||||
#### Date Formats
|
||||
|
||||
When providing data for the time scale, Chart.js supports all of the formats that Moment.js accepts. See [Moment.js docs](http://momentjs.com/docs/#/parsing/) for details.
|
||||
|
||||
#### Display Formats
|
||||
|
||||
The following display formats are used to configure how different time units are formed into strings for the axis tick marks. See [moment.js](http://momentjs.com/docs/#/displaying/format/) for the allowable format strings.
|
||||
|
||||
Name | Default
|
||||
--- | ---
|
||||
millisecond | 'SSS [ms]'
|
||||
second | 'h:mm:ss a'
|
||||
minute | 'h:mm:ss a'
|
||||
hour | 'MMM D, hA'
|
||||
day | 'll'
|
||||
week | 'll'
|
||||
month | 'MMM YYYY'
|
||||
quarter | '[Q]Q - YYYY'
|
||||
year | 'YYYY'
|
||||
|
||||
For example, to set the display format for the 'quarter' unit to show the month and year, the following config would be passed to the chart constructor.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
displayFormats: {
|
||||
quarter: 'MMM YYYY'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Time Units
|
||||
|
||||
The following time measurements are supported. The names can be passed as strings to the `time.unit` config option to force a certain unit.
|
||||
|
||||
* millisecond
|
||||
* second
|
||||
* minute
|
||||
* hour
|
||||
* day
|
||||
* week
|
||||
* month
|
||||
* quarter
|
||||
* year
|
||||
|
||||
For example, to create a chart with a time scale that always displayed units per month, the following config could be used.
|
||||
|
||||
```javascript
|
||||
var chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
unit: 'month'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Radial Linear Scale
|
||||
|
||||
The radial linear scale is used specifically for the radar and polar are chart types. It overlays the chart area, rather than being positioned on one of the edges.
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
The following additional configuration options are provided by the radial linear scale.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
lineArc | Boolean | false | If true, circular arcs are used else straight lines are used. The former is used by the polar area chart and the latter by the radar chart
|
||||
angleLines | Object | - | See the [Angle Lines](#scales-angle-line-options) section below for details.
|
||||
pointLabels | Object | - | See the [Point Label](#scales-point-label) section below for details.
|
||||
ticks | Object | - | See the Ticks table below for options.
|
||||
|
||||
#### Angle Line Options
|
||||
|
||||
The following options are used to configure angled lines that radiate from the center of the chart to the point labels. They can be found in the `angleLines` sub options. Note that these options only apply if `lineArc` is false.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true | If true, angle lines are shown.
|
||||
color | Color | 'rgba(0, 0, 0, 0.1)' | Color of angled lines
|
||||
lineWidth | Number | 1 | Width of angled lines
|
||||
|
||||
#### Point Label Options
|
||||
|
||||
The following options are used to configure the point labels that are shown on the perimeter of the scale. They can be found in the `pointLabel` sub options. Note that these options only apply if `lineArc` is false.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
callback | Function | - | Callback function to transform data label to axis label
|
||||
fontColor | Color | '#666' | Font color
|
||||
fontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family to render
|
||||
fontSize | Number | 10 | Font size in pixels
|
||||
fontStyle | String | 'normal' | Font Style to use
|
||||
|
||||
|
||||
#### Tick Options
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
backdropColor | Color | 'rgba(255, 255, 255, 0.75)' | Color of label backdrops
|
||||
backdropPaddingX | Number | 2 | Horizontal padding of label backdrop
|
||||
backdropPaddingY | Number | 2 | Vertical padding of label backdrop
|
||||
maxTicksLimit | Number | 11 | Maximum number of ticks and gridlines to show. If not defined, it will limit to 11 ticks but will show all gridlines.
|
||||
showLabelBackdrop | Boolean | true | If true, draw a background behind the tick labels
|
||||
|
||||
### Update Default Scale config
|
||||
|
||||
The default configuration for a scale can be easily changed using the scale service. Pass in a partial configuration that will be merged with the current scale default configuration.
|
||||
|
||||
For example, to set the minimum value of 0 for all linear scales, you would do the following. Any linear scales created after this time would now have a minimum of 0.
|
||||
```
|
||||
Chart.scaleService.updateScaleDefaults('linear', {
|
||||
ticks: {
|
||||
min: 0
|
||||
}
|
||||
})
|
||||
```
|
@ -3,15 +3,13 @@ title: Line Chart
|
||||
anchor: line-chart
|
||||
---
|
||||
### Introduction
|
||||
A line chart is a way of plotting data points on a line.
|
||||
|
||||
Often, it is used to show trend data, and the comparison of two data sets.
|
||||
A line chart is a way of plotting data points on a line. Often, it is used to show trend data, and the comparison of two data sets.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
### Example Usage
|
||||
```javascript
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
@ -27,7 +25,8 @@ var myLineChart = Chart.Line(ctx, {
|
||||
options: options
|
||||
});
|
||||
```
|
||||
### Data structure
|
||||
|
||||
### Data Structure
|
||||
|
||||
The following options can be included in a line chart dataset to configure options for that specific dataset.
|
||||
|
||||
@ -35,7 +34,7 @@ All point* properties can be specified as an array. If these are set to an array
|
||||
|
||||
Property | Type | Usage
|
||||
--- | --- | ---
|
||||
data | `Array<Number>` | The data to plot in a line
|
||||
data | See [data point](#line-chart-data-points) section | The data to plot in a line
|
||||
label | `String` | The label for the dataset which appears in the legend and tooltips
|
||||
xAxisID | `String` | The ID of the x axis to plot this dataset on
|
||||
yAxisID | `String` | The ID of the y axis to plot this dataset on
|
||||
@ -57,7 +56,7 @@ pointHitRadius | `Number or Array<Number>` | The pixel size of the non-displayed
|
||||
pointHoverBackgroundColor | `Color or Array<Color>` | Point background color when hovered
|
||||
pointHoverBorderColor | `Color or Array<Color>` | Point border color when hovered
|
||||
pointHoverBorderWidth | `Number or Array<Number>` | Border width of point when hovered
|
||||
pointStyle | `String or Array<String>` | The style of point. Options include 'circle', 'triangle', 'rect', 'rectRot', 'cross', 'crossRot', 'star', 'line', and 'dash'
|
||||
pointStyle | `String, Array<String>, Image, Array<Image>` | The style of point. Options are 'circle', 'triangle', 'rect', 'rectRot', 'cross', 'crossRot', 'star', 'line', and 'dash'. If the option is an image, that image is drawn on the canvas using `drawImage`.
|
||||
|
||||
An example data object using these attributes is shown below.
|
||||
```javascript
|
||||
@ -89,52 +88,92 @@ var data = {
|
||||
};
|
||||
```
|
||||
|
||||
The line chart requires an array of labels. This labels are shown on the X axis. There must be one label for each data point. More labels than datapoints are allowed, in which case the line ends at the last data point.
|
||||
The line chart usually requires an array of labels. This labels are shown on the X axis. There must be one label for each data point. More labels than datapoints are allowed, in which case the line ends at the last data point.
|
||||
The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.
|
||||
|
||||
The label key on each dataset is optional, and can be used when generating a scale for the chart.
|
||||
|
||||
### Chart options
|
||||
### Data Points
|
||||
|
||||
These are the customisation options specific to Line charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
The data passed to the chart can be passed in two formats. The most common method is to pass the data array as an array of numbers. In this case, the `data.labels` array must be specified and must contain a label for each point.
|
||||
|
||||
The default options for line chart are defined in `Chart.defaults.line`.
|
||||
The alternate is used for sparse datasets. Data is specified using an object containing `x` and `y` properties. This is used for scatter charts as documented below.
|
||||
|
||||
### Scatter Line Charts
|
||||
|
||||
Scatter line charts can be created by changing the X axis to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties. The example below creates a scatter chart with 3 points.
|
||||
|
||||
```javascript
|
||||
var scatterChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Scatter Dataset',
|
||||
data: [{
|
||||
x: -10,
|
||||
y: 0
|
||||
}, {
|
||||
x: 0,
|
||||
y: 10
|
||||
}, {
|
||||
x: 10,
|
||||
y: 5
|
||||
}]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'linear',
|
||||
position: 'bottom'
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Line charts. These options are merged with the [global chart configuration options](#chart-configuration-global-configuration), and form the options of the chart.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
showLines | Boolean | true | If false, the lines between points are not drawn
|
||||
stacked | Boolean | false | If true, lines stack on top of each other along the y axis.
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
elements | Object | - | -
|
||||
*elements*.point | Object | - | -
|
||||
*elements.point*.radius | Number | `3` | Defines the size of the Point shape. Can be set to zero to skip rendering a point.
|
||||
scales | Object | - | -
|
||||
*scales*.xAxes | Array | `[{type:"category","id":"x-axis-0"}]` | Defines all of the x axes used in the chart. See the [scale documentation](#scales) for details on the available options.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "category" | As defined in ["Category"](#scales-category-scale).
|
||||
id | String | "x-axis-0" | Id of the axis so that data can bind to it.
|
||||
| | |
|
||||
*scales*.yAxes | Array | `[{type:"linear","id":"y-axis-0"}]` | Defines all of the y axes used in the chart. See the [scale documentation](#scales) for details on the available options.
|
||||
*Options for yAxes* | | |
|
||||
type | String | "linear" | As defined in ["Linear"](#scales-linear-scale).
|
||||
id | String | "y-axis-0" | Id of the axis so that data can bind to it.
|
||||
|
||||
You can override these for your `Chart` instance by passing a member `options` into the `Line` method.
|
||||
|
||||
For example, we could have a line chart display without an x axis by doing the following. The config merge is smart enough to handle arrays so that you do not need to specify all axis settings to change one thing.
|
||||
For example, we could have a line chart display without an X axis by doing the following. The config merge is smart enough to handle arrays so that you do not need to specify all axis settings to change one thing.
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
xAxes: [{
|
||||
display: false
|
||||
}]
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: false
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Line chart defaults, but this particular instance will have the x axis not displaying.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Line type that is created, this object is available at `Chart.defaults.line`.
|
||||
|
||||
### Stacked Charts
|
||||
|
||||
Stacked area charts can be created by setting the Y axis to a stacked configuration. The following example would have stacked lines.
|
||||
|
||||
```javascript
|
||||
var stackedLine = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
@ -12,7 +12,7 @@ It is sometimes used to show trend data, and the comparison of multiple data set
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
### Example Usage
|
||||
```javascript
|
||||
var myBarChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
@ -31,7 +31,7 @@ var myBarChart = new Chart(ctx, {
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
### Data Structure
|
||||
The following options can be included in a bar chart dataset to configure options for that specific dataset.
|
||||
|
||||
Some properties can be specified as an array. If these are set to an array value, the first value applies to the first bar, the second value to the second bar, and so on.
|
||||
@ -73,20 +73,20 @@ We have an array of labels too for display. In the example, we are showing the s
|
||||
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Bar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
These are the customisation options specific to Bar charts. These options are merged with the [global chart configuration options](#global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for bar chart are defined in `Chart.defaults.bar`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
stacked | Boolean | false |
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
scales | Object | - | -
|
||||
*scales*.xAxes | Array | | The bar chart officially supports only 1 x-axis but uses an array to keep the API consistent. Use a scatter chart if you need multiple x axes.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "Category" | As defined in [Scales](#scales-category-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
id | String | "x-axis-1" | Id of the axis so that data can bind to it
|
||||
id | String | "x-axis-0" | Id of the axis so that data can bind to it
|
||||
stacked | Boolean | false | If true, bars are stacked on the x-axis
|
||||
categoryPercentage | Number | 0.8 | Percent (0-1) of the available width (the space between the gridlines for small datasets) for each data-point to use for the bars. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
barPercentage | Number | 0.9 | Percent (0-1) of the available width each bar should be within the category percentage. 1.0 will take the whole category width and put the bars right next to each other. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
gridLines | Object | [See Scales](#scales) |
|
||||
@ -96,7 +96,8 @@ gridLines | Object | [See Scales](#scales) |
|
||||
*Options for xAxes* | | |
|
||||
type | String | "linear" | As defined in [Scales](#scales-linear-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
id | String | "y-axis-1" | Id of the axis so that data can bind to it.
|
||||
id | String | "y-axis-0" | Id of the axis so that data can bind to it.
|
||||
stacked | Boolean | false | If true, bars are stacked on the y-axis
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Bar` method as an object with the keys you want to override.
|
||||
|
||||
@ -156,4 +157,4 @@ Sample: |==============|
|
||||
Bar: |1.||1.|
|
||||
Category: | .5 |
|
||||
Sample: |==============|
|
||||
```
|
||||
```
|
@ -12,7 +12,7 @@ They are often useful for comparing the points of two or more different data set
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
### Example Usage
|
||||
|
||||
```javascript
|
||||
var myRadarChart = new Chart(ctx, {
|
||||
@ -22,7 +22,7 @@ var myRadarChart = new Chart(ctx, {
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
### Data Structure
|
||||
|
||||
The following options can be included in a radar chart dataset to configure options for that specific dataset.
|
||||
|
||||
@ -88,7 +88,7 @@ The label key on each dataset is optional, and can be used when generating a sca
|
||||
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Radar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
These are the customisation options specific to Radar charts. These options are merged with the [global chart configuration options](#global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for radar chart are defined in `Chart.defaults.radar`.
|
||||
|
@ -11,7 +11,7 @@ This type of chart is often useful when we want to show a comparison data simila
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
### Example Usage
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
@ -21,7 +21,7 @@ new Chart(ctx, {
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
### Data Structure
|
||||
|
||||
The following options can be included in a polar area chart dataset to configure options for that specific dataset.
|
||||
|
||||
@ -70,9 +70,9 @@ var data = {
|
||||
```
|
||||
As you can see, for the chart data you pass in an array of objects, with a value and a colour. The value attribute should be a number, while the color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
|
||||
|
||||
### Chart options
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Polar Area charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
These are the customisation options specific to Polar Area charts. These options are merged with the [global chart configuration options](#global-chart-configuration), and form the options of the chart.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
@ -20,7 +20,7 @@ They are also registered under two aliases in the `Chart` core. Other than their
|
||||
</div>
|
||||
<br>
|
||||
|
||||
### Example usage
|
||||
### Example Usage
|
||||
|
||||
```javascript
|
||||
// For a pie chart
|
||||
@ -40,7 +40,7 @@ var myDoughnutChart = new Chart(ctx, {
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
### Data Structure
|
||||
|
||||
Property | Type | Usage
|
||||
--- | --- | ---
|
||||
@ -59,7 +59,7 @@ An example data object using these attributes is shown below.
|
||||
var data = {
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
"Yellow"
|
||||
],
|
||||
datasets: [
|
||||
@ -81,9 +81,9 @@ var data = {
|
||||
|
||||
For a pie chart, datasets need to contain an array of data points. The data points should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. You can also add an array of background colors. The color attributes should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
|
||||
|
||||
### Chart options
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Pie & Doughnut charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
These are the customisation options specific to Pie & Doughnut charts. These options are merged with the [global chart configuration options](#global-chart-configuration), and form the options of the chart.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
@ -92,7 +92,7 @@ rotation | Number | -0.5 * Math.PI | Starting angle to draw arcs from
|
||||
circumference | Number | 2 * Math.PI | Sweep to allow arcs to cover
|
||||
*animation*.animateRotate | Boolean |true | If true, will animate the rotation of the chart.
|
||||
*animation*.animateScale | Boolean | false | If true, will animate scaling the Doughnut from the centre.
|
||||
*legend*.*labels*.generateLabels | Function | `function(data) {} ` | Returns labels for each the legend
|
||||
*legend*.*labels*.generateLabels | Function | `function(chart) {} ` | Returns a label for each item to be displayed on the legend.
|
||||
*legend*.onClick | Function | function(event, legendItem) {} ` | Handles clicking an individual legend item
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Doughnut` method as an object with the keys you want to override.
|
100
vendors/Chart.js/docs/08-Bubble-Chart.md
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Bubble Chart
|
||||
anchor: bubble-chart
|
||||
---
|
||||
### Introduction
|
||||
A bubble chart is used to display three dimensions of data at the same time. The location of the bubble is determined by the first two dimensions and the corresponding horizontal and vertical axes. The third dimension is represented by the size of the individual bubbles.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
### Example Usage
|
||||
|
||||
```javascript
|
||||
// For a bubble chart
|
||||
var myBubbleChart = new Chart(ctx,{
|
||||
type: 'bubble',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data Structure
|
||||
|
||||
Property | Type | Usage
|
||||
--- | --- | ---
|
||||
data | `Array<BubbleDataObject>` | The data to plot as bubbles. See [Data format](#bubble-chart-data-format)
|
||||
label | `String` | The label for the dataset which appears in the legend and tooltips
|
||||
backgroundColor | `Color Array<Color>` | The fill color of the bubbles.
|
||||
borderColor | `Color or Array<Color>` | The stroke color of the bubbles.
|
||||
borderWidth | `Number or Array<Number>` | The stroke width of bubble in pixels.
|
||||
hoverBackgroundColor | `Color or Array<Color>` | The fill color of the bubbles when hovered.
|
||||
hoverBorderColor | `Color or Array<Color>` | The stroke color of the bubbles when hovered.
|
||||
hoverBorderWidth | `Number or Array<Number>` | The stroke width of the bubbles when hovered.
|
||||
hoverRadius | `Number or Array<Number>` | Additional radius to add to data radius on hover.
|
||||
|
||||
An example data object using these attributes is shown below. This example creates a single dataset with 2 different bubbles.
|
||||
|
||||
```javascript
|
||||
var data = {
|
||||
datasets: [
|
||||
{
|
||||
label: 'First Dataset',
|
||||
data: [
|
||||
{
|
||||
x: 20,
|
||||
y: 30,
|
||||
r: 15
|
||||
},
|
||||
{
|
||||
x: 40,
|
||||
y: 10,
|
||||
r: 10
|
||||
}
|
||||
],
|
||||
backgroundColor:"#FF6384",
|
||||
hoverBackgroundColor: "#FF6384",
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
### Data Object
|
||||
|
||||
Data for the bubble chart is passed in the form of an object. The object must implement the following interface. It is important to note that the radius property, `r` is **not** scaled by the chart. It is the raw radius in pixels of the bubble that is drawn on the canvas.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// X Value
|
||||
x: <Number>,
|
||||
|
||||
// Y Value
|
||||
y: <Number>,
|
||||
|
||||
// Radius of bubble. This is not scaled.
|
||||
r: <Number>
|
||||
}
|
||||
```
|
||||
|
||||
### Chart Options
|
||||
|
||||
The bubble chart has no unique configuration options. To configure options common to all of the bubbles, the point element options are used.
|
||||
|
||||
For example, to give all bubbles a 1px wide black border, the following options would be used.
|
||||
|
||||
```javascript
|
||||
new Chart(ctx,{
|
||||
type:"bubble",
|
||||
options: {
|
||||
elements: {
|
||||
points: {
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgb(0, 0, 0)'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
We can also change the default values for the Bubble chart type. Doing so will give all bubble charts created after this point the new defaults. The default configuration for the bubble chart can be accessed at `Chart.defaults.bubble`.
|
@ -4,7 +4,7 @@ anchor: advanced-usage
|
||||
---
|
||||
|
||||
|
||||
### Prototype methods
|
||||
### Prototype Methods
|
||||
|
||||
For each chart, there are a set of global prototype methods on the shared `ChartType` which you may find useful. These are available on all charts created with Chart.js, but for the examples, let's use a line chart we've made.
|
||||
|
||||
@ -161,7 +161,7 @@ var myPieChart = new Chart(ctx, {
|
||||
|
||||
See `sample/line-customTooltips.html` for examples on how to get started.
|
||||
|
||||
### Writing new scale types
|
||||
### Writing New Scale Types
|
||||
|
||||
Starting with Chart.js 2.0 scales can be individually extended. Scales should always derive from Chart.Scale.
|
||||
|
||||
@ -293,7 +293,7 @@ The Core.Scale base class also has some utility functions that you may find usef
|
||||
}
|
||||
```
|
||||
|
||||
### Writing new chart types
|
||||
### Writing New Chart Types
|
||||
|
||||
Chart.js 2.0 introduces the concept of controllers for each dataset. Like scales, new controllers can be written as needed.
|
||||
|
||||
@ -355,7 +355,7 @@ The following methods may optionally be overridden by derived dataset controller
|
||||
}
|
||||
```
|
||||
|
||||
### Extending existing chart types
|
||||
### Extending Existing Chart Types
|
||||
|
||||
Extending or replacing an existing controller type is easy. Simply replace the constructor for one of the built in types with your own.
|
||||
|
||||
@ -377,9 +377,11 @@ Plugins will be called at the following times
|
||||
* Start of initialization
|
||||
* End of initialization
|
||||
* Start of update
|
||||
* End of update
|
||||
* After the chart scales have calculated
|
||||
* End of update (before render occurs)
|
||||
* Start of draw
|
||||
* End of draw
|
||||
* Before an animation is started
|
||||
|
||||
Plugins should derive from Chart.PluginBase and implement the following interface
|
||||
```javascript
|
||||
@ -388,6 +390,7 @@ Plugins should derive from Chart.PluginBase and implement the following interfac
|
||||
afterInit: function(chartInstance) { },
|
||||
|
||||
beforeUpdate: function(chartInstance) { },
|
||||
afterScaleUpdate: function(chartInstance) { }
|
||||
afterUpdate: function(chartInstance) { },
|
||||
|
||||
// This is called at the start of a render. It is only called once, even if the animation will run for a number of frames. Use beforeDraw or afterDraw
|
@ -4,7 +4,7 @@ anchor: notes
|
||||
---
|
||||
### Previous versions
|
||||
|
||||
Please note - documentation for previous versions are available on the GitHub repo.
|
||||
Please note - documentation for previous versions are available on the GitHub repo. Version 1.x may continue to receive updates for bug fixes or high priority items.
|
||||
|
||||
- [1.x Documentation](https://github.com/chartjs/Chart.js/tree/v1.1.1/docs)
|
||||
|
||||
@ -14,6 +14,8 @@ Chart.js offers support for all browsers where canvas is supported.
|
||||
|
||||
Browser support for the canvas element is available in all modern & major mobile browsers <a href="http://caniuse.com/#feat=canvas" target="_blank">(http://caniuse.com/#feat=canvas)</a>.
|
||||
|
||||
Thanks to <a href="https://browserstack.com" target="_blank">BrowserStack</a> for allowing our team to test on thousands of browsers.
|
||||
|
||||
|
||||
### Bugs & issues
|
||||
|
61
vendors/Chart.js/gulpfile.js
vendored
@ -22,17 +22,16 @@ var gulp = require('gulp'),
|
||||
|
||||
var srcDir = './src/';
|
||||
var outDir = './dist/';
|
||||
var testDir = './test/';
|
||||
|
||||
var header = "/*!\n\
|
||||
* Chart.js\n\
|
||||
* http://chartjs.org/\n\
|
||||
* Version: {{ version }}\n\
|
||||
*\n\
|
||||
* Copyright 2016 Nick Downie\n\
|
||||
* Released under the MIT license\n\
|
||||
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n\
|
||||
*/\n";
|
||||
var header = "/*!\n" +
|
||||
" * Chart.js\n" +
|
||||
" * http://chartjs.org/\n" +
|
||||
" * Version: {{ version }}\n" +
|
||||
" *\n" +
|
||||
" * Copyright 2016 Nick Downie\n" +
|
||||
" * Released under the MIT license\n" +
|
||||
" * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n" +
|
||||
" */\n";
|
||||
|
||||
var preTestFiles = [
|
||||
'./node_modules/moment/min/moment.min.js',
|
||||
@ -76,9 +75,9 @@ function buildTask() {
|
||||
.pipe(insert.prepend(header))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(gulp.dest(outDir))
|
||||
.pipe(streamify(uglify({
|
||||
preserveComments: 'some'
|
||||
})))
|
||||
.pipe(streamify(uglify()))
|
||||
.pipe(insert.prepend(header))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(streamify(concat('Chart.bundle.min.js')))
|
||||
.pipe(gulp.dest(outDir));
|
||||
|
||||
@ -89,9 +88,9 @@ function buildTask() {
|
||||
.pipe(insert.prepend(header))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(gulp.dest(outDir))
|
||||
.pipe(streamify(uglify({
|
||||
preserveComments: 'some'
|
||||
})))
|
||||
.pipe(streamify(uglify()))
|
||||
.pipe(insert.prepend(header))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(streamify(concat('Chart.min.js')))
|
||||
.pipe(gulp.dest(outDir));
|
||||
|
||||
@ -116,7 +115,8 @@ function bumpTask(complete) {
|
||||
choices: choices
|
||||
}, function(res) {
|
||||
var increment = res.version.split(' ')[0],
|
||||
newVersion = semver.inc(package.version, increment);
|
||||
newVersion = semver.inc(package.version, increment),
|
||||
oldVersion = package.version;
|
||||
|
||||
// Set the new versions into the bower/package object
|
||||
package.version = newVersion;
|
||||
@ -125,6 +125,13 @@ function bumpTask(complete) {
|
||||
// Write these to their own files, then build the output
|
||||
fs.writeFileSync('package.json', JSON.stringify(package, null, 2));
|
||||
fs.writeFileSync('bower.json', JSON.stringify(bower, null, 2));
|
||||
|
||||
var oldCDN = 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/'+oldVersion+'/Chart.min.js',
|
||||
newCDN = 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/'+newVersion+'/Chart.min.js';
|
||||
|
||||
gulp.src(['./README.md'])
|
||||
.pipe(replace(oldCDN, newCDN))
|
||||
.pipe(gulp.dest('./'));
|
||||
|
||||
complete();
|
||||
});
|
||||
@ -149,13 +156,15 @@ function validHTMLTask() {
|
||||
.pipe(htmlv());
|
||||
}
|
||||
|
||||
|
||||
function unittestTask() {
|
||||
function startTest() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
return files;
|
||||
}
|
||||
|
||||
return gulp.src(files)
|
||||
function unittestTask() {
|
||||
return gulp.src(startTest())
|
||||
.pipe(karma({
|
||||
configFile: 'karma.conf.ci.js',
|
||||
action: 'run'
|
||||
@ -163,11 +172,7 @@ function unittestTask() {
|
||||
}
|
||||
|
||||
function unittestWatchTask() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
|
||||
return gulp.src(files)
|
||||
return gulp.src(startTest())
|
||||
.pipe(karma({
|
||||
configFile: 'karma.conf.js',
|
||||
action: 'watch'
|
||||
@ -175,11 +180,7 @@ function unittestWatchTask() {
|
||||
}
|
||||
|
||||
function coverageTask() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
|
||||
return gulp.src(files)
|
||||
return gulp.src(startTest())
|
||||
.pipe(karma({
|
||||
configFile: 'karma.coverage.conf.js',
|
||||
action: 'run'
|
||||
|
6
vendors/Chart.js/package.json
vendored
@ -2,7 +2,7 @@
|
||||
"name": "chart.js",
|
||||
"homepage": "http://www.chartjs.org",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.4",
|
||||
"license": "MIT",
|
||||
"main": "src/chart.js",
|
||||
"repository": {
|
||||
@ -47,7 +47,7 @@
|
||||
"main": "Chart.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chartjs-color": "^1.0.2",
|
||||
"chartjs-color": "^2.0.0",
|
||||
"moment": "^2.10.6"
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
|
||||
<head>
|
||||
<title>Time Scale Point Data</title>
|
||||
<script src="../../node_modules/moment/min/moment.min.js"></script>
|
||||
<script src="../../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
@ -96,7 +95,7 @@
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
}
|
||||
}, ],
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
|
22
vendors/Chart.js/src/chart.js
vendored
@ -13,12 +13,10 @@ require('./core/core.scaleService')(Chart);
|
||||
require('./core/core.title')(Chart);
|
||||
require('./core/core.tooltip')(Chart);
|
||||
|
||||
require('./controllers/controller.bar')(Chart);
|
||||
require('./controllers/controller.bubble')(Chart);
|
||||
require('./controllers/controller.doughnut')(Chart);
|
||||
require('./controllers/controller.line')(Chart);
|
||||
require('./controllers/controller.polarArea')(Chart);
|
||||
require('./controllers/controller.radar')(Chart);
|
||||
require('./elements/element.arc')(Chart);
|
||||
require('./elements/element.line')(Chart);
|
||||
require('./elements/element.point')(Chart);
|
||||
require('./elements/element.rectangle')(Chart);
|
||||
|
||||
require('./scales/scale.category')(Chart);
|
||||
require('./scales/scale.linear')(Chart);
|
||||
@ -26,10 +24,14 @@ require('./scales/scale.logarithmic')(Chart);
|
||||
require('./scales/scale.radialLinear')(Chart);
|
||||
require('./scales/scale.time')(Chart);
|
||||
|
||||
require('./elements/element.arc')(Chart);
|
||||
require('./elements/element.line')(Chart);
|
||||
require('./elements/element.point')(Chart);
|
||||
require('./elements/element.rectangle')(Chart);
|
||||
// Controllers must be loaded after elements
|
||||
// See Chart.core.datasetController.dataElementType
|
||||
require('./controllers/controller.bar')(Chart);
|
||||
require('./controllers/controller.bubble')(Chart);
|
||||
require('./controllers/controller.doughnut')(Chart);
|
||||
require('./controllers/controller.line')(Chart);
|
||||
require('./controllers/controller.polarArea')(Chart);
|
||||
require('./controllers/controller.radar')(Chart);
|
||||
|
||||
require('./charts/Chart.Bar')(Chart);
|
||||
require('./charts/Chart.Bubble')(Chart);
|
||||
|
10
vendors/Chart.js/src/charts/Chart.Radar.js
vendored
@ -1,15 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
aspectRatio: 1
|
||||
};
|
||||
|
||||
|
||||
Chart.Radar = function(context, config) {
|
||||
config.options = helpers.configMerge(defaultConfig, config.options);
|
||||
config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);
|
||||
config.type = 'radar';
|
||||
|
||||
return new Chart(context, config);
|
||||
|
392
vendors/Chart.js/src/controllers/controller.bar.js
vendored
@ -29,12 +29,16 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
Chart.controllers.bar = Chart.DatasetController.extend({
|
||||
|
||||
dataElementType: Chart.elements.Rectangle,
|
||||
|
||||
initialize: function(chart, datasetIndex) {
|
||||
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
||||
|
||||
// Use this to indicate that this is a bar dataset.
|
||||
this.getMeta().bar = true;
|
||||
},
|
||||
|
||||
// Get the number of datasets that display bars. We use this to correctly calculate the bar width
|
||||
getBarCount: function getBarCount() {
|
||||
var barCount = 0;
|
||||
@ -47,80 +51,44 @@ module.exports = function(Chart) {
|
||||
return barCount;
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Rectangle({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
|
||||
addElementAndReset: function(index) {
|
||||
var rectangle = new Chart.elements.Rectangle({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
var numBars = this.getBarCount();
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, rectangle);
|
||||
this.updateElement(rectangle, index, true, numBars);
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var numBars = this.getBarCount();
|
||||
|
||||
helpers.each(this.getMeta().data, function(rectangle, index) {
|
||||
this.updateElement(rectangle, index, reset, numBars);
|
||||
this.updateElement(rectangle, index, reset);
|
||||
}, this);
|
||||
},
|
||||
|
||||
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
||||
updateElement: function updateElement(rectangle, index, reset) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var yScalePoint;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
// all less than 0. use the top
|
||||
yScalePoint = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
yScalePoint = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
yScalePoint = yScale.getPixelForValue(0);
|
||||
}
|
||||
var scaleBase = yScale.getBasePixel();
|
||||
var rectangleElementOptions = this.chart.options.elements.rectangle;
|
||||
var custom = rectangle.custom || {};
|
||||
var dataset = this.getDataset();
|
||||
|
||||
helpers.extend(rectangle, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: this.calculateBarX(index, this.index),
|
||||
y: reset ? yScalePoint : this.calculateBarY(index, this.index),
|
||||
y: reset ? scaleBase : this.calculateBarY(index, this.index),
|
||||
|
||||
// Tooltip
|
||||
label: this.chart.data.labels[index],
|
||||
datasetLabel: this.getDataset().label,
|
||||
datasetLabel: dataset.label,
|
||||
|
||||
// Appearance
|
||||
base: reset ? yScalePoint : this.calculateBarBase(this.index, index),
|
||||
width: this.calculateBarWidth(numBars),
|
||||
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
|
||||
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
|
||||
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
|
||||
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
|
||||
base: reset ? scaleBase : this.calculateBarBase(this.index, index),
|
||||
width: this.calculateBarWidth(index),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
||||
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
|
||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
|
||||
}
|
||||
});
|
||||
rectangle.pivot();
|
||||
@ -128,28 +96,27 @@ module.exports = function(Chart) {
|
||||
|
||||
calculateBarBase: function(datasetIndex, index) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var base = 0;
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var value = this.chart.data.datasets[datasetIndex].data[index];
|
||||
var chart = this.chart;
|
||||
var datasets = chart.data.datasets;
|
||||
var value = datasets[datasetIndex].data[index];
|
||||
|
||||
if (value < 0) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var negDS = this.chart.data.datasets[i];
|
||||
var negDSMeta = this.chart.getDatasetMeta(i);
|
||||
if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
|
||||
var negDS = datasets[i];
|
||||
var negDSMeta = chart.getDatasetMeta(i);
|
||||
if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
|
||||
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var j = 0; j < datasetIndex; j++) {
|
||||
var posDS = this.chart.data.datasets[j];
|
||||
var posDSMeta = this.chart.getDatasetMeta(j);
|
||||
if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(j)) {
|
||||
var posDS = datasets[j];
|
||||
var posDSMeta = chart.getDatasetMeta(j);
|
||||
if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {
|
||||
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
@ -158,33 +125,22 @@ module.exports = function(Chart) {
|
||||
return yScale.getPixelForValue(base);
|
||||
}
|
||||
|
||||
base = yScale.getPixelForValue(yScale.min);
|
||||
|
||||
if (yScale.beginAtZero || ((yScale.min <= 0 && yScale.max >= 0) || (yScale.min >= 0 && yScale.max <= 0))) {
|
||||
base = yScale.getPixelForValue(0, 0);
|
||||
//base += yScale.options.gridLines.lineWidth;
|
||||
} else if (yScale.min < 0 && yScale.max < 0) {
|
||||
// All values are negative. Use the top as the base
|
||||
base = yScale.getPixelForValue(yScale.max);
|
||||
}
|
||||
|
||||
return base;
|
||||
|
||||
return yScale.getBasePixel();
|
||||
},
|
||||
|
||||
getRuler: function() {
|
||||
getRuler: function(index) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var datasetCount = this.getBarCount();
|
||||
|
||||
var tickWidth = (function() {
|
||||
var min = xScale.getPixelForTick(1) - xScale.getPixelForTick(0);
|
||||
for (var i = 2; i < this.getDataset().data.length; i++) {
|
||||
min = Math.min(xScale.getPixelForTick(i) - xScale.getPixelForTick(i - 1), min);
|
||||
}
|
||||
return min;
|
||||
}).call(this);
|
||||
var tickWidth;
|
||||
|
||||
if (xScale.options.type === 'category') {
|
||||
tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);
|
||||
} else {
|
||||
// Average width
|
||||
tickWidth = xScale.width / xScale.ticks.length;
|
||||
}
|
||||
var categoryWidth = tickWidth * xScale.options.categoryPercentage;
|
||||
var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;
|
||||
var fullBarWidth = categoryWidth / datasetCount;
|
||||
@ -208,9 +164,9 @@ module.exports = function(Chart) {
|
||||
};
|
||||
},
|
||||
|
||||
calculateBarWidth: function() {
|
||||
calculateBarWidth: function(index) {
|
||||
var xScale = this.getScaleForId(this.getMeta().xAxisID);
|
||||
var ruler = this.getRuler();
|
||||
var ruler = this.getRuler(index);
|
||||
return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
|
||||
},
|
||||
|
||||
@ -231,11 +187,10 @@ module.exports = function(Chart) {
|
||||
|
||||
calculateBarX: function(index, datasetIndex) {
|
||||
var meta = this.getMeta();
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var barIndex = this.getBarIndex(datasetIndex);
|
||||
|
||||
var ruler = this.getRuler();
|
||||
var ruler = this.getRuler(index);
|
||||
var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
|
||||
leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;
|
||||
|
||||
@ -253,9 +208,7 @@ module.exports = function(Chart) {
|
||||
|
||||
calculateBarY: function(index, datasetIndex) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var value = this.getDataset().data[index];
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
@ -299,18 +252,23 @@ module.exports = function(Chart) {
|
||||
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
||||
var index = rectangle._index;
|
||||
|
||||
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.hoverBackgroundColor ? rectangle.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(rectangle._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
rectangle._model.borderColor = rectangle.custom && rectangle.custom.hoverBorderColor ? rectangle.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(rectangle._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.hoverBorderWidth ? rectangle.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, rectangle._model.borderWidth);
|
||||
var custom = rectangle.custom || {};
|
||||
var model = rectangle._model;
|
||||
model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
|
||||
model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
|
||||
model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(rectangle) {
|
||||
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
||||
var index = rectangle._index;
|
||||
var custom = rectangle.custom || {};
|
||||
var model = rectangle._model;
|
||||
var rectangleElementOptions = this.chart.options.elements.rectangle;
|
||||
|
||||
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor);
|
||||
rectangle._model.borderColor = rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor);
|
||||
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth);
|
||||
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);
|
||||
model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);
|
||||
model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);
|
||||
}
|
||||
|
||||
});
|
||||
@ -318,17 +276,17 @@ module.exports = function(Chart) {
|
||||
|
||||
// including horizontalBar in the bar file, instead of a file of its own
|
||||
// it extends bar (like pie extends doughnut)
|
||||
Chart.defaults.horizontalBar = {
|
||||
hover: {
|
||||
mode: "label"
|
||||
Chart.defaults.horizontalBar = {
|
||||
hover: {
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "linear",
|
||||
position: "bottom"
|
||||
}],
|
||||
yAxes: [{
|
||||
position: "bottom"
|
||||
}],
|
||||
yAxes: [{
|
||||
position: "left",
|
||||
type: "category",
|
||||
|
||||
@ -337,57 +295,76 @@ module.exports = function(Chart) {
|
||||
barPercentage: 0.9,
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
offsetGridLines: true
|
||||
}
|
||||
gridLines: {
|
||||
offsetGridLines: true
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderSkipped: 'left'
|
||||
}
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function(tooltipItems, data) {
|
||||
// Pick first xLabel for now
|
||||
var title = '';
|
||||
|
||||
if (tooltipItems.length > 0) {
|
||||
if (tooltipItems[0].yLabel) {
|
||||
title = tooltipItems[0].yLabel;
|
||||
} else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {
|
||||
title = data.labels[tooltipItems[0].index];
|
||||
}
|
||||
}
|
||||
|
||||
return title;
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
|
||||
return datasetLabel + ': ' + tooltipItem.xLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
|
||||
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
||||
Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
|
||||
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var xScalePoint;
|
||||
|
||||
if (xScale.min < 0 && xScale.max < 0) {
|
||||
// all less than 0. use the right
|
||||
xScalePoint = xScale.getPixelForValue(xScale.max);
|
||||
} else if (xScale.min > 0 && xScale.max > 0) {
|
||||
xScalePoint = xScale.getPixelForValue(xScale.min);
|
||||
} else {
|
||||
xScalePoint = xScale.getPixelForValue(0);
|
||||
}
|
||||
var scaleBase = xScale.getBasePixel();
|
||||
var custom = rectangle.custom || {};
|
||||
var dataset = this.getDataset();
|
||||
var rectangleElementOptions = this.chart.options.elements.rectangle;
|
||||
|
||||
helpers.extend(rectangle, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: reset ? xScalePoint : this.calculateBarX(index, this.index),
|
||||
_model: {
|
||||
x: reset ? scaleBase : this.calculateBarX(index, this.index),
|
||||
y: this.calculateBarY(index, this.index),
|
||||
|
||||
// Tooltip
|
||||
label: this.chart.data.labels[index],
|
||||
datasetLabel: this.getDataset().label,
|
||||
datasetLabel: dataset.label,
|
||||
|
||||
// Appearance
|
||||
base: reset ? xScalePoint : this.calculateBarBase(this.index, index),
|
||||
height: this.calculateBarHeight(numBars),
|
||||
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
|
||||
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
|
||||
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
|
||||
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
|
||||
base: reset ? scaleBase : this.calculateBarBase(this.index, index),
|
||||
height: this.calculateBarHeight(index),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
||||
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
|
||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
|
||||
},
|
||||
|
||||
draw: function () {
|
||||
draw: function () {
|
||||
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
@ -400,10 +377,10 @@ module.exports = function(Chart) {
|
||||
|
||||
// Canvas doesn't allow us to stroke inside the width so we can
|
||||
// adjust the sizes to fit if we're setting a stroke on the line
|
||||
if (vm.borderWidth) {
|
||||
if (vm.borderWidth) {
|
||||
topY += halfStroke;
|
||||
bottomY -= halfStroke;
|
||||
right += halfStroke;
|
||||
right += halfStroke;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
@ -428,8 +405,8 @@ module.exports = function(Chart) {
|
||||
if (startCorner === -1)
|
||||
startCorner = 0;
|
||||
|
||||
function cornerAt(index) {
|
||||
return corners[(startCorner + index) % 4];
|
||||
function cornerAt(index) {
|
||||
return corners[(startCorner + index) % 4];
|
||||
}
|
||||
|
||||
// Draw rectangle from 'startCorner'
|
||||
@ -438,162 +415,147 @@ module.exports = function(Chart) {
|
||||
ctx.lineTo.apply(ctx, cornerAt(i));
|
||||
|
||||
ctx.fill();
|
||||
if (vm.borderWidth) {
|
||||
ctx.stroke();
|
||||
}
|
||||
if (vm.borderWidth) {
|
||||
ctx.stroke();
|
||||
}
|
||||
},
|
||||
|
||||
inRange: function (mouseX, mouseY) {
|
||||
inRange: function (mouseX, mouseY) {
|
||||
var vm = this._view;
|
||||
var inRange = false;
|
||||
|
||||
if (vm) {
|
||||
if (vm.x < vm.base) {
|
||||
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
|
||||
} else {
|
||||
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
|
||||
}
|
||||
if (vm) {
|
||||
if (vm.x < vm.base) {
|
||||
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
|
||||
} else {
|
||||
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
|
||||
}
|
||||
}
|
||||
|
||||
return inRange;
|
||||
}
|
||||
return inRange;
|
||||
}
|
||||
});
|
||||
|
||||
rectangle.pivot();
|
||||
rectangle.pivot();
|
||||
},
|
||||
|
||||
calculateBarBase: function (datasetIndex, index) {
|
||||
calculateBarBase: function (datasetIndex, index) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var base = 0;
|
||||
|
||||
if (xScale.options.stacked) {
|
||||
if (xScale.options.stacked) {
|
||||
|
||||
var value = this.chart.data.datasets[datasetIndex].data[index];
|
||||
|
||||
if (value < 0) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
if (value < 0) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var negDS = this.chart.data.datasets[i];
|
||||
var negDSMeta = this.chart.getDatasetMeta(i);
|
||||
if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
||||
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var j = 0; j < datasetIndex; j++) {
|
||||
if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
||||
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var j = 0; j < datasetIndex; j++) {
|
||||
var posDS = this.chart.data.datasets[j];
|
||||
var posDSMeta = this.chart.getDatasetMeta(j);
|
||||
if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(j)) {
|
||||
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(j)) {
|
||||
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xScale.getPixelForValue(base);
|
||||
return xScale.getPixelForValue(base);
|
||||
}
|
||||
|
||||
base = xScale.getPixelForValue(xScale.min);
|
||||
|
||||
if (xScale.beginAtZero || ((xScale.min <= 0 && xScale.max >= 0) || (xScale.min >= 0 && xScale.max <= 0))) {
|
||||
base = xScale.getPixelForValue(0, 0);
|
||||
} else if (xScale.min < 0 && xScale.max < 0) {
|
||||
// All values are negative. Use the right as the base
|
||||
base = xScale.getPixelForValue(xScale.max);
|
||||
}
|
||||
|
||||
return base;
|
||||
return xScale.getBasePixel();
|
||||
},
|
||||
|
||||
getRuler: function () {
|
||||
getRuler: function (index) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var datasetCount = this.getBarCount();
|
||||
|
||||
var tickHeight = (function () {
|
||||
var min = yScale.getPixelForTick(1) - yScale.getPixelForTick(0);
|
||||
for (var i = 2; i < this.getDataset().data.length; i++) {
|
||||
min = Math.min(yScale.getPixelForTick(i) - yScale.getPixelForTick(i - 1), min);
|
||||
}
|
||||
return min;
|
||||
}).call(this);
|
||||
var tickHeight;
|
||||
if (yScale.options.type === 'category') {
|
||||
tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);
|
||||
} else {
|
||||
// Average width
|
||||
tickHeight = yScale.width / yScale.ticks.length;
|
||||
}
|
||||
var categoryHeight = tickHeight * yScale.options.categoryPercentage;
|
||||
var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
|
||||
var fullBarHeight = categoryHeight / datasetCount;
|
||||
|
||||
if (yScale.ticks.length !== this.chart.data.labels.length) {
|
||||
if (yScale.ticks.length !== this.chart.data.labels.length) {
|
||||
var perc = yScale.ticks.length / this.chart.data.labels.length;
|
||||
fullBarHeight = fullBarHeight * perc;
|
||||
fullBarHeight = fullBarHeight * perc;
|
||||
}
|
||||
|
||||
var barHeight = fullBarHeight * yScale.options.barPercentage;
|
||||
var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
|
||||
|
||||
return {
|
||||
return {
|
||||
datasetCount: datasetCount,
|
||||
tickHeight: tickHeight,
|
||||
categoryHeight: categoryHeight,
|
||||
categorySpacing: categorySpacing,
|
||||
fullBarHeight: fullBarHeight,
|
||||
barHeight: barHeight,
|
||||
barSpacing: barSpacing,
|
||||
};
|
||||
barSpacing: barSpacing,
|
||||
};
|
||||
},
|
||||
|
||||
calculateBarHeight: function () {
|
||||
calculateBarHeight: function (index) {
|
||||
var yScale = this.getScaleForId(this.getMeta().yAxisID);
|
||||
var ruler = this.getRuler();
|
||||
return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
|
||||
var ruler = this.getRuler(index);
|
||||
return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
|
||||
},
|
||||
|
||||
calculateBarX: function (index, datasetIndex) {
|
||||
calculateBarX: function (index, datasetIndex) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
var value = this.getDataset().data[index];
|
||||
|
||||
if (xScale.options.stacked) {
|
||||
|
||||
if (xScale.options.stacked) {
|
||||
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var ds = this.chart.data.datasets[i];
|
||||
var dsMeta = this.chart.getDatasetMeta(i);
|
||||
if (dsMeta.bar && dsMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
sumPos += ds.data[index] || 0;
|
||||
}
|
||||
}
|
||||
if (dsMeta.bar && dsMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
sumPos += ds.data[index] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return xScale.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return xScale.getPixelForValue(sumPos + value);
|
||||
if (value < 0) {
|
||||
return xScale.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return xScale.getPixelForValue(sumPos + value);
|
||||
}
|
||||
}
|
||||
|
||||
return xScale.getPixelForValue(value);
|
||||
return xScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
calculateBarY: function (index, datasetIndex) {
|
||||
calculateBarY: function (index, datasetIndex) {
|
||||
var meta = this.getMeta();
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var barIndex = this.getBarIndex(datasetIndex);
|
||||
|
||||
var ruler = this.getRuler();
|
||||
var ruler = this.getRuler(index);
|
||||
var topTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
|
||||
topTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
|
||||
if (yScale.options.stacked) {
|
||||
return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
|
||||
}
|
||||
|
||||
return topTick +
|
||||
@ -601,7 +563,7 @@ module.exports = function(Chart) {
|
||||
ruler.categorySpacing +
|
||||
(ruler.barHeight * barIndex) +
|
||||
(ruler.barSpacing / 2) +
|
||||
(ruler.barSpacing * barIndex);
|
||||
}
|
||||
(ruler.barSpacing * barIndex);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -37,69 +37,32 @@ module.exports = function(Chart) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Chart.controllers.bubble = Chart.DatasetController.extend({
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, point);
|
||||
this.updateElement(point, index, true);
|
||||
},
|
||||
dataElementType: Chart.elements.Point,
|
||||
|
||||
update: function update(reset) {
|
||||
var meta = this.getMeta();
|
||||
var points = meta.data;
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
// Update Points
|
||||
helpers.each(points, function(point, index) {
|
||||
this.updateElement(point, index, reset);
|
||||
}, this);
|
||||
|
||||
},
|
||||
|
||||
updateElement: function(point, index, reset) {
|
||||
var meta = this.getMeta();
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var scaleBase;
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
var custom = point.custom || {};
|
||||
var dataset = this.getDataset();
|
||||
var data = dataset.data[index];
|
||||
var pointElementOptions = this.chart.options.elements.point;
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: this.index,
|
||||
@ -107,20 +70,21 @@ module.exports = function(Chart) {
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
y: reset ? scaleBase : yScale.getPixelForValue(this.getDataset().data[index], index, this.index),
|
||||
x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, this.index, this.chart.isCombo),
|
||||
y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, this.index),
|
||||
// Appearance
|
||||
radius: reset ? 0 : point.custom && point.custom.radius ? point.custom.radius : this.getRadius(this.getDataset().data[index]),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.point.borderWidth),
|
||||
radius: reset ? 0 : custom.radius ? custom.radius : this.getRadius(data),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor),
|
||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth),
|
||||
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
|
||||
}
|
||||
});
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
var model = point._model;
|
||||
model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));
|
||||
|
||||
point.pivot();
|
||||
},
|
||||
@ -129,36 +93,30 @@ module.exports = function(Chart) {
|
||||
return value.r || this.chart.options.elements.point.radius;
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
|
||||
// Transition and Draw the Points
|
||||
helpers.each(this.getMeta().data, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
point.draw();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
var custom = point.custom || {};
|
||||
var model = point._model;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, point._model.borderWidth);
|
||||
model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);
|
||||
model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
|
||||
model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
|
||||
model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
var custom = point.custom || {};
|
||||
var model = point._model;
|
||||
var pointElementOptions = this.chart.options.elements.point;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : this.getRadius(this.getDataset().data[point._index]);
|
||||
point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.point.backgroundColor);
|
||||
point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.point.borderColor);
|
||||
point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.point.borderWidth);
|
||||
model.radius = custom.radius ? custom.radius : this.getRadius(dataset.data[point._index]);
|
||||
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor);
|
||||
model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor);
|
||||
model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var helpers = Chart.helpers,
|
||||
defaults = Chart.defaults;
|
||||
|
||||
Chart.defaults.doughnut = {
|
||||
defaults.doughnut = {
|
||||
animation: {
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate: true,
|
||||
@ -19,11 +20,15 @@ module.exports = function(Chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '"></span>');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
var data = chart.data;
|
||||
var datasets = data.datasets;
|
||||
var labels = data.labels;
|
||||
|
||||
if (datasets.length) {
|
||||
for (var i = 0; i < datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
|
||||
if (labels[i]) {
|
||||
text.push(labels[i]);
|
||||
}
|
||||
text.push('</li>');
|
||||
}
|
||||
@ -41,9 +46,12 @@ module.exports = function(Chart) {
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var ds = data.datasets[0];
|
||||
var arc = meta.data[i];
|
||||
var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor);
|
||||
var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor);
|
||||
var bw = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(ds.borderWidth, i, this.chart.options.elements.arc.borderWidth);
|
||||
var custom = arc.custom || {};
|
||||
var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
|
||||
var arcOpts = chart.options.elements.arc;
|
||||
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
|
||||
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
|
||||
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
|
||||
|
||||
return {
|
||||
text: label,
|
||||
@ -55,7 +63,7 @@ module.exports = function(Chart) {
|
||||
// Extra data used for toggling the correct item
|
||||
index: i
|
||||
};
|
||||
}, this);
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@ -98,43 +106,17 @@ module.exports = function(Chart) {
|
||||
}
|
||||
};
|
||||
|
||||
Chart.defaults.pie = helpers.clone(Chart.defaults.doughnut);
|
||||
helpers.extend(Chart.defaults.pie, {
|
||||
defaults.pie = helpers.clone(defaults.doughnut);
|
||||
helpers.extend(defaults.pie, {
|
||||
cutoutPercentage: 0
|
||||
});
|
||||
|
||||
|
||||
Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// no scales for doughnut
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
dataElementType: Chart.elements.Arc,
|
||||
|
||||
addElementAndReset: function(index, colorForNewElement) {
|
||||
var arc = new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
if (colorForNewElement && helpers.isArray(this.getDataset().backgroundColor)) {
|
||||
this.getDataset().backgroundColor.splice(index, 0, colorForNewElement);
|
||||
}
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, arc);
|
||||
this.updateElement(arc, index, true);
|
||||
},
|
||||
linkScales: helpers.noop,
|
||||
|
||||
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
|
||||
getRingIndex: function getRingIndex(datasetIndex) {
|
||||
@ -150,23 +132,34 @@ module.exports = function(Chart) {
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var availableWidth = this.chart.chartArea.right - this.chart.chartArea.left - this.chart.options.elements.arc.borderWidth;
|
||||
var availableHeight = this.chart.chartArea.bottom - this.chart.chartArea.top - this.chart.options.elements.arc.borderWidth;
|
||||
var minSize = Math.min(availableWidth, availableHeight);
|
||||
var offset = {x: 0, y: 0};
|
||||
var _this = this;
|
||||
var chart = _this.chart,
|
||||
chartArea = chart.chartArea,
|
||||
opts = chart.options,
|
||||
arcOpts = opts.elements.arc,
|
||||
availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
|
||||
availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
|
||||
minSize = Math.min(availableWidth, availableHeight),
|
||||
offset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
meta = _this.getMeta(),
|
||||
cutoutPercentage = opts.cutoutPercentage,
|
||||
circumference = opts.circumference;
|
||||
|
||||
// If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
|
||||
if (this.chart.options.circumference < Math.PI * 2.0) {
|
||||
var startAngle = this.chart.options.rotation % (Math.PI * 2.0);
|
||||
if (circumference < Math.PI * 2.0) {
|
||||
var startAngle = opts.rotation % (Math.PI * 2.0);
|
||||
startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
|
||||
var endAngle = startAngle + this.chart.options.circumference;
|
||||
var endAngle = startAngle + circumference;
|
||||
var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
|
||||
var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
|
||||
var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
|
||||
var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
|
||||
var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
|
||||
var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
|
||||
var cutout = this.chart.options.cutoutPercentage / 100.0;
|
||||
var cutout = cutoutPercentage / 100.0;
|
||||
var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
|
||||
var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
|
||||
var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
|
||||
@ -174,94 +167,80 @@ module.exports = function(Chart) {
|
||||
offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
|
||||
}
|
||||
|
||||
this.chart.outerRadius = Math.max(minSize / 2, 0);
|
||||
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
|
||||
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
|
||||
this.chart.offsetX = offset.x * this.chart.outerRadius;
|
||||
this.chart.offsetY = offset.y * this.chart.outerRadius;
|
||||
chart.outerRadius = Math.max(minSize / 2, 0);
|
||||
chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);
|
||||
chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
|
||||
chart.offsetX = offset.x * chart.outerRadius;
|
||||
chart.offsetY = offset.y * chart.outerRadius;
|
||||
|
||||
this.getMeta().total = this.calculateTotal();
|
||||
meta.total = _this.calculateTotal();
|
||||
|
||||
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.getRingIndex(this.index));
|
||||
this.innerRadius = this.outerRadius - this.chart.radiusLength;
|
||||
_this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.getRingIndex(_this.index));
|
||||
_this.innerRadius = _this.outerRadius - chart.radiusLength;
|
||||
|
||||
helpers.each(this.getMeta().data, function(arc, index) {
|
||||
this.updateElement(arc, index, reset);
|
||||
}, this);
|
||||
helpers.each(meta.data, function(arc, index) {
|
||||
_this.updateElement(arc, index, reset);
|
||||
});
|
||||
},
|
||||
|
||||
updateElement: function(arc, index, reset) {
|
||||
var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2;
|
||||
var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2;
|
||||
var startAngle = this.chart.options.rotation; // non reset case handled later
|
||||
var endAngle = this.chart.options.rotation; // non reset case handled later
|
||||
var circumference = reset && this.chart.options.animation.animateRotate ? 0 : arc.hidden? 0 : this.calculateCircumference(this.getDataset().data[index]) * (this.chart.options.circumference / (2.0 * Math.PI));
|
||||
var innerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.innerRadius;
|
||||
var outerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.outerRadius;
|
||||
var _this = this;
|
||||
var chart = _this.chart,
|
||||
chartArea = chart.chartArea,
|
||||
opts = chart.options,
|
||||
animationOpts = opts.animation,
|
||||
arcOpts = opts.elements.arc,
|
||||
centerX = (chartArea.left + chartArea.right) / 2,
|
||||
centerY = (chartArea.top + chartArea.bottom) / 2,
|
||||
startAngle = opts.rotation, // non reset case handled later
|
||||
endAngle = opts.rotation, // non reset case handled later
|
||||
dataset = _this.getDataset(),
|
||||
circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : _this.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),
|
||||
innerRadius = reset && animationOpts.animateScale ? 0 : _this.innerRadius,
|
||||
outerRadius = reset && animationOpts.animateScale ? 0 : _this.outerRadius,
|
||||
custom = arc.custom || {},
|
||||
valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
|
||||
|
||||
helpers.extend(arc, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_datasetIndex: _this.index,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: centerX + this.chart.offsetX,
|
||||
y: centerY + this.chart.offsetY,
|
||||
x: centerX + chart.offsetX,
|
||||
y: centerY + chart.offsetY,
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle,
|
||||
circumference: circumference,
|
||||
outerRadius: outerRadius,
|
||||
innerRadius: innerRadius,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
hoverBackgroundColor: arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().hoverBackgroundColor, index, this.chart.options.elements.arc.hoverBackgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.getDataset().label, index, this.chart.data.labels[index])
|
||||
label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
|
||||
}
|
||||
});
|
||||
|
||||
// Set correct angles if not resetting
|
||||
if (!reset || !this.chart.options.animation.animateRotate) {
|
||||
var model = arc._model;
|
||||
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor);
|
||||
model.hoverBackgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, arcOpts.hoverBackgroundColor);
|
||||
model.borderWidth = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth);
|
||||
model.borderColor = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor);
|
||||
|
||||
// Set correct angles if not resetting
|
||||
if (!reset || !animationOpts.animateRotate) {
|
||||
if (index === 0) {
|
||||
arc._model.startAngle = this.chart.options.rotation;
|
||||
model.startAngle = opts.rotation;
|
||||
} else {
|
||||
arc._model.startAngle = this.getMeta().data[index - 1]._model.endAngle;
|
||||
model.startAngle = _this.getMeta().data[index - 1]._model.endAngle;
|
||||
}
|
||||
|
||||
arc._model.endAngle = arc._model.startAngle + arc._model.circumference;
|
||||
model.endAngle = model.startAngle + model.circumference;
|
||||
}
|
||||
|
||||
arc.pivot();
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getMeta().data, function(arc, index) {
|
||||
arc.transition(easingDecimal).draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(arc._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderColor = arc.custom && arc.custom.hoverBorderColor ? arc.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(arc._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, arc._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor);
|
||||
arc._model.borderColor = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor);
|
||||
arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth);
|
||||
Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
|
||||
},
|
||||
|
||||
calculateTotal: function() {
|
||||
|
294
vendors/Chart.js/src/controllers/controller.line.js
vendored
@ -23,107 +23,87 @@ module.exports = function(Chart) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Chart.controllers.line = Chart.DatasetController.extend({
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
meta.dataset = meta.dataset || new Chart.elements.Line({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_points: meta.data
|
||||
});
|
||||
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
datasetElementType: Chart.elements.Line,
|
||||
|
||||
dataElementType: Chart.elements.Point,
|
||||
|
||||
addElementAndReset: function(index) {
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
var me = this;
|
||||
var options = me.chart.options;
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, point);
|
||||
this.updateElement(point, index, true);
|
||||
Chart.DatasetController.prototype.addElementAndReset.call(me, index);
|
||||
|
||||
// Make sure bezier control points are updated
|
||||
if (this.chart.options.showLines && this.chart.options.elements.line.tension !== 0)
|
||||
this.updateBezierControlPoints();
|
||||
if (options.showLines && options.elements.line.tension !== 0) {
|
||||
me.updateBezierControlPoints();
|
||||
}
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var meta = this.getMeta();
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var line = meta.dataset;
|
||||
var points = meta.data;
|
||||
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
var points = meta.data || [];
|
||||
var options = me.chart.options;
|
||||
var lineElementOptions = options.elements.line;
|
||||
var scale = me.getScaleForId(meta.yAxisID);
|
||||
var i, ilen, dataset, custom;
|
||||
|
||||
// Update Line
|
||||
if (this.chart.options.showLines) {
|
||||
if (options.showLines) {
|
||||
dataset = me.getDataset();
|
||||
custom = line.custom || {};
|
||||
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
|
||||
dataset.lineTension = dataset.tension;
|
||||
}
|
||||
|
||||
// Utility
|
||||
line._scale = yScale;
|
||||
line._datasetIndex = this.index;
|
||||
line._scale = scale;
|
||||
line._datasetIndex = me.index;
|
||||
// Data
|
||||
line._children = points;
|
||||
// Model
|
||||
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((this.getDataset().tension !== undefined) && (this.getDataset().lineTension === undefined))
|
||||
{
|
||||
this.getDataset().lineTension = this.getDataset().tension;
|
||||
}
|
||||
|
||||
line._model = {
|
||||
// Appearance
|
||||
tension: line.custom && line.custom.tension ? line.custom.tension : helpers.getValueOrDefault(this.getDataset().lineTension, this.chart.options.elements.line.tension),
|
||||
backgroundColor: line.custom && line.custom.backgroundColor ? line.custom.backgroundColor : (this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor),
|
||||
borderWidth: line.custom && line.custom.borderWidth ? line.custom.borderWidth : (this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth),
|
||||
borderColor: line.custom && line.custom.borderColor ? line.custom.borderColor : (this.getDataset().borderColor || this.chart.options.elements.line.borderColor),
|
||||
borderCapStyle: line.custom && line.custom.borderCapStyle ? line.custom.borderCapStyle : (this.getDataset().borderCapStyle || this.chart.options.elements.line.borderCapStyle),
|
||||
borderDash: line.custom && line.custom.borderDash ? line.custom.borderDash : (this.getDataset().borderDash || this.chart.options.elements.line.borderDash),
|
||||
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
|
||||
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
|
||||
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
|
||||
tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
|
||||
borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
|
||||
borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
|
||||
borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
|
||||
borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
|
||||
borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
|
||||
fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
|
||||
// Scale
|
||||
scaleTop: yScale.top,
|
||||
scaleBottom: yScale.bottom,
|
||||
scaleZero: scaleBase
|
||||
scaleTop: scale.top,
|
||||
scaleBottom: scale.bottom,
|
||||
scaleZero: scale.getBasePixel()
|
||||
};
|
||||
|
||||
line.pivot();
|
||||
}
|
||||
|
||||
// Update Points
|
||||
helpers.each(points, function(point, index) {
|
||||
this.updateElement(point, index, reset);
|
||||
}, this);
|
||||
for (i=0, ilen=points.length; i<ilen; ++i) {
|
||||
me.updateElement(points[i], i, reset);
|
||||
}
|
||||
|
||||
if (this.chart.options.showLines && this.chart.options.elements.line.tension !== 0)
|
||||
this.updateBezierControlPoints();
|
||||
if (options.showLines && lineElementOptions.tension !== 0) {
|
||||
me.updateBezierControlPoints();
|
||||
}
|
||||
},
|
||||
|
||||
getPointBackgroundColor: function(point, index) {
|
||||
var backgroundColor = this.chart.options.elements.point.backgroundColor;
|
||||
var dataset = this.getDataset();
|
||||
var custom = point.custom || {};
|
||||
|
||||
if (point.custom && point.custom.backgroundColor) {
|
||||
backgroundColor = point.custom.backgroundColor;
|
||||
if (custom.backgroundColor) {
|
||||
backgroundColor = custom.backgroundColor;
|
||||
} else if (dataset.pointBackgroundColor) {
|
||||
backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
|
||||
} else if (dataset.backgroundColor) {
|
||||
@ -132,29 +112,33 @@ module.exports = function(Chart) {
|
||||
|
||||
return backgroundColor;
|
||||
},
|
||||
|
||||
getPointBorderColor: function(point, index) {
|
||||
var borderColor = this.chart.options.elements.point.borderColor;
|
||||
var dataset = this.getDataset();
|
||||
var custom = point.custom || {};
|
||||
|
||||
if (point.custom && point.custom.borderColor) {
|
||||
borderColor = point.custom.borderColor;
|
||||
if (custom.borderColor) {
|
||||
borderColor = custom.borderColor;
|
||||
} else if (dataset.pointBorderColor) {
|
||||
borderColor = helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, borderColor);
|
||||
borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
|
||||
} else if (dataset.borderColor) {
|
||||
borderColor = dataset.borderColor;
|
||||
}
|
||||
|
||||
return borderColor;
|
||||
},
|
||||
|
||||
getPointBorderWidth: function(point, index) {
|
||||
var borderWidth = this.chart.options.elements.point.borderWidth;
|
||||
var dataset = this.getDataset();
|
||||
var custom = point.custom || {};
|
||||
|
||||
if (point.custom && point.custom.borderWidth !== undefined) {
|
||||
borderWidth = point.custom.borderWidth;
|
||||
} else if (dataset.pointBorderWidth !== undefined) {
|
||||
if (custom.borderWidth) {
|
||||
borderWidth = custom.borderWidth;
|
||||
} else if (dataset.pointBorderWidth) {
|
||||
borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
|
||||
} else if (dataset.borderWidth !== undefined) {
|
||||
} else if (dataset.borderWidth) {
|
||||
borderWidth = dataset.borderWidth;
|
||||
}
|
||||
|
||||
@ -162,68 +146,65 @@ module.exports = function(Chart) {
|
||||
},
|
||||
|
||||
updateElement: function(point, index, reset) {
|
||||
var meta = this.getMeta();
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var scaleBase;
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var custom = point.custom || {};
|
||||
var dataset = me.getDataset();
|
||||
var datasetIndex = me.index;
|
||||
var value = dataset.data[index];
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var xScale = me.getScaleForId(meta.xAxisID);
|
||||
var pointOptions = me.chart.options.elements.point;
|
||||
var x, y;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
|
||||
dataset.pointRadius = dataset.radius;
|
||||
}
|
||||
if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
|
||||
dataset.pointHitRadius = dataset.hitRadius;
|
||||
}
|
||||
|
||||
x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);
|
||||
y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);
|
||||
|
||||
// Utility
|
||||
point._chart = this.chart.chart;
|
||||
point._xScale = xScale;
|
||||
point._yScale = yScale;
|
||||
point._datasetIndex = this.index;
|
||||
point._datasetIndex = datasetIndex;
|
||||
point._index = index;
|
||||
|
||||
// Desired view properties
|
||||
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((this.getDataset().radius !== undefined) && (this.getDataset().pointRadius === undefined))
|
||||
{
|
||||
this.getDataset().pointRadius = this.getDataset().radius;
|
||||
}
|
||||
if ((this.getDataset().hitRadius !== undefined) && (this.getDataset().pointHitRadius === undefined))
|
||||
{
|
||||
this.getDataset().pointHitRadius = this.getDataset().hitRadius;
|
||||
}
|
||||
|
||||
point._model = {
|
||||
x: xScale.getPixelForValue(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
y: reset ? scaleBase : this.calculatePointY(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
x: x,
|
||||
y: y,
|
||||
skip: custom.skip || isNaN(x) || isNaN(y),
|
||||
// Appearance
|
||||
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius),
|
||||
pointStyle: point.custom && point.custom.pointStyle ? point.custom.pointStyle : helpers.getValueAtIndexOrDefault(this.getDataset().pointStyle, index, this.chart.options.elements.point.pointStyle),
|
||||
backgroundColor: this.getPointBackgroundColor(point, index),
|
||||
borderColor: this.getPointBorderColor(point, index),
|
||||
borderWidth: this.getPointBorderWidth(point, index),
|
||||
radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
|
||||
pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
|
||||
backgroundColor: me.getPointBackgroundColor(point, index),
|
||||
borderColor: me.getPointBorderColor(point, index),
|
||||
borderWidth: me.getPointBorderWidth(point, index),
|
||||
tension: meta.dataset._model ? meta.dataset._model.tension : 0,
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().pointHitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
|
||||
};
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
},
|
||||
|
||||
calculatePointY: function(value, index, datasetIndex, isCombo) {
|
||||
var meta = this.getMeta();
|
||||
var xScale = this.getScaleForId(meta.xAxisID);
|
||||
var yScale = this.getScaleForId(meta.yAxisID);
|
||||
var me = this;
|
||||
var chart = me.chart;
|
||||
var meta = me.getMeta();
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var sumPos = 0;
|
||||
var sumNeg = 0;
|
||||
var i, ds, dsMeta;
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var ds = this.chart.data.datasets[i];
|
||||
var dsMeta = this.chart.getDatasetMeta(i);
|
||||
if (dsMeta.type === 'line' && this.chart.isDatasetVisible(i)) {
|
||||
for (i = 0; i < datasetIndex; i++) {
|
||||
ds = chart.data.datasets[i];
|
||||
dsMeta = chart.getDatasetMeta(i);
|
||||
if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
@ -243,72 +224,83 @@ module.exports = function(Chart) {
|
||||
},
|
||||
|
||||
updateBezierControlPoints: function() {
|
||||
// Update bezier control points
|
||||
var meta = this.getMeta();
|
||||
helpers.each(meta.data, function(point, index) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
helpers.previousItem(meta.data, index)._model,
|
||||
point._model,
|
||||
helpers.nextItem(meta.data, index)._model,
|
||||
var area = this.chart.chartArea;
|
||||
var points = meta.data || [];
|
||||
var i, ilen, point, model, controlPoints;
|
||||
|
||||
for (i=0, ilen=points.length; i<ilen; ++i) {
|
||||
point = points[i];
|
||||
model = point._model;
|
||||
controlPoints = helpers.splineCurve(
|
||||
helpers.previousItem(points, i)._model,
|
||||
model,
|
||||
helpers.nextItem(points, i)._model,
|
||||
meta.dataset._model.tension
|
||||
);
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, area.right), area.left);
|
||||
model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, area.bottom), area.top);
|
||||
model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, area.right), area.left);
|
||||
model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, area.bottom), area.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var meta = this.getMeta();
|
||||
var points = meta.data || [];
|
||||
var easingDecimal = ease || 1;
|
||||
var i, ilen;
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(meta.data, function(point) {
|
||||
point.transition(easingDecimal);
|
||||
});
|
||||
for (i=0, ilen=points.length; i<ilen; ++i) {
|
||||
points[i].transition(easingDecimal);
|
||||
}
|
||||
|
||||
// Transition and Draw the line
|
||||
if (this.chart.options.showLines)
|
||||
if (this.chart.options.showLines) {
|
||||
meta.dataset.transition(easingDecimal).draw();
|
||||
}
|
||||
|
||||
// Draw the points
|
||||
helpers.each(meta.data, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
for (i=0, ilen=points.length; i<ilen; ++i) {
|
||||
points[i].draw();
|
||||
}
|
||||
},
|
||||
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
var custom = point.custom || {};
|
||||
var model = point._model;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, point._model.borderWidth);
|
||||
model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
|
||||
model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
|
||||
model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var me = this;
|
||||
var dataset = me.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
var custom = point.custom || {};
|
||||
var model = point._model;
|
||||
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((this.getDataset().radius !== undefined) && (this.getDataset().pointRadius === undefined))
|
||||
{
|
||||
this.getDataset().pointRadius = this.getDataset().radius;
|
||||
if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
|
||||
dataset.pointRadius = dataset.radius;
|
||||
}
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius);
|
||||
point._model.backgroundColor = this.getPointBackgroundColor(point, index);
|
||||
point._model.borderColor = this.getPointBorderColor(point, index);
|
||||
point._model.borderWidth = this.getPointBorderWidth(point, index);
|
||||
model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);
|
||||
model.backgroundColor = me.getPointBackgroundColor(point, index);
|
||||
model.borderColor = me.getPointBorderColor(point, index);
|
||||
model.borderWidth = me.getPointBorderWidth(point, index);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -22,11 +22,15 @@ module.exports = function(Chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '">');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
var data = chart.data;
|
||||
var datasets = data.datasets;
|
||||
var labels = data.labels;
|
||||
|
||||
if (datasets.length) {
|
||||
for (var i = 0; i < datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');
|
||||
if (labels[i]) {
|
||||
text.push(labels[i]);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
@ -44,9 +48,12 @@ module.exports = function(Chart) {
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var ds = data.datasets[0];
|
||||
var arc = meta.data[i];
|
||||
var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor);
|
||||
var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor);
|
||||
var bw = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(ds.borderWidth, i, this.chart.options.elements.arc.borderWidth);
|
||||
var custom = arc.custom || {};
|
||||
var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
|
||||
var arcOpts = chart.options.elements.arc;
|
||||
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
|
||||
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
|
||||
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
|
||||
|
||||
return {
|
||||
text: label,
|
||||
@ -58,7 +65,7 @@ module.exports = function(Chart) {
|
||||
// Extra data used for toggling the correct item
|
||||
index: i
|
||||
};
|
||||
}, this);
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@ -93,66 +100,61 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
Chart.controllers.polarArea = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// no scales for doughnut
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
dataElementType: Chart.elements.Arc,
|
||||
|
||||
addElementAndReset: function(index) {
|
||||
var arc = new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, arc);
|
||||
this.updateElement(arc, index, true);
|
||||
},
|
||||
linkScales: helpers.noop,
|
||||
|
||||
update: function update(reset) {
|
||||
var _this = this;
|
||||
var chart = _this.chart;
|
||||
var chartArea = chart.chartArea;
|
||||
var meta = this.getMeta();
|
||||
var minSize = Math.min(this.chart.chartArea.right - this.chart.chartArea.left, this.chart.chartArea.bottom - this.chart.chartArea.top);
|
||||
this.chart.outerRadius = Math.max((minSize - this.chart.options.elements.arc.borderWidth / 2) / 2, 0);
|
||||
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
|
||||
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
|
||||
var opts = chart.options;
|
||||
var arcOpts = opts.elements.arc;
|
||||
var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
||||
chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);
|
||||
chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
|
||||
chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
|
||||
|
||||
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index);
|
||||
this.innerRadius = this.outerRadius - this.chart.radiusLength;
|
||||
_this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.index);
|
||||
_this.innerRadius = _this.outerRadius - chart.radiusLength;
|
||||
|
||||
meta.count = this.countVisibleElements();
|
||||
meta.count = _this.countVisibleElements();
|
||||
|
||||
helpers.each(meta.data, function(arc, index) {
|
||||
this.updateElement(arc, index, reset);
|
||||
}, this);
|
||||
_this.updateElement(arc, index, reset);
|
||||
});
|
||||
},
|
||||
|
||||
updateElement: function(arc, index, reset) {
|
||||
var circumference = this.calculateCircumference(this.getDataset().data[index]);
|
||||
var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2;
|
||||
var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2;
|
||||
var _this = this;
|
||||
var chart = _this.chart;
|
||||
var chartArea = chart.chartArea;
|
||||
var dataset = _this.getDataset();
|
||||
var opts = chart.options;
|
||||
var animationOpts = opts.animation;
|
||||
var arcOpts = opts.elements.arc;
|
||||
var custom = arc.custom || {};
|
||||
var scale = chart.scale;
|
||||
var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
|
||||
var labels = chart.data.labels;
|
||||
|
||||
var circumference = _this.calculateCircumference(dataset.data[index]);
|
||||
var centerX = (chartArea.left + chartArea.right) / 2;
|
||||
var centerY = (chartArea.top + chartArea.bottom) / 2;
|
||||
|
||||
// If there is NaN data before us, we need to calculate the starting angle correctly.
|
||||
// We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
|
||||
var visibleCount = 0;
|
||||
var meta = this.getMeta();
|
||||
var meta = _this.getMeta();
|
||||
for (var i = 0; i < index; ++i) {
|
||||
if (!isNaN(this.getDataset().data[i]) && !meta.data[i].hidden) {
|
||||
if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {
|
||||
++visibleCount;
|
||||
}
|
||||
}
|
||||
|
||||
var distance = arc.hidden? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]);
|
||||
var distance = arc.hidden? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
|
||||
var startAngle = (-0.5 * Math.PI) + (circumference * visibleCount);
|
||||
var endAngle = startAngle + (arc.hidden? 0 : circumference);
|
||||
|
||||
@ -160,23 +162,22 @@ module.exports = function(Chart) {
|
||||
x: centerX,
|
||||
y: centerY,
|
||||
innerRadius: 0,
|
||||
outerRadius: this.chart.options.animation.animateScale ? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]),
|
||||
startAngle: this.chart.options.animation.animateRotate ? Math.PI * -0.5 : startAngle,
|
||||
endAngle: this.chart.options.animation.animateRotate ? Math.PI * -0.5 : endAngle,
|
||||
outerRadius: animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]),
|
||||
startAngle: animationOpts.animateRotate ? Math.PI * -0.5 : startAngle,
|
||||
endAngle: animationOpts.animateRotate ? Math.PI * -0.5 : endAngle,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),
|
||||
borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.chart.data.labels, index, this.chart.data.labels[index])
|
||||
label: getValueAtIndexOrDefault(labels, index, labels[index])
|
||||
};
|
||||
|
||||
helpers.extend(arc, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_datasetIndex: _this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
_scale: scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: reset ? resetModel : {
|
||||
@ -187,40 +188,19 @@ module.exports = function(Chart) {
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),
|
||||
borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.chart.data.labels, index, this.chart.data.labels[index])
|
||||
label: getValueAtIndexOrDefault(labels, index, labels[index])
|
||||
}
|
||||
});
|
||||
|
||||
arc.pivot();
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getMeta().data, function(arc, index) {
|
||||
arc.transition(easingDecimal).draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(arc._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderColor = arc.custom && arc.custom.hoverBorderColor ? arc.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(arc._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, arc._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor);
|
||||
arc._model.borderColor = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor);
|
||||
arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth);
|
||||
Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
|
||||
},
|
||||
|
||||
countVisibleElements: function() {
|
||||
|
143
vendors/Chart.js/src/controllers/controller.radar.js
vendored
@ -4,7 +4,6 @@ module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
|
||||
Chart.defaults.radar = {
|
||||
scale: {
|
||||
type: "radialLinear"
|
||||
@ -17,42 +16,15 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
Chart.controllers.radar = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// No need. Single scale only
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
var meta = this.getMeta();
|
||||
datasetElementType: Chart.elements.Line,
|
||||
|
||||
meta.dataset = meta.dataset || new Chart.elements.Line({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_points: meta.data,
|
||||
_loop: true
|
||||
});
|
||||
dataElementType: Chart.elements.Point,
|
||||
|
||||
linkScales: helpers.noop,
|
||||
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
meta.data[index] = meta.data[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_model: {
|
||||
x: 0, //xScale.getPixelForValue(null, index, true),
|
||||
y: 0 //this.chartArea.bottom,
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Add to the points array and reset it
|
||||
this.getMeta().data.splice(index, 0, point);
|
||||
this.updateElement(point, index, true);
|
||||
Chart.DatasetController.prototype.addElementAndReset.call(this, index);
|
||||
|
||||
// Make sure bezier control points are updated
|
||||
this.updateBezierControlPoints();
|
||||
@ -62,22 +34,14 @@ module.exports = function(Chart) {
|
||||
var meta = this.getMeta();
|
||||
var line = meta.dataset;
|
||||
var points = meta.data;
|
||||
|
||||
var custom = line.custom || {};
|
||||
var dataset = this.getDataset();
|
||||
var lineElementOptions = this.chart.options.elements.line;
|
||||
var scale = this.chart.scale;
|
||||
var scaleBase;
|
||||
|
||||
if (scale.min < 0 && scale.max < 0) {
|
||||
scaleBase = scale.getPointPositionForValue(0, scale.max);
|
||||
} else if (scale.min > 0 && scale.max > 0) {
|
||||
scaleBase = scale.getPointPositionForValue(0, scale.min);
|
||||
} else {
|
||||
scaleBase = scale.getPointPositionForValue(0, 0);
|
||||
}
|
||||
|
||||
// Compatibility: If the properties are defined with only the old name, use those values
|
||||
if ((this.getDataset().tension !== undefined) && (this.getDataset().lineTension === undefined))
|
||||
{
|
||||
this.getDataset().lineTension = this.getDataset().tension;
|
||||
if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
|
||||
dataset.lineTension = dataset.tension;
|
||||
}
|
||||
|
||||
helpers.extend(meta.dataset, {
|
||||
@ -85,23 +49,24 @@ module.exports = function(Chart) {
|
||||
_datasetIndex: this.index,
|
||||
// Data
|
||||
_children: points,
|
||||
_loop: true,
|
||||
// Model
|
||||
_model: {
|
||||
// Appearance
|
||||
tension: line.custom && line.custom.tension ? line.custom.tension : helpers.getValueOrDefault(this.getDataset().lineTension, this.chart.options.elements.line.tension),
|
||||
backgroundColor: line.custom && line.custom.backgroundColor ? line.custom.backgroundColor : (this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor),
|
||||
borderWidth: line.custom && line.custom.borderWidth ? line.custom.borderWidth : (this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth),
|
||||
borderColor: line.custom && line.custom.borderColor ? line.custom.borderColor : (this.getDataset().borderColor || this.chart.options.elements.line.borderColor),
|
||||
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
|
||||
borderCapStyle: line.custom && line.custom.borderCapStyle ? line.custom.borderCapStyle : (this.getDataset().borderCapStyle || this.chart.options.elements.line.borderCapStyle),
|
||||
borderDash: line.custom && line.custom.borderDash ? line.custom.borderDash : (this.getDataset().borderDash || this.chart.options.elements.line.borderDash),
|
||||
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
|
||||
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
|
||||
tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
|
||||
borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
|
||||
fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
|
||||
borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
|
||||
borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
|
||||
borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
|
||||
borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
|
||||
|
||||
// Scale
|
||||
scaleTop: scale.top,
|
||||
scaleBottom: scale.bottom,
|
||||
scaleZero: scaleBase
|
||||
scaleZero: scale.getBasePosition()
|
||||
}
|
||||
});
|
||||
|
||||
@ -117,50 +82,57 @@ module.exports = function(Chart) {
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
updateElement: function(point, index, reset) {
|
||||
var pointPosition = this.chart.scale.getPointPositionForValue(index, this.getDataset().data[index]);
|
||||
var custom = point.custom || {};
|
||||
var dataset = this.getDataset();
|
||||
var scale = this.chart.scale;
|
||||
var pointElementOptions = this.chart.options.elements.point;
|
||||
var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
_scale: scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: reset ? this.chart.scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: reset ? this.chart.scale.yCenter : pointPosition.y,
|
||||
x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: reset ? scale.yCenter : pointPosition.y,
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
|
||||
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
|
||||
pointStyle: point.custom && point.custom.pointStyle ? point.custom.pointStyle : helpers.getValueAtIndexOrDefault(this.getDataset().pointStyle, index, this.chart.options.elements.point.pointStyle),
|
||||
tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.tension, this.chart.options.elements.line.tension),
|
||||
radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),
|
||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),
|
||||
pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),
|
||||
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
|
||||
}
|
||||
});
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
},
|
||||
updateBezierControlPoints: function() {
|
||||
var chartArea = this.chart.chartArea;
|
||||
var meta = this.getMeta();
|
||||
|
||||
helpers.each(meta.data, function(point, index) {
|
||||
var model = point._model;
|
||||
var controlPoints = helpers.splineCurve(
|
||||
helpers.previousItem(meta.data, index, true)._model,
|
||||
point._model,
|
||||
model,
|
||||
helpers.nextItem(meta.data, index, true)._model,
|
||||
point._model.tension
|
||||
model.tension
|
||||
);
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
|
||||
model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
|
||||
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
|
||||
model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
@ -188,22 +160,27 @@ module.exports = function(Chart) {
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var custom = point.custom || {};
|
||||
var index = point._index;
|
||||
var model = point._model;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, point._model.borderWidth);
|
||||
model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
|
||||
model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
|
||||
model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var custom = point.custom || {};
|
||||
var index = point._index;
|
||||
var model = point._model;
|
||||
var pointElementOptions = this.chart.options.elements.point;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius);
|
||||
point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor);
|
||||
point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor);
|
||||
point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth);
|
||||
model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);
|
||||
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);
|
||||
model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);
|
||||
model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
325
vendors/Chart.js/src/core/core.controller.js
vendored
@ -98,82 +98,71 @@ module.exports = function(Chart) {
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
ensureScalesHaveIDs: function ensureScalesHaveIDs() {
|
||||
var defaultXAxisID = 'x-axis-';
|
||||
var defaultYAxisID = 'y-axis-';
|
||||
var options = this.options;
|
||||
var scalesOptions = options.scales || {};
|
||||
var scaleOptions = options.scale;
|
||||
|
||||
if (this.options.scales) {
|
||||
if (this.options.scales.xAxes && this.options.scales.xAxes.length) {
|
||||
helpers.each(this.options.scales.xAxes, function(xAxisOptions, index) {
|
||||
xAxisOptions.id = xAxisOptions.id || (defaultXAxisID + index);
|
||||
});
|
||||
}
|
||||
helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
|
||||
xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
|
||||
});
|
||||
|
||||
if (this.options.scales.yAxes && this.options.scales.yAxes.length) {
|
||||
// Build the y axes
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions, index) {
|
||||
yAxisOptions.id = yAxisOptions.id || (defaultYAxisID + index);
|
||||
});
|
||||
}
|
||||
helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {
|
||||
yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
|
||||
});
|
||||
|
||||
if (scaleOptions) {
|
||||
scaleOptions.id = scaleOptions.id || 'scale';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds a map of scale ID to scale object for future lookup.
|
||||
*/
|
||||
buildScales: function buildScales() {
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
var me = this;
|
||||
var options = me.options;
|
||||
var scales = me.scales = {};
|
||||
var items = [];
|
||||
|
||||
// Build the x axes
|
||||
if (this.options.scales) {
|
||||
if (this.options.scales.xAxes && this.options.scales.xAxes.length) {
|
||||
helpers.each(this.options.scales.xAxes, function(xAxisOptions, index) {
|
||||
var xType = helpers.getValueOrDefault(xAxisOptions.type, 'category');
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(xType);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: xAxisOptions,
|
||||
chart: this,
|
||||
id: xAxisOptions.id
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (this.options.scales.yAxes && this.options.scales.yAxes.length) {
|
||||
// Build the y axes
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions, index) {
|
||||
var yType = helpers.getValueOrDefault(yAxisOptions.type, 'linear');
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(yType);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
chart: this,
|
||||
id: yAxisOptions.id
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
if (options.scales) {
|
||||
items = items.concat(
|
||||
(options.scales.xAxes || []).map(function(xAxisOptions) {
|
||||
return { options: xAxisOptions, dtype: 'category' }; }),
|
||||
(options.scales.yAxes || []).map(function(yAxisOptions) {
|
||||
return { options: yAxisOptions, dtype: 'linear' }; }));
|
||||
}
|
||||
if (this.options.scale) {
|
||||
// Build radial axes
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(this.options.scale.type);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.scale,
|
||||
chart: this
|
||||
});
|
||||
|
||||
this.scale = scale;
|
||||
|
||||
this.scales.radialScale = scale;
|
||||
}
|
||||
if (options.scale) {
|
||||
items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });
|
||||
}
|
||||
|
||||
helpers.each(items, function(item, index) {
|
||||
var scaleOptions = item.options;
|
||||
var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);
|
||||
var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
|
||||
if (!scaleClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scale = new scaleClass({
|
||||
id: scaleOptions.id,
|
||||
options: scaleOptions,
|
||||
ctx: me.chart.ctx,
|
||||
chart: me
|
||||
});
|
||||
|
||||
scales[scale.id] = scale;
|
||||
|
||||
// TODO(SB): I think we should be able to remove this custom case (options.scale)
|
||||
// and consider it as a regular scale part of the "scales"" map only! This would
|
||||
// make the logic easier and remove some useless? custom code.
|
||||
if (item.isDefault) {
|
||||
me.scale = scale;
|
||||
}
|
||||
});
|
||||
|
||||
Chart.scaleService.addScalesToLayout(this);
|
||||
},
|
||||
|
||||
@ -257,6 +246,9 @@ module.exports = function(Chart) {
|
||||
|
||||
Chart.layoutService.update(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Apply changes to the dataets that require the scales to have been calculated i.e BorderColor chages
|
||||
Chart.pluginService.notifyPlugins('afterScaleUpdate', [this]);
|
||||
|
||||
// Can only reset the new controllers after the scales have been updated
|
||||
helpers.each(newControllers, function(controller) {
|
||||
controller.reset();
|
||||
@ -267,18 +259,20 @@ module.exports = function(Chart) {
|
||||
this.getDatasetMeta(datasetIndex).controller.update();
|
||||
}, this);
|
||||
|
||||
this.render(animationDuration, lazy);
|
||||
|
||||
// Do this before render so that any plugins that need final scale updates can use it
|
||||
Chart.pluginService.notifyPlugins('afterUpdate', [this]);
|
||||
|
||||
this.render(animationDuration, lazy);
|
||||
},
|
||||
|
||||
render: function render(duration, lazy) {
|
||||
Chart.pluginService.notifyPlugins('beforeRender', [this]);
|
||||
|
||||
if (this.options.animation && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && this.options.animation.duration !== 0))) {
|
||||
var animationOptions = this.options.animation;
|
||||
if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
|
||||
var animation = new Chart.Animation();
|
||||
animation.numSteps = (duration || this.options.animation.duration) / 16.66; //60 fps
|
||||
animation.easing = this.options.animation.easing;
|
||||
animation.numSteps = (duration || animationOptions.duration) / 16.66; //60 fps
|
||||
animation.easing = animationOptions.easing;
|
||||
|
||||
// render function
|
||||
animation.render = function(chartInstance, animationObject) {
|
||||
@ -290,14 +284,14 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
// user events
|
||||
animation.onAnimationProgress = this.options.animation.onProgress;
|
||||
animation.onAnimationComplete = this.options.animation.onComplete;
|
||||
animation.onAnimationProgress = animationOptions.onProgress;
|
||||
animation.onAnimationComplete = animationOptions.onComplete;
|
||||
|
||||
Chart.animationService.addAnimation(this, animation, duration, lazy);
|
||||
} else {
|
||||
this.draw();
|
||||
if (this.options.animation && this.options.animation.onComplete && this.options.animation.onComplete.call) {
|
||||
this.options.animation.onComplete.call(this);
|
||||
if (animationOptions && animationOptions.onComplete && animationOptions.onComplete.call) {
|
||||
animationOptions.onComplete.call(this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@ -318,10 +312,11 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
// Clip out the chart area so that anything outside does not draw. This is necessary for zoom and pan to function
|
||||
this.chart.ctx.save();
|
||||
this.chart.ctx.beginPath();
|
||||
this.chart.ctx.rect(this.chartArea.left, this.chartArea.top, this.chartArea.right - this.chartArea.left, this.chartArea.bottom - this.chartArea.top);
|
||||
this.chart.ctx.clip();
|
||||
var context = this.chart.ctx;
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.rect(this.chartArea.left, this.chartArea.top, this.chartArea.right - this.chartArea.left, this.chartArea.bottom - this.chartArea.top);
|
||||
context.clip();
|
||||
|
||||
// Draw each dataset via its respective controller (reversed to support proper line stacking)
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
@ -331,7 +326,7 @@ module.exports = function(Chart) {
|
||||
}, this, true);
|
||||
|
||||
// Restore from the clipping operation
|
||||
this.chart.ctx.restore();
|
||||
context.restore();
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
@ -393,6 +388,20 @@ module.exports = function(Chart) {
|
||||
return elementsArray;
|
||||
},
|
||||
|
||||
getElementsAtEventForMode: function(e, mode) {
|
||||
var me = this;
|
||||
switch (mode) {
|
||||
case 'single':
|
||||
return me.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return me.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return me.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
},
|
||||
|
||||
getDatasetAtEvent: function(e) {
|
||||
var elementsArray = this.getElementAtEvent(e);
|
||||
|
||||
@ -489,134 +498,106 @@ module.exports = function(Chart) {
|
||||
this.eventHandler(evt);
|
||||
});
|
||||
},
|
||||
|
||||
updateHoverStyle: function(elements, mode, enabled) {
|
||||
var method = enabled? 'setHoverStyle' : 'removeHoverStyle';
|
||||
var element, i, ilen;
|
||||
|
||||
switch (mode) {
|
||||
case 'single':
|
||||
elements = [ elements[0] ];
|
||||
break;
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
// elements = elements;
|
||||
break;
|
||||
default:
|
||||
// unsupported mode
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0, ilen=elements.length; i<ilen; ++i) {
|
||||
element = elements[i];
|
||||
if (element) {
|
||||
this.getDatasetMeta(element._datasetIndex).controller[method](element);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
eventHandler: function eventHandler(e) {
|
||||
this.lastActive = this.lastActive || [];
|
||||
this.lastTooltipActive = this.lastTooltipActive || [];
|
||||
var me = this;
|
||||
var tooltip = me.tooltip;
|
||||
var options = me.options || {};
|
||||
var hoverOptions = options.hover;
|
||||
var tooltipsOptions = options.tooltips;
|
||||
|
||||
me.lastActive = me.lastActive || [];
|
||||
me.lastTooltipActive = me.lastTooltipActive || [];
|
||||
|
||||
// Find Active Elements for hover and tooltips
|
||||
if (e.type === 'mouseout') {
|
||||
this.active = [];
|
||||
this.tooltipActive = [];
|
||||
me.active = [];
|
||||
me.tooltipActive = [];
|
||||
} else {
|
||||
|
||||
var _this = this;
|
||||
var getItemsForMode = function(mode) {
|
||||
switch (mode) {
|
||||
case 'single':
|
||||
return _this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return _this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return _this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
this.active = getItemsForMode(this.options.hover.mode);
|
||||
this.tooltipActive = getItemsForMode(this.options.tooltips.mode);
|
||||
me.active = me.getElementsAtEventForMode(e, hoverOptions.mode);
|
||||
me.tooltipActive = me.getElementsAtEventForMode(e, tooltipsOptions.mode);
|
||||
}
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
if (hoverOptions.onHover) {
|
||||
hoverOptions.onHover.call(me, me.active);
|
||||
}
|
||||
|
||||
if (e.type === 'mouseup' || e.type === 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
if (options.onClick) {
|
||||
options.onClick.call(me, e, me.active);
|
||||
}
|
||||
|
||||
if (this.legend && this.legend.handleEvent) {
|
||||
this.legend.handleEvent(e);
|
||||
if (me.legend && me.legend.handleEvent) {
|
||||
me.legend.handleEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
this.getDatasetMeta(this.lastActive[0]._datasetIndex).controller.removeHoverStyle(this.lastActive[0], this.lastActive[0]._datasetIndex, this.lastActive[0]._index);
|
||||
break;
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
if (this.lastActive[i])
|
||||
this.getDatasetMeta(this.lastActive[i]._datasetIndex).controller.removeHoverStyle(this.lastActive[i], this.lastActive[i]._datasetIndex, this.lastActive[i]._index);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
if (me.lastActive.length) {
|
||||
me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
this.getDatasetMeta(this.active[0]._datasetIndex).controller.setHoverStyle(this.active[0]);
|
||||
break;
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var j = 0; j < this.active.length; j++) {
|
||||
if (this.active[j])
|
||||
this.getDatasetMeta(this.active[j]._datasetIndex).controller.setHoverStyle(this.active[j]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
if (me.active.length && hoverOptions.mode) {
|
||||
me.updateHoverStyle(me.active, hoverOptions.mode, true);
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled || this.options.tooltips.custom) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
this.tooltip._active = this.tooltipActive;
|
||||
this.tooltip.update();
|
||||
if (tooltipsOptions.enabled || tooltipsOptions.custom) {
|
||||
tooltip.initialize();
|
||||
tooltip._active = me.tooltipActive;
|
||||
tooltip.update(true);
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
helpers.each(this.tooltipActive, function(element, index) {
|
||||
if (element !== this.lastTooltipActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
tooltip.pivot();
|
||||
|
||||
if (!me.animating) {
|
||||
// If entering, leaving, or changing elements, animate the change via pivot
|
||||
if ((this.lastActive.length !== this.active.length) ||
|
||||
(this.lastTooltipActive.length !== this.tooltipActive.length) ||
|
||||
changed) {
|
||||
if (!helpers.arrayEquals(me.active, me.lastActive) ||
|
||||
!helpers.arrayEquals(me.tooltipActive, me.lastTooltipActive)) {
|
||||
|
||||
this.stop();
|
||||
me.stop();
|
||||
|
||||
if (this.options.tooltips.enabled || this.options.tooltips.custom) {
|
||||
this.tooltip.update(true);
|
||||
if (tooltipsOptions.enabled || tooltipsOptions.custom) {
|
||||
tooltip.update(true);
|
||||
}
|
||||
|
||||
// We only need to render at this point. Updating will cause scales to be recomputed generating flicker & using more
|
||||
// memory than necessary.
|
||||
this.render(this.options.hover.animationDuration, true);
|
||||
// We only need to render at this point. Updating will cause scales to be
|
||||
// recomputed generating flicker & using more memory than necessary.
|
||||
me.render(hoverOptions.animationDuration, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Actives
|
||||
this.lastActive = this.active;
|
||||
this.lastTooltipActive = this.tooltipActive;
|
||||
return this;
|
||||
me.lastActive = me.active;
|
||||
me.lastTooltipActive = me.tooltipActive;
|
||||
return me;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
107
vendors/Chart.js/src/core/core.datasetController.js
vendored
@ -3,6 +3,7 @@
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var noop = helpers.noop;
|
||||
|
||||
// Base class for all dataset controllers (line, bar, etc)
|
||||
Chart.DatasetController = function(chart, datasetIndex) {
|
||||
@ -10,12 +11,26 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
helpers.extend(Chart.DatasetController.prototype, {
|
||||
|
||||
/**
|
||||
* Element type used to generate a meta dataset (e.g. Chart.element.Line).
|
||||
* @type {Chart.core.element}
|
||||
*/
|
||||
datasetElementType: null,
|
||||
|
||||
/**
|
||||
* Element type used to generate a meta data (e.g. Chart.element.Point).
|
||||
* @type {Chart.core.element}
|
||||
*/
|
||||
dataElementType: null,
|
||||
|
||||
initialize: function(chart, datasetIndex) {
|
||||
this.chart = chart;
|
||||
this.index = datasetIndex;
|
||||
this.linkScales();
|
||||
this.addElements();
|
||||
},
|
||||
|
||||
updateIndex: function(datasetIndex) {
|
||||
this.index = datasetIndex;
|
||||
},
|
||||
@ -48,16 +63,57 @@ module.exports = function(Chart) {
|
||||
this.update(true);
|
||||
},
|
||||
|
||||
createMetaDataset: function() {
|
||||
var me = this;
|
||||
var type = me.datasetElementType;
|
||||
return type && new type({
|
||||
_chart: me.chart.chart,
|
||||
_datasetIndex: me.index
|
||||
});
|
||||
},
|
||||
|
||||
createMetaData: function(index) {
|
||||
var me = this;
|
||||
var type = me.dataElementType;
|
||||
return type && new type({
|
||||
_chart: me.chart.chart,
|
||||
_datasetIndex: me.index,
|
||||
_index: index
|
||||
});
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var data = me.getDataset().data || [];
|
||||
var metaData = meta.data;
|
||||
var i, ilen;
|
||||
|
||||
for (i=0, ilen=data.length; i<ilen; ++i) {
|
||||
metaData[i] = metaData[i] || me.createMetaData(meta, i);
|
||||
}
|
||||
|
||||
meta.dataset = meta.dataset || me.createMetaDataset();
|
||||
},
|
||||
|
||||
addElementAndReset: function(index) {
|
||||
var me = this;
|
||||
var element = me.createMetaData(index);
|
||||
me.getMeta().data.splice(index, 0, element);
|
||||
me.updateElement(element, index, true);
|
||||
},
|
||||
|
||||
buildOrUpdateElements: function buildOrUpdateElements() {
|
||||
// Handle the number of data points changing
|
||||
var meta = this.getMeta();
|
||||
var numData = this.getDataset().data.length;
|
||||
var numMetaData = meta.data.length;
|
||||
var meta = this.getMeta(),
|
||||
md = meta.data,
|
||||
numData = this.getDataset().data.length,
|
||||
numMetaData = md.length;
|
||||
|
||||
// Make sure that we handle number of datapoints changing
|
||||
if (numData < numMetaData) {
|
||||
// Remove excess bars for data points that have been removed
|
||||
meta.data.splice(numData, numMetaData - numData);
|
||||
md.splice(numData, numMetaData - numData);
|
||||
} else if (numData > numMetaData) {
|
||||
// Add new elements
|
||||
for (var index = numMetaData; index < numData; ++index) {
|
||||
@ -66,15 +122,42 @@ module.exports = function(Chart) {
|
||||
}
|
||||
},
|
||||
|
||||
// Controllers should implement the following
|
||||
addElements: helpers.noop,
|
||||
addElementAndReset: helpers.noop,
|
||||
draw: helpers.noop,
|
||||
removeHoverStyle: helpers.noop,
|
||||
setHoverStyle: helpers.noop,
|
||||
update: helpers.noop
|
||||
update: noop,
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getMeta().data, function(element, index) {
|
||||
element.transition(easingDecimal).draw();
|
||||
});
|
||||
},
|
||||
|
||||
removeHoverStyle: function(element, elementOpts) {
|
||||
var dataset = this.chart.data.datasets[element._datasetIndex],
|
||||
index = element._index,
|
||||
custom = element.custom || {},
|
||||
valueOrDefault = helpers.getValueAtIndexOrDefault,
|
||||
color = helpers.color,
|
||||
model = element._model;
|
||||
|
||||
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
|
||||
model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
|
||||
model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
|
||||
},
|
||||
|
||||
setHoverStyle: function(element) {
|
||||
var dataset = this.chart.data.datasets[element._datasetIndex],
|
||||
index = element._index,
|
||||
custom = element.custom || {},
|
||||
valueOrDefault = helpers.getValueAtIndexOrDefault,
|
||||
color = helpers.color,
|
||||
getHoverColor = helpers.getHoverColor,
|
||||
model = element._model;
|
||||
|
||||
model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));
|
||||
model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
|
||||
model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.DatasetController.extend = helpers.inherits;
|
||||
|
||||
};
|
4
vendors/Chart.js/src/core/core.element.js
vendored
@ -39,7 +39,7 @@ module.exports = function(Chart) {
|
||||
|
||||
helpers.each(this._model, function(value, key) {
|
||||
|
||||
if (key[0] === '_' || !this._model.hasOwnProperty(key)) {
|
||||
if (key[0] === '_') {
|
||||
// Only non-underscored properties
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ module.exports = function(Chart) {
|
||||
// Color transitions if possible
|
||||
else if (typeof value === 'string') {
|
||||
try {
|
||||
var color = helpers.color(this._start[key]).mix(helpers.color(this._model[key]), ease);
|
||||
var color = helpers.color(this._model[key]).mix(helpers.color(this._start[key]), ease);
|
||||
this._view[key] = color.rgbString();
|
||||
} catch (err) {
|
||||
this._view[key] = value;
|
||||
|
297
vendors/Chart.js/src/core/core.helpers.js
vendored
@ -5,7 +5,6 @@
|
||||
var color = require('chartjs-color');
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
//Global Chart helpers object for utility methods and classes
|
||||
var helpers = Chart.helpers = {};
|
||||
|
||||
@ -35,14 +34,12 @@ module.exports = function(Chart) {
|
||||
helpers.clone = function(obj) {
|
||||
var objClone = {};
|
||||
helpers.each(obj, function(value, key) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (helpers.isArray(value)) {
|
||||
objClone[key] = value.slice(0);
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
objClone[key] = helpers.clone(value);
|
||||
} else {
|
||||
objClone[key] = value;
|
||||
}
|
||||
if (helpers.isArray(value)) {
|
||||
objClone[key] = value.slice(0);
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
objClone[key] = helpers.clone(value);
|
||||
} else {
|
||||
objClone[key] = value;
|
||||
}
|
||||
});
|
||||
return objClone;
|
||||
@ -55,9 +52,7 @@ module.exports = function(Chart) {
|
||||
}
|
||||
helpers.each(additionalArgs, function(extensionObject) {
|
||||
helpers.each(extensionObject, function(value, key) {
|
||||
if (extensionObject.hasOwnProperty(key)) {
|
||||
base[key] = value;
|
||||
}
|
||||
base[key] = value;
|
||||
});
|
||||
});
|
||||
return base;
|
||||
@ -67,42 +62,40 @@ module.exports = function(Chart) {
|
||||
var base = helpers.clone(_base);
|
||||
helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {
|
||||
helpers.each(extension, function(value, key) {
|
||||
if (extension.hasOwnProperty(key)) {
|
||||
if (key === 'scales') {
|
||||
// Scale config merging is complex. Add out own function here for that
|
||||
base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);
|
||||
if (key === 'scales') {
|
||||
// Scale config merging is complex. Add out own function here for that
|
||||
base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);
|
||||
|
||||
} else if (key === 'scale') {
|
||||
// Used in polar area & radar charts since there is only one scale
|
||||
base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
|
||||
} else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
|
||||
// In this case we have an array of objects replacing another array. Rather than doing a strict replace,
|
||||
// merge. This allows easy scale option merging
|
||||
var baseArray = base[key];
|
||||
} else if (key === 'scale') {
|
||||
// Used in polar area & radar charts since there is only one scale
|
||||
base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
|
||||
} else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
|
||||
// In this case we have an array of objects replacing another array. Rather than doing a strict replace,
|
||||
// merge. This allows easy scale option merging
|
||||
var baseArray = base[key];
|
||||
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
|
||||
if (index < baseArray.length) {
|
||||
if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {
|
||||
// Two objects are coming together. Do a merge of them.
|
||||
baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
|
||||
} else {
|
||||
// Just overwrite in this case since there is nothing to merge
|
||||
baseArray[index] = valueObj;
|
||||
}
|
||||
if (index < baseArray.length) {
|
||||
if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {
|
||||
// Two objects are coming together. Do a merge of them.
|
||||
baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
|
||||
} else {
|
||||
baseArray.push(valueObj); // nothing to merge
|
||||
// Just overwrite in this case since there is nothing to merge
|
||||
baseArray[index] = valueObj;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
baseArray.push(valueObj); // nothing to merge
|
||||
}
|
||||
});
|
||||
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
}
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -131,38 +124,36 @@ module.exports = function(Chart) {
|
||||
var base = helpers.clone(_base);
|
||||
|
||||
helpers.each(extension, function(value, key) {
|
||||
if (extension.hasOwnProperty(key)) {
|
||||
if (key === 'xAxes' || key === 'yAxes') {
|
||||
// These properties are arrays of items
|
||||
if (base.hasOwnProperty(key)) {
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);
|
||||
if (index >= base[key].length || !base[key][index].type) {
|
||||
base[key].push(helpers.configMerge(axisDefaults, valueObj));
|
||||
} else if (valueObj.type && valueObj.type !== base[key][index].type) {
|
||||
// Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults
|
||||
base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);
|
||||
} else {
|
||||
// Type is the same
|
||||
base[key][index] = helpers.configMerge(base[key][index], valueObj);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
base[key] = [];
|
||||
helpers.each(value, function(valueObj) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));
|
||||
});
|
||||
}
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
|
||||
if (key === 'xAxes' || key === 'yAxes') {
|
||||
// These properties are arrays of items
|
||||
if (base.hasOwnProperty(key)) {
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);
|
||||
if (index >= base[key].length || !base[key][index].type) {
|
||||
base[key].push(helpers.configMerge(axisDefaults, valueObj));
|
||||
} else if (valueObj.type && valueObj.type !== base[key][index].type) {
|
||||
// Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults
|
||||
base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);
|
||||
} else {
|
||||
// Type is the same
|
||||
base[key][index] = helpers.configMerge(base[key][index], valueObj);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
base[key] = [];
|
||||
helpers.each(value, function(valueObj) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));
|
||||
});
|
||||
}
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
@ -194,15 +185,19 @@ module.exports = function(Chart) {
|
||||
}
|
||||
};
|
||||
helpers.where = function(collection, filterCallback) {
|
||||
var filtered = [];
|
||||
if (helpers.isArray(collection) && Array.prototype.filter) {
|
||||
return collection.filter(filterCallback);
|
||||
} else {
|
||||
var filtered = [];
|
||||
|
||||
helpers.each(collection, function(item) {
|
||||
if (filterCallback(item)) {
|
||||
filtered.push(item);
|
||||
}
|
||||
});
|
||||
helpers.each(collection, function(item) {
|
||||
if (filterCallback(item)) {
|
||||
filtered.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return filtered;
|
||||
return filtered;
|
||||
}
|
||||
};
|
||||
helpers.findIndex = function(arrayToSearch, callback, thisArg) {
|
||||
var index = -1;
|
||||
@ -653,9 +648,10 @@ module.exports = function(Chart) {
|
||||
canvas = evt.currentTarget || evt.srcElement,
|
||||
boundingRect = canvas.getBoundingClientRect();
|
||||
|
||||
if (e.touches && e.touches.length > 0) {
|
||||
mouseX = e.touches[0].clientX;
|
||||
mouseY = e.touches[0].clientY;
|
||||
var touches = e.touches;
|
||||
if (touches && touches.length > 0) {
|
||||
mouseX = touches[0].clientX;
|
||||
mouseY = touches[0].clientY;
|
||||
|
||||
} else {
|
||||
mouseX = e.clientX;
|
||||
@ -703,19 +699,19 @@ module.exports = function(Chart) {
|
||||
};
|
||||
helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {
|
||||
// Create the events object if it's not already present
|
||||
if (!chartInstance.events)
|
||||
chartInstance.events = {};
|
||||
var events = chartInstance.events = chartInstance.events || {};
|
||||
|
||||
helpers.each(arrayOfEvents, function(eventName) {
|
||||
chartInstance.events[eventName] = function() {
|
||||
events[eventName] = function() {
|
||||
handler.apply(chartInstance, arguments);
|
||||
};
|
||||
helpers.addEvent(chartInstance.chart.canvas, eventName, chartInstance.events[eventName]);
|
||||
helpers.addEvent(chartInstance.chart.canvas, eventName, events[eventName]);
|
||||
});
|
||||
};
|
||||
helpers.unbindEvents = function(chartInstance, arrayOfEvents) {
|
||||
var canvas = chartInstance.chart.canvas;
|
||||
helpers.each(arrayOfEvents, function(handler, eventName) {
|
||||
helpers.removeEvent(chartInstance.chart.canvas, eventName, handler);
|
||||
helpers.removeEvent(canvas, eventName, handler);
|
||||
});
|
||||
};
|
||||
|
||||
@ -736,21 +732,35 @@ module.exports = function(Chart) {
|
||||
return valueInPixels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given value contains an effective constraint.
|
||||
* @private
|
||||
*/
|
||||
function isConstrainedValue(value) {
|
||||
return value !== undefined && value !== null && value !== 'none';
|
||||
}
|
||||
|
||||
// Private helper to get a constraint dimension
|
||||
// @param domNode : the node to check the constraint on
|
||||
// @param maxStyle : the style that defines the maximum for the direction we are using (max-width / max-height)
|
||||
// @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)
|
||||
// @param percentageProperty : property of parent to use when calculating width as a percentage
|
||||
// @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser
|
||||
function getConstraintDimension(domNode, maxStyle, percentageProperty) {
|
||||
var constrainedDimension;
|
||||
var constrainedNode = document.defaultView.getComputedStyle(domNode)[maxStyle];
|
||||
var constrainedContainer = document.defaultView.getComputedStyle(domNode.parentNode)[maxStyle];
|
||||
var hasCNode = constrainedNode !== null && constrainedNode !== "none";
|
||||
var hasCContainer = constrainedContainer !== null && constrainedContainer !== "none";
|
||||
var view = document.defaultView;
|
||||
var parentNode = domNode.parentNode;
|
||||
var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
|
||||
var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
|
||||
var hasCNode = isConstrainedValue(constrainedNode);
|
||||
var hasCContainer = isConstrainedValue(constrainedContainer);
|
||||
var infinity = Number.POSITIVE_INFINITY;
|
||||
|
||||
if (hasCNode || hasCContainer) {
|
||||
constrainedDimension = Math.min((hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : Number.POSITIVE_INFINITY), (hasCContainer ? parseMaxStyle(constrainedContainer, domNode.parentNode, percentageProperty) : Number.POSITIVE_INFINITY));
|
||||
return Math.min(
|
||||
hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
|
||||
hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
|
||||
}
|
||||
return constrainedDimension;
|
||||
|
||||
return 'none';
|
||||
}
|
||||
// returns Number or undefined if no constraint
|
||||
helpers.getConstraintWidth = function(domNode) {
|
||||
@ -763,26 +773,16 @@ module.exports = function(Chart) {
|
||||
helpers.getMaximumWidth = function(domNode) {
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));
|
||||
|
||||
var w = container.clientWidth - padding;
|
||||
var cw = helpers.getConstraintWidth(domNode);
|
||||
if (cw !== undefined) {
|
||||
w = Math.min(w, cw);
|
||||
}
|
||||
|
||||
return w;
|
||||
return isNaN(cw)? w : Math.min(w, cw);
|
||||
};
|
||||
helpers.getMaximumHeight = function(domNode) {
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));
|
||||
|
||||
var h = container.clientHeight - padding;
|
||||
var ch = helpers.getConstraintHeight(domNode);
|
||||
if (ch !== undefined) {
|
||||
h = Math.min(h, ch);
|
||||
}
|
||||
|
||||
return h;
|
||||
return isNaN(ch)? h : Math.min(h, ch);
|
||||
};
|
||||
helpers.getStyle = function(el, property) {
|
||||
return el.currentStyle ?
|
||||
@ -791,13 +791,14 @@ module.exports = function(Chart) {
|
||||
};
|
||||
helpers.retinaScale = function(chart) {
|
||||
var ctx = chart.ctx;
|
||||
var width = chart.canvas.width;
|
||||
var height = chart.canvas.height;
|
||||
var canvas = chart.canvas;
|
||||
var width = canvas.width;
|
||||
var height = canvas.height;
|
||||
var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
if (pixelRatio !== 1) {
|
||||
ctx.canvas.height = height * pixelRatio;
|
||||
ctx.canvas.width = width * pixelRatio;
|
||||
canvas.height = height * pixelRatio;
|
||||
canvas.width = width * pixelRatio;
|
||||
ctx.scale(pixelRatio, pixelRatio);
|
||||
|
||||
// Store the device pixel ratio so that we can go backwards in `destroy`.
|
||||
@ -806,8 +807,8 @@ module.exports = function(Chart) {
|
||||
chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
|
||||
}
|
||||
|
||||
ctx.canvas.style.width = width + 'px';
|
||||
ctx.canvas.style.height = height + 'px';
|
||||
canvas.style.width = width + 'px';
|
||||
canvas.style.height = height + 'px';
|
||||
};
|
||||
//-- Canvas methods
|
||||
helpers.clear = function(chart) {
|
||||
@ -818,12 +819,12 @@ module.exports = function(Chart) {
|
||||
};
|
||||
helpers.longestText = function(ctx, font, arrayOfStrings, cache) {
|
||||
cache = cache || {};
|
||||
cache.data = cache.data || {};
|
||||
cache.garbageCollect = cache.garbageCollect || [];
|
||||
var data = cache.data = cache.data || {};
|
||||
var gc = cache.garbageCollect = cache.garbageCollect || [];
|
||||
|
||||
if (cache.font !== font) {
|
||||
cache.data = {};
|
||||
cache.garbageCollect = [];
|
||||
data = cache.data = {};
|
||||
gc = cache.garbageCollect = [];
|
||||
cache.font = font;
|
||||
}
|
||||
|
||||
@ -832,10 +833,10 @@ module.exports = function(Chart) {
|
||||
helpers.each(arrayOfStrings, function(string) {
|
||||
// Undefined strings should not be measured
|
||||
if (string !== undefined && string !== null) {
|
||||
var textWidth = cache.data[string];
|
||||
var textWidth = data[string];
|
||||
if (!textWidth) {
|
||||
textWidth = cache.data[string] = ctx.measureText(string).width;
|
||||
cache.garbageCollect.push(string);
|
||||
textWidth = data[string] = ctx.measureText(string).width;
|
||||
gc.push(string);
|
||||
}
|
||||
|
||||
if (textWidth > longest) {
|
||||
@ -844,12 +845,12 @@ module.exports = function(Chart) {
|
||||
}
|
||||
});
|
||||
|
||||
var gcLen = cache.garbageCollect.length / 2;
|
||||
var gcLen = gc.length / 2;
|
||||
if (gcLen > arrayOfStrings.length) {
|
||||
for (var i = 0; i < gcLen; i++) {
|
||||
delete cache.data[cache.garbageCollect[i]];
|
||||
delete data[gc[i]];
|
||||
}
|
||||
cache.garbageCollect.splice(0, gcLen);
|
||||
gc.splice(0, gcLen);
|
||||
}
|
||||
|
||||
return longest;
|
||||
@ -893,16 +894,17 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
// Set the style
|
||||
hiddenIframe.style.width = '100%';
|
||||
hiddenIframe.style.display = 'block';
|
||||
hiddenIframe.style.border = 0;
|
||||
hiddenIframe.style.height = 0;
|
||||
hiddenIframe.style.margin = 0;
|
||||
hiddenIframe.style.position = 'absolute';
|
||||
hiddenIframe.style.left = 0;
|
||||
hiddenIframe.style.right = 0;
|
||||
hiddenIframe.style.top = 0;
|
||||
hiddenIframe.style.bottom = 0;
|
||||
var style = hiddenIframe.style;
|
||||
style.width = '100%';
|
||||
style.display = 'block';
|
||||
style.border = 0;
|
||||
style.height = 0;
|
||||
style.margin = 0;
|
||||
style.position = 'absolute';
|
||||
style.left = 0;
|
||||
style.right = 0;
|
||||
style.top = 0;
|
||||
style.bottom = 0;
|
||||
|
||||
// Insert the iframe so that contentWindow is available
|
||||
node.insertBefore(hiddenIframe, node.firstChild);
|
||||
@ -927,6 +929,30 @@ module.exports = function(Chart) {
|
||||
}
|
||||
return Array.isArray(obj);
|
||||
};
|
||||
//! @see http://stackoverflow.com/a/14853974
|
||||
helpers.arrayEquals = function(a0, a1) {
|
||||
var i, ilen, v0, v1;
|
||||
|
||||
if (!a0 || !a1 || a0.length != a1.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0, ilen=a0.length; i < ilen; ++i) {
|
||||
v0 = a0[i];
|
||||
v1 = a1[i];
|
||||
|
||||
if (v0 instanceof Array && v1 instanceof Array) {
|
||||
if (!helpers.arrayEquals(v0, v1)) {
|
||||
return false;
|
||||
}
|
||||
} else if (v0 != v1) {
|
||||
// NOTE: two different object instances will never be equal: {x:20} != {x:20}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
helpers.pushAllIfDefined = function(element, array) {
|
||||
if (typeof element === "undefined") {
|
||||
return;
|
||||
@ -943,5 +969,10 @@ module.exports = function(Chart) {
|
||||
fn.apply(_tArg, args);
|
||||
}
|
||||
};
|
||||
|
||||
helpers.getHoverColor = function(color) {
|
||||
/* global CanvasPattern */
|
||||
return (color instanceof CanvasPattern) ?
|
||||
color :
|
||||
helpers.color(color).saturate(0.5).darken(0.1).rgbString();
|
||||
};
|
||||
};
|
||||
|
184
vendors/Chart.js/src/core/core.legend.js
vendored
@ -3,6 +3,7 @@
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var noop = helpers.noop;
|
||||
|
||||
Chart.defaults.global.legend = {
|
||||
|
||||
@ -14,13 +15,14 @@ module.exports = function(Chart) {
|
||||
// a callback that will handle
|
||||
onClick: function(e, legendItem) {
|
||||
var index = legendItem.datasetIndex;
|
||||
var meta = this.chart.getDatasetMeta(index);
|
||||
var ci = this.chart;
|
||||
var meta = ci.getDatasetMeta(index);
|
||||
|
||||
// See controller.isDatasetVisible comment
|
||||
meta.hidden = meta.hidden === null? !this.chart.data.datasets[index].hidden : null;
|
||||
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
|
||||
|
||||
// We hid a dataset ... rerender the chart
|
||||
this.chart.update();
|
||||
ci.update();
|
||||
},
|
||||
|
||||
labels: {
|
||||
@ -75,7 +77,7 @@ module.exports = function(Chart) {
|
||||
// Any function defined here is inherited by all legend types.
|
||||
// Any function can be extended by the legend type
|
||||
|
||||
beforeUpdate: helpers.noop,
|
||||
beforeUpdate: noop,
|
||||
update: function(maxWidth, maxHeight, margins) {
|
||||
|
||||
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
|
||||
@ -104,11 +106,11 @@ module.exports = function(Chart) {
|
||||
|
||||
return this.minSize;
|
||||
},
|
||||
afterUpdate: helpers.noop,
|
||||
afterUpdate: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeSetDimensions: helpers.noop,
|
||||
beforeSetDimensions: noop,
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
if (this.isHorizontal()) {
|
||||
@ -136,90 +138,92 @@ module.exports = function(Chart) {
|
||||
height: 0
|
||||
};
|
||||
},
|
||||
afterSetDimensions: helpers.noop,
|
||||
afterSetDimensions: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeBuildLabels: helpers.noop,
|
||||
beforeBuildLabels: noop,
|
||||
buildLabels: function() {
|
||||
this.legendItems = this.options.labels.generateLabels.call(this, this.chart);
|
||||
if(this.options.reverse){
|
||||
this.legendItems.reverse();
|
||||
}
|
||||
},
|
||||
afterBuildLabels: helpers.noop,
|
||||
afterBuildLabels: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeFit: helpers.noop,
|
||||
beforeFit: noop,
|
||||
fit: function() {
|
||||
var opts = this.options;
|
||||
var labelOpts = opts.labels;
|
||||
var display = opts.display;
|
||||
|
||||
var ctx = this.ctx;
|
||||
var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
var globalDefault = Chart.defaults.global,
|
||||
itemOrDefault = helpers.getValueOrDefault,
|
||||
fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
|
||||
fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
|
||||
fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
|
||||
labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
// Reset hit boxes
|
||||
this.legendHitBoxes = [];
|
||||
var hitboxes = this.legendHitBoxes = [];
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.width = this.maxWidth; // fill all the width
|
||||
} else {
|
||||
this.minSize.width = this.options.display ? 10 : 0;
|
||||
}
|
||||
var minSize = this.minSize;
|
||||
var isHorizontal = this.isHorizontal();
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = this.options.display ? 10 : 0;
|
||||
if (isHorizontal) {
|
||||
minSize.width = this.maxWidth; // fill all the width
|
||||
minSize.height = display ? 10 : 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
minSize.width = display ? 10 : 0;
|
||||
minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Increase sizes here
|
||||
if (this.options.display) {
|
||||
if (this.isHorizontal()) {
|
||||
if (display) {
|
||||
if (isHorizontal) {
|
||||
// Labels
|
||||
|
||||
// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
|
||||
this.lineWidths = [0];
|
||||
var totalHeight = this.legendItems.length ? fontSize + (this.options.labels.padding) : 0;
|
||||
var lineWidths = this.lineWidths = [0];
|
||||
var totalHeight = this.legendItems.length ? fontSize + (labelOpts.padding) : 0;
|
||||
|
||||
ctx.textAlign = "left";
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = labelFont;
|
||||
|
||||
helpers.each(this.legendItems, function(legendItem, i) {
|
||||
var width = this.options.labels.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
|
||||
if (this.lineWidths[this.lineWidths.length - 1] + width + this.options.labels.padding >= this.width) {
|
||||
totalHeight += fontSize + (this.options.labels.padding);
|
||||
this.lineWidths[this.lineWidths.length] = this.left;
|
||||
var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
|
||||
if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= this.width) {
|
||||
totalHeight += fontSize + (labelOpts.padding);
|
||||
lineWidths[lineWidths.length] = this.left;
|
||||
}
|
||||
|
||||
// Store the hitbox width and height here. Final position will be updated in `draw`
|
||||
this.legendHitBoxes[i] = {
|
||||
hitboxes[i] = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: width,
|
||||
height: fontSize
|
||||
};
|
||||
|
||||
this.lineWidths[this.lineWidths.length - 1] += width + this.options.labels.padding;
|
||||
lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
|
||||
}, this);
|
||||
|
||||
this.minSize.height += totalHeight;
|
||||
minSize.height += totalHeight;
|
||||
|
||||
} else {
|
||||
// TODO vertical
|
||||
}
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
|
||||
this.width = minSize.width;
|
||||
this.height = minSize.height;
|
||||
},
|
||||
afterFit: helpers.noop,
|
||||
afterFit: noop,
|
||||
|
||||
// Shared Methods
|
||||
isHorizontal: function() {
|
||||
@ -228,19 +232,26 @@ module.exports = function(Chart) {
|
||||
|
||||
// Actualy draw the legend on the canvas
|
||||
draw: function() {
|
||||
if (this.options.display) {
|
||||
var ctx = this.ctx;
|
||||
var cursor = {
|
||||
x: this.left + ((this.width - this.lineWidths[0]) / 2),
|
||||
y: this.top + this.options.labels.padding,
|
||||
line: 0
|
||||
};
|
||||
var opts = this.options;
|
||||
var labelOpts = opts.labels;
|
||||
var globalDefault = Chart.defaults.global,
|
||||
lineDefault = globalDefault.elements.line,
|
||||
legendWidth = this.width,
|
||||
lineWidths = this.lineWidths;
|
||||
|
||||
var fontColor = helpers.getValueOrDefault(this.options.labels.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
if (opts.display) {
|
||||
var ctx = this.ctx,
|
||||
cursor = {
|
||||
x: this.left + ((legendWidth - lineWidths[0]) / 2),
|
||||
y: this.top + labelOpts.padding,
|
||||
line: 0
|
||||
},
|
||||
itemOrDefault = helpers.getValueOrDefault,
|
||||
fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),
|
||||
fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
|
||||
fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
|
||||
fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
|
||||
labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
// Horizontal
|
||||
if (this.isHorizontal()) {
|
||||
@ -252,57 +263,58 @@ module.exports = function(Chart) {
|
||||
ctx.fillStyle = fontColor; // render in correct colour
|
||||
ctx.font = labelFont;
|
||||
|
||||
helpers.each(this.legendItems, function(legendItem, i) {
|
||||
var textWidth = ctx.measureText(legendItem.text).width;
|
||||
var width = this.options.labels.boxWidth + (fontSize / 2) + textWidth;
|
||||
var boxWidth = labelOpts.boxWidth,
|
||||
hitboxes = this.legendHitBoxes;
|
||||
|
||||
if (cursor.x + width >= this.width) {
|
||||
cursor.y += fontSize + (this.options.labels.padding);
|
||||
helpers.each(this.legendItems, function(legendItem, i) {
|
||||
var textWidth = ctx.measureText(legendItem.text).width,
|
||||
width = boxWidth + (fontSize / 2) + textWidth,
|
||||
x = cursor.x,
|
||||
y = cursor.y;
|
||||
|
||||
if (x + width >= legendWidth) {
|
||||
y = cursor.y += fontSize + (labelOpts.padding);
|
||||
cursor.line++;
|
||||
cursor.x = this.left + ((this.width - this.lineWidths[cursor.line]) / 2);
|
||||
x = cursor.x = this.left + ((legendWidth - lineWidths[cursor.line]) / 2);
|
||||
}
|
||||
|
||||
// Set the ctx for the box
|
||||
ctx.save();
|
||||
|
||||
var itemOrDefault = function(item, defaulVal) {
|
||||
return item !== undefined ? item : defaulVal;
|
||||
};
|
||||
|
||||
ctx.fillStyle = itemOrDefault(legendItem.fillStyle, Chart.defaults.global.defaultColor);
|
||||
ctx.lineCap = itemOrDefault(legendItem.lineCap, Chart.defaults.global.elements.line.borderCapStyle);
|
||||
ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, Chart.defaults.global.elements.line.borderDashOffset);
|
||||
ctx.lineJoin = itemOrDefault(legendItem.lineJoin, Chart.defaults.global.elements.line.borderJoinStyle);
|
||||
ctx.lineWidth = itemOrDefault(legendItem.lineWidth, Chart.defaults.global.elements.line.borderWidth);
|
||||
ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, Chart.defaults.global.defaultColor);
|
||||
ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
|
||||
ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
|
||||
ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
|
||||
ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
|
||||
ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
|
||||
ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
|
||||
|
||||
if (ctx.setLineDash) {
|
||||
// IE 9 and 10 do not support line dash
|
||||
ctx.setLineDash(itemOrDefault(legendItem.lineDash, Chart.defaults.global.elements.line.borderDash));
|
||||
ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));
|
||||
}
|
||||
|
||||
// Draw the box
|
||||
ctx.strokeRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
|
||||
ctx.fillRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
|
||||
ctx.strokeRect(x, y, boxWidth, fontSize);
|
||||
ctx.fillRect(x, y, boxWidth, fontSize);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
this.legendHitBoxes[i].left = cursor.x;
|
||||
this.legendHitBoxes[i].top = cursor.y;
|
||||
hitboxes[i].left = x;
|
||||
hitboxes[i].top = y;
|
||||
|
||||
// Fill the actual label
|
||||
ctx.fillText(legendItem.text, this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y);
|
||||
ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);
|
||||
|
||||
if (legendItem.hidden) {
|
||||
// Strikethrough the text if hidden
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 2;
|
||||
ctx.moveTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y + (fontSize / 2));
|
||||
ctx.lineTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x + textWidth, cursor.y + (fontSize / 2));
|
||||
ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));
|
||||
ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
cursor.x += width + (this.options.labels.padding);
|
||||
cursor.x += width + (labelOpts.padding);
|
||||
}, this);
|
||||
} else {
|
||||
|
||||
@ -312,17 +324,21 @@ module.exports = function(Chart) {
|
||||
|
||||
// Handle an event
|
||||
handleEvent: function(e) {
|
||||
var position = helpers.getRelativePosition(e, this.chart.chart);
|
||||
var position = helpers.getRelativePosition(e, this.chart.chart),
|
||||
x = position.x,
|
||||
y = position.y,
|
||||
opts = this.options;
|
||||
|
||||
if (position.x >= this.left && position.x <= this.right && position.y >= this.top && position.y <= this.bottom) {
|
||||
if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {
|
||||
// See if we are touching one of the dataset boxes
|
||||
for (var i = 0; i < this.legendHitBoxes.length; ++i) {
|
||||
var hitBox = this.legendHitBoxes[i];
|
||||
var lh = this.legendHitBoxes;
|
||||
for (var i = 0; i < lh.length; ++i) {
|
||||
var hitBox = lh[i];
|
||||
|
||||
if (position.x >= hitBox.left && position.x <= hitBox.left + hitBox.width && position.y >= hitBox.top && position.y <= hitBox.top + hitBox.height) {
|
||||
if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
|
||||
// Touching an element
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.legendItems[i]);
|
||||
if (opts.onClick) {
|
||||
opts.onClick.call(this, e, this.legendItems[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
25
vendors/Chart.js/src/core/core.plugin.js
vendored
@ -8,16 +8,18 @@ module.exports = function(Chart) {
|
||||
Chart.pluginService = {
|
||||
// Register a new plugin
|
||||
register: function(plugin) {
|
||||
if (Chart.plugins.indexOf(plugin) === -1) {
|
||||
Chart.plugins.push(plugin);
|
||||
var p = Chart.plugins;
|
||||
if (p.indexOf(plugin) === -1) {
|
||||
p.push(plugin);
|
||||
}
|
||||
},
|
||||
|
||||
// Remove a registered plugin
|
||||
remove: function(plugin) {
|
||||
var idx = Chart.plugins.indexOf(plugin);
|
||||
var p = Chart.plugins;
|
||||
var idx = p.indexOf(plugin);
|
||||
if (idx !== -1) {
|
||||
Chart.plugins.splice(idx, 1);
|
||||
p.splice(idx, 1);
|
||||
}
|
||||
},
|
||||
|
||||
@ -31,28 +33,29 @@ module.exports = function(Chart) {
|
||||
}
|
||||
};
|
||||
|
||||
var noop = helpers.noop;
|
||||
Chart.PluginBase = Chart.Element.extend({
|
||||
// Plugin methods. All functions are passed the chart instance
|
||||
|
||||
// Called at start of chart init
|
||||
beforeInit: helpers.noop,
|
||||
beforeInit: noop,
|
||||
|
||||
// Called at end of chart init
|
||||
afterInit: helpers.noop,
|
||||
afterInit: noop,
|
||||
|
||||
// Called at start of update
|
||||
beforeUpdate: helpers.noop,
|
||||
beforeUpdate: noop,
|
||||
|
||||
// Called at end of update
|
||||
afterUpdate: helpers.noop,
|
||||
afterUpdate: noop,
|
||||
|
||||
// Called at start of draw
|
||||
beforeDraw: helpers.noop,
|
||||
beforeDraw: noop,
|
||||
|
||||
// Called at end of draw
|
||||
afterDraw: helpers.noop,
|
||||
afterDraw: noop,
|
||||
|
||||
// Called during destroy
|
||||
destroy: helpers.noop,
|
||||
destroy: noop
|
||||
});
|
||||
};
|
||||
|
584
vendors/Chart.js/src/core/core.scale.js
vendored
@ -13,6 +13,7 @@ module.exports = function(Chart) {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1,
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
tickMarkLength: 10,
|
||||
@ -33,6 +34,7 @@ module.exports = function(Chart) {
|
||||
// label settings
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -40,6 +42,7 @@ module.exports = function(Chart) {
|
||||
display: true,
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0,
|
||||
callback: function(value) {
|
||||
return '' + value;
|
||||
}
|
||||
@ -178,19 +181,23 @@ module.exports = function(Chart) {
|
||||
helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);
|
||||
},
|
||||
calculateTickRotation: function() {
|
||||
var context = this.ctx;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var optionTicks = this.options.ticks;
|
||||
|
||||
//Get the width of each grid by calculating the difference
|
||||
//between x offsets between 0 and 1.
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
this.ctx.font = tickLabelFont;
|
||||
context.font = tickLabelFont;
|
||||
|
||||
var firstWidth = this.ctx.measureText(this.ticks[0]).width;
|
||||
var lastWidth = this.ctx.measureText(this.ticks[this.ticks.length - 1]).width;
|
||||
var firstWidth = context.measureText(this.ticks[0]).width;
|
||||
var lastWidth = context.measureText(this.ticks[this.ticks.length - 1]).width;
|
||||
var firstRotated;
|
||||
|
||||
this.labelRotation = 0;
|
||||
this.labelRotation = optionTicks.minRotation || 0;
|
||||
this.paddingRight = 0;
|
||||
this.paddingLeft = 0;
|
||||
|
||||
@ -202,7 +209,7 @@ module.exports = function(Chart) {
|
||||
if (!this.longestTextCache) {
|
||||
this.longestTextCache = {};
|
||||
}
|
||||
var originalLabelWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);
|
||||
var originalLabelWidth = helpers.longestText(context, tickLabelFont, this.ticks, this.longestTextCache);
|
||||
var labelWidth = originalLabelWidth;
|
||||
var cosRotation;
|
||||
var sinRotation;
|
||||
@ -212,7 +219,7 @@ module.exports = function(Chart) {
|
||||
var tickWidth = this.getPixelForTick(1) - this.getPixelForTick(0) - 6;
|
||||
|
||||
//Max label rotation can be set or default to 90 - also act as a loop counter
|
||||
while (labelWidth > tickWidth && this.labelRotation < this.options.ticks.maxRotation) {
|
||||
while (labelWidth > tickWidth && this.labelRotation < optionTicks.maxRotation) {
|
||||
cosRotation = Math.cos(helpers.toRadians(this.labelRotation));
|
||||
sinRotation = Math.sin(helpers.toRadians(this.labelRotation));
|
||||
|
||||
@ -252,47 +259,56 @@ module.exports = function(Chart) {
|
||||
helpers.callCallback(this.options.beforeFit, [this]);
|
||||
},
|
||||
fit: function() {
|
||||
|
||||
this.minSize = {
|
||||
// Reset
|
||||
var minSize = this.minSize = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var opts = this.options;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var tickOpts = opts.ticks;
|
||||
var scaleLabelOpts = opts.scaleLabel;
|
||||
var display = opts.display;
|
||||
var isHorizontal = this.isHorizontal();
|
||||
|
||||
var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(this.options.scaleLabel.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(this.options.scaleLabel.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(this.options.scaleLabel.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
|
||||
|
||||
var tickMarkLength = opts.gridLines.tickMarkLength;
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
if (isHorizontal) {
|
||||
// subtract the margins to line up with the chartArea if we are a full width scale
|
||||
this.minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth;
|
||||
minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth;
|
||||
} else {
|
||||
this.minSize.width = this.options.gridLines.tickMarkLength;
|
||||
minSize.width = display ? tickMarkLength : 0;
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = this.options.gridLines.tickMarkLength;
|
||||
if (isHorizontal) {
|
||||
minSize.height = display ? tickMarkLength : 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Are we showing a title for the scale?
|
||||
if (this.options.scaleLabel.display) {
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height += (scaleLabelFontSize * 1.5);
|
||||
if (scaleLabelOpts.display && display) {
|
||||
if (isHorizontal) {
|
||||
minSize.height += (scaleLabelFontSize * 1.5);
|
||||
} else {
|
||||
this.minSize.width += (scaleLabelFontSize * 1.5);
|
||||
minSize.width += (scaleLabelFontSize * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.display && this.options.display) {
|
||||
if (tickOpts.display && display) {
|
||||
// Don't bother fitting the ticks if we are not showing them
|
||||
if (!this.longestTextCache) {
|
||||
this.longestTextCache = {};
|
||||
@ -300,14 +316,14 @@ module.exports = function(Chart) {
|
||||
|
||||
var largestTextWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
if (isHorizontal) {
|
||||
// A horizontal axis is more constrained by the height.
|
||||
this.longestLabelWidth = largestTextWidth;
|
||||
|
||||
// TODO - improve this calculation
|
||||
var labelHeight = (Math.sin(helpers.toRadians(this.labelRotation)) * this.longestLabelWidth) + 1.5 * tickFontSize;
|
||||
|
||||
this.minSize.height = Math.min(this.maxHeight, this.minSize.height + labelHeight);
|
||||
minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight);
|
||||
this.ctx.font = tickLabelFont;
|
||||
|
||||
var firstLabelWidth = this.ctx.measureText(this.ticks[0]).width;
|
||||
@ -321,19 +337,23 @@ module.exports = function(Chart) {
|
||||
this.paddingRight = this.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated
|
||||
} else {
|
||||
// A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first
|
||||
var maxLabelWidth = this.maxWidth - this.minSize.width;
|
||||
var maxLabelWidth = this.maxWidth - minSize.width;
|
||||
|
||||
// Account for padding
|
||||
if (!this.options.ticks.mirror) {
|
||||
var mirror = tickOpts.mirror;
|
||||
if (!mirror) {
|
||||
largestTextWidth += this.options.ticks.padding;
|
||||
} else {
|
||||
// If mirrored text is on the inside so don't expand
|
||||
largestTextWidth = 0;
|
||||
}
|
||||
|
||||
if (largestTextWidth < maxLabelWidth) {
|
||||
// We don't need all the room
|
||||
this.minSize.width += largestTextWidth;
|
||||
minSize.width += largestTextWidth;
|
||||
} else {
|
||||
// Expand to max size
|
||||
this.minSize.width = this.maxWidth;
|
||||
minSize.width = this.maxWidth;
|
||||
}
|
||||
|
||||
this.paddingTop = tickFontSize / 2;
|
||||
@ -348,8 +368,8 @@ module.exports = function(Chart) {
|
||||
this.paddingBottom = Math.max(this.paddingBottom - this.margins.bottom, 0);
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
this.width = minSize.width;
|
||||
this.height = minSize.height;
|
||||
|
||||
},
|
||||
afterFit: function() {
|
||||
@ -376,7 +396,7 @@ module.exports = function(Chart) {
|
||||
}
|
||||
// If it is in fact an object, dive in one more level
|
||||
if (typeof(rawValue) === "object") {
|
||||
if (rawValue instanceof Date) {
|
||||
if ((rawValue instanceof Date) || (rawValue.isValid)) {
|
||||
return rawValue;
|
||||
} else {
|
||||
return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
|
||||
@ -431,260 +451,288 @@ module.exports = function(Chart) {
|
||||
}
|
||||
},
|
||||
|
||||
getBasePixel: function() {
|
||||
var me = this;
|
||||
var min = me.min;
|
||||
var max = me.max;
|
||||
|
||||
return me.getPixelForValue(
|
||||
me.beginAtZero? 0:
|
||||
min < 0 && max < 0? max :
|
||||
min > 0 && max > 0? min :
|
||||
0);
|
||||
},
|
||||
|
||||
// Actualy draw the scale on the canvas
|
||||
// @param {rectangle} chartArea : the area of the chart to draw full grid lines on
|
||||
draw: function(chartArea) {
|
||||
if (this.options.display) {
|
||||
var options = this.options;
|
||||
if (!options.display) {
|
||||
return;
|
||||
}
|
||||
|
||||
var setContextLineSettings;
|
||||
var isRotated = this.labelRotation !== 0;
|
||||
var skipRatio;
|
||||
var scaleLabelX;
|
||||
var scaleLabelY;
|
||||
var useAutoskipper = this.options.ticks.autoSkip;
|
||||
var context = this.ctx;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var optionTicks = options.ticks;
|
||||
var gridLines = options.gridLines;
|
||||
var scaleLabel = options.scaleLabel;
|
||||
|
||||
var setContextLineSettings;
|
||||
var isRotated = this.labelRotation !== 0;
|
||||
var skipRatio;
|
||||
var scaleLabelX;
|
||||
var scaleLabelY;
|
||||
var useAutoskipper = optionTicks.autoSkip;
|
||||
|
||||
// figure out the maximum number of gridlines to show
|
||||
var maxTicks;
|
||||
// figure out the maximum number of gridlines to show
|
||||
var maxTicks;
|
||||
if (optionTicks.maxTicksLimit) {
|
||||
maxTicks = optionTicks.maxTicksLimit;
|
||||
}
|
||||
|
||||
if (this.options.ticks.maxTicksLimit) {
|
||||
maxTicks = this.options.ticks.maxTicksLimit;
|
||||
var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
|
||||
var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
var tl = gridLines.tickMarkLength;
|
||||
|
||||
var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabel.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabel.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
|
||||
|
||||
var labelRotationRadians = helpers.toRadians(this.labelRotation);
|
||||
var cosRotation = Math.cos(labelRotationRadians);
|
||||
var sinRotation = Math.sin(labelRotationRadians);
|
||||
var longestRotatedLabel = this.longestLabelWidth * cosRotation;
|
||||
var rotatedLabelHeight = tickFontSize * sinRotation;
|
||||
|
||||
// Make sure we draw text in the correct color and font
|
||||
context.fillStyle = tickFontColor;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
setContextLineSettings = true;
|
||||
var yTickStart = options.position === "bottom" ? this.top : this.bottom - tl;
|
||||
var yTickEnd = options.position === "bottom" ? this.top + tl : this.bottom;
|
||||
skipRatio = false;
|
||||
|
||||
// Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation
|
||||
// See #2584
|
||||
if (isRotated) {
|
||||
longestRotatedLabel /= 2;
|
||||
}
|
||||
|
||||
if ((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length > (this.width - (this.paddingLeft + this.paddingRight))) {
|
||||
skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length) / (this.width - (this.paddingLeft + this.paddingRight)));
|
||||
}
|
||||
|
||||
var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
var tl = this.options.gridLines.tickMarkLength;
|
||||
// if they defined a max number of optionTicks,
|
||||
// increase skipRatio until that number is met
|
||||
if (maxTicks && this.ticks.length > maxTicks) {
|
||||
while (!skipRatio || this.ticks.length / (skipRatio || 1) > maxTicks) {
|
||||
if (!skipRatio) {
|
||||
skipRatio = 1;
|
||||
}
|
||||
skipRatio += 1;
|
||||
}
|
||||
}
|
||||
|
||||
var scaleLabelFontColor = helpers.getValueOrDefault(this.options.scaleLabel.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(this.options.scaleLabel.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(this.options.scaleLabel.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(this.options.scaleLabel.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
|
||||
|
||||
var cosRotation = Math.cos(helpers.toRadians(this.labelRotation));
|
||||
var sinRotation = Math.sin(helpers.toRadians(this.labelRotation));
|
||||
var longestRotatedLabel = this.longestLabelWidth * cosRotation;
|
||||
var rotatedLabelHeight = tickFontSize * sinRotation;
|
||||
|
||||
// Make sure we draw text in the correct color and font
|
||||
this.ctx.fillStyle = tickFontColor;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
setContextLineSettings = true;
|
||||
var yTickStart = this.options.position === "bottom" ? this.top : this.bottom - tl;
|
||||
var yTickEnd = this.options.position === "bottom" ? this.top + tl : this.bottom;
|
||||
if (!useAutoskipper) {
|
||||
skipRatio = false;
|
||||
|
||||
if (((longestRotatedLabel / 2) + this.options.ticks.autoSkipPadding) * this.ticks.length > (this.width - (this.paddingLeft + this.paddingRight))) {
|
||||
skipRatio = 1 + Math.floor((((longestRotatedLabel / 2) + this.options.ticks.autoSkipPadding) * this.ticks.length) / (this.width - (this.paddingLeft + this.paddingRight)));
|
||||
}
|
||||
|
||||
// if they defined a max number of ticks,
|
||||
// increase skipRatio until that number is met
|
||||
if (maxTicks && this.ticks.length > maxTicks) {
|
||||
while (!skipRatio || this.ticks.length / (skipRatio || 1) > maxTicks) {
|
||||
if (!skipRatio) {
|
||||
skipRatio = 1;
|
||||
}
|
||||
skipRatio += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useAutoskipper) {
|
||||
skipRatio = false;
|
||||
}
|
||||
|
||||
helpers.each(this.ticks, function(label, index) {
|
||||
// Blank ticks
|
||||
var isLastTick = this.ticks.length === index + 1;
|
||||
|
||||
// Since we always show the last tick,we need may need to hide the last shown one before
|
||||
var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio > this.ticks.length);
|
||||
if (shouldSkip && !isLastTick || (label === undefined || label === null)) {
|
||||
return;
|
||||
}
|
||||
var xLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
var xLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
xLineValue += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
this.ctx.beginPath();
|
||||
|
||||
if (this.options.gridLines.drawTicks) {
|
||||
this.ctx.moveTo(xLineValue, yTickStart);
|
||||
this.ctx.lineTo(xLineValue, yTickEnd);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (this.options.gridLines.drawOnChartArea) {
|
||||
this.ctx.moveTo(xLineValue, chartArea.top);
|
||||
this.ctx.lineTo(xLineValue, chartArea.bottom);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.display) {
|
||||
this.ctx.save();
|
||||
this.ctx.translate(xLabelValue, (isRotated) ? this.top + 12 : this.options.position === "top" ? this.bottom - tl : this.top + tl);
|
||||
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
|
||||
this.ctx.font = tickLabelFont;
|
||||
this.ctx.textAlign = (isRotated) ? "right" : "center";
|
||||
this.ctx.textBaseline = (isRotated) ? "middle" : this.options.position === "top" ? "bottom" : "top";
|
||||
this.ctx.fillText(label, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.fillStyle = scaleLabelFontColor; // render in correct colour
|
||||
this.ctx.font = scaleLabelFont;
|
||||
|
||||
scaleLabelX = this.left + ((this.right - this.left) / 2); // midpoint of the width
|
||||
scaleLabelY = this.options.position === 'bottom' ? this.bottom - (scaleLabelFontSize / 2) : this.top + (scaleLabelFontSize / 2);
|
||||
|
||||
this.ctx.fillText(this.options.scaleLabel.labelString, scaleLabelX, scaleLabelY);
|
||||
}
|
||||
|
||||
} else {
|
||||
setContextLineSettings = true;
|
||||
var xTickStart = this.options.position === "right" ? this.left : this.right - 5;
|
||||
var xTickEnd = this.options.position === "right" ? this.left + 5 : this.right;
|
||||
|
||||
helpers.each(this.ticks, function(label, index) {
|
||||
// If the callback returned a null or undefined value, do not draw this line
|
||||
if (label === undefined || label === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var yLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
yLineValue += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
this.ctx.beginPath();
|
||||
|
||||
if (this.options.gridLines.drawTicks) {
|
||||
this.ctx.moveTo(xTickStart, yLineValue);
|
||||
this.ctx.lineTo(xTickEnd, yLineValue);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (this.options.gridLines.drawOnChartArea) {
|
||||
this.ctx.moveTo(chartArea.left, yLineValue);
|
||||
this.ctx.lineTo(chartArea.right, yLineValue);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.display) {
|
||||
var xLabelValue;
|
||||
var yLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
this.ctx.save();
|
||||
|
||||
if (this.options.position === "left") {
|
||||
if (this.options.ticks.mirror) {
|
||||
xLabelValue = this.right + this.options.ticks.padding;
|
||||
this.ctx.textAlign = "left";
|
||||
} else {
|
||||
xLabelValue = this.right - this.options.ticks.padding;
|
||||
this.ctx.textAlign = "right";
|
||||
}
|
||||
} else {
|
||||
// right side
|
||||
if (this.options.ticks.mirror) {
|
||||
xLabelValue = this.left - this.options.ticks.padding;
|
||||
this.ctx.textAlign = "right";
|
||||
} else {
|
||||
xLabelValue = this.left + this.options.ticks.padding;
|
||||
this.ctx.textAlign = "left";
|
||||
}
|
||||
}
|
||||
|
||||
this.ctx.translate(xLabelValue, yLabelValue);
|
||||
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
|
||||
this.ctx.font = tickLabelFont;
|
||||
this.ctx.textBaseline = "middle";
|
||||
this.ctx.fillText(label, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
scaleLabelX = this.options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);
|
||||
scaleLabelY = this.top + ((this.bottom - this.top) / 2);
|
||||
var rotation = this.options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(scaleLabelX, scaleLabelY);
|
||||
this.ctx.rotate(rotation);
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.fillStyle =scaleLabelFontColor; // render in correct colour
|
||||
this.ctx.font = scaleLabelFont;
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.fillText(this.options.scaleLabel.labelString, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
helpers.each(this.ticks, function (label, index) {
|
||||
// Blank optionTicks
|
||||
var isLastTick = this.ticks.length === index + 1;
|
||||
|
||||
// Since we always show the last tick,we need may need to hide the last shown one before
|
||||
var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= this.ticks.length);
|
||||
if (shouldSkip && !isLastTick || (label === undefined || label === null)) {
|
||||
return;
|
||||
}
|
||||
var xLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
var xLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
|
||||
|
||||
if (gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
context.lineWidth = gridLines.zeroLineWidth;
|
||||
context.strokeStyle = gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
context.lineWidth = gridLines.lineWidth;
|
||||
context.strokeStyle = gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
xLineValue += helpers.aliasPixel(context.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
context.beginPath();
|
||||
|
||||
if (gridLines.drawTicks) {
|
||||
context.moveTo(xLineValue, yTickStart);
|
||||
context.lineTo(xLineValue, yTickEnd);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (gridLines.drawOnChartArea) {
|
||||
context.moveTo(xLineValue, chartArea.top);
|
||||
context.lineTo(xLineValue, chartArea.bottom);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
if (optionTicks.display) {
|
||||
context.save();
|
||||
context.translate(xLabelValue + optionTicks.labelOffset, (isRotated) ? this.top + 12 : options.position === "top" ? this.bottom - tl : this.top + tl);
|
||||
context.rotate(labelRotationRadians * -1);
|
||||
context.font = tickLabelFont;
|
||||
context.textAlign = (isRotated) ? "right" : "center";
|
||||
context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top";
|
||||
context.fillText(label, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
context.textAlign = "center";
|
||||
context.textBaseline = 'middle';
|
||||
context.fillStyle = scaleLabelFontColor; // render in correct colour
|
||||
context.font = scaleLabelFont;
|
||||
|
||||
scaleLabelX = this.left + ((this.right - this.left) / 2); // midpoint of the width
|
||||
scaleLabelY = options.position === 'bottom' ? this.bottom - (scaleLabelFontSize / 2) : this.top + (scaleLabelFontSize / 2);
|
||||
|
||||
context.fillText(scaleLabel.labelString, scaleLabelX, scaleLabelY);
|
||||
}
|
||||
|
||||
} else {
|
||||
setContextLineSettings = true;
|
||||
var xTickStart = options.position === "right" ? this.left : this.right - 5;
|
||||
var xTickEnd = options.position === "right" ? this.left + 5 : this.right;
|
||||
|
||||
helpers.each(this.ticks, function (label, index) {
|
||||
// If the callback returned a null or undefined value, do not draw this line
|
||||
if (label === undefined || label === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var yLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
|
||||
if (gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
context.lineWidth = gridLines.zeroLineWidth;
|
||||
context.strokeStyle = gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
context.lineWidth = gridLines.lineWidth;
|
||||
context.strokeStyle = gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
yLineValue += helpers.aliasPixel(context.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
context.beginPath();
|
||||
|
||||
if (gridLines.drawTicks) {
|
||||
context.moveTo(xTickStart, yLineValue);
|
||||
context.lineTo(xTickEnd, yLineValue);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (gridLines.drawOnChartArea) {
|
||||
context.moveTo(chartArea.left, yLineValue);
|
||||
context.lineTo(chartArea.right, yLineValue);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
if (optionTicks.display) {
|
||||
var xLabelValue;
|
||||
var yLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
|
||||
|
||||
context.save();
|
||||
|
||||
if (options.position === "left") {
|
||||
if (optionTicks.mirror) {
|
||||
xLabelValue = this.right + optionTicks.padding;
|
||||
context.textAlign = "left";
|
||||
} else {
|
||||
xLabelValue = this.right - optionTicks.padding;
|
||||
context.textAlign = "right";
|
||||
}
|
||||
} else {
|
||||
// right side
|
||||
if (optionTicks.mirror) {
|
||||
xLabelValue = this.left - optionTicks.padding;
|
||||
context.textAlign = "right";
|
||||
} else {
|
||||
xLabelValue = this.left + optionTicks.padding;
|
||||
context.textAlign = "left";
|
||||
}
|
||||
}
|
||||
|
||||
context.translate(xLabelValue, yLabelValue + optionTicks.labelOffset);
|
||||
context.rotate(labelRotationRadians * -1);
|
||||
context.font = tickLabelFont;
|
||||
context.textBaseline = "middle";
|
||||
context.fillText(label, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
scaleLabelX = options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);
|
||||
scaleLabelY = this.top + ((this.bottom - this.top) / 2);
|
||||
var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
|
||||
context.save();
|
||||
context.translate(scaleLabelX, scaleLabelY);
|
||||
context.rotate(rotation);
|
||||
context.textAlign = "center";
|
||||
context.fillStyle = scaleLabelFontColor; // render in correct colour
|
||||
context.font = scaleLabelFont;
|
||||
context.textBaseline = 'middle';
|
||||
context.fillText(scaleLabel.labelString, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
|
||||
if (gridLines.drawBorder) {
|
||||
// Draw the line at the edge of the axis
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
context.lineWidth = gridLines.lineWidth;
|
||||
context.strokeStyle = gridLines.color;
|
||||
var x1 = this.left,
|
||||
x2 = this.right,
|
||||
y1 = this.top,
|
||||
y2 = this.bottom;
|
||||
|
||||
var aliasPixel = helpers.aliasPixel(context.lineWidth);
|
||||
if (this.isHorizontal()) {
|
||||
y1 = y2 = this.options.position === 'top' ? this.bottom : this.top;
|
||||
y1 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
y2 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
y1 = y2 = options.position === 'top' ? this.bottom : this.top;
|
||||
y1 += aliasPixel;
|
||||
y2 += aliasPixel;
|
||||
} else {
|
||||
x1 = x2 = this.options.position === 'left' ? this.right : this.left;
|
||||
x1 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
x2 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
x1 = x2 = options.position === 'left' ? this.right : this.left;
|
||||
x1 += aliasPixel;
|
||||
x2 += aliasPixel;
|
||||
}
|
||||
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x1, y1);
|
||||
this.ctx.lineTo(x2, y2);
|
||||
this.ctx.stroke();
|
||||
context.beginPath();
|
||||
context.moveTo(x1, y1);
|
||||
context.lineTo(x2, y2);
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -24,6 +24,12 @@ module.exports = function(Chart) {
|
||||
// Return the scale defaults merged with the global settings so that we always use the latest ones
|
||||
return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};
|
||||
},
|
||||
updateScaleDefaults: function(type, additions) {
|
||||
var defaults = this.defaults;
|
||||
if (defaults.hasOwnProperty(type)) {
|
||||
defaults[type] = helpers.extend(defaults[type], additions);
|
||||
}
|
||||
},
|
||||
addScalesToLayout: function(chartInstance) {
|
||||
// Adds each scale to the chart.boxes array to be sized accordingly
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
|
131
vendors/Chart.js/src/core/core.title.js
vendored
@ -16,6 +16,7 @@ module.exports = function(Chart) {
|
||||
text: ''
|
||||
};
|
||||
|
||||
var noop = helpers.noop;
|
||||
Chart.Title = Chart.Element.extend({
|
||||
|
||||
initialize: function(config) {
|
||||
@ -28,7 +29,7 @@ module.exports = function(Chart) {
|
||||
|
||||
// These methods are ordered by lifecyle. Utilities then follow.
|
||||
|
||||
beforeUpdate: helpers.noop,
|
||||
beforeUpdate: noop,
|
||||
update: function(maxWidth, maxHeight, margins) {
|
||||
|
||||
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
|
||||
@ -58,11 +59,11 @@ module.exports = function(Chart) {
|
||||
return this.minSize;
|
||||
|
||||
},
|
||||
afterUpdate: helpers.noop,
|
||||
afterUpdate: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeSetDimensions: helpers.noop,
|
||||
beforeSetDimensions: noop,
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
if (this.isHorizontal()) {
|
||||
@ -90,103 +91,89 @@ module.exports = function(Chart) {
|
||||
height: 0
|
||||
};
|
||||
},
|
||||
afterSetDimensions: helpers.noop,
|
||||
afterSetDimensions: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeBuildLabels: helpers.noop,
|
||||
buildLabels: helpers.noop,
|
||||
afterBuildLabels: helpers.noop,
|
||||
beforeBuildLabels: noop,
|
||||
buildLabels: noop,
|
||||
afterBuildLabels: noop,
|
||||
|
||||
//
|
||||
|
||||
beforeFit: helpers.noop,
|
||||
beforeFit: noop,
|
||||
fit: function() {
|
||||
|
||||
var ctx = this.ctx;
|
||||
var fontSize = helpers.getValueOrDefault(this.options.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
var _this = this,
|
||||
ctx = _this.ctx,
|
||||
valueOrDefault = helpers.getValueOrDefault,
|
||||
opts = _this.options,
|
||||
globalDefaults = Chart.defaults.global,
|
||||
display = opts.display,
|
||||
fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
|
||||
minSize = _this.minSize;
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.width = this.maxWidth; // fill all the width
|
||||
if (_this.isHorizontal()) {
|
||||
minSize.width = _this.maxWidth; // fill all the width
|
||||
minSize.height = display ? fontSize + (opts.padding * 2) : 0;
|
||||
} else {
|
||||
this.minSize.width = 0;
|
||||
minSize.width = display ? fontSize + (opts.padding * 2) : 0;
|
||||
minSize.height = _this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Increase sizes here
|
||||
if (this.isHorizontal()) {
|
||||
|
||||
// Title
|
||||
if (this.options.display) {
|
||||
this.minSize.height += fontSize + (this.options.padding * 2);
|
||||
}
|
||||
} else {
|
||||
if (this.options.display) {
|
||||
this.minSize.width += fontSize + (this.options.padding * 2);
|
||||
}
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
_this.width = minSize.width;
|
||||
_this.height = minSize.height;
|
||||
|
||||
},
|
||||
afterFit: helpers.noop,
|
||||
afterFit: noop,
|
||||
|
||||
// Shared Methods
|
||||
isHorizontal: function() {
|
||||
return this.options.position === "top" || this.options.position === "bottom";
|
||||
var pos = this.options.position;
|
||||
return pos === "top" || pos === "bottom";
|
||||
},
|
||||
|
||||
// Actualy draw the title block on the canvas
|
||||
draw: function() {
|
||||
if (this.options.display) {
|
||||
var ctx = this.ctx;
|
||||
var titleX, titleY;
|
||||
var _this = this,
|
||||
ctx = _this.ctx,
|
||||
valueOrDefault = helpers.getValueOrDefault,
|
||||
opts = _this.options,
|
||||
globalDefaults = Chart.defaults.global;
|
||||
|
||||
var fontColor = helpers.getValueOrDefault(this.options.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var fontSize = helpers.getValueOrDefault(this.options.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
if (opts.display) {
|
||||
var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
|
||||
fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),
|
||||
fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),
|
||||
titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),
|
||||
rotation = 0,
|
||||
titleX,
|
||||
titleY,
|
||||
top = _this.top,
|
||||
left = _this.left,
|
||||
bottom = _this.bottom,
|
||||
right = _this.right;
|
||||
|
||||
ctx.fillStyle = fontColor; // render in correct colour
|
||||
ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour
|
||||
ctx.font = titleFont;
|
||||
|
||||
// Horizontal
|
||||
if (this.isHorizontal()) {
|
||||
// Title
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
titleX = this.left + ((this.right - this.left) / 2); // midpoint of the width
|
||||
titleY = this.top + ((this.bottom - this.top) / 2); // midpoint of the height
|
||||
|
||||
ctx.fillText(this.options.text, titleX, titleY);
|
||||
if (_this.isHorizontal()) {
|
||||
titleX = left + ((right - left) / 2); // midpoint of the width
|
||||
titleY = top + ((bottom - top) / 2); // midpoint of the height
|
||||
} else {
|
||||
|
||||
// Title
|
||||
titleX = this.options.position === 'left' ? this.left + (fontSize / 2) : this.right - (fontSize / 2);
|
||||
titleY = this.top + ((this.bottom - this.top) / 2);
|
||||
var rotation = this.options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(titleX, titleY);
|
||||
ctx.rotate(rotation);
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(this.options.text, 0, 0);
|
||||
ctx.restore();
|
||||
titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);
|
||||
titleY = top + ((bottom - top) / 2);
|
||||
rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(titleX, titleY);
|
||||
ctx.rotate(rotation);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(opts.text, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
61
vendors/Chart.js/src/core/core.tooltip.js
vendored
@ -84,47 +84,50 @@ module.exports = function(Chart) {
|
||||
|
||||
Chart.Tooltip = Chart.Element.extend({
|
||||
initialize: function() {
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
var options = this._options;
|
||||
var tooltips = options.tooltips;
|
||||
|
||||
helpers.extend(this, {
|
||||
_model: {
|
||||
// Positioning
|
||||
xPadding: options.tooltips.xPadding,
|
||||
yPadding: options.tooltips.yPadding,
|
||||
xAlign : options.tooltips.yAlign,
|
||||
yAlign : options.tooltips.xAlign,
|
||||
xPadding: tooltips.xPadding,
|
||||
yPadding: tooltips.yPadding,
|
||||
xAlign : tooltips.yAlign,
|
||||
yAlign : tooltips.xAlign,
|
||||
|
||||
// Body
|
||||
bodyColor: options.tooltips.bodyColor,
|
||||
_bodyFontFamily: helpers.getValueOrDefault(options.tooltips.bodyFontFamily, Chart.defaults.global.defaultFontFamily),
|
||||
_bodyFontStyle: helpers.getValueOrDefault(options.tooltips.bodyFontStyle, Chart.defaults.global.defaultFontStyle),
|
||||
_bodyAlign: options.tooltips.bodyAlign,
|
||||
bodyFontSize: helpers.getValueOrDefault(options.tooltips.bodyFontSize, Chart.defaults.global.defaultFontSize),
|
||||
bodySpacing: options.tooltips.bodySpacing,
|
||||
bodyColor: tooltips.bodyColor,
|
||||
_bodyFontFamily: helpers.getValueOrDefault(tooltips.bodyFontFamily, globalDefaults.defaultFontFamily),
|
||||
_bodyFontStyle: helpers.getValueOrDefault(tooltips.bodyFontStyle, globalDefaults.defaultFontStyle),
|
||||
_bodyAlign: tooltips.bodyAlign,
|
||||
bodyFontSize: helpers.getValueOrDefault(tooltips.bodyFontSize, globalDefaults.defaultFontSize),
|
||||
bodySpacing: tooltips.bodySpacing,
|
||||
|
||||
// Title
|
||||
titleColor: options.tooltips.titleColor,
|
||||
_titleFontFamily: helpers.getValueOrDefault(options.tooltips.titleFontFamily, Chart.defaults.global.defaultFontFamily),
|
||||
_titleFontStyle: helpers.getValueOrDefault(options.tooltips.titleFontStyle, Chart.defaults.global.defaultFontStyle),
|
||||
titleFontSize: helpers.getValueOrDefault(options.tooltips.titleFontSize, Chart.defaults.global.defaultFontSize),
|
||||
_titleAlign: options.tooltips.titleAlign,
|
||||
titleSpacing: options.tooltips.titleSpacing,
|
||||
titleMarginBottom: options.tooltips.titleMarginBottom,
|
||||
titleColor: tooltips.titleColor,
|
||||
_titleFontFamily: helpers.getValueOrDefault(tooltips.titleFontFamily, globalDefaults.defaultFontFamily),
|
||||
_titleFontStyle: helpers.getValueOrDefault(tooltips.titleFontStyle, globalDefaults.defaultFontStyle),
|
||||
titleFontSize: helpers.getValueOrDefault(tooltips.titleFontSize, globalDefaults.defaultFontSize),
|
||||
_titleAlign: tooltips.titleAlign,
|
||||
titleSpacing: tooltips.titleSpacing,
|
||||
titleMarginBottom: tooltips.titleMarginBottom,
|
||||
|
||||
// Footer
|
||||
footerColor: options.tooltips.footerColor,
|
||||
_footerFontFamily: helpers.getValueOrDefault(options.tooltips.footerFontFamily, Chart.defaults.global.defaultFontFamily),
|
||||
_footerFontStyle: helpers.getValueOrDefault(options.tooltips.footerFontStyle, Chart.defaults.global.defaultFontStyle),
|
||||
footerFontSize: helpers.getValueOrDefault(options.tooltips.footerFontSize, Chart.defaults.global.defaultFontSize),
|
||||
_footerAlign: options.tooltips.footerAlign,
|
||||
footerSpacing: options.tooltips.footerSpacing,
|
||||
footerMarginTop: options.tooltips.footerMarginTop,
|
||||
footerColor: tooltips.footerColor,
|
||||
_footerFontFamily: helpers.getValueOrDefault(tooltips.footerFontFamily, globalDefaults.defaultFontFamily),
|
||||
_footerFontStyle: helpers.getValueOrDefault(tooltips.footerFontStyle, globalDefaults.defaultFontStyle),
|
||||
footerFontSize: helpers.getValueOrDefault(tooltips.footerFontSize, globalDefaults.defaultFontSize),
|
||||
_footerAlign: tooltips.footerAlign,
|
||||
footerSpacing: tooltips.footerSpacing,
|
||||
footerMarginTop: tooltips.footerMarginTop,
|
||||
|
||||
// Appearance
|
||||
caretSize: options.tooltips.caretSize,
|
||||
cornerRadius: options.tooltips.cornerRadius,
|
||||
backgroundColor: options.tooltips.backgroundColor,
|
||||
caretSize: tooltips.caretSize,
|
||||
cornerRadius: tooltips.cornerRadius,
|
||||
backgroundColor: tooltips.backgroundColor,
|
||||
opacity: 0,
|
||||
legendColorBackground: options.tooltips.multiKeyBackground
|
||||
legendColorBackground: tooltips.multiKeyBackground
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -194,7 +197,7 @@ module.exports = function(Chart) {
|
||||
var yPositions = [];
|
||||
|
||||
helpers.each(elements, function(el) {
|
||||
if (el) {
|
||||
if (el && el.hasValue()){
|
||||
var pos = el.tooltipPosition();
|
||||
xPositions.push(pos.x);
|
||||
yPositions.push(pos.y);
|
||||
|
39
vendors/Chart.js/src/elements/element.arc.js
vendored
@ -2,10 +2,11 @@
|
||||
|
||||
module.exports = function(Chart, moment) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var helpers = Chart.helpers,
|
||||
globalOpts = Chart.defaults.global;
|
||||
|
||||
Chart.defaults.global.elements.arc = {
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
globalOpts.elements.arc = {
|
||||
backgroundColor: globalOpts.defaultColor,
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2
|
||||
};
|
||||
@ -21,14 +22,15 @@ module.exports = function(Chart, moment) {
|
||||
}
|
||||
},
|
||||
inRange: function(chartX, chartY) {
|
||||
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
var pointRelativePosition = helpers.getAngleFromPoint(vm, {
|
||||
x: chartX,
|
||||
y: chartY
|
||||
});
|
||||
x: chartX,
|
||||
y: chartY
|
||||
}),
|
||||
angle = pointRelativePosition.angle,
|
||||
distance = pointRelativePosition.distance;
|
||||
|
||||
//Sanitise angle range
|
||||
var startAngle = vm.startAngle;
|
||||
@ -36,16 +38,16 @@ module.exports = function(Chart, moment) {
|
||||
while (endAngle < startAngle) {
|
||||
endAngle += 2.0 * Math.PI;
|
||||
}
|
||||
while (pointRelativePosition.angle > endAngle) {
|
||||
pointRelativePosition.angle -= 2.0 * Math.PI;
|
||||
while (angle > endAngle) {
|
||||
angle -= 2.0 * Math.PI;
|
||||
}
|
||||
while (pointRelativePosition.angle < startAngle) {
|
||||
pointRelativePosition.angle += 2.0 * Math.PI;
|
||||
while (angle < startAngle) {
|
||||
angle += 2.0 * Math.PI;
|
||||
}
|
||||
|
||||
//Check if within the range of the open/close angle
|
||||
var betweenAngles = (pointRelativePosition.angle >= startAngle && pointRelativePosition.angle <= endAngle),
|
||||
withinRadius = (pointRelativePosition.distance >= vm.innerRadius && pointRelativePosition.distance <= vm.outerRadius);
|
||||
var betweenAngles = (angle >= startAngle && angle <= endAngle),
|
||||
withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
|
||||
|
||||
return (betweenAngles && withinRadius);
|
||||
} else {
|
||||
@ -64,14 +66,15 @@ module.exports = function(Chart, moment) {
|
||||
},
|
||||
draw: function() {
|
||||
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
var ctx = this._chart.ctx,
|
||||
vm = this._view,
|
||||
sA = vm.startAngle,
|
||||
eA = vm.endAngle;
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.arc(vm.x, vm.y, vm.outerRadius, vm.startAngle, vm.endAngle);
|
||||
|
||||
ctx.arc(vm.x, vm.y, vm.innerRadius, vm.endAngle, vm.startAngle, true);
|
||||
ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
|
||||
ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
|
||||
|
||||
ctx.closePath();
|
||||
ctx.strokeStyle = vm.borderColor;
|
||||
|
20
vendors/Chart.js/src/elements/element.line.js
vendored
@ -3,12 +3,13 @@
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
|
||||
Chart.defaults.global.elements.line = {
|
||||
tension: 0.4,
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
backgroundColor: globalDefaults.defaultColor,
|
||||
borderWidth: 3,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
borderColor: globalDefaults.defaultColor,
|
||||
borderCapStyle: 'butt',
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
@ -115,23 +116,24 @@ module.exports = function(Chart) {
|
||||
ctx.lineTo(this._children[0]._view.x, vm.scaleZero);
|
||||
}
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor || Chart.defaults.global.defaultColor;
|
||||
ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
var globalOptionLineElements = globalDefaults.elements.line;
|
||||
// Now draw the line between all the points with any borders
|
||||
ctx.lineCap = vm.borderCapStyle || Chart.defaults.global.elements.line.borderCapStyle;
|
||||
ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
|
||||
|
||||
// IE 9 and 10 do not support line dash
|
||||
if (ctx.setLineDash) {
|
||||
ctx.setLineDash(vm.borderDash || Chart.defaults.global.elements.line.borderDash);
|
||||
ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
|
||||
}
|
||||
|
||||
ctx.lineDashOffset = vm.borderDashOffset || Chart.defaults.global.elements.line.borderDashOffset;
|
||||
ctx.lineJoin = vm.borderJoinStyle || Chart.defaults.global.elements.line.borderJoinStyle;
|
||||
ctx.lineWidth = vm.borderWidth || Chart.defaults.global.elements.line.borderWidth;
|
||||
ctx.strokeStyle = vm.borderColor || Chart.defaults.global.defaultColor;
|
||||
ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
|
||||
ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
|
||||
ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
|
||||
ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
|
||||
ctx.beginPath();
|
||||
|
||||
helpers.each(this._children, function(point, index) {
|
||||
|
212
vendors/Chart.js/src/elements/element.point.js
vendored
@ -2,40 +2,30 @@
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var helpers = Chart.helpers,
|
||||
globalOpts = Chart.defaults.global,
|
||||
defaultColor = globalOpts.defaultColor;
|
||||
|
||||
Chart.defaults.global.elements.point = {
|
||||
globalOpts.elements.point = {
|
||||
radius: 3,
|
||||
pointStyle: 'circle',
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
backgroundColor: defaultColor,
|
||||
borderWidth: 1,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
borderColor: defaultColor,
|
||||
// Hover
|
||||
hitRadius: 1,
|
||||
hoverRadius: 4,
|
||||
hoverBorderWidth: 1
|
||||
};
|
||||
|
||||
|
||||
Chart.elements.Point = Chart.Element.extend({
|
||||
inRange: function(mouseX, mouseY) {
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
var hoverRange = vm.hitRadius + vm.radius;
|
||||
return ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(hoverRange, 2));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
|
||||
},
|
||||
inLabelRange: function(mouseX) {
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
@ -46,108 +36,112 @@ module.exports = function(Chart) {
|
||||
};
|
||||
},
|
||||
draw: function() {
|
||||
|
||||
var vm = this._view;
|
||||
var ctx = this._chart.ctx;
|
||||
|
||||
var pointStyle = vm.pointStyle;
|
||||
var radius = vm.radius;
|
||||
var x = vm.x;
|
||||
var y = vm.y;
|
||||
var type, edgeLength, xOffset, yOffset, height, size;
|
||||
|
||||
if (vm.skip) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof vm.pointStyle === 'object' && ((vm.pointStyle.toString() === '[object HTMLImageElement]') || (vm.pointStyle.toString() === '[object HTMLCanvasElement]'))) {
|
||||
ctx.drawImage(vm.pointStyle, vm.x - vm.pointStyle.width / 2, vm.y - vm.pointStyle.height / 2);
|
||||
if (typeof pointStyle === 'object') {
|
||||
type = pointStyle.toString();
|
||||
if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
|
||||
ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNaN(radius) || radius <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNaN(vm.radius) && vm.radius > 0) {
|
||||
ctx.strokeStyle = vm.borderColor || defaultColor;
|
||||
ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);
|
||||
ctx.fillStyle = vm.backgroundColor || defaultColor;
|
||||
|
||||
ctx.strokeStyle = vm.borderColor || Chart.defaults.global.defaultColor;
|
||||
ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, Chart.defaults.global.elements.point.borderWidth);
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor || Chart.defaults.global.defaultColor;
|
||||
|
||||
var radius = vm.radius;
|
||||
|
||||
var xOffset;
|
||||
var yOffset;
|
||||
|
||||
switch (vm.pointStyle) {
|
||||
// Default includes circle
|
||||
default: ctx.beginPath();
|
||||
ctx.arc(vm.x, vm.y, radius, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
case 'triangle':
|
||||
ctx.beginPath();
|
||||
var edgeLength = 3 * radius / Math.sqrt(3);
|
||||
var height = edgeLength * Math.sqrt(3) / 2;
|
||||
ctx.moveTo(vm.x - edgeLength / 2, vm.y + height / 3);
|
||||
ctx.lineTo(vm.x + edgeLength / 2, vm.y + height / 3);
|
||||
ctx.lineTo(vm.x, vm.y - 2 * height / 3);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
case 'rect':
|
||||
ctx.fillRect(vm.x - 1 / Math.SQRT2 * radius, vm.y - 1 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius);
|
||||
ctx.strokeRect(vm.x - 1 / Math.SQRT2 * radius, vm.y - 1 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius);
|
||||
break;
|
||||
case 'rectRot':
|
||||
ctx.translate(vm.x, vm.y);
|
||||
ctx.rotate(Math.PI / 4);
|
||||
ctx.fillRect(-1 / Math.SQRT2 * radius, -1 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius);
|
||||
ctx.strokeRect(-1 / Math.SQRT2 * radius, -1 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius, 2 / Math.SQRT2 * radius);
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
break;
|
||||
case 'cross':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vm.x, vm.y + radius);
|
||||
ctx.lineTo(vm.x, vm.y - radius);
|
||||
ctx.moveTo(vm.x - radius, vm.y);
|
||||
ctx.lineTo(vm.x + radius, vm.y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'crossRot':
|
||||
ctx.beginPath();
|
||||
xOffset = Math.cos(Math.PI / 4) * radius;
|
||||
yOffset = Math.sin(Math.PI / 4) * radius;
|
||||
ctx.moveTo(vm.x - xOffset, vm.y - yOffset);
|
||||
ctx.lineTo(vm.x + xOffset, vm.y + yOffset);
|
||||
ctx.moveTo(vm.x - xOffset, vm.y + yOffset);
|
||||
ctx.lineTo(vm.x + xOffset, vm.y - yOffset);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'star':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vm.x, vm.y + radius);
|
||||
ctx.lineTo(vm.x, vm.y - radius);
|
||||
ctx.moveTo(vm.x - radius, vm.y);
|
||||
ctx.lineTo(vm.x + radius, vm.y);
|
||||
xOffset = Math.cos(Math.PI / 4) * radius;
|
||||
yOffset = Math.sin(Math.PI / 4) * radius;
|
||||
ctx.moveTo(vm.x - xOffset, vm.y - yOffset);
|
||||
ctx.lineTo(vm.x + xOffset, vm.y + yOffset);
|
||||
ctx.moveTo(vm.x - xOffset, vm.y + yOffset);
|
||||
ctx.lineTo(vm.x + xOffset, vm.y - yOffset);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'line':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vm.x - radius, vm.y);
|
||||
ctx.lineTo(vm.x + radius, vm.y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'dash':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vm.x, vm.y);
|
||||
ctx.lineTo(vm.x + radius, vm.y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
switch (pointStyle) {
|
||||
// Default includes circle
|
||||
default:
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
case 'triangle':
|
||||
ctx.beginPath();
|
||||
edgeLength = 3 * radius / Math.sqrt(3);
|
||||
height = edgeLength * Math.sqrt(3) / 2;
|
||||
ctx.moveTo(x - edgeLength / 2, y + height / 3);
|
||||
ctx.lineTo(x + edgeLength / 2, y + height / 3);
|
||||
ctx.lineTo(x, y - 2 * height / 3);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
case 'rect':
|
||||
size = 1 / Math.SQRT2 * radius;
|
||||
ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
|
||||
ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
|
||||
break;
|
||||
case 'rectRot':
|
||||
ctx.translate(x, y);
|
||||
ctx.rotate(Math.PI / 4);
|
||||
size = 1 / Math.SQRT2 * radius;
|
||||
ctx.fillRect(-size, -size, 2 * size, 2 * size);
|
||||
ctx.strokeRect(-size, -size, 2 * size, 2 * size);
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
break;
|
||||
case 'cross':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y + radius);
|
||||
ctx.lineTo(x, y - radius);
|
||||
ctx.moveTo(x - radius, y);
|
||||
ctx.lineTo(x + radius, y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'crossRot':
|
||||
ctx.beginPath();
|
||||
xOffset = Math.cos(Math.PI / 4) * radius;
|
||||
yOffset = Math.sin(Math.PI / 4) * radius;
|
||||
ctx.moveTo(x - xOffset, y - yOffset);
|
||||
ctx.lineTo(x + xOffset, y + yOffset);
|
||||
ctx.moveTo(x - xOffset, y + yOffset);
|
||||
ctx.lineTo(x + xOffset, y - yOffset);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'star':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y + radius);
|
||||
ctx.lineTo(x, y - radius);
|
||||
ctx.moveTo(x - radius, y);
|
||||
ctx.lineTo(x + radius, y);
|
||||
xOffset = Math.cos(Math.PI / 4) * radius;
|
||||
yOffset = Math.sin(Math.PI / 4) * radius;
|
||||
ctx.moveTo(x - xOffset, y - yOffset);
|
||||
ctx.lineTo(x + xOffset, y + yOffset);
|
||||
ctx.moveTo(x - xOffset, y + yOffset);
|
||||
ctx.lineTo(x + xOffset, y - yOffset);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'line':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x - radius, y);
|
||||
ctx.lineTo(x + radius, y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'dash':
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x + radius, y);
|
||||
ctx.closePath();
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var helpers = Chart.helpers,
|
||||
globalOpts = Chart.defaults.global;
|
||||
|
||||
Chart.defaults.global.elements.rectangle = {
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
globalOpts.elements.rectangle = {
|
||||
backgroundColor: globalOpts.defaultColor,
|
||||
borderWidth: 0,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
borderColor: globalOpts.defaultColor,
|
||||
borderSkipped: 'bottom'
|
||||
};
|
||||
|
||||
Chart.elements.Rectangle = Chart.Element.extend({
|
||||
draw: function() {
|
||||
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
|
||||
@ -32,7 +32,6 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor;
|
||||
ctx.strokeStyle = vm.borderColor;
|
||||
ctx.lineWidth = vm.borderWidth;
|
||||
@ -73,26 +72,15 @@ module.exports = function(Chart) {
|
||||
},
|
||||
inRange: function(mouseX, mouseY) {
|
||||
var vm = this._view;
|
||||
var inRange = false;
|
||||
|
||||
if (vm) {
|
||||
if (vm.y < vm.base) {
|
||||
inRange = (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base);
|
||||
} else {
|
||||
inRange = (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y);
|
||||
}
|
||||
}
|
||||
|
||||
return inRange;
|
||||
return vm ?
|
||||
(vm.y < vm.base ?
|
||||
(mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base) :
|
||||
(mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y)) :
|
||||
false;
|
||||
},
|
||||
inLabelRange: function(mouseX) {
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
return (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return vm ? (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) : false;
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
|
204
vendors/Chart.js/src/scales/scale.linear.js
vendored
@ -37,17 +37,29 @@ module.exports = function(Chart) {
|
||||
|
||||
var LinearScale = Chart.Scale.extend({
|
||||
determineDataLimits: function() {
|
||||
// First Calculate the range
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
var _this = this;
|
||||
var opts = _this.options;
|
||||
var tickOpts = opts.ticks;
|
||||
var chart = _this.chart;
|
||||
var data = chart.data;
|
||||
var datasets = data.datasets;
|
||||
var isHorizontal = _this.isHorizontal();
|
||||
|
||||
if (this.options.stacked) {
|
||||
function IDMatches(meta) {
|
||||
return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;
|
||||
}
|
||||
|
||||
// First Calculate the range
|
||||
_this.min = null;
|
||||
_this.max = null;
|
||||
|
||||
if (opts.stacked) {
|
||||
var valuesPerType = {};
|
||||
var hasPositiveValues = false;
|
||||
var hasNegativeValues = false;
|
||||
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
var meta = this.chart.getDatasetMeta(datasetIndex);
|
||||
helpers.each(datasets, function(dataset, datasetIndex) {
|
||||
var meta = chart.getDatasetMeta(datasetIndex);
|
||||
if (valuesPerType[meta.type] === undefined) {
|
||||
valuesPerType[meta.type] = {
|
||||
positiveValues: [],
|
||||
@ -59,9 +71,9 @@ module.exports = function(Chart) {
|
||||
var positiveValues = valuesPerType[meta.type].positiveValues;
|
||||
var negativeValues = valuesPerType[meta.type].negativeValues;
|
||||
|
||||
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
|
||||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = +this.getRightValue(rawValue);
|
||||
var value = +_this.getRightValue(rawValue);
|
||||
if (isNaN(value) || meta.data[index].hidden) {
|
||||
return;
|
||||
}
|
||||
@ -69,7 +81,7 @@ module.exports = function(Chart) {
|
||||
positiveValues[index] = positiveValues[index] || 0;
|
||||
negativeValues[index] = negativeValues[index] || 0;
|
||||
|
||||
if (this.options.relativePoints) {
|
||||
if (opts.relativePoints) {
|
||||
positiveValues[index] = 100;
|
||||
} else {
|
||||
if (value < 0) {
|
||||
@ -80,81 +92,88 @@ module.exports = function(Chart) {
|
||||
positiveValues[index] += value;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
helpers.each(valuesPerType, function(valuesForType) {
|
||||
var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
|
||||
var minVal = helpers.min(values);
|
||||
var maxVal = helpers.max(values);
|
||||
this.min = this.min === null ? minVal : Math.min(this.min, minVal);
|
||||
this.max = this.max === null ? maxVal : Math.max(this.max, maxVal);
|
||||
}, this);
|
||||
_this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);
|
||||
_this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);
|
||||
});
|
||||
|
||||
} else {
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
var meta = this.chart.getDatasetMeta(datasetIndex);
|
||||
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
|
||||
helpers.each(datasets, function(dataset, datasetIndex) {
|
||||
var meta = chart.getDatasetMeta(datasetIndex);
|
||||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = +this.getRightValue(rawValue);
|
||||
var value = +_this.getRightValue(rawValue);
|
||||
if (isNaN(value) || meta.data[index].hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
if (_this.min === null) {
|
||||
_this.min = value;
|
||||
} else if (value < _this.min) {
|
||||
_this.min = value;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
if (_this.max === null) {
|
||||
_this.max = value;
|
||||
} else if (value > _this.max) {
|
||||
_this.max = value;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
|
||||
// If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
|
||||
// do nothing since that would make the chart weird. If the user really wants a weird chart
|
||||
// axis, they can manually override it
|
||||
if (this.options.ticks.beginAtZero) {
|
||||
var minSign = helpers.sign(this.min);
|
||||
var maxSign = helpers.sign(this.max);
|
||||
if (tickOpts.beginAtZero) {
|
||||
var minSign = helpers.sign(_this.min);
|
||||
var maxSign = helpers.sign(_this.max);
|
||||
|
||||
if (minSign < 0 && maxSign < 0) {
|
||||
// move the top up to 0
|
||||
this.max = 0;
|
||||
_this.max = 0;
|
||||
} else if (minSign > 0 && maxSign > 0) {
|
||||
// move the botttom down to 0
|
||||
this.min = 0;
|
||||
_this.min = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.min !== undefined) {
|
||||
this.min = this.options.ticks.min;
|
||||
} else if (this.options.ticks.suggestedMin !== undefined) {
|
||||
this.min = Math.min(this.min, this.options.ticks.suggestedMin);
|
||||
if (tickOpts.min !== undefined) {
|
||||
_this.min = tickOpts.min;
|
||||
} else if (tickOpts.suggestedMin !== undefined) {
|
||||
_this.min = Math.min(_this.min, tickOpts.suggestedMin);
|
||||
}
|
||||
|
||||
if (this.options.ticks.max !== undefined) {
|
||||
this.max = this.options.ticks.max;
|
||||
} else if (this.options.ticks.suggestedMax !== undefined) {
|
||||
this.max = Math.max(this.max, this.options.ticks.suggestedMax);
|
||||
if (tickOpts.max !== undefined) {
|
||||
_this.max = tickOpts.max;
|
||||
} else if (tickOpts.suggestedMax !== undefined) {
|
||||
_this.max = Math.max(_this.max, tickOpts.suggestedMax);
|
||||
}
|
||||
|
||||
if (this.min === this.max) {
|
||||
this.min--;
|
||||
this.max++;
|
||||
if (_this.min === _this.max) {
|
||||
_this.max++;
|
||||
|
||||
if (!tickOpts.beginAtZero) {
|
||||
_this.min--;
|
||||
}
|
||||
}
|
||||
},
|
||||
buildTicks: function() {
|
||||
var _this = this;
|
||||
var opts = _this.options;
|
||||
var tickOpts = opts.ticks;
|
||||
var getValueOrDefault = helpers.getValueOrDefault;
|
||||
var isHorizontal = _this.isHorizontal();
|
||||
|
||||
// Then calulate the ticks
|
||||
this.ticks = [];
|
||||
var ticks = _this.ticks = [];
|
||||
|
||||
// Figure out what the max number of ticks we can support it is based on the size of
|
||||
// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
|
||||
@ -163,12 +182,12 @@ module.exports = function(Chart) {
|
||||
|
||||
var maxTicks;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, Math.ceil(this.width / 50));
|
||||
if (isHorizontal) {
|
||||
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.width / 50));
|
||||
} else {
|
||||
// The factor of 2 used to scale the font size has been experimentally determined.
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, Math.ceil(this.height / (2 * tickFontSize)));
|
||||
var tickFontSize = getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.height / (2 * tickFontSize)));
|
||||
}
|
||||
|
||||
// Make sure we always have at least 2 ticks
|
||||
@ -179,15 +198,15 @@ module.exports = function(Chart) {
|
||||
// for details.
|
||||
|
||||
var spacing;
|
||||
var fixedStepSizeSet = (this.options.ticks.fixedStepSize && this.options.ticks.fixedStepSize > 0) || (this.options.ticks.stepSize && this.options.ticks.stepSize > 0);
|
||||
var fixedStepSizeSet = (tickOpts.fixedStepSize && tickOpts.fixedStepSize > 0) || (tickOpts.stepSize && tickOpts.stepSize > 0);
|
||||
if (fixedStepSizeSet) {
|
||||
spacing = helpers.getValueOrDefault(this.options.ticks.fixedStepSize, this.options.ticks.stepSize);
|
||||
spacing = getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize);
|
||||
} else {
|
||||
var niceRange = helpers.niceNum(this.max - this.min, false);
|
||||
var niceRange = helpers.niceNum(_this.max - _this.min, false);
|
||||
spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
|
||||
}
|
||||
var niceMin = Math.floor(this.min / spacing) * spacing;
|
||||
var niceMax = Math.ceil(this.max / spacing) * spacing;
|
||||
var niceMin = Math.floor(_this.min / spacing) * spacing;
|
||||
var niceMax = Math.ceil(_this.max / spacing) * spacing;
|
||||
var numSpaces = (niceMax - niceMin) / spacing;
|
||||
|
||||
// If very close to our rounded value, use it.
|
||||
@ -198,71 +217,74 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
// Put the values into the ticks array
|
||||
this.ticks.push(this.options.ticks.min !== undefined ? this.options.ticks.min : niceMin);
|
||||
ticks.push(tickOpts.min !== undefined ? tickOpts.min : niceMin);
|
||||
for (var j = 1; j < numSpaces; ++j) {
|
||||
this.ticks.push(niceMin + (j * spacing));
|
||||
ticks.push(niceMin + (j * spacing));
|
||||
}
|
||||
this.ticks.push(this.options.ticks.max !== undefined ? this.options.ticks.max : niceMax);
|
||||
ticks.push(tickOpts.max !== undefined ? tickOpts.max : niceMax);
|
||||
|
||||
if (this.options.position === "left" || this.options.position === "right") {
|
||||
if (!isHorizontal) {
|
||||
// We are in a vertical orientation. The top value is the highest. So reverse the array
|
||||
this.ticks.reverse();
|
||||
ticks.reverse();
|
||||
}
|
||||
|
||||
// At this point, we need to update our max and min given the tick values since we have expanded the
|
||||
// range of the scale
|
||||
this.max = helpers.max(this.ticks);
|
||||
this.min = helpers.min(this.ticks);
|
||||
_this.max = helpers.max(ticks);
|
||||
_this.min = helpers.min(ticks);
|
||||
|
||||
if (this.options.ticks.reverse) {
|
||||
this.ticks.reverse();
|
||||
if (tickOpts.reverse) {
|
||||
ticks.reverse();
|
||||
|
||||
this.start = this.max;
|
||||
this.end = this.min;
|
||||
_this.start = _this.max;
|
||||
_this.end = _this.min;
|
||||
} else {
|
||||
this.start = this.min;
|
||||
this.end = this.max;
|
||||
_this.start = _this.min;
|
||||
_this.end = _this.max;
|
||||
}
|
||||
},
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
|
||||
},
|
||||
convertTicksToLabels: function() {
|
||||
this.ticksAsNumbers = this.ticks.slice();
|
||||
this.zeroLineIndex = this.ticks.indexOf(0);
|
||||
var _this = this;
|
||||
_this.ticksAsNumbers = _this.ticks.slice();
|
||||
_this.zeroLineIndex = _this.ticks.indexOf(0);
|
||||
|
||||
Chart.Scale.prototype.convertTicksToLabels.call(this);
|
||||
Chart.Scale.prototype.convertTicksToLabels.call(_this);
|
||||
},
|
||||
// Utils
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
// This must be called after fit has been run so that
|
||||
// this.left, this.top, this.right, and this.bottom have been defined
|
||||
var rightValue = +this.getRightValue(value);
|
||||
var pixel;
|
||||
var range = this.end - this.start;
|
||||
var _this = this;
|
||||
var paddingLeft = _this.paddingLeft;
|
||||
var paddingBottom = _this.paddingBottom;
|
||||
var start = _this.start;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
pixel = this.left + (innerWidth / range * (rightValue - this.start));
|
||||
return Math.round(pixel + this.paddingLeft);
|
||||
var rightValue = +_this.getRightValue(value);
|
||||
var pixel;
|
||||
var innerDimension;
|
||||
var range = _this.end - start;
|
||||
|
||||
if (_this.isHorizontal()) {
|
||||
innerDimension = _this.width - (paddingLeft + _this.paddingRight);
|
||||
pixel = _this.left + (innerDimension / range * (rightValue - start));
|
||||
return Math.round(pixel + paddingLeft);
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (rightValue - this.start));
|
||||
innerDimension = _this.height - (_this.paddingTop + paddingBottom);
|
||||
pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (rightValue - start));
|
||||
return Math.round(pixel);
|
||||
}
|
||||
},
|
||||
getValueForPixel: function(pixel) {
|
||||
var offset;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
offset = (pixel - this.left - this.paddingLeft) / innerWidth;
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
offset = (this.bottom - this.paddingBottom - pixel) / innerHeight;
|
||||
}
|
||||
|
||||
return this.start + ((this.end - this.start) * offset);
|
||||
var _this = this;
|
||||
var isHorizontal = _this.isHorizontal();
|
||||
var paddingLeft = _this.paddingLeft;
|
||||
var paddingBottom = _this.paddingBottom;
|
||||
var innerDimension = isHorizontal ? _this.width - (paddingLeft + _this.paddingRight) : _this.height - (_this.paddingTop + paddingBottom);
|
||||
var offset = (isHorizontal ? pixel - _this.left - paddingLeft : _this.bottom - paddingBottom - pixel) / innerDimension;
|
||||
return _this.start + ((_this.end - _this.start) * offset);
|
||||
},
|
||||
getPixelForTick: function(index, includeOffset) {
|
||||
return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);
|
||||
|
164
vendors/Chart.js/src/scales/scale.logarithmic.js
vendored
@ -10,7 +10,7 @@ module.exports = function(Chart) {
|
||||
// label settings
|
||||
ticks: {
|
||||
callback: function(value, index, arr) {
|
||||
var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));
|
||||
var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));
|
||||
|
||||
if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {
|
||||
return value.toExponential();
|
||||
@ -23,99 +23,116 @@ module.exports = function(Chart) {
|
||||
|
||||
var LogarithmicScale = Chart.Scale.extend({
|
||||
determineDataLimits: function() {
|
||||
// Calculate Range
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
var _this = this;
|
||||
var opts = _this.options;
|
||||
var tickOpts = opts.ticks;
|
||||
var chart = _this.chart;
|
||||
var data = chart.data;
|
||||
var datasets = data.datasets;
|
||||
var getValueOrDefault = helpers.getValueOrDefault;
|
||||
var isHorizontal = _this.isHorizontal();
|
||||
function IDMatches(meta) {
|
||||
return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;
|
||||
}
|
||||
|
||||
if (this.options.stacked) {
|
||||
// Calculate Range
|
||||
_this.min = null;
|
||||
_this.max = null;
|
||||
|
||||
if (opts.stacked) {
|
||||
var valuesPerType = {};
|
||||
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
var meta = this.chart.getDatasetMeta(datasetIndex);
|
||||
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
|
||||
helpers.each(datasets, function(dataset, datasetIndex) {
|
||||
var meta = chart.getDatasetMeta(datasetIndex);
|
||||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
|
||||
if (valuesPerType[meta.type] === undefined) {
|
||||
valuesPerType[meta.type] = [];
|
||||
}
|
||||
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var values = valuesPerType[meta.type];
|
||||
var value = +this.getRightValue(rawValue);
|
||||
var value = +_this.getRightValue(rawValue);
|
||||
if (isNaN(value) || meta.data[index].hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
values[index] = values[index] || 0;
|
||||
|
||||
if (this.options.relativePoints) {
|
||||
if (opts.relativePoints) {
|
||||
values[index] = 100;
|
||||
} else {
|
||||
// Don't need to split positive and negative since the log scale can't handle a 0 crossing
|
||||
values[index] += value;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
|
||||
helpers.each(valuesPerType, function(valuesForType) {
|
||||
var minVal = helpers.min(valuesForType);
|
||||
var maxVal = helpers.max(valuesForType);
|
||||
this.min = this.min === null ? minVal : Math.min(this.min, minVal);
|
||||
this.max = this.max === null ? maxVal : Math.max(this.max, maxVal);
|
||||
}, this);
|
||||
_this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);
|
||||
_this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);
|
||||
});
|
||||
|
||||
} else {
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
var meta = this.chart.getDatasetMeta(datasetIndex);
|
||||
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
|
||||
helpers.each(datasets, function(dataset, datasetIndex) {
|
||||
var meta = chart.getDatasetMeta(datasetIndex);
|
||||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = +this.getRightValue(rawValue);
|
||||
var value = +_this.getRightValue(rawValue);
|
||||
if (isNaN(value) || meta.data[index].hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
if (_this.min === null) {
|
||||
_this.min = value;
|
||||
} else if (value < _this.min) {
|
||||
_this.min = value;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
if (_this.max === null) {
|
||||
_this.max = value;
|
||||
} else if (value > _this.max) {
|
||||
_this.max = value;
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
|
||||
this.min = this.options.ticks.min !== undefined ? this.options.ticks.min : this.min;
|
||||
this.max = this.options.ticks.max !== undefined ? this.options.ticks.max : this.max;
|
||||
_this.min = getValueOrDefault(tickOpts.min, _this.min);
|
||||
_this.max = getValueOrDefault(tickOpts.max, _this.max);
|
||||
|
||||
if (this.min === this.max) {
|
||||
if (this.min !== 0 && this.min !== null) {
|
||||
this.min = Math.pow(10, Math.floor(helpers.log10(this.min)) - 1);
|
||||
this.max = Math.pow(10, Math.floor(helpers.log10(this.max)) + 1);
|
||||
if (_this.min === _this.max) {
|
||||
if (_this.min !== 0 && _this.min !== null) {
|
||||
_this.min = Math.pow(10, Math.floor(helpers.log10(_this.min)) - 1);
|
||||
_this.max = Math.pow(10, Math.floor(helpers.log10(_this.max)) + 1);
|
||||
} else {
|
||||
this.min = 1;
|
||||
this.max = 10;
|
||||
_this.min = 1;
|
||||
_this.max = 10;
|
||||
}
|
||||
}
|
||||
},
|
||||
buildTicks: function() {
|
||||
var _this = this;
|
||||
var opts = _this.options;
|
||||
var tickOpts = opts.ticks;
|
||||
var getValueOrDefault = helpers.getValueOrDefault;
|
||||
|
||||
// Reset the ticks array. Later on, we will draw a grid line at these positions
|
||||
// The array simply contains the numerical value of the spots where ticks will be
|
||||
this.ticks = [];
|
||||
var ticks = _this.ticks = [];
|
||||
|
||||
// Figure out what the max number of ticks we can support it is based on the size of
|
||||
// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
|
||||
// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
|
||||
// the graph
|
||||
|
||||
var tickVal = this.options.ticks.min !== undefined ? this.options.ticks.min : Math.pow(10, Math.floor(helpers.log10(this.min)));
|
||||
var tickVal = getValueOrDefault(tickOpts.min, Math.pow(10, Math.floor(helpers.log10(_this.min))));
|
||||
|
||||
while (tickVal < this.max) {
|
||||
this.ticks.push(tickVal);
|
||||
while (tickVal < _this.max) {
|
||||
ticks.push(tickVal);
|
||||
|
||||
var exp = Math.floor(helpers.log10(tickVal));
|
||||
var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;
|
||||
@ -128,27 +145,27 @@ module.exports = function(Chart) {
|
||||
tickVal = significand * Math.pow(10, exp);
|
||||
}
|
||||
|
||||
var lastTick = this.options.ticks.max !== undefined ? this.options.ticks.max : tickVal;
|
||||
this.ticks.push(lastTick);
|
||||
var lastTick = getValueOrDefault(tickOpts.max, tickVal);
|
||||
ticks.push(lastTick);
|
||||
|
||||
if (this.options.position === "left" || this.options.position === "right") {
|
||||
if (!_this.isHorizontal()) {
|
||||
// We are in a vertical orientation. The top value is the highest. So reverse the array
|
||||
this.ticks.reverse();
|
||||
ticks.reverse();
|
||||
}
|
||||
|
||||
// At this point, we need to update our max and min given the tick values since we have expanded the
|
||||
// range of the scale
|
||||
this.max = helpers.max(this.ticks);
|
||||
this.min = helpers.min(this.ticks);
|
||||
_this.max = helpers.max(ticks);
|
||||
_this.min = helpers.min(ticks);
|
||||
|
||||
if (this.options.ticks.reverse) {
|
||||
this.ticks.reverse();
|
||||
if (tickOpts.reverse) {
|
||||
ticks.reverse();
|
||||
|
||||
this.start = this.max;
|
||||
this.end = this.min;
|
||||
_this.start = _this.max;
|
||||
_this.end = _this.min;
|
||||
} else {
|
||||
this.start = this.min;
|
||||
this.end = this.max;
|
||||
_this.start = _this.min;
|
||||
_this.end = _this.max;
|
||||
}
|
||||
},
|
||||
convertTicksToLabels: function() {
|
||||
@ -164,48 +181,55 @@ module.exports = function(Chart) {
|
||||
return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);
|
||||
},
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
var _this = this;
|
||||
var innerDimension;
|
||||
var pixel;
|
||||
|
||||
var newVal = +this.getRightValue(value)
|
||||
; var range = helpers.log10(this.end) - helpers.log10(this.start);
|
||||
var start = _this.start;
|
||||
var newVal = +_this.getRightValue(value);
|
||||
var range = helpers.log10(_this.end) - helpers.log10(start);
|
||||
var paddingTop = _this.paddingTop;
|
||||
var paddingBottom = _this.paddingBottom;
|
||||
var paddingLeft = _this.paddingLeft;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
if (_this.isHorizontal()) {
|
||||
|
||||
if (newVal === 0) {
|
||||
pixel = this.left + this.paddingLeft;
|
||||
pixel = _this.left + paddingLeft;
|
||||
} else {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
pixel = this.left + (innerWidth / range * (helpers.log10(newVal) - helpers.log10(this.start)));
|
||||
pixel += this.paddingLeft;
|
||||
innerDimension = _this.width - (paddingLeft + _this.paddingRight);
|
||||
pixel = _this.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
|
||||
pixel += paddingLeft;
|
||||
}
|
||||
} else {
|
||||
// Bottom - top since pixels increase downard on a screen
|
||||
if (newVal === 0) {
|
||||
pixel = this.top + this.paddingTop;
|
||||
pixel = _this.top + paddingTop;
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (helpers.log10(newVal) - helpers.log10(this.start)));
|
||||
innerDimension = _this.height - (paddingTop + paddingBottom);
|
||||
pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
|
||||
}
|
||||
}
|
||||
|
||||
return pixel;
|
||||
},
|
||||
getValueForPixel: function(pixel) {
|
||||
var _this = this;
|
||||
var offset;
|
||||
var range = helpers.log10(this.end) - helpers.log10(this.start);
|
||||
var range = helpers.log10(_this.end) - helpers.log10(_this.start);
|
||||
var value;
|
||||
var innerDimension;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
value = this.start * Math.pow(10, (pixel - this.left - this.paddingLeft) * range / innerWidth);
|
||||
if (_this.isHorizontal()) {
|
||||
innerDimension = _this.width - (_this.paddingLeft + _this.paddingRight);
|
||||
value = _this.start * Math.pow(10, (pixel - _this.left - _this.paddingLeft) * range / innerDimension);
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
value = Math.pow(10, (this.bottom - this.paddingBottom - pixel) * range / innerHeight) / this.start;
|
||||
innerDimension = _this.height - (_this.paddingTop + _this.paddingBottom);
|
||||
value = Math.pow(10, (_this.bottom - _this.paddingBottom - pixel) * range / innerDimension) / _this.start;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
});
|
||||
Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
|
||||
var defaultConfig = {
|
||||
display: true,
|
||||
@ -49,6 +50,7 @@ module.exports = function(Chart) {
|
||||
return this.chart.data.labels.length;
|
||||
},
|
||||
setDimensions: function() {
|
||||
var options = this.options;
|
||||
// Set the unconstrained dimension before label rotation
|
||||
this.width = this.maxWidth;
|
||||
this.height = this.maxHeight;
|
||||
@ -56,8 +58,8 @@ module.exports = function(Chart) {
|
||||
this.yCenter = Math.round(this.height / 2);
|
||||
|
||||
var minSize = helpers.min([this.height, this.width]);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
this.drawingArea = (this.options.display) ? (minSize / 2) - (tickFontSize / 2 + this.options.ticks.backdropPaddingY) : (minSize / 2);
|
||||
var tickFontSize = helpers.getValueOrDefault(options.ticks.fontSize, globalDefaults.defaultFontSize);
|
||||
this.drawingArea = (options.display) ? (minSize / 2) - (tickFontSize / 2 + options.ticks.backdropPaddingY) : (minSize / 2);
|
||||
},
|
||||
determineDataLimits: function() {
|
||||
this.min = null;
|
||||
@ -129,7 +131,7 @@ module.exports = function(Chart) {
|
||||
// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
|
||||
// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
|
||||
// the graph
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);
|
||||
var maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));
|
||||
maxTicks = Math.max(2, maxTicks); // Make sure we always have at least 2 ticks
|
||||
|
||||
@ -206,9 +208,10 @@ module.exports = function(Chart) {
|
||||
* https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
|
||||
*/
|
||||
|
||||
var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var pointLabels = this.options.pointLabels;
|
||||
var pointLabelFontSize = helpers.getValueOrDefault(pointLabels.fontSize, globalDefaults.defaultFontSize);
|
||||
var pointLabeFontStyle = helpers.getValueOrDefault(pointLabels.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var pointLabeFontFamily = helpers.getValueOrDefault(pointLabels.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
|
||||
|
||||
// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
|
||||
@ -318,6 +321,19 @@ module.exports = function(Chart) {
|
||||
getPointPositionForValue: function(index, value) {
|
||||
return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
|
||||
},
|
||||
|
||||
getBasePosition: function() {
|
||||
var me = this;
|
||||
var min = me.min;
|
||||
var max = me.max;
|
||||
|
||||
return me.getPointPositionForValue(0,
|
||||
me.beginAtZero? 0:
|
||||
min < 0 && max < 0? max :
|
||||
min > 0 && max > 0? min :
|
||||
0);
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
if (this.options.display) {
|
||||
var ctx = this.ctx;
|
||||
@ -355,10 +371,10 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
if (this.options.ticks.display) {
|
||||
var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, globalDefaults.defaultFontColor);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
ctx.font = tickLabelFont;
|
||||
|
||||
@ -397,10 +413,10 @@ module.exports = function(Chart) {
|
||||
// Extra 3px out for some label spacing
|
||||
var pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);
|
||||
|
||||
var pointLabelFontColor = helpers.getValueOrDefault(this.options.pointLabels.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var pointLabelFontColor = helpers.getValueOrDefault(this.options.pointLabels.fontColor, globalDefaults.defaultFontColor);
|
||||
var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, globalDefaults.defaultFontSize);
|
||||
var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, globalDefaults.defaultFontStyle);
|
||||
var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, globalDefaults.defaultFontFamily);
|
||||
var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
|
||||
|
||||
ctx.font = pointLabeFont;
|
||||
|
34
vendors/Chart.js/src/scales/scale.time.js
vendored
@ -47,6 +47,7 @@ module.exports = function(Chart) {
|
||||
unit: false, // false == automatic or override with week, month, year, etc.
|
||||
round: false, // none, or override with week, month, year, etc.
|
||||
displayFormat: false, // DEPRECATED
|
||||
isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/
|
||||
|
||||
// defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormats: {
|
||||
@ -77,6 +78,13 @@ module.exports = function(Chart) {
|
||||
getLabelMoment: function(datasetIndex, index) {
|
||||
return this.labelMoments[datasetIndex][index];
|
||||
},
|
||||
getMomentStartOf: function(tick) {
|
||||
if (this.options.time.unit === 'week' && this.options.time.isoWeekday !== false) {
|
||||
return tick.clone().startOf('isoWeek').isoWeekday(this.options.time.isoWeekday);
|
||||
} else {
|
||||
return tick.clone().startOf(this.tickUnit);
|
||||
}
|
||||
},
|
||||
determineDataLimits: function() {
|
||||
this.labelMoments = [];
|
||||
|
||||
@ -106,7 +114,7 @@ module.exports = function(Chart) {
|
||||
var momentsForDataset = [];
|
||||
var datasetVisible = this.chart.isDatasetVisible(datasetIndex);
|
||||
|
||||
if (typeof dataset.data[0] === 'object') {
|
||||
if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
var labelMoment = this.parseTime(this.getRightValue(value));
|
||||
|
||||
@ -208,8 +216,8 @@ module.exports = function(Chart) {
|
||||
unitDefinition = time.units[unitDefinitionIndex];
|
||||
|
||||
this.tickUnit = unitDefinition.name;
|
||||
var leadingUnitBuffer = this.firstTick.diff(this.firstTick.clone().startOf(this.tickUnit), this.tickUnit, true);
|
||||
var trailingUnitBuffer = this.lastTick.clone().add(1, this.tickUnit).startOf(this.tickUnit).diff(this.lastTick, this.tickUnit, true);
|
||||
var leadingUnitBuffer = this.firstTick.diff(this.getMomentStartOf(this.firstTick), this.tickUnit, true);
|
||||
var trailingUnitBuffer = this.getMomentStartOf(this.lastTick.clone().add(1, this.tickUnit)).diff(this.lastTick, this.tickUnit, true);
|
||||
this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer;
|
||||
this.displayFormat = this.options.time.displayFormats[unitDefinition.name];
|
||||
}
|
||||
@ -220,18 +228,18 @@ module.exports = function(Chart) {
|
||||
|
||||
// Only round the first tick if we have no hard minimum
|
||||
if (!this.options.time.min) {
|
||||
this.firstTick.startOf(this.tickUnit);
|
||||
this.firstTick = this.getMomentStartOf(this.firstTick);
|
||||
roundedStart = this.firstTick;
|
||||
} else {
|
||||
roundedStart = this.firstTick.clone().startOf(this.tickUnit);
|
||||
roundedStart = this.getMomentStartOf(this.firstTick);
|
||||
}
|
||||
|
||||
// Only round the last tick if we have no hard maximum
|
||||
if (!this.options.time.max) {
|
||||
var roundedEnd = this.lastTick.clone().startOf(this.tickUnit);
|
||||
var roundedEnd = this.getMomentStartOf(this.lastTick);
|
||||
if (roundedEnd.diff(this.lastTick, this.tickUnit, true) !== 0) {
|
||||
// Do not use end of because we need this to be in the next time unit
|
||||
this.lastTick.add(1, this.tickUnit).startOf(this.tickUnit);
|
||||
this.lastTick = this.getMomentStartOf(this.lastTick.add(1, this.tickUnit));
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +286,7 @@ module.exports = function(Chart) {
|
||||
this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.ctx.restore();
|
||||
},
|
||||
// Get tooltip label
|
||||
@ -299,14 +307,17 @@ module.exports = function(Chart) {
|
||||
// Function to format an individual tick mark
|
||||
tickFormatFunction: function tickFormatFunction(tick, index, ticks) {
|
||||
var formattedTick = tick.format(this.displayFormat);
|
||||
var tickOpts = this.options.ticks;
|
||||
var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);
|
||||
|
||||
if (this.options.ticks.userCallback) {
|
||||
return this.options.ticks.userCallback(formattedTick, index, ticks);
|
||||
if (callback) {
|
||||
return callback(formattedTick, index, ticks);
|
||||
} else {
|
||||
return formattedTick;
|
||||
}
|
||||
},
|
||||
convertTicksToLabels: function() {
|
||||
this.tickMoments = this.ticks;
|
||||
this.ticks = this.ticks.map(this.tickFormatFunction, this);
|
||||
},
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
@ -332,6 +343,9 @@ module.exports = function(Chart) {
|
||||
}
|
||||
}
|
||||
},
|
||||
getPixelForTick: function(index, includeOffset) {
|
||||
return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);
|
||||
},
|
||||
getValueForPixel: function(pixel) {
|
||||
var innerDimension = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);
|
||||
var offset = (pixel - (this.isHorizontal() ? this.left + this.paddingLeft : this.top + this.paddingTop)) / innerDimension;
|
||||
|
35
vendors/Chart.js/test/core.helpers.tests.js
vendored
@ -215,6 +215,7 @@ describe('Core helper tests', function() {
|
||||
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
tickMarkLength: 10,
|
||||
@ -231,6 +232,7 @@ describe('Core helper tests', function() {
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -238,7 +240,8 @@ describe('Core helper tests', function() {
|
||||
display: true,
|
||||
callback: merged.scales.yAxes[1].ticks.callback, // make it nicer, then check explicitly below
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0,
|
||||
},
|
||||
type: 'linear'
|
||||
}, {
|
||||
@ -246,6 +249,7 @@ describe('Core helper tests', function() {
|
||||
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label,
|
||||
tickMarkLength: 10,
|
||||
@ -262,6 +266,7 @@ describe('Core helper tests', function() {
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -269,7 +274,8 @@ describe('Core helper tests', function() {
|
||||
display: true,
|
||||
callback: merged.scales.yAxes[2].ticks.callback, // make it nicer, then check explicitly below
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0,
|
||||
},
|
||||
type: 'linear'
|
||||
}]
|
||||
@ -684,4 +690,29 @@ describe('Core helper tests', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Background hover color helper', function() {
|
||||
it('should return a CanvasPattern when called with a CanvasPattern', function(done) {
|
||||
var dots = new Image();
|
||||
dots.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAAD1BMVEUAAAD///////////////+PQt5oAAAABXRSTlMAHlFhZsfk/BEAAAAqSURBVHgBY2BgZGJmYmSAAUYWEIDzmcBcJhiXGcxlRpPFrhdmMiqgvX0AcGIBEUAo6UAAAAAASUVORK5CYII=';
|
||||
dots.onload = function() {
|
||||
var chartContext = document.createElement('canvas').getContext('2d');
|
||||
var patternCanvas = document.createElement('canvas');
|
||||
var patternContext = patternCanvas.getContext('2d');
|
||||
var pattern = patternContext.createPattern(dots, 'repeat');
|
||||
patternContext.fillStyle = pattern;
|
||||
|
||||
var backgroundColor = helpers.getHoverColor(chartContext.createPattern(patternCanvas, 'repeat'));
|
||||
|
||||
expect(backgroundColor instanceof CanvasPattern).toBe(true);
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should return a modified version of color when called with a color', function() {
|
||||
var originalColorRGB = 'rgb(70, 191, 189)';
|
||||
|
||||
expect(helpers.getHoverColor('#46BFBD')).not.toEqual(originalColorRGB);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
29
vendors/Chart.js/test/core.scaleService.tests.js
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Tests of the scale service
|
||||
describe('Test the scale service', function() {
|
||||
|
||||
it('should update scale defaults', function() {
|
||||
var defaults = {
|
||||
testProp: true
|
||||
};
|
||||
var type = 'my_test_type';
|
||||
var Constructor = function() {
|
||||
this.initialized = true;
|
||||
};
|
||||
Chart.scaleService.registerScaleType(type, Constructor, defaults);
|
||||
|
||||
// Should equal defaults but not be an identical object
|
||||
expect(Chart.scaleService.getScaleDefaults(type)).toEqual(jasmine.objectContaining({
|
||||
testProp: true
|
||||
}));
|
||||
|
||||
Chart.scaleService.updateScaleDefaults(type, {
|
||||
testProp: 'red',
|
||||
newProp: 42
|
||||
});
|
||||
|
||||
expect(Chart.scaleService.getScaleDefaults(type)).toEqual(jasmine.objectContaining({
|
||||
testProp: 'red',
|
||||
newProp: 42
|
||||
}));
|
||||
});
|
||||
});
|
14
vendors/Chart.js/test/core.title.tests.js
vendored
@ -107,9 +107,21 @@ describe('Title block tests', function() {
|
||||
expect(context.getCalls()).toEqual([{
|
||||
name: 'setFillStyle',
|
||||
args: ['#666']
|
||||
}, {
|
||||
name: 'save',
|
||||
args: []
|
||||
}, {
|
||||
name: 'translate',
|
||||
args: [300, 66]
|
||||
}, {
|
||||
name: 'rotate',
|
||||
args: [0]
|
||||
}, {
|
||||
name: 'fillText',
|
||||
args: ['My title', 300, 66]
|
||||
args: ['My title', 0, 0]
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
|
||||
|
@ -14,6 +14,7 @@ describe('Category scale tests', function() {
|
||||
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
tickMarkLength: 10,
|
||||
@ -30,6 +31,7 @@ describe('Category scale tests', function() {
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -37,7 +39,8 @@ describe('Category scale tests', function() {
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0
|
||||
}
|
||||
});
|
||||
|
||||
|
32
vendors/Chart.js/test/scale.linear.tests.js
vendored
@ -25,6 +25,7 @@ describe('Linear Scale', function() {
|
||||
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
tickMarkLength: 10,
|
||||
@ -41,6 +42,7 @@ describe('Linear Scale', function() {
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -48,7 +50,8 @@ describe('Linear Scale', function() {
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this work nicer, then check below
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0
|
||||
}
|
||||
});
|
||||
|
||||
@ -409,6 +412,31 @@ describe('Linear Scale', function() {
|
||||
expect(chartInstance.scales.yScale0.max).toBe(1);
|
||||
});
|
||||
|
||||
it('Should ensure that the scale has a max and min that are not equal when beginAtZero is set', function() {
|
||||
chartInstance = window.acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [],
|
||||
labels: ['a', 'b', 'c', 'd', 'e', 'f']
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
id: 'yScale0',
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(chartInstance.scales.yScale0).not.toEqual(undefined); // must construct
|
||||
expect(chartInstance.scales.yScale0.min).toBe(0);
|
||||
expect(chartInstance.scales.yScale0.max).toBe(1);
|
||||
});
|
||||
|
||||
it('Should use the suggestedMin and suggestedMax options', function() {
|
||||
chartInstance = window.acquireChart({
|
||||
type: 'bar',
|
||||
@ -608,7 +636,7 @@ describe('Linear Scale', function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var xScale = chartInstance.scales.xScale0;
|
||||
expect(xScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(501); // right - paddingRight
|
||||
expect(xScale.getPixelForValue(-1, 0, 0)).toBeCloseToPixel(41); // left + paddingLeft
|
||||
|
@ -20,6 +20,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
tickMarkLength: 10,
|
||||
@ -36,6 +37,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
@ -43,7 +45,8 @@ describe('Logarithmic Scale tests', function() {
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 0
|
||||
autoSkipPadding: 0,
|
||||
labelOffset: 0
|
||||
},
|
||||
});
|
||||
|
||||
|