Highchart pie legend circles - javascript

Im using a highchart pie chart to create a donut chart but would like the legend icons to be circles any ideas??? Below is the mockup and the actual web version. Thanks...

In recent versions of Highcharts you can use symbolWidth: width and symbolRadius: width/2 inside legend: {}.
See this JSFiddle demonstration: http://jsfiddle.net/Wzs9L/

I prepared solution based on pie chart. Legend is generated on data points, automatically as HTML list. Then all elements gets colors from series, and use CSS3 to generate circle object (border-radius). As a result you need to add click event.
http://jsfiddle.net/N3KAC/1/
$legend = $('#customLegend');
$.each(chart.series[0].data, function (j, data) {
$legend.append('<div class="item"><div class="symbol" style="background-color:'+data.color+'"></div><div class="serieName" id="">' + data.name + '</div></div>');
});
$('#customLegend .item').click(function(){
var inx = $(this).index(),
point = chart.series[0].data[inx];
if(point.visible)
point.setVisible(false);
else
point.setVisible(true);
});
CSS:
.symbol {
width:20px;
height:20px;
margin-right:20px;
float:left;
-webkit-border-radius: 10px;
border-radius: 10px;
}
.serieName {
float:left;
cursor:pointer;
}
.item {
height:40px;
clear:both;
}

Another way to achieve this can be overriding the style using CSS.
Simply add class below to your stylesheet:
.highcharts-legend-item rect {
width: 12px;
height: 12px; /* height = width */
rx: 50%;
ry: 50%;
}
and this would override the default style for the SVG Rectangle element.

There's quite an easy fix. Just set the following properties in chartoptions:
chartoptions.legend.symbolHeight = 12;
chartoptions.legend.symbolWidth = 12;
chartoptions.legend.symbolRadius = 6;
For further reference, check highcharts api documentation.
Checkout this jsFiddle.

Related

D3 tooltip position offset from mouse when hosted on sharepoint

I have the following HTML
<div id="chart1">
<div class="tooltip"></div>
</div>
and here is the CSS for the tooltip
.tooltip
{
position: absolute;
border: 1px dashed gray;
background-color: white;
padding: 5px 20px;
min-width: 50px;
min-height: 20px;
text-align: center;
visibility: hidden;
pointer-events: none;
}
and here is my JS
pie.on("mouseenter",function(){
d3.select("#chart1 .tooltip").style("visibility", "visible");
})
.on('mousemove',function(d){
var tooltip = d3.select("#chart1 .tooltip");
show_data(tooltip,d); // custom function to populate tooltip html
tooltip.style("left", (d3.event.pageX - 50) + "px")
.style("top", (d3.event.pageY - 40) + "px");
});
This works perfectly on my local machine, both in Chrome and Explorer Edge.
But when I host all of the files on sharepoint, the tooltip is offset from the mouse pointer. It still follows the same direction as the mouse, but there is a gap in the Y position.
Please see the image below to understand what is going on.
I tried a combination of things, including using window.pageYOffset but that did not work. I am sure sharepoint is adding iframes or sub-html documents behind the scene which makes the mouse position on the SVG element differs from when the file is directly displayed without sharepoint intervention.
What can I do to make the tooltip stick to the mouse position on sharepoint hosted files?
I managed to find a solution to my question.
Instead of populating pure html element with tooltip data, I decided to create an SVG group within my chart.
That worked perfectly across all browsers and even locally
var pie = svg.selectAll(".pie")
.on('mouseenter',show_tooltip)
.on('mousemove',move_tooltip)
.on('mouseout',hide_tooltip );
function create_tooltip() {
tooltip = svg.append("g")
.attr("class","tooltip");
tooltip.append("rect").attr("class","box");
tooltip.append("text").attr("id","division");
tooltip.append("rect").attr("id","legend")
.attr("width","20")
.attr("height","20");
}
function move_tooltip(d) {
var coords = d3.mouse(this);
var x = coords[0] - 30;
var y = coords[1] - 40;
tooltip.attr("transform","translate("+x+","+y+")");
}
function hide_tooltip(d) {
tooltip.transition().attr("opacity","0");
}
function show_tooltip(d) {
tooltip.transition().delay(500).attr("opacity","0.95");
tooltip.select("#division").text(d.data.division);
tooltip.select("#legend").attr("fill",function(){
return color(d.data.division)
});
}

AngularJS UI Bootstrap merge two progress bars

I have set up two progress bars in UI Bootstrap, however my goal is to merge them into one, main bar and a secondary one which only is in the form of a vertical bar.
Here is the HTML code for my progress bars:
<div>
<h3 class="inline-block no-margin">Main</h3>
<uib-progressbar value="95"
class="progress-xs no-radius"
type="success"></uib-progressbar>
<h4 class="no-margin">SubCategory</h4>
<uib-progressbar value="50"
class="progress-xs no-radius no-margin"
type="danger"></uib-progressbar>
</div>
My question is how can I merge these two so that the secondary one only appears as a small vertical bar on the main bar?
So that the main bar showing 95% of the bar and the subcategory showing only a vertical bar at 50%.
There is an example similar to this in here called limit lines, but it is another old library.
You can make use of ng-style to update the position of a vertical line div in order to solve this problem. This will allow you to easily set the position and value of the vertical bar. Check out this working example on plunkr.:
HTML
<uib-progressbar animate="false" value=95 type="success"><b>95%</b></uib-progressbar>
<div id="vertical-mark" ng-style="style()"> {{mark}}%</div>
JS
$scope.mark = 50;
$scope.style = function() {
return {
'left': $scope.mark + '%'
}
}
CSS
#vertical-mark {
position:relative;
border-left:1px solid #000;
height:50px;
top:-57px;
}
As an alternative I've also added a similar implementation with a stacked progress-bar.
I haven't tried this out on my own, but it's what came to mind when I saw your question.
You could modify the CSS of the ui-progressbars such that they were overlaid on one another; perhaps with an position:absolute or what have you. This would allow the numerical markers to all sit next to each other like you want.
Next, you could modify the CSS of the bars themselves. Any bars less than the max, perhaps give them a .no-fill class or something. It would be tricky, but that way you can have any bars less than max % to only consist of a border-right property, while the max % bar would be the one with the background and all the normal progress bar styles.
A gotcha that might show up is that you may also have to order the bars' z-index so that the largest value bar sits behind the lesser values and their vertical lines show up.
Good luck!
FINAL UPDATE (with plunkr)
JS
$scope.stacked = [{
value: 55,
type: 'info'
}, {
value: 95,
type: 'success'
}];
HTML
<div class="progress-wrapper">
<uib-progress max="100" ng-repeat="bar in stacked | orderBy:'value':true">
<uib-bar value="bar.value" type="{{bar.type}}">
<span class="marker" ng-hide="bar.value < 5">
{{bar.value}}%
</span>
</uib-bar>
</uib-progress>
</div>
CSS
/* wrapper to help us contain the bars and their positioning */
.progress-wrapper {
position: relative;
padding-top: 30px;
}
/* make all progress bars the same, no bg so they 'stack' */
.progress-wrapper .progress {
width: 100%;
position: absolute;
overflow: visible;
background: none;
}
/* first child is the background bar, give it color */
.progress-wrapper .progress:first-child {
background: #EEE;
}
/* make all bars invisible and with a right, border;
except the last/furthest back bar, give it color only
*/
.progress-wrapper .progress .progress-bar {
background: none;
border-right: solid 2px #FFF;
}
.progress-wrapper .progress:first-child .progress-bar {
background: #0AF;
border-right: none;
}
/* makes sure that markers behave,
otherwise they'll fly away
*/
.progress .progress-bar {
position: relative;
}
/* style for marker element and drop triangle */
.progress .marker {
position: absolute;
padding: 0 2px;
top: -30px;
right: -15px;
color: #FFF;
background: #000;
}
.progress .marker:after {
content: '';
width: 10px;
height: 10px;
background: #000;
position: absolute;
left: 30%;
bottom: -5px;
transform: rotate(45deg);
}
You can make use of stacked progressbar with some custom styles.
<uib-progress><uib-bar ng-repeat="bar in stacked track by $index" value="bar.value" type="{{bar.type}}"><span ng-hide="bar.value < 5">{{bar.value}}%</span></uib-bar></uib-progress>
$scope.stacked = [{
value: 10,
type: 'info'
}, {
value: 35,
type: 'success'
}];
});
Refer progressbar in this https://angular-ui.github.io/bootstrap/
My example is here https://plnkr.co/edit/9qCP1lV40BQ9DYDHvayo?p=preview
I have edited the code in stacked progressbar. Think this helps.
You can add custom styles to this to show the progress value.

dc.js legend is not displaying

I have a pie chart that I am displaying within a quadrant <div> box. The pie chart displays fine and when I inspect the element on the page I can see the legend but it has a width and height of 0. I've tried using .dc-legend svg { width: 100px; height: 100px; } to force it to be a certain size but it remains 0x0
<div class="quadrant_right">
<div id="CityCharttext"><span>Dummy graph</span></div>
<div id="city-chart"></div>
</div>
<script>
function InitPieChart(string){
// cities.forEach(function(city){
cities.forEach(function(city){
DataForPieGraph.push({Name:city,data:(test.SumHelper(Projectsall, city, string))});
})
var ndx = crossfilter(DataForPieGraph),
nameDim = ndx.dimension(function(d) {return d.Name;}),
spendPerName = nameDim.group().reduceSum(function(d) {return +d.data;});
CityChart
.width(200).height(176)
.dimension(nameDim)
.group(spendPerName)
.innerRadius(30)
.colors(['#39393B', '#58585B', '#858688', '#A7A9AB','#E8EBF1','#C4D6ED','#64BBE3','#049FD9','#097DBC','#004BAF'])
.label(function(d) { return d.data.value})
.legend(dc.legend().x(0).y(0).itemHeight(13).gap(5));
CityChart.render()
}
</script>
I left out a bunch of other stuff to focus my topic on this question and to not clutter up the code, but I may have left something out.
Thanks in advance!!
CSS
#city-chart svg { width: 350px; }
#city-chart{
width:350px;
border: 1px solid black;
height: 100%;
margin: 0px -1px;
position:relative;
float:left;
}
Try setting the CSS for #city-chart too.

How do I render a 1px gutter between segments with a very small percentage width?

I am creating a UI control. It is a bar which shows colored areas in relative proportion to each other based on the input. A few of the requirements are that there be a 1px gutter between the colors and that every color must be shown at a minimum of 1px no matter how small the relative width.
The bar looks like this:
The gutters are being placed using a technique described by the pocketgrid documentation:
.threshold-container {
height: 8px;
$threshold-horiz-gutter: 1px;
&.block-group {
margin-left: -$threshold-horiz-gutter;
}
.threshold {
height: 100%;
min-width: 2px;
&.block {
padding-left: $threshold-horiz-gutter;
}
.colored-area {
height: 100%;
width: 100%;
}
}
}
There is a codepen here which provides a working example: http://codepen.io/ghoti143/pen/eZNXVW
The problem I face is that when the relative proportion of any one color is sufficiently small, the last color area wraps to the next line and looks like this:
To replicate this issue, visit the codepen project and enter this as the Threshold Array value:
[{"value":0,"color":"LightGreen"},
{"value":50,"color":"PaleGoldenrod"},
{"value":5000,"color":"LightSalmon"},
{"value":10000,"color":"Salmon"}]
In this case, the width style of the LightGreen area is 0.33333%. This equates to 0.495px at a bar width of 150px. However, because of the requirement to always show at least 1px of width for each color, the LightGreen area is consuming 2px of width (1px content + 1px padding).
Thanks for any insights you may have!
You can use the css calc function to subtract out the 1px margins from the width calculations for each section. [For example]http://codepen.io/anon/pen/ZWGNVY
coloredAreas.push({
color: thresholds[i].color,
width: 'calc(' + width + '% - 1px)'
});

How to update the margin or padding for the xAxis in nvd3 chart?

Plnkr: http://plnkr.co/edit/ymrqIOGTBqF6TVMTvC4T?p=preview
^ In my example above the xAxis time data is too close to the bottom of the chart, I've been playing with the CSS, but haven't had any luck in making anything move. Is there another way to give at least even a 5 pixel space padding/margin between the xAxis time data and the chart?
What I've tried:
#chart {
height: 400px;
}
.nv-axisMaxMin,
.nv-axisMaxMin-x,
.nv-axisMin-x {
position: relative;
top: 5px;
margin-top: 5px;
}
Even this doesn't work:
svg text {
font: 400 12px Arial;
margin-top: 5px;
position: absolute; // Just move! :'(
top: 10px;
}
Changing the css will not work, since the the x and y value attributes of the text are dynamically generated.
Here is a cheeky way of doing,
// FOR THE REGULAR VALUES
d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > g > g.tick > text').each(function(d,i){
d3.select(this).attr('dy', '2em');
});
// For the MIN and MAX values
d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > .nv-axisMaxMin > text').each(function(d,i){
d3.select(this).attr('dy', '2em');
})
Hope it helps.

Categories

Resources