I have a problem with the pie chart when the container has a display property none in small devices and I have the following error :
Uncaught IndexSizeError: Failed to execute 'arc' on 'CanvasRenderingContext2D': The radius provided (-0.5) is negative.
my HTML code is
<div class="container-fluid charts hidden-xs">
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Annual sales</div>
<div class="panel-body">
<canvas class="annualChart" width="400" height="400"></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Visitors per shop</div>
<div class="panel-body">
<canvas class="visitorsChart" width="400" height="400"></canvas>
<div id="legend"></div>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Fans</div>
<div class="panel-body">
<canvas class="annualfanschart" width="400" height="400" ></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">General sales</div>
<div class="panel-body">
<canvas class="generalSalesChart" width="400" height="400"></canvas>
</div>
</div>
</div>
</div>
</div>
and my JS code for the pie chart div is (the others are line and bar charts)
var data = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Men"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Women"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Children",
}
];
var options = {
animationSteps : 100,
animationEasing : "easeOutBounce",
animateRotate : true,
animateScale : true
}
var ctx = $(".visitorsChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx).Pie(data,{
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color: <%=segments[i].fillColor%>\"></span><%if(segments[i].label){%> <%=segments[i].label%><%}%></li><%}%></ul>"
});
var legend = myPieChart.generateLegend();
$("#legend").html(legend);
I face this problem only with the pie type, the other types doesn't show errors
There's currently a bug in chart.js: https://github.com/nnnick/Chart.js/issues/592
Try to skip chart rendering if the element is not visible
if ($(".visitorsChart").is(":visible")) {
var ctx = $(".visitorsChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx).Pie(data,{});
}
Related
I am using PhotoSwipe to display images within my web page developed using wordpress, using the code from the library to display an image as follows
<button id="btn">open</button>
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close"></button>
<button class="pswp__button pswp__button--share"></button>
<button class="pswp__button pswp__button--fs"></button>
<button class="pswp__button pswp__button--zoom"></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left"></button>
<button class="pswp__button pswp__button--arrow--right"></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
</div>
Then I implement the javascript function to show two images
<script>
var openPhotoSwipe = function(){
var pswpElement = document.querySelectorAll(\'.pswp\')[0];
var items = [{
src: \'https://empresas.blogthinkbig.com/wp-content/uploads/2019/11/Imagen3-245003649.jpg\',
w: 1440,
h:1024
},
{
src: \'https://empresas.blogthinkbig.com/wp-content/uploads/2019/11/Imagen3-245003649.jpg\',
w: 1440,
h:1024
}];
var options = {
history: false,
focus: false,
showAnimationDuration: 0,
hideAnimationDuration: 0
};
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
}
openPhotoSwipe();
document.getElementById(\'btn\').onclick = openPhotoSwipe;
</script>
Everything works fine, but when I go to my page to see the result, I find that the menu is above my PhotoSwipe
I tried to add a z-index, but it didn't work and the image is still hidden by the highlighted elements in the image
.pswp {
z-index: 9999999999999999999;
}
I'm fairly new at learning to code and I'm just playing around with something. I have a panel and I have a button above it to resize the panel.
Here is my code:
var panel = document.getElementById("panel");
function panelResize() {
if (panel.style.width >= "75%") {
panel.style.width = "50%";
} else {
panel.style.width = "75%";
}
}
<button style="margin:10px" onclick="panelResize()">button</button>
<div class="col-md-12">
<div class="col-md-6" id="panel">
<div class="panel panel-default">
<div class="panel-heading">
<p>panel heading</p>
</div>
<div class="panel-body">
<p>panel body</p>
</div>
</div>
</div>
</div>
I know this code may not be 100% so I apologize.
I would like the button to be able to increase the width of the panel to col-md-8 for example, then to return back to col-md-6 with the same button if possible.
You can do this
var panel = document.getElementById("panel");
if(panel.classList.contains('col-md-6')){
panel.classList.remove('col-md-6');
panel.classList.add('col-md-8');
} else {
panel.classList.remove('col-md-8');
panel.classList.add('col-md-6');
}
I'm using this plugin called Dragula which needs an ObservableArray as a source for the data..
HTML/Knockout-bindings
<div class="widget-container">
<div class="widget-content visible" id="team-setup">
<div class="header">
<p>Lagoppsett</p>
<p></p>
</div>
<div class="col-sm-12">
<div class="row">
<div class="widget-container">
<div class="col-xs-6 widget-content visible">
<div class="header">
<p>Tilgjengelige spillere</p>
<p></p>
</div>
<div class="player-card-container-mini" data-bind="dragula: { data: availablePlayers, group: 'playerz' } ">
<div class="player-card-mini">
<div class="player-card-left">
<div class="player-avatar" style="margin-left: 85%;">
<img src="Content/Images/player-female.png" id="imgAvatar" runat="server" />
<div class="player-shirt-no" data-bind="text: ShirtNo"></div>
</div>
</div>
<div class="player-card-subtext">
<div class="player-text">
<div class="player-card-header-small" data-bind="text: PlayerName"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-6 widget-content visible">
<div class="header">
<p>Lag</p>
<p></p>
</div>
<div data-bind="foreach: teamsetup">
<div data-bind="foreach: SubTeams">
<h1 data-bind="text: TeamSubName"></h1>
<div class="player-card-container-mini" data-bind="dragula: { data: Players, group: 'playerz' } " style="border: 1px solid red; min-height:200px">
<div class="player-card-mini">
<div class="player-card-left">
<div class="player-avatar" style="margin-left: 85%;">
<img src="Content/Images/player-female.png" id="img1" runat="server" />
<div class="player-shirt-no" data-bind="text: ShirtNo"></div>
</div>
</div>
<div class="player-card-subtext">
<div class="player-text">
<div class="player-card-header-small" data-bind="text: PlayerName"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="clear:both"> </div>
</div>
</div>
Knockout code :
var TeamSetupViewModel = function () {
var self = this;
self.teamsetup = ko.observableArray();
self.availablePlayers = ko.observableArray();
self.testPlayers = ko.observableArray();
}
var model = new TeamSetupViewModel();
ko.applyBindings(model, document.getElementById("team-setup"));
var uri = 'api/MainPage/GetTeamSetup/' + getQueryVariable("teamId");
$.get(uri,
function (data) {
model.teamsetup(data);
model.availablePlayers(data.AvailablePlayers);
model.testPlayers(data.AvailablePlayers);
console.log(data);
}, 'json');
});
The problem is... that i'm having a ObservableArray at the top node, and i do need ObservableArrays further down in the hierarchy.
model.availablePlayers works fine, but when accessing the other players in the html/ko foreach loops through teamsetup -> SubTeams -> Players it doesn't work due to Players isn't an ObservableArray. (There might be everyting from 1 to 7 SubTeams with players).
So how can i make the Players in each SubTeams an ObservableArray ?
See the image for the datastructure :
You could use Mapping plugin, but if players is the only thing you need, you can do it manually:
Simplify your view model:
var TeamSetupViewModel = function () {
var self = this;
self.availablePlayers = ko.observableArray();
self.subTeams = ko.observableArray();
}
After you get the data from the server, populate the view model converting the array of players on every team to an observable array of players:
$.get(uri,
function (data) {
model.availablePlayers(data.AvailablePlayers);
model.subTeams(data.SubTeams.map(function(t) { t.Players = ko.observableArray(t.Players); return t; }));
}, 'json');
});
Finally, remove the following line in your template (with its closing tag) - nothing to iterate over anymore:
<div data-bind="foreach: teamsetup">
... and update the name of the property in the next line, so it is camel case like in the VM:
<div data-bind="foreach: subTeams">
I have an app running with angular.js and one of my view should load an chart. I'm using chart.js for it, but for some reason it's not working and no error is shown on my console.
Here is my function that creates the chart:
$scope.writeBatteryChart = function(){
console.log("Function was called");
var data = {
labels: ["10:30am", "11:00am", "11:30am", "12:00pm", "12:30pm", "01:00pm", "01:30pm"],
datasets: [
{
label: "Battery",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}
]
};
var options = {
responsive: true,
bezierCurve : false
}
var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx).Line(data, options);
}
Here's the HTML where the chart should appear:
<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8" style="padding-left: 0px;">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Battery <i class="fi-battery-half"></i></h3>
</div>
<div class="panel-body">
<canvas id="myChart" height="300"></canvas>
</div>
</div>
</div>
<div class="col-md-4 col-sm-4 col-xs-4" style="padding-left: 0px; padding-right: 0px;">
</div>
</div>
and I'm also loading the latest version of the Chart.js:
<!--Chart plugin -->
<script src="bower_components/Chart.js/Chart.js" language="javascript"></script>
One thing that I noticed is that the canvas is being rendered with 0 dimensions:
Does someone can see where I'm doing something wrong?
The problem: I was calling the function before the canvas be loaded on the view, so I used a setTimeout() to call the writeBatteryChart() with a delay in order to wait the canvas be rendered.
You have to add your rendered things inside of canvas. Hope it will help Link
I have a new problem with Morris.js. I am currently using the redraw function to redraw the graph on tab click in order for it to display correctly. The problem is that when doing this with the donut graphs, when the graph is redrawn, the centre label position is miscalculated. Once on the tab if you hover over a section it works fine again. If you leave the tab and come back it's fine. It is just the first time the centre text loads. I assume the redraw() in morris is not covering the text. Not sure how to tackle this one.
Here is the jsfiddle http://jsfiddle.net/d1owfmoc/1/
HTML:
<div id="tabs2">
<div id="tabs-1" class="statdiv">
<h4>Tab 1</h4>
<div class="statgrid">
<div class="col-2-6">
<div id="morris-donut-chart"></div>
</div>
</div>
<div class="statgrid">
<div class="col-4-6">
<div class="col-5-6">Item 1</div>
<div class="col-1-6">£10.00</div>
</div>
</div>
</div>
<div id="tabs-2" class="statdiv">
<h4>Tab 2</h4>
<div class="statgrid">
<div class="col-2-6">
<div id="morris-donut-chart2"></div>
</div>
</div>
<div class="statgrid">
<div class="col-4-6">
<div class="col-5-6">Item 2</div>
<div class="col-1-6">£10.00</div>
</div>
</div>
</div>
<div id="tabs-3" class="statdiv">
<h4>Tab 3</h4>
<div class="statgrid">
<div class="col-2-6">
<div id="morris-donut-chart3"></div>
</div>
</div>
<div class="statgrid">
<div class="col-4-6">
<div class="col-5-6">Item 3</div>
<div class="col-1-6">£10.00</div>
</div>
</div>
</div>
<div id="tabs-4" class="statdiv">
<h4>Tab 4</h4>
<div class="statgrid">
<div class="col-2-6">
<div id="morris-donut-chart4"></div>
</div>
</div>
<div class="statgrid">
<div class="col-4-6">
<div class="col-5-6">Item 4</div>
<div class="col-1-6">£10.00</div>
</div>
</div>
</div>
<div id="tabcontain3">
<ul class="mytabs2">
<li class="stattab1">Tab 1
</li>
<li class="stattab2">Tab 2
</li>
<li class="stattab3">Tab 3
</li>
<li class="stattab4">Tab 4
</li>
</ul>
</div>
JS:
$(function () {
$("#tabs2").tabs();
});
$('ul.mytabs a').on('shown.bs.tab', function (e) {
var types = $(this).attr("data-identifier");
var typesArray = types.split(",");
$.each(typesArray, function (key, value) {
eval(value + ".redraw()");
})
});
$(function () {
var donut1_data = [{
label: "Download Sales",
value: 12
}, {
label: "In-Store Sales",
value: 30
}, {
label: "Mail-Order Sales",
value: 20
}];
var donut1 = {
element: 'morris-donut-chart',
data: donut1_data,
resize: false
}
donut1 = Morris.Donut(donut1)
var donut2_data = [{
label: "Download Sales",
value: 10
}, {
label: "In-Store Sales",
value: 30
}, {
label: "Mail-Order Sales",
value: 20
}];
var donut2 = {
element: 'morris-donut-chart2',
data: donut2_data,
resize: false
}
donut2 = Morris.Donut(donut2)
var donut3_data = [{
label: "Download Sales",
value: 8
}, {
label: "In-Store Sales",
value: 30
}, {
label: "Mail-Order Sales",
value: 20
}];
var donut3 = {
element: 'morris-donut-chart3',
data: donut3_data,
resize: false
}
donut3 = Morris.Donut(donut3)
var donut4_data = [{
label: "Download Sales",
value: 2
}, {
label: "In-Store Sales",
value: 30
}, {
label: "Mail-Order Sales",
value: 20
}];
var donut4 = {
element: 'morris-donut-chart4',
data: donut4_data,
resize: false
}
donut4 = Morris.Donut(donut4)
});
CSS:
#morris-donut-chart svg, #morris-donut-chart2 svg, #morris-donut-chart3 svg, #morris-donut-chart4 svg {
width:250px;
height:250px;
}
#morris-donut-chart, #morris-donut-chart2, #morris-donut-chart3, #morris-donut-chart4 {
width:250px;
height:250px;
}
First of all you should replace mytabs with mytabs2 in your jquery code because you dont have a mytabs class.
After that change shown.bs.tab to click because you want to redraw the donut when a tab is clicked.
And at last, move your click function into the $(function () because the variables donut1,donut2, etc are not accessible outside function():
$(function () {
$('ul.mytabs2 a').on('click', function (e) {
var types = $(this).attr("data-identifier");
var typesArray = types.split(",");
$.each(typesArray, function (key, value) {
eval(value + ".redraw()");
})
});
});
Here's the working example: DEMO