# wt-security/2.2.3/htdocs/js/Chart.js

WebTotem Security, version 2.2.3. 265 lines.

- Page: https://pluginprobe.com/plugins/wt-security/2.2.3/code/htdocs/js/Chart.js
- Raw: https://pluginprobe.com/plugins/wt-security/2.2.3/raw/htdocs/js/Chart.js
- Modified: 2020-11-27T08:50:22+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/wt-security/2.2.3/code/htdocs/js/Chart.js#L10-L20`.

```javascript
if(typeof waf_chart == "object"){
    const data = waf_chart;
    drawLineChart(data);
}

async function drawLineChart(dataset) {
    var diagram = document.getElementById('wtotem_chart_diagram');
    var days = diagram.dataset.days;

    const attacksAccessor = (d) => d.attacks;
    const blockedAccessor = (d) => d.blocked;
    const biggerAccessor = (d) =>
        d.attacks > d.blocked ? d.attacks : d.blocked;
    const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
    const xAccessor = (d) => dateParser(d.date);


    const chartWrapper = document.getElementById('line-chart')
    let dimensions = {
        width: chartWrapper.offsetWidth,
        height: 251,
        margin: {
            top: 15,
            right: 15,
            bottom: 40,
            left: 60,
        },
    };
    dimensions.boundedWidth =
        dimensions.width - dimensions.margin.left - dimensions.margin.right;
    dimensions.boundedHeight =
        dimensions.height - dimensions.margin.top - dimensions.margin.bottom;

    const wrapper = d3
        .select("#line-chart")
        .append("svg")
        .attr("width", dimensions.width)
        .attr("height", dimensions.height);

    const bounds = wrapper
        .append("g")
        .style(
            "transform",
            `translate(${dimensions.margin.left - 10}px, ${
                dimensions.margin.top
            }px)`
        );

    const yScale = d3
        .scaleLinear()
        .domain(d3.extent(dataset, biggerAccessor))
        .range([dimensions.boundedHeight, 0]);
    const xScale = d3
        .scaleTime()
        .domain(d3.extent(dataset, xAccessor))
        .range([0, dimensions.boundedWidth]);

    function make_y_gridlines() {
        return d3.axisLeft(yScale).ticks(5);
    }

    bounds
        .append("g")
        .attr("class", "grid")
        .call(
            make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
        );

    const area1 = d3
        .area()
        .x((d) => xScale(xAccessor(d)))
        .y0(dimensions.height)
        .y1((d) => yScale(attacksAccessor(d)));

    const area2 = d3
        .area()
        .x((d) => xScale(xAccessor(d)))
        .y0(dimensions.height)
        .y1((d) => yScale(blockedAccessor(d)));

    bounds
        .append("linearGradient")
        .attr("id", "area-gradient1")
        .attr("gradientUnits", "userSpaceOnUse")
        .attr("x1", 0)
        .attr("y1", yScale(0))
        .attr("x2", 0)
        .attr("y2", yScale(100))
        .selectAll("stop")
        .data([
            { offset: "0%", color: "#d46c6a", opacity: 0 },
            { offset: "100%", color: "#d46c6a", opacity: 0.6 },
        ])
        .enter()
        .append("stop")
        .attr("offset", function (d) {
            return d.offset;
        })
        .attr("stop-color", function (d) {
            return d.color;
        })
        .attr("stop-opacity", function (d) {
            return d.opacity;
        });

    bounds
        .append("linearGradient")
        .attr("id", "area-gradient2")
        .attr("gradientUnits", "userSpaceOnUse")
        .attr("x1", 0)
        .attr("y1", yScale(0))
        .attr("x2", 0)
        .attr("y2", yScale(100))
        .selectAll("stop")
        .data([
            { offset: "0%", color: "#bace3d", opacity: 0 },
            { offset: "100%", color: "#bace3d", opacity: 0.6 },
        ])
        .enter()
        .append("stop")
        .attr("offset", function (d) {
            return d.offset;
        })
        .attr("stop-color", function (d) {
            return d.color;
        })
        .attr("stop-opacity", function (d) {
            return d.opacity;
        });

    const lineGenerator1 = d3
        .line()
        .x((d) => xScale(xAccessor(d)))
        .y((d) => yScale(attacksAccessor(d)));
    const lineGenerator2 = d3
        .line()
        .x((d) => xScale(xAccessor(d)))
        .y((d) => yScale(attacksAccessor(d)));

    const line1 = bounds
        .append("path")
        .datum(dataset)
        .attr("d", lineGenerator1(dataset))
        .attr("class", "area")
        .attr("d", area1)
        .style("fill", "url(#area-gradient1)");

    const line2 = bounds
        .append("path")
        .datum(dataset)
        .attr("d", lineGenerator2(dataset))
        .attr("class", "area")
        .attr("d", area2)
        .style("fill", "url(#area-gradient2)");

    const yAxisGenerator = d3.axisLeft().scale(yScale);
    const xAxisGenerator = d3.axisBottom().scale(xScale);
    const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
    const xAxis = bounds
        .append("g")
        .call(xAxisGenerator)
        .attr("class", "axis")
        .style("transform", `translateY(${dimensions.boundedHeight}px)`);

    const listeningRect = bounds
        .append("rect")
        .attr("class", "listening-rect")
        .attr("width", dimensions.boundedWidth)
        .attr("height", dimensions.boundedHeight)
        .on("mousemove", onMouseMove)
        .on("mouseleave", onMouseLeave);

    const tooltipAttacks = d3.select("#tooltipAttacks");
    const tooltipBlocked = d3.select("#tooltipBlocked");
    const tooltipCircle1 = bounds
        .append("circle")
        .attr("class", "tooltip-circle")
        .attr("r", 4)
        .attr("stroke", "#F3F5F6")
        .attr("fill", "#1D293F")
        .attr("stroke-width", 2)
        .style("opacity", 0);
    const tooltipCircle2 = bounds
        .append("circle")
        .attr("class", "tooltip-circle")
        .attr("r", 4)
        .attr("stroke", "#F3F5F6")
        .attr("fill", "#1D293F")
        .attr("stroke-width", 2)
        .style("opacity", 0);
    function onMouseMove() {
        const mousePosition = d3.mouse(this);
        const hoveredDate = xScale.invert(mousePosition[0]);

        const getDistanceFromHoveredDate = (d) =>
            Math.abs(xAccessor(d) - hoveredDate);
        const closestIndex = d3.scan(
            dataset,
            (a, b) =>
                getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
        );
        const closestDataPoint = dataset[closestIndex];

        const closestXValue = xAccessor(closestDataPoint);
        const closestAttacksValue = attacksAccessor(closestDataPoint);
        const closestBlockedValue = blockedAccessor(closestDataPoint);

        const x = xScale(closestXValue) + dimensions.margin.left + 8;
        const yAttacks =
            yScale(closestAttacksValue) + dimensions.margin.top + 10;
        const yBlocked =
            yScale(closestBlockedValue) + dimensions.margin.top + 10;

        tooltipAttacks.style(
            "transform",
            `translate(` +
                `calc( -50% + ${x}px),` +
                `calc(-100% + ${yAttacks}px)` +
                `)`
        );
        tooltipBlocked.style(
            "transform",
            `translate(` +
                `calc( -50% + ${x}px),` +
                `calc(-100% + ${yBlocked}px)` +
                `)`
        );

        tooltipAttacks.style("opacity", 1);
        tooltipBlocked.style("opacity", 1);

        tooltipAttacks.select("#countAttacks").html(closestAttacksValue);
        tooltipBlocked.select("#countBlocked").html(closestBlockedValue);
        tooltipCircle1
            .attr("cx", xScale(closestXValue))
            .attr("cy", yScale(closestAttacksValue))
            .style("opacity", 1);
        tooltipCircle2
            .attr("cx", xScale(closestXValue))
            .attr("cy", yScale(closestBlockedValue))
            .style("opacity", 1);
    }

    function onMouseLeave() {
        tooltipAttacks.style("opacity", 0);
        tooltipBlocked.style("opacity", 0);

        tooltipCircle1.style("opacity", 0);
        tooltipCircle2.style("opacity", 0);
    }
}


var resizeTimer;
window.onresize = function (event) {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function () {
        var s = d3.select("#line-chart").selectAll("svg");
        s = s.remove();
        if(typeof data != "undefined"){
            drawLineChart(data);
        }
    }, 10);
};

```
