As the title says I have a bubble chart made with chartjs. The problem is the size of bubbles that do not change depending of the screen size, they are not responsive. I multiple the radius with 5 but I do not want this as it is not responsive. Is there a way to achive that in chartjs? I read on the documentation that the bubble sizes are in pixes. Any way to transform it in dynamic value, like percentage for example?
<div id="<%= containerId %>" class="item">
<script>
async function createChart() {
response = await axios.get(`<%= url %>`);
if(Object.keys(response["data"]["data"]).length) {
container = document.getElementById(`<%= containerId %>`)
container.innerHTML = ` <div class="container">
<div class="section">
<div class="py-4">
<img src="/images/logo.png" width="180" alt="">
</div>
<h2 class="fw-700" id="<%= mainTitleId %>" style="text-transform: capitalize"></h2>
<hr>
<br><br>
<div style="width: 100%;">
<canvas id="<%= chartId %>" style="display: block; width: 1379px; height: 686px;" width="1379" height="689"></canvas>
</div>
</div>
</div>
`
mainTitleElement = document.getElementById(`<%= mainTitleId %>`)
mainTitleElement.innerHTML = response["data"]["data"]["slide_title"]
var phases = [
"Phase 1",
"Phase 2",
"Phase 3",
"Phase 4",
];
var sponsors = response["data"]["data"]["sponsors"];
var dataPoints = response["data"]["data"]["phases_per_sponsors"]
var myBubbleChart = new Chart(document.getElementById(`<%= chartId %>`), {
type: 'bubble',
plugins: [{
afterDatasetUpdate: chart => {
chart.getDatasetMeta(0).data.forEach(v => {
v._model.radius = v._model.radius * 5
v._options.hoverRadius = v._model.radius;
})
}
}],
data: {
datasets: [
{
label: "",
data: dataPoints,
backgroundColor: 'rgba(237, 130, 60, 0.5)',
}
]
},
options: {
legend: {
display: false
},
responsive: true,
scales: {
yAxes: [{
ticks: {
stepSize: 1,
callback: function (value, index, values) {
if (index < sponsors.length) {
return sponsors[sponsors.length - (1 + index)]; //this is to reverse the ordering
}
}
},
position: 'left'
}],
xAxes: [{
ticks: {
stepSize: 1,
callback: function (value, index, values) {
if (index < phases.length) {
return phases[index];
}
}
},
position: 'bottom'
}]
}
}
});
} else {
container = document.getElementById(`<%= containerId %>`)
container.innerHTML = `
<div class="container">
<div class="py-4">
<img src="/images/logo.png" width="180" alt="">
</div>
</div>
<div class="container center">
<div class="section pt-4 px-20">
<h1 class="fw-800 text-center">
${response["data"]["message"]}
</h1>
<hr class="hr-mid">
</div>
</div>
`
};
}
createChart();
</script>
</div>
Related
I can't seem to get this block of code to work. Any suggestions on how I can get it to work? It works if it's only an array, but when I make objects inside it doesn't show anything.
So could the problem be that the code dosent reach the objects?
So could the problem be that the code dosent reach the objects?
Error message
const playersArray = [{
name: 'Darwin Núñez',
number: 27,
age: 23,
position: 'Forward',
image: 'nunez.png'
},
{
name: 'Mohamed Salah',
number: 11,
age: 30,
position: 'Midfielder',
image: 'salah.png'
},
{
name: 'Diogo Jota',
number: 20,
age: 25,
position: 'Forward',
image: 'jota.png'
},
];
function updateResult(query) {
let resultList = document.querySelector(".result");
resultList.innerHTML = "";
playersArray.map(function(player) {
query.split(" ").map(function(word) {
if (player.toLowerCase().indexOf(word.toLowerCase()) != -1) {
resultList.innerHTML += `<p class="list-group-item">${player}</p>`;
}
})
})
}
updateResult("")
<div class="container">
<div class="col-xs-8 col-xs-offset-2 search-box">
<div class="input-group">
<input oninput="updateResult(this.value)" type="search" class="form-control" placeholder="Search..." />
</div>
</div>
<div class="container">
<div class="list-group result"></div>
</div>
</div>
So, first we lowercase the query.
Then, we filter the array of players by checking each property.
Finally, we iterate the results and add them to the p element.
Have a nice day :)
const playersArray = [{
name: 'Darwin Núñez',
number: 27,
age: 23,
position: 'Forward',
image: 'nunez.png'
},
{
name: 'Mohamed Salah',
number: 11,
age: 30,
position: 'Midfielder',
image: 'salah.png'
},
{
name: 'Diogo Jota',
number: 20,
age: 25,
position: 'Forward',
image: 'jota.png'
},
];
let resultList = document.querySelector(".result");
function updateResult(query) {
if (query.length == 0) {
resultList.innerHTML = "";
return;
}
query = query.toLowerCase();
let player = playersArray.filter(el =>
el.name.toLowerCase().indexOf(query) != -1
|| el.number.toString().indexOf(query) != -1
|| el.age.toString().indexOf(query) != -1
|| el.position.toLowerCase().indexOf(query) != -1
|| el.image.toLowerCase().indexOf(query) != -1
);
resultList.innerHTML = "";
player.forEach((data, index) => {
resultList.innerHTML += `
<div class="list-group-item" style="border: 1px solid black; margin-top: 2px;">
<div>Name: ${data.name}<div>
<div>Id: ${data.number}<div>
<div>Age: ${data.age}<div>
<div>Position: ${data.position}<div>
<div>Image: ${data.image}<div>
</div>`;
})
}
updateResult("")
<div class="container">
<div class="col-xs-8 col-xs-offset-2 search-box">
<div class="input-group">
<input oninput="updateResult(this.value)" type="search" class="form-control" placeholder="Search..." />
</div>
</div>
<div class="container">
<div class="list-group result"></div>
</div>
</div>
Owlcarousel-slider works fine when I use below code.
HTML Code:
<div class="banner">
<div class="main-banner owl-carousel" id="homeage-data">
<div class="item" v-for="slider in sliders">
<div v-bind:class="slider.class_type"> <img v-bind:src="slider.image_src" alt="Electrro">
<div class="banner-detail">
<div class="container">
<div class="row">
<div class="col-md-3 col-3" v-if="slider.align_right"></div>
<div class="col-md-9 col-8">
<div class="banner-detail-inner">
<span class="slogan">{{ slider.label }}</span>
<h1 class="banner-title" v-html="slider.banner_title"></h1>
<span class="offer">{{ slider.banner_desc }}</span>
</div>
<a class="btn btn-color big" v-bind:href="slider.button_link" v-if="slider.button_np" target="_blank">{{ slider.button_text }}</a>
<a class="btn btn-color big" v-bind:href="slider.button_link" v-else-if="!slider.button_np">{{ slider.button_text }}</a>
</div>
<div class="col-md-3 col-4" v-if="!slider.align_right"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
JavaScript Code:
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
{
"label": "Discover",
"banner_title": "Top Branded for <br>headphone",
"banner_desc": "best selling, and popular.",
"image_src": "images/banner1.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-1",
"button_np": true,
"align_right": false
},
{
"label": "curved tv",
"banner_title": "Get latest TV models",
"banner_desc": "Get the top brands for TV",
"image_src": "images/banner2.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-2",
"button_np": false,
"align_right": true
},
{
"label": "Premium",
"banner_title": "drone cameras",
"banner_desc": "The latest camera up to 30% off",
"image_src": "images/banner3.jpg",
"button_text": "Shop Now!",
"button_link": "#link",
"class_type" : "banner-3",
"button_np": true,
"align_right": false
}
]
},
});
</script>
Output Image: (Very Nice!)
But when I call the code remotely with Fetch, the image is broken.
JavaScript Code: (I uploaded the slider array to the api.php file and called it remotely.)
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
]
},
created() {
fetch("/api/api.php")
.then((response) => { return response.json() })
.then((response) => {
this.sliders = response.sliders;
});
}
});
</script>
Output Image:
As I understand it, it cannot render JQuery code because it was added later.
No matter what I did, I couldn't find the right way.
I have not tried the code below. It didn't happen :(
<script>
new Vue({
el: '#homeage-data',
data: {
sliders: [
]
},
created() {
fetch("/api/api.php")
.then((response) => { return response.json() })
.then((response) => {
this.sliders = response.sliders;
});
$(".main-banner, #client").owlCarousel({
//navigation : true, Show next and prev buttons
items: 1,
nav: true,
slideSpeed : 300,
paginationSpeed : 400,
loop:true,
autoPlay: false,
dots: true,
singleItem:true,
nav:true
});
}
});
</script>
Demo of using VueOwlCarousel in Vue2, without npm:
Vue.use(VueOwlCarousel);
new Vue({
el: '#app',
data: () => ({
slides: 0,
options: {
autoplay: true,
autoplaySpeed: 800,
autoplayTimeout: 1800,
lazyLoad: true,
autoplayHoverPause: true
}
}),
mounted() {
setTimeout(() => {
this.slides = 7
}, 2000)
},
})
div.owl-carousel {
width: 400px;
height: 180px;
}
.owl-stage-outer {
height: 111px;
}
.loader {
height: 180px;
display: flex;
align-items: center;
width: 400px;
justify-content: center;
}
h2 {
color: #ddd;
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
<script src="https://v2.vuejs.org/js/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-owl-carousel#2.0.3/dist/vue-owl-carousel.min.js"></script>
<div id="app">
<vue-owl-carousel :items="1"
v-if="slides"
v-bind="options">
<img v-for="s in slides"
:key="s"
:src="`https://placeimg.com/400/111/any?${s}`">
</vue-owl-carousel>
<div v-else class="loader">
<h2>Loading...</h2>
</div>
</div>
Personal advice: do not mix jQuery with Vue. You only want one source of truth for your DOM manipulations.
That's the underlying cause of your issue.
Note: Owl carousel can't be initialised with empty slides. For this reason, I've placed a v-if="slides" (or, if slides would have been an array, v-if="slides.length").
Also note Owl takes control over the carousel DOM element and, from that moment on, even if you change the slides array, it won't react to the change. If you wanted to update the slides, you'd need the owl instance, change its internal slides (which are built from the original DOM) and then call its internal .refresh() method.
Sorry, this is my first stackoverflow question so let me know if I've formatted this wrong.
I attempted to use document.getElementById("id").value in order to get the input value from the input box but I couldn't quite figure out how to make it work. I saw other answers making use of JSON or JQuery but I don't have much experience in those yet so if I could make this work without those(if possible) I'll take that option.
Any bits of code that are commented out are just me trying to get it to work.
(Sidenote: I know my HTML code might be a bit scuffed, that isn't a priority right now)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Pricer.ie</title>
<link rel="stylesheet" href="homepage.css"/>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script type="text/javascript" src="/js/themes/gray.js"></script>
<meta name="viewport" content="initial-scale=1.0, width=device-width"/>
</head>
<body>
<nav class="navbar">
<ul>
<li class="logo">
<img src="logopricer.png" alt="logo" id="logo" >
</li>
<li>
Login
</li>
</ul>
</nav>
<main>
<figure class="highcharts-figure">
<div id="container" style="width:100%; height:400px;"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var myChart = Highcharts.chart({
chart: {
renderTo: 'container',
type: 'pie',
events: {
load: function(event) {
var chart = this,
points = chart.series[0].points,
len = points.length,
total = 0,
i = 0;
for (; i < len; i++) {
total += points[i].y;
}
chart.setTitle({
text: '<span style="font-size: 13px">Current Price</small><br>' + '<b>' + '€' + total.toFixed(2) + '</b>',
align: 'center',
verticalAlign: 'middle',
y: -10,
});
}
}
},
title: {
text: 'Product Details'
},
tooltip: {
pointFormat: '<b>{point.percentage:.1f}</b>' + '<b>%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '{point.name}: €{point.y:.2f}'
}
}
},
series: [{
name: 'Total', [{
name: 'Profit Margin',
// y: document.getElementById('pcost').value
y : 0.29
}, {
name: 'Taxes',
// y: document.getElementById('taxes').value // external thing! database cuz tax changes depending on product
y : 4.25
}, {
name: 'Ebay Fees',
// y: document.getElementById('listfee').value
y : 3.93
}, {
name: 'Unit + Shipping Costs',
// y : document.getElementById('icost').value + document.getElementById('scost').value
y : 17.03
}],
size: '60%',
innerSize: '70%',
showInLegend:true,
dataLabels: {
enabled: true
}
}]
},
)
}
)
</script>
</figure>
<article>
<form>
<label for="icost">Item Cost:</label>
<input type="number" id="icost" name="icost" step="0.01"><br><br>
<label for="scost">Shipping Cost:</label>
<input type="number" id="scost" name="scost" step="0.01"><br><br> <!-- names and ids are incorrect just like this for now -->
<label for="pcost">Pickpack Cost:</label>
<input type="number" id="pcost" name="scost" step="0.01"><br><br>
<label for="taxes">Taxes:</label>
<input type="number" id="taxes" name="taxes" step="0.01"><br><br> <!-- shouldnt exist as taxes is from database but sure look-->
<label for="listfee">Listing Fee:</label>
<input type="number" id="listfee" name="listfee"><br><br>
<button onclick="Function()">Save Changes</button>
</form>
</article>
</main>
<footer>
</footer>
</body>
<html>
I would link to a JSFiddle but not sure how I would do that as my JS is currently embedded within my HTML lol. Thanks in advance to anyone that decides to give me a hand with this. Any advice with this is useful!
You need to get data and put them in a format required by Highcharts. Simple example below:
document.getElementById('btn').addEventListener('click', function() {
var data = [
parseInt(document.getElementById('data1').value),
parseInt(document.getElementById('data2').value)
];
Highcharts.chart('container', {
series: [{
type: 'pie',
data
}]
});
});
Live demo: http://jsfiddle.net/BlackLabel/dyp5208b/
API Reference: https://api.highcharts.com/highcharts/series.pie.data
Basically, I have a container divided to col-xs-3, col-xs-7(which holds the graph), and col-xs-2 , and also three tables underneath with the same bootstrap classes(col-xs-3,...).
On the container I have a graph created with highcharts, and I want it to be aligned with the table underneath(as shown by purple arrows),this is what I want as a result, and also be responsive when window width changes:
Right now I have it like this:
I already tried some approches like moving the graph to the left, scale the graph on different media queries, but these just work on some specific width.
Highcharts.chart('container', {
chart: {
renderTo: ''
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
lineWidth: 0,
minorTickLength: 0,
tickLength: 0,
labels: {
rotation: -45,
enabled: false
},
//maxZoom: 24 * 3600 * 1000 * 30, // fourteen days
title: {
//text: 'sample'
}
},
yAxis: {
min: 0,
max: 150,
tickInterval: 50,
gridLineWidth: 0,
lineWidth: 4,
plotLines: [{
color: '#ccc',
dashStyle: 'dash',
width: 2,
value: 100
}],
title: {
text: ''
},
labels: {
style: {
color: '#ccc'
},
formatter: function () {
if ('100' == this.value) {
return '<span style="fill: #000;">' + this.value + ' %</span>';
} else {
return this.value + ' %';
}
}
}
},
tooltip: {
shared: true,
formatter: function () {
var result = '<b>' + Highcharts.dateFormat('%b %e, %Y', this.x) + '</b>';
$.each(this.points, function (i, datum) {
result += '<br />' + Math.round(datum.y) + ' %';
});
return result;
}
},
legend: {
enabled: false,
},
plotOptions: {
line: {
marker: {
enabled: false
}
}
},
series: [{
name: '',
data: [[0, 50.57],
[10, 50.63],
[20, 75.14],
[30, 100.08],
[40, 40.28],
[130, 68.25],
[140, 125.01], ],
lineWidth: 5,
threshold: 99,
step: 'center',
tooltip: {
valueDecimals: 2
}
}]
});
.empty {
background-color: #f3f3f3;
height: 250px;
}
.row {
margin: 10px 0;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-xs-3 empty"></div>
<div class="col-xs-7" style="">
<div id="container" style="height: 250px; width: 100%"></div>
</div>
<div class="col-xs-2 empty"></div>
</div>
<div class="row">
<div class="col-xs-3 empty"></div>
<div class="col-xs-7" style="">
<div id=""></div>
</div>
<div class="col-xs-2 empty"></div>
</div>
</div>
Here is a jsfiddle of my code
I solved it by making a few changes to the chart. These are the things I changed:
In the JS file:
chart: {
renderTo: 'chartcontainer'
}
In the HTML file:
<div id="container" style="height: 250px;width:calc(100% + 90px);"></div>
In the CSS file:
.highcharts-container {
left: -70px;
}
Here is the jsfiddle.
I'm using a angular masonry directive created by passy and I'm having a problem when the first element have almost 100% of width. In this case all the elements merge in a single column otherwise i think the behaviour is ok.
I created a plunker,to see if anyone out there can help me.
http://plnkr.co/edit/P8kVidzDV97U7mslECJJ?p=preview
<div ng-controller="CarOperatingPanelCtrl">
<div class="one-column">
<div class="two-column">
<label class="item item-input item-stacked-label">
<span class="input-label"> Width:</span>
<input type="number" ng-model="carOperatingPanel.width" value="{{carOperatingPanel.width}}" placeholder="mm" />
</label>
</div>
<div class="two-column">
<label class="item item-input item-stacked-label">
<span class="input-label"> Height:</span>
<input type="number" ng-model="carOperatingPanel.height" value="{{carOperatingPanel.height}}" placeholder="mm" />
</label>
</div>
</div>
<ul class="draggable-objects">
<li ng-repeat="obj in draggableObjects">
<div ng-drag="true" ng-drag-data="obj" data-allow-transform="true"> {{obj.name}} </div>
</li>
</ul>
<div masonry check-last ng-drop="true" ng-drop-success="onDropComplete1($data,$event)">
<div class="masonry-brick" ng-repeat="obj in droppedObjects1"
flexible-dimensions
ng-drag="true"
ng-drag-data="obj"
ng-drag-success="onDragSuccess1($data,$event)"
>
{{obj.name}}
</div>
</div>
angular.module('starter', ['ngDraggable','wu.masonry'])
.controller('CarOperatingPanelCtrl', function ($scope ) {
$scope.carOperatingPanel = {};
$scope.carOperatingPanel.width = 100;
$scope.carOperatingPanel.height = 200;
$scope.draggableObjects = [{ name: '1', width: 20, height: 20 },
{ name: '2', width: 20, height: 20 },
{ name: '3', width: 20, height: 20 },
{ name: '4', width: 20, height: 20 },
{ name: '5', width: 20, height: 20 },
{ name: '6', width: 20, height: 40 },
{ name: '7', width: 40, height: 20 },
//{ name: '8', width: 80, height: 40 }
];
$scope.droppedObjects1 = [{ name: '8', width: 80, height: 40 }];
$scope.onDropComplete1 = function (data, evt) {
var index = $scope.droppedObjects1.indexOf(data);
if (index == -1)
$scope.droppedObjects1.push(data);
}
$scope.onDragSuccess1 = function (data, evt) {
//debugger;
//console.log("133", "$scope", "onDragSuccess1", "", evt);
var index = $scope.droppedObjects1.indexOf(data);
if (index > -1) {
$scope.droppedObjects1.splice(index, 1);
}
}
var inArray = function (array, obj) {
var index = array.indexOf(obj);
}
})
.directive('flexibleDimensions', function ($document) {
return function (scope, element, attr) {
element.css({
//0,1cm 1mm
'margin': (((element.parent()[0].offsetWidth * 1) / scope.carOperatingPanel.width) / 2) + 'px',
width: ((element.parent()[0].offsetWidth * scope.obj.width) / scope.carOperatingPanel.width) + 'px',
height: ((element.parent()[0].offsetHeight * scope.obj.height) / scope.carOperatingPanel.height) + 'px'
});
};
});
Im using to a ngDraggable to push the elements to the drop area and re-organize them. For better understanding by default i put already the biggest div already selected.
If anyone see something that shouldn't be there tell me.
Thanks
As described here, Angular JS Masonry Directive uses the size of the first element to compute the default column width unless the column-width attribute is present. I don't know what exactly You want to achieve, but You might want to try to set that attribute to make the column width constant.