Using Bootstrap 4 flexbox to equally divide four charts - css

I am trying to plot four different stacked charts in one browser window as shown here. But as it is, the size of the charts aren't equal. I have tried tweaking various CSS properties, but being unfamiliar with CSS+HTML layout, I wasn't able to.
Any suggestion/help would be greatly appreciated. Thank you.
All of my code is below:
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/autocomplete-0.3.css" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<style>
.custom-select-lg {
border: 2px solid #ccc;
height: 52px;
padding: 0 0 0 15px;
font-size: 125%;
width: 290px;
}
.vh-100 {
min-height: 100vh;
}
.choose-plot {
padding-top: 15px;
padding-bottom: 15px;
}
.bordered {
border: 1px solid #ccc;
border-radius: 10px;
}
</style>
</head>
<body>
<div class="container-fluid d-flex h-100 flex-column vh-100">
<div class="row">
<div class="col choose-plot">
<strong class="mb-2">Instruction here</strong>
<div class="row">
<div class="col-1">
<button id="load_plot" class="btn btn-primary btn-lg">Load plot</button>
</div>
</div>
</div>
</div>
<div class="row flex-fill d-flex justify-content-start">
<div class="col-6 bordered">1 of 4
<div id="container-0" style="height: 100%;"></div>
</div>
<div class="col-6 bordered">2 of 4
<div id="container-1" style="height: 100%;"></div>
</div>
<div class="col-6 bordered">3 of 4
<div id="container-2" style="height: 100%;"></div>
</div>
<div class="col-6 bordered">4 of 4
<div id="container-3" style="height: 100%;"></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js" integrity="sha384-u/bQvRA/1bobcXlcEYpsEdFVK/vJs3+T+nXLsBYJthmdBuavHvAW6UsmqO2Gd/F9" crossorigin="anonymous"></script>
<script src="js/echarts-4.1.0.js"></script>
<script type="text/javascript">
var doms = [
document.getElementById("container-0"),
document.getElementById("container-1"),
document.getElementById("container-2"),
document.getElementById("container-3"),
];
var myCharts = [];
var myOption = {
tooltip : {
trigger: 'axis',
axisPointer : {
type : 'shadow'
}
},
legend: {
data: ['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['周一','周二','周三','周四','周五','周六','周日']
},
yAxis: {
type: 'value'
},
series: [
{
name: '直接访问',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [320, 302, 301, 334, 390, 330, 320]
},
{
name: '邮件营销',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '联盟广告',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '视频广告',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [150, 212, 201, 154, 190, 330, 410]
},
{
name: '搜索引擎',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [820, 832, 901, 934, 1290, 1330, 1320]
}
]
}; //myOption ends
$('#load_plot').on('click', function() {
if (myCharts.length != 0) {
myCharts.forEach(function (c) {
c.dispose();
});
}
doms.forEach(function(ele){
var curChart = echarts.init(ele, null, {renderer: 'canvas'});
curChart.showLoading();
curChart.setOption(curOption = myOption);
curChart.hideLoading();
console.log("done loading");
myCharts.push(curChart);
});
});
</script>
</body>
</html>

Remove inline height of 100% from the div just inside .col-6.bordered and add the following style.
.col-6.bordered > div {
height: 50vh;
}
.col-6.bordered>div {
height: 50vh;
}
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<style>
.custom-select-lg {
border: 2px solid #ccc;
height: 52px;
padding: 0 0 0 15px;
font-size: 125%;
width: 290px;
}
.vh-100 {
min-height: 100vh;
}
.choose-plot {
padding-top: 15px;
padding-bottom: 15px;
}
.bordered {
border: 1px solid #ccc;
border-radius: 10px;
}
</style>
</head>
<body>
<div class="container-fluid d-flex h-100 flex-column vh-100">
<div class="row">
<div class="col choose-plot">
<strong class="mb-2">Instruction here</strong>
<div class="row">
<div class="col-1">
<button id="load_plot" class="btn btn-primary btn-lg">Load plot</button>
</div>
</div>
</div>
</div>
<div class="row flex-fill d-flex justify-content-start">
<div class="col-6 bordered">1 of 4
<div id="container-0"></div>
</div>
<div class="col-6 bordered">2 of 4
<div id="container-1"></div>
</div>
<div class="col-6 bordered">3 of 4
<div id="container-2"></div>
</div>
<div class="col-6 bordered">4 of 4
<div id="container-3" "></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js " integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin=" anonymous "></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.bundle.min.js " integrity="sha384-u/bQvRA/1bobcXlcEYpsEdFVK/vJs3+T+nXLsBYJthmdBuavHvAW6UsmqO2Gd/F9 " crossorigin="anonymous "></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts-en.js "></script>
<script>
var doms = [
document.getElementById("container-0 "),
document.getElementById("container-1 "),
document.getElementById("container-2 "),
document.getElementById("container-3 "),
];
var myCharts = [];
var myOption = {
tooltip : {
trigger: 'axis',
axisPointer : {
type : 'shadow'
}
},
legend: {
data: ['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['周一','周二','周三','周四','周五','周六','周日']
},
yAxis: {
type: 'value'
},
series: [
{
name: '直接访问',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [320, 302, 301, 334, 390, 330, 320]
},
{
name: '邮件营销',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '联盟广告',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '视频广告',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [150, 212, 201, 154, 190, 330, 410]
},
{
name: '搜索引擎',
type: 'bar',
stack: 'a',
label: {
normal: {
show: true,
position: 'insideRight'
}
},
data: [820, 832, 901, 934, 1290, 1330, 1320]
}
]
}; //myOption ends
$('#load_plot').on('click', function() {
if (myCharts.length != 0) {
myCharts.forEach(function (c) {
c.dispose();
});
}
doms.forEach(function(ele){
var curChart = echarts.init(ele, null, {renderer: 'canvas'});
curChart.showLoading();
curChart.setOption(curOption = myOption);
curChart.hideLoading();
console.log("done loading ");
myCharts.push(curChart);
});
});
</script>
</body>
</html>
See updated fiddle

The default definition is min-height:1px whats mean that the height will be automatic as the height of the content
For provide it you can set height: 100vh;
.bordered{
height: 100vh;
}

Related

Why CSS styles can't be applied to elements created by Buefy?

I'm trying to change the background-color of a table row that was generated by Buefy.
I don't understand why I'm unable to change the color of the table row, but I can change its children color.
I tried both ways, setting the whole class name or just the class name of the element that I want:
.table.is-hoverable tbody tr.detail:not(.is-selected):hover {
background-color: rgb(218, 11, 11) !important;
}
.detail {
background-color: rgb(218, 11, 11) !important;
}
I can, for example change the color of an inner element:
.media {
background-color: yellow !important;
}
Full code
<template>
<section class="hero">
<div class="hero-body">
<div class="container">
<b-table
:data="downloads"
ref="table"
:loading="isLoading"
hoverable
detailed
detail-key="version"
selectable
#select="toggle"
>
<template slot-scope="props">
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="version"
label="Version"
width="70"
>
<span class="tag is-info">{{ props.row.version }}</span>
</b-table-column>
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="download_count"
label="Download Count"
sortable
numeric
>{{ props.row.download_count.toLocaleString() }}</b-table-column>
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="release_date"
label="Release Date"
sortable
centered
>{{props.row.release_date ? new Date(props.row.release_date).toLocaleDateString() : "unknown"}}</b-table-column>
</template>
<template slot="empty">
<section v-if="!isLoading" class="section">
<div class="content has-text-grey has-text-centered">
<p>Looks like it was not possible to load the data.</p>
</div>
</section>
</template>
<template slot="detail" slot-scope="props">
<article class="media">
<div class="media-content">Some text.
<hr>Some other text.
</div>
</article>
</template>
<template slot="footer">
<div v-if="!isLoading" class="has-text-right">This is a footer.</div>
</template>
</b-table>
</div>
</div>
</section>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
downloads: [],
isLoading: true
};
},
mounted() {
this.downloads = [
{ version: "1.5", download_count: 500, release_date: new Date() },
{ version: "1.4", download_count: 400, release_date: new Date() },
{ version: "1.3", download_count: 300, release_date: new Date() },
{ version: "1.2", download_count: 200, release_date: new Date() },
{ version: "1.1", download_count: 100, release_date: new Date() }
];
this.isLoading = false;
},
methods: {
toggle(row) {
this.$refs.table.toggleDetails(row);
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
//This is how I expect it should work.
.table.is-hoverable tbody tr.detail:not(.is-selected):hover {
background-color: rgb(218, 11, 11) !important;
}
//Applying the property to the
.detail {
background-color: rgb(218, 11, 11) !important;
}
.media {
background-color: yellow !important;
}
</style>
Reproduction link:
https://codesandbox.io/s/misty-sea-bmyvc?file=/src/components/HelloWorld.vue
Your CSS is scoped. In the end those classes are assorted with a [data-xxx] selector so they are applied only on this component.
.detail[data-xxx] won't override the lib's CSS, you need just .detail
So put this CSS code into a separated simple <style lang="scss"> and let your component's own CSS in <style lang="scss" scoped>

Image flickering on hover and not resizing

I have an image column in a grid, and I show the image to 25px x 25px so it fits in the row nicely.
I added a hover to the images and when the mouse hovers on them there are supposed be offset from the left (which it does) and then the image is supposed to get bigger so you can see it better.
2 things are happening
1) When I hover on the image, its flickers continuously
2) Even though the image goes 100px to the left, it doesn't expand to the new size.
I have no idea why this is happening.
$(document).ready(function() {
LoadCatalogsGrid();
});
var myData = [{
"RoomName": "Room 1",
"OptionImageFile": "a"
},
{
"RoomName": "Room 2",
"OptionImageFile": "b"
}
];
function optionGridImage(url) {
return "<div class='imageOptionsList'><a style='text-align:center;height:25px;width:25px;' href='" +
GetCatalogImageLocation(url) +
"'><img src='" +
GetCatalogImageLocation(url) +
"' style='height:25px;width:25px;' alt=''/></a></div>";
}
function GetCatalogImageLocation(imageName) {
if (imageName == "a") {
return "https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/king_lead.jpg?itok=4b75-ttE&resize=1100x1100";
} else {
return "https://pmcvariety.files.wordpress.com/2017/08/king-of-the-hill.jpg?w=1000&h=562&crop=1";
}
}
function LoadCatalogsGrid() {
$("#Grid").empty();
$("#Grid").kendoGrid({
scrollable: true,
selectable: "row",
filterable: false,
height: 700,
columns: [{
field: "RoomName",
title: "Room Name",
width: "120px",
template: "<div >#=RoomName #</div>"
},
{
field: "OptionImageFile",
title: "Image",
template: "#= optionGridImage(OptionImageFile) #",
attributes: {
style: "margin:0 auto;"
},
width: 50
}
],
dataSource: {
data: myData
},
dataBound: function(e) {
}
});
}
.imageOptionsList:hover a {
visibility: visible;
width: 250px !important;
height: 325px !important;
margin-left: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.mobile.all.min.css">
<script src="https://kendo.cdn.telerik.com/2019.1.115/js/kendo.all.min.js"></script>
<div id="Grid"></div>
** Snippet Edit **
So now when I hover the image is no longer flickering, however when you hover over the image it moves left, and it shouldn't it should just stay in its spot and when hovered show a bigger version
Here you are:
$(document).ready(function() {
LoadCatalogsGrid();
});
var myData = [{
"RoomName": "Room 1",
"OptionImageFile": "a"
},
{
"RoomName": "Room 2",
"OptionImageFile": "b"
}
];
function optionGridImage(url) {
url = GetCatalogImageLocation(url);
return `
<div class="imageOptionsList">
<a style="background-image:url(${url})" href="${url}">
<img src="${url}" alt="">
</a>
</div>
`;
}
function GetCatalogImageLocation(imageName) {
if (imageName == "a") {
return "https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/king_lead.jpg?itok=4b75-ttE&resize=1100x1100";
} else {
return "https://pmcvariety.files.wordpress.com/2017/08/king-of-the-hill.jpg?w=1000&h=562&crop=1";
}
}
function LoadCatalogsGrid() {
$("#Grid").empty();
$("#Grid").kendoGrid({
scrollable: true,
selectable: "row",
filterable: false,
height: 700,
columns: [{
field: "RoomName",
title: "Room Name",
width: "120px",
template: "<div >#=RoomName #</div>"
},
{
field: "OptionImageFile",
title: "Image",
template: "#= optionGridImage(OptionImageFile) #",
attributes: {
style: "margin:0 auto;"
},
width: 50
}
],
dataSource: {
data: myData
},
dataBound: function(e) {
}
});
}
.k-grid td {
overflow: visible !important
}
.imageOptionsList a {
position: relative;
display: inline-block;
height: 25px;
width: 25px;
background-size: cover;
}
.imageOptionsList a img {
position: absolute;
top: 50%;
right: 50%;
width: 0;
height: 0;
transition: .5s
}
.imageOptionsList a:hover {
z-index: 1
}
.imageOptionsList a:hover img {
width: 50vw;
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.mobile.all.min.css">
<script src="https://kendo.cdn.telerik.com/2019.1.115/js/kendo.all.min.js"></script>
<div id="Grid"></div>
Remove the margin-left: 100px line from your hover class. Also, try using transform for increasing image size. The code below will double the image size.
.imageOptionsList:hover img {
visibility: visible;
transform: scale(2);
}
You've got some conflicting information in your post. You mention the left offset as correct, then say it should at the end.
Below I removed the inline styles you had on the image and updated your selector to target img tags within .imageOptionsList. I've also added a transition so it doesn't do a hard snap, feel free to remove.
$(document).ready(function() {
LoadCatalogsGrid();
});
var myData = [{
"RoomName": "Room 1",
"OptionImageFile": "a"
},
{
"RoomName": "Room 2",
"OptionImageFile": "b"
}
];
function optionGridImage(url) {
return "<div class='imageOptionsList'><a style='text-align:center;height:25px;width:25px;' href='" +
GetCatalogImageLocation(url) +
"'><img src='" +
GetCatalogImageLocation(url) +
"alt=''/></a></div>";
}
function GetCatalogImageLocation(imageName) {
if (imageName == "a") {
return "https://images.mentalfloss.com/sites/default/files/styles/mf_image_16x9/public/king_lead.jpg?itok=4b75-ttE&resize=1100x1100";
} else {
return "https://pmcvariety.files.wordpress.com/2017/08/king-of-the-hill.jpg?w=1000&h=562&crop=1";
}
}
function LoadCatalogsGrid() {
$("#Grid").empty();
$("#Grid").kendoGrid({
scrollable: true,
selectable: "row",
filterable: false,
height: 700,
columns: [{
field: "RoomName",
title: "Room Name",
width: "120px",
template: "<div >#=RoomName #</div>"
},
{
field: "OptionImageFile",
title: "Image",
template: "#= optionGridImage(OptionImageFile) #",
attributes: {
style: "margin:0 auto;"
},
width: 50
}
],
dataSource: {
data: myData
},
dataBound: function(e) {
}
});
}
.imageOptionsList img {
width: 25px;
height: 25px;
transition: height 500ms ease-in-out, width 500ms ease-in-out;
}
.imageOptionsList img:hover {
width: 250px;
height: 325px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2019.1.115/styles/kendo.mobile.all.min.css">
<script src="https://kendo.cdn.telerik.com/2019.1.115/js/kendo.all.min.js"></script>
<div id="Grid"></div>

change css display block to none in React

I am really new to React, and I have code set up like below, I want to click the button and make the content disappear.Wish someone could help me with this. I tried use state, but I did not get the results I want, I also tried https://jsfiddle.net/uwadhwnr/ not work. I am really frustrating right now.
<div id="content" style="height:1000px">
<script type="text/jsx">
var styles = {
container: {
height: '100vh',
width: '100%',
backgroundColor: 'blue',
},
title: {
textAlign: 'center',
},
modal: {
display: 'block',
position: 'fixed',
zIndex: '1',
paddingTop: '100px',
left: '0',
top: '0',
width: '100vw',
height: '100vh',
overflow: 'auto',
backgroundColor: 'rgb(0,0,0)',
backgroundColor: 'rgba(0,0,0,0.4)',
},
modalContent: {
position: 'relative',
backgroundColor: '#fefefe',
margin: 'auto',
padding: '0',
border: '1px solid #888',
width: '80vw',
},
modalHeader: {
padding: '2px 16px',
backgroundColor: '#5cb85c',
color: 'white',
},
modalBody: {padding: '2px 16px'},
modalFooter: {
padding: '2px 16px',
backgroundColor: '#5cb85c',
color: 'white',
},
upload: {
position: 'absolute',
right: '5%',
top: '5%',
},
};
var PopUp = React.createClass({
render: function() {
return (
<div>
<i className="fa fa-plus-circle fa-3x" aria-hidden="true" style={styles.upload} onClick={this.handleClick}></i>
<div id="myModal" className="modal" style={styles.modal}>
<div className="modal-content" style={styles.modalContent}>
<div className="modal-header" style={styles.modalHeader}>
<h2>Modal Header</h2>
</div>
<div classN="modal-body" style={styles.modalBody}>
<p>Some text aa the Modal Body</p>
<p>Some other text...</p>
</div>
<div className="modal-footer" style={styles.modalFooter}>
<h3>Modal Footer</h3>
</div>
</div>
</div>
</div>
);
}
});
var FilterableProductTable = React.createClass({
render: function() {
return (
<div>
<PopUp />
</div>
);
}
});
React.render(
<FilterableProductTable />,
document.getElementById('content'));
</script>
What's the difficult in that?
Just setup a CSS class with this property:
display: none
and switch the class by setting a new state on button click.
Here's an example: https://jsfiddle.net/8aoue71m/

Angular 2 wrapping responsive horizontal gallery

I'm trying to implement an horizontal gallery that wraps images based on their dimension.
The effect I would like to achieve is like this:
Is there any way to do this?
EDIT
I'll add something that I tried.
1. I've used angular/flex-layout with the fxLayoutWrap functionality. This wraps images correctly but I've not been able to create an horizontal scrolling gallery. Moreover the images dimension is a bit static and I need a dynamic wrapping:
<div fxFlex="80%" fxLayout="row" fxLayoutWrap>
<div fxFlex="30%" style="background:#ff0000">IMAGE 1</div>
<div fxFlex="45%" style="background:#ff6a00">IMAGE 2</div>
<div fxFlex="25%" style="background:#b200ff">IMAGE 3</div>
<div fxFlex="33%" style="background:#ffd800">IMAGE 4</div>
<div fxFlex="67%" style="background:#ff006e">IMAGE 5</div>
<div fxFlex="50%" style="background:#808080">IMAGE 6</div>
<div fxFlex style="background:#00ff90">IMAGE 7</div>
</div>
2. I tried to use custom css and html. In this case I'm able to build an horizontal scrolling gallery but I'm not able to wrap images dinamically and I have to set width and height manually.
Html code:
<div class="h-scroll-container">
<div class="h-scroll">
<div style="display:inline-block; width:15em; height:100%">
<div class="thumb" style="background-image:url(images/project_1.jpg); width:100%; height:50%;"></div>
<div class="thumb" style="background-image:url(images/project_2.jpg); width:100%; height:50%;"></div>
</div>
<div class="thumb" style="background-image:url(images/project_3.jpg); display:inline-block; width:15em; height:100%;"></div>
<div style="display:inline-block; width:30em; height:100%;">
<div style="width:100%; height:50%;">
<div class="thumb" style="background-image:url(images/project_4.jpg); display:inline-block; width:50%; height:100%;"></div>
<div class="thumb" style="background-image:url(images/project_5.jpg); display:inline-block; width:50%; height:100%;"></div>
</div>
<div class="thumb" style="background-image:url(images/project_6.jpg); display:inline-block; width:100%; height:50%;"></div>
</div>
<div class="thumb" style="background-image:url(images/project_7.jpg); display:inline-block; width:15em; height:100%;"></div>
<div style="display:inline-block; width:30em; height:100%">
<div class="thumb" style="background-image:url(images/project_8.jpg); width:100%; height:50%;"></div>
<div class="thumb" style="background-image:url(images/project_9.jpg); width:50%; height:50%;"></div>
</div>
</div>
</div>
CSS code:
.h-scroll-container {
width: 100%;
height: 100%;
overflow-x: auto!important;
overflow-y: hidden!important;
}
.h-scroll {
height: calc(100% - .5em);
white-space: nowrap;
}
.thumb {
background-position:center;
background-size:cover;
}
3. I'm now trying to adapt this to my case. Here the code:
import { Component, ViewChild, ViewChildren, ElementRef, HostListener, Input, SimpleChanges, QueryList, ChangeDetectorRef, OnChanges, AfterViewInit } from "#angular/core";
import { slideToLeft } from "../../router.animations";
var $: JQueryStatic = require('jquery');
import 'jquery-mousewheel';
require("jquery-mousewheel")($);
require('malihu-custom-scrollbar-plugin')($);
export class Image {
name: string;
path: string;
width: number;
height: number;
galleryImageLoaded: boolean;
srcAfterFocus: string;
}
#Component({
selector: "projects",
template: require("./projects.component.html"),
styles: [require("./projects.component.css")]
})
export class ProjectsComponent implements OnChanges, AfterViewInit {
#Input('flexBorderSize') providedImageMargin: number = 10
#Input('flexImageSize') providedImageSize: number = 10
#ViewChild('galleryContainer') galleryContainer: ElementRef
#ViewChildren('imageElement') imageElements: QueryList<any>
#HostListener('window:scroll', ['$event']) triggerCycle(event) {
this.scaleGallery()
}
#HostListener('window:resize', ['$event']) windowResize(event) {
this.render()
}
private images: Image[] = [];
private gallery: any[] = [];
constructor(private ChangeDetectorRef: ChangeDetectorRef) {
}
ngAfterViewInit() {
this.fetchDataAndRender()
}
public ngOnChanges(changes: SimpleChanges) {
// input params changed
this.render()
}
private fetchDataAndRender() {
var images: Image[] = [
{
name: "project_1.jpg",
path: "images/projects/project_1.jpg",
width: 521,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_2.jpg",
path: "images/projects/project_2.jpg",
width: 534,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_3.jpg",
path: "images/projects/project_3.jpg",
width: 220,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_4.jpg",
path: "images/projects/project_4.jpg",
width: 443,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_5.jpg",
path: "images/projects/project_5.jpg",
width: 374,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_6.jpg",
path: "images/projects/project_6.jpg",
width: 1052,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_7.jpg",
path: "images/projects/project_7.jpg",
width: 235,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_8.jpg",
path: "images/projects/project_8.jpg",
width: 570,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_9.jpg",
path: "images/projects/project_9.jpg",
width: 328,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_10.jpg",
path: "images/projects/project_10.jpg",
width: 521,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_11.jpg",
path: "images/projects/project_11.jpg",
width: 534,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_12.jpg",
path: "images/projects/project_12.jpg",
width: 220,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_13.jpg",
path: "images/projects/project_13.jpg",
width: 235,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
{
name: "project_14.jpg",
path: "images/projects/project_14.jpg",
width: 570,
height: 375,
galleryImageLoaded: false,
srcAfterFocus: ''
},
]
this.images = images;
//this.ImageService.updateImages(this.images)
// twice, single leads to different strange browser behaviour
this.render();
this.render();
}
private render() {
this.gallery = []
let tempRow = [this.images[0]]
let rowIndex = 0
let i = 0
for (i; i < this.images.length; i++) {
while (this.images[i + 1] && this.shouldAddCandidate(tempRow, this.images[i + 1])) {
i++
}
if (this.images[i + 1]) {
tempRow.pop()
}
this.gallery[rowIndex++] = tempRow
tempRow = [this.images[i + 1]]
}
this.scaleGallery()
}
private shouldAddCandidate(imgRow: Image[], candidate: Image): boolean {
let oldDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow)
imgRow.push(candidate)
let newDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow)
return Math.abs(oldDifference) > Math.abs(newDifference) || (this.getGalleryWidth() + 1000) > this.calcOriginalRowWidth(imgRow)
}
private calcRowHeight(imgRow: Image[]) {
let originalRowWidth = this.calcOriginalRowWidth(imgRow)
let ratio = (this.getGalleryWidth() - (imgRow.length - 1) * this.calcImageMargin()) / originalRowWidth
let rowHeight = imgRow[0].height * ratio
return rowHeight
}
private calcImageMargin() {
let galleryWidth = this.getGalleryWidth()
let ratio = galleryWidth / 1920
return Math.round(Math.max(1, this.providedImageMargin * ratio))
}
private calcOriginalRowWidth(imgRow: Image[]) {
let originalRowWidth = 0
imgRow.forEach((img) => {
let individualRatio = this.calcIdealHeight() / img.height
img.width = img.width * individualRatio
img.height = this.calcIdealHeight()
originalRowWidth += img.width
})
return originalRowWidth
}
private calcIdealHeight() {
return this.getGalleryWidth() / (80 / this.providedImageSize) + 100
}
private getGalleryWidth() {
if (this.galleryContainer.nativeElement.clientWidth === 0) {
// IE11
return this.galleryContainer.nativeElement.scrollWidth
}
return this.galleryContainer.nativeElement.clientWidth
}
private scaleGallery() {
let imageCounter = 0
let maximumGalleryImageHeight = 0
this.gallery.forEach((imgRow: Image[]) => {
let originalRowWidth = this.calcOriginalRowWidth(imgRow)
if (imgRow !== this.gallery[this.gallery.length - 1]) {
let ratio = (this.getGalleryWidth() - (imgRow.length - 1) * this.calcImageMargin()) / originalRowWidth
imgRow.forEach((img) => {
img.width = img.width * ratio
img.height = img.height * ratio
maximumGalleryImageHeight = Math.max(maximumGalleryImageHeight, img.height)
this.checkForAsyncLoading(img, imageCounter++)
})
}
else {
imgRow.forEach((img) => {
img.width = img.width
img.height = img.height
maximumGalleryImageHeight = Math.max(maximumGalleryImageHeight, img.height)
this.checkForAsyncLoading(img, imageCounter++)
})
}
})
//if (maximumGalleryImageHeight > 375) {
// this.minimalQualityCategory = 'preview_xs'
//} else {
// this.minimalQualityCategory = 'preview_xxs'
//}
this.ChangeDetectorRef.detectChanges()
}
private checkForAsyncLoading(image: Image, imageCounter: number) {
let imageElements = this.imageElements.toArray()
if (image.galleryImageLoaded ||
(imageElements.length > 0 && this.isScrolledIntoView(imageElements[imageCounter].nativeElement))) {
image.galleryImageLoaded = true
image.srcAfterFocus = image.path
}
else {
image.srcAfterFocus = ''
}
}
private isScrolledIntoView(element) {
let elementTop = element.getBoundingClientRect().top
let elementBottom = element.getBoundingClientRect().bottom
return elementTop < window.innerHeight && elementBottom >= 0 && (elementBottom > 0 || elementTop > 0)
}
}
I've quite achieved my objective but I have to set manually the width check inside shouldAddCandidate method and rows are not of the same height. Some suggestions to make this more dynamic ad responsive?

google chart size issue

Multiple charts are displayed on one page, some users have larger screen and some have small standard screen.
Is there any way to have flexible width so it can fit on any size of monitor screen.
I have tried setting width to 100% but it doesn't work.
<table width="100%">
<tr>
<td>
<div id="chart_GP" class="chart_div">
<div class="chart_preloader"> </div>
</div>
</td>
<td id="td_profit">
<div id="chart_Profit" class="chart_div">
<div class="chart_preloader"> </div>
</div>
</td>
<td>
<div id="chart_Visits" class="chart_div">
<div class="chart_preloader"> </div>
</div>
</td>
</tr>
</table>
CSS
.chart_preloader {
height:250px;
width: 100%;
background:url('/images/pie.gif') center center no-repeat;
background-color : #EEF;
}
.chart_div {
border-color: #006699;
border-style: solid;
border-width: 1px;
}
Google Chart Options
var options = {
title: "Last 12 Months Gross Profit per Month",
animation: {
duration: 1500,
startup: true //This is the new option
},
pointSize: 5,
curveType: 'function',
backgroundColor: chart_background_Color,
colors: [chartLine_Color],
legend: 'none',
width: 385,
height: 250,
tooltip: { isHtml: true },
hAxis: {
slantedText: true,
slantedTextAngle: 90
},
vAxis: {
title: 'Profit',
titleTextStyle: { italic: false, fontName: 'Calibri', fontSize: '12', bold: 'false' }
//format: '#\'%\''
}
};
recommend leaving width settings out of the chart options and use a css layout
which the chart will follow
rarely use tables, so depends on layout you're looking for, following is one example
to make the chart responsive, re-draw the chart when the window resizes...
google.charts.load('current', {
callback: function () {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Time of Day');
data.addColumn('number', 'Rating');
data.addRows([
[new Date(2015, 0, 1), 5],
[new Date(2015, 0, 7), 3],
[new Date(2015, 0, 14), 3],
[new Date(2015, 0, 21), 2],
[new Date(2015, 0, 28), 8]
]);
var options = {
title: "Last 12 Months Gross Profit per Month",
animation: {
duration: 1500,
startup: true //This is the new option
},
pointSize: 5,
curveType: 'function',
backgroundColor: 'cyan',
colors: ['red'],
legend: 'none',
height: 250,
tooltip: { isHtml: true },
hAxis: {
slantedText: true,
slantedTextAngle: 90
},
vAxis: {
title: 'Profit',
titleTextStyle: { italic: false, fontName: 'Calibri', fontSize: '12', bold: 'false' }
//format: '#\'%\''
}
};
var chart1 = new google.visualization.LineChart(document.getElementById('chart_GP'));
drawChart(chart1);
var chart2 = new google.visualization.LineChart(document.getElementById('chart_Profit'));
drawChart(chart2);
var chart3 = new google.visualization.LineChart(document.getElementById('chart_Visits'));
drawChart(chart3);
// make chart responsive
window.addEventListener('resize', function () {
drawChart(chart1);
drawChart(chart2);
drawChart(chart3);
}, false);
function drawChart(chart) {
chart.draw(data, options);
}
},
packages:['corechart']
});
.chart_preloader {
height:250px;
width: 100%;
background:url('/images/pie.gif') center center no-repeat;
background-color : #EEF;
}
.dashboard {
text-align: center;
}
#chart_GP {
float: left;
}
#chart_Profit {
display: inline-block;
}
#chart_Visits {
float: right;
}
.chart_div {
border-color: #006699;
border-style: solid;
border-width: 1px;
width: 32%;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="dashboard">
<div id="chart_GP" class="chart_div">
<div class="chart_preloader"> </div>
</div>
<div id="chart_Profit" class="chart_div">
<div class="chart_preloader"> </div>
</div>
<div id="chart_Visits" class="chart_div">
<div class="chart_preloader"> </div>
</div>
</div>

Resources