I developed this grid which displays number of records for X & Y, user can click each number to see a list. (I didn't add list markup to fiddle yet - so lets not worried about it for now.)
What I believe is that I overcomplicated this simple project by choosing SVG, and it can be improved massively by using simple HTML, maybe in the future (years time I would like to add zooming to it, maybe which is why I used SVG).
Could you improve it to simplest level please, preferably using HTML and avoiding SVG?
function CreateHeatmap() {
$("#svgContainer").empty();
var
width = $(window).innerWidth() - ($(window).innerWidth() / 50),
height = $(window).innerHeight() - ($(window).innerHeight() / 40),
sideRectW = width / 17,
sideRectH = height / 17,
boxW = (width - sideRectW) / (4 + 1), // getting number "4" from web services as number of boxes depends
boxH = (height - sideRectH) / (4 + 1), // getting number "4" from web services as number of boxes depends
boxSize = boxW + boxH;
var svgContainer = d3.select("#mainContainer")
.append("svg")
.attr("id", "svgContainer")
.attr("width", "100%")
.attr("height", "100%")
.attr("preserveAspectRatio", "none")
.attr("viewBox", "0 0 " + width + " " + height)
.attr("float", "right")
.attr("overflow", "hidden");
svgContainer.append("rect")
.attr("fill", "url(#svgLG1)")
.attr("width", "100%")
.attr("height", "100%");
var CreateGradient = function () {
var gradient = svgContainer.append("svg:linearGradient").attr("id", "svgLG1").attr("x1", "0").attr("y1", "1").attr("x2", "1").attr("y2", "0");
gradient.append("svg:stop").attr("offset", "0").attr("stop-color", "#0f0");
gradient.append("svg:stop").attr("offset", "0.7").attr("stop-color", "#ff0");
gradient.append("svg:stop").attr("offset", "1").attr("stop-color", "#f00");
};
var ShowList = function (item) {
var id = $(item).attr("id");
var quantity = id.charAt(1);
var quality = id.charAt(2);
};
var CreateRect = function (x, y, boxId) {
svgContainer.append("g").attr("id", "g" + boxId).on("click", function () {
ShowList(this);
}).append("rect").attr("x", x).attr("y", y).attr("id", "rectBoxNo" + boxId).attr("width", boxW).attr("height", boxH).attr("stroke", "black").attr("stroke-width", "1").attr("fill", "none");
};
var CreateRects = function () {
for (var i = 0; i <= 4; i++) { // getting number of x and y from web services, but for example let assume it's 4
var b = 4;
for (var j = 0; j <= 4; j++) {
CreateRect(sideRectW + (boxW * i), boxH * b, "" + i + j);
b--;
}
}
};
var CreateCoordinatesRect = function (x, y, w, h, boxColor) {
svgContainer.append("rect").attr("x", x).attr("y", y).attr("width", w).attr("height", h).attr("fill", boxColor);
};
var CreateText = function (x, y, text, textColor, size) {
svgContainer.append("text").attr("x", x).attr("y", y).attr("fill", textColor).attr("font-size", size).text(text);
};
var CreateText90Degree = function (x, y, text, textColor, size) {
svgContainer.append("text").attr("x", x).attr("y", y).attr("fill", textColor).attr("font-size", size).attr("transform", "rotate(-90," + x + 13 + ", " + y + 15 + ")").text(text);
};
var CreateCoordinatesNumbers = function () {
var j = 0;
for (var i = 0; i <= 4; i++) {
CreateText(sideRectW + (boxW * i) + (boxW / 2), height - sideRectH / 2, "" + (j++), "white", 12);
}
j = 4;
for (var i = 0; i <= 4; i++) {
CreateText(sideRectW / 2, (boxH * i) + (boxH / 2), "" + (j--), "white", 12);
}
};
CreateGradient();
CreateCoordinatesRect(0, 0, sideRectW, $("#mainContainer").height(), "Black");
CreateCoordinatesRect(0, height - sideRectH, width, sideRectH, "Black");
CreateText(((width - sideRectW) / 2) + 13, (height - sideRectH / 5) + 4, "X", "white", 16);
CreateText90Degree(0, ((height - sideRectH) / 2) + 20, "Y", "white", 16);
CreateCoordinatesNumbers();
CreateRects();
}
function PopulateHeatmap(data) {
var AddNumberOfFruitCratesToEachBox = function (text, xy) {
var rectContainer = d3.selectAll("#rectBoxNo" + xy);
var xDivider = 2.5, yDivider = 1.6;
if (text >= 10 && text <= 99) xDivider = xDivider + (0.6);
else if (text >= 100) yDivider = yDivider + (0.6);
var w = Number(rectContainer.attr("width"));
var h = Number(rectContainer.attr("height"));
var x = Number(rectContainer.attr("x")) + (w / xDivider);
var y = Number(rectContainer.attr("y")) + (h / yDivider);
var svgContainer = d3.selectAll("#svgContainer");
svgContainer.selectAll("#g" + xy).append("text")
.attr("x", x)
.attr("y", y)
.attr("fill", "white")
.attr("font-size", 0.15 * (w + h))
.attr("class", "hover_grouptext").text(text);
};
var fCount = {};
for (var i = 0; i < 4; i += 1) {
for (var j = 0; j < 4; j += 1) {
fCount["" + i + j] = 0;
}
}
$.each(data, function (index, item) {
if (item.x > -1 && item.y > -1) {
fCount["" + item.x + item.y]++;
}
});
for (var i = 0; i < 4; i += 1) {
for (var j = 0; j < 4; j += 1) {
if (fCount["" + i + j] > 0) {
AddNumberOfFruitCratesToEachBox(fCount["" + i + j], "" + i + j);
}
}
}
}
function OwResize() {
$("#mainContainer").height($(window).innerHeight() - ($(window).innerHeight() / 40));
}
var containerData = [
{
"x": 0,
"y": 0,
"Title": "Crate Number 1",
"Url": "http:www.fruitfactory.com\crates\1",
"Comments": null,
"ObjectOther1": [
],
"ObjectOther2": [
]
},
{
"x": 0,
"y": 0,
"Title": "Crate Number 2",
"Url": "http:www.fruitfactory.com\crates\2",
"Comments": null,
"ObjectOther1": [
],
"ObjectOther2": [
]
},
{
"x": 3,
"y": 3,
"Title": "Crate Number 3",
"Url": "http:www.fruitfactory.com\crates\3",
"Comments": null,
"ObjectOther1": [
],
"ObjectOther2": [
]
}
];
$(window).resize(OwResize);
CreateHeatmap();
PopulateHeatmap(containerData);
.hover_group:hover {
opacity: 0.5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<div id="mainContainer">
<div id="fruit-grid"></div>
</div>
You are free to use anything but it should work with IE-8 & Chrome.
Fiddle
http://jsfiddle.net/nhe613kt/388/
Please Note:
In example code I am adding heatmap and populating them one after another but in real, I am creating it at one point and populating at another, I can't do both at same time as I am getting data from ajax get request.
Bounty Edit
I would expect a better version of what I developed in html using any third party library you want, just one thing need to keep in mind is that, I am creating rectangles or boxes you can say by getting numbers from web services, so hard coding won't help here for number of boxes here as I can do that myself using a table. Thanks for your time :)