vis.js redraw and changing data

elboffor picture elboffor · Jun 28, 2016 · Viewed 10.4k times · Source

I'm using vis.js timeline to display events and got all items displaying from an ajax call.

currently I have a working filters on the page so the timeline goes to a specific range and this works fine.

What I am trying to do is narrow down the information displayed. My initial thoughts on how to do this was to change the ajax call so it returns a json of just the information I need.

An example:

  1. Select region:
    • Northern England
    • Southern England
  2. The Ajax called would filter on the database so it would only display items that have that property in a particular column
  3. I would then redraw the timeline utilising the new json from the ajax call

Where I am coming unstuck is part 1 and 2, does anyone know how I would specify a different Ajax url and then how to redraw the table?

I've tried timeline.redraw(): with no luck, so I destroyed the table first but still no dice (timeline.destroy(); timeline.redraw();) the destroy comman works but not the redraw.

Here is my code (note the date filters work fine) HTML

<!-- this is just the filter section -->
<div id="filters" style="margin: 10px; background-color: RGB(229,229,229); border-radius: 10px; padding: 5px">
        <div id="filterscontainer" style="display: inline-block">
            <table>
                <tr>
                    <td>
                        <div style="float: left; font-size: 1.25em">Filters</div>
                </td>
                <td></td>
                <td>
                    <div id="expandcollapseFilters" class="chevron bottom" title="Click to expand the filter menu" style="float: left"></div>
                </td>
            </tr>
        </table>
    </div>
    <div id="filtercontent" style="display: none">
        <table>
            <tr><td colspan="2"><button id="reset">Reset all filters</button></td></tr>
            <tr>
                <td>
                    <table>
                        <tr>
                            <td style="text-align: right">Date from:</td>
                            <td>
                                <input id="dateFrom" class="date"/></td>
                            <td style="text-align: right">Date to:</td>
                            <td>
                                <input id="dateTo" class="date"/></td>
                            <td>
                                <button id="dateRangeFilter">Apply Filter</button></td>
                        </tr>
                    </table>
                </td>
                <td></td>
            </tr>
        </table>
    </div>
</div>
<div id="currentlyShowing"><h3>Currently showing: <span class="currentlyShowing">All items</span></h3></div>
<div id="mytimeline"></div>
<div id="loading">loading...</div>

Javascript/jquery:

<script type="text/javascript">
    $("#filterscontainer").on("click", function () {
        $('#currentlyShowing').slideToggle('slow');
        $('#filtercontent').slideToggle('slow');
        if ($("#expandcollapseFilters").prop("class") === "chevron top") {
            $('#expandcollapseFilters').prop('collapseFilters', "Click here to collapse the filter menu");
            $('#expandcollapseFilters').addClass('bottom').removeClass('top');
        } else {
            $('#expandcollapseFilters').prop('collapseFilters', "Click to expand the filter menu");
            $('#expandcollapseFilters').addClass('top').removeClass('bottom');
        }
    });
    $.ajax({
        type: "POST",
        url: 'Ajax.asp?RT=RoadMap', data: {},
        success: function (data) {
            var result = JSON.parse(JSON.parse(JSON.stringify(data)));
            document.getElementById('loading').style.display = 'none';
            var items = new vis.DataSet(result);
            var options = {
                orientation: 'top',
                groupOrder: 'order',
                showCurrentTime: false,
                align: 'left',
                editable: false,
                minHeight: '300px',
                min: new Date(2016, 0, 1),                // lower limit of visible range
                max: new Date(2018, 0, 1),                // upper limit of visible range
                zoomMin: 1000 * 60 * 60 * 24 * 7,         // one week in milliseconds
                zoomMax: 1000 * 60 * 60 * 24 * 365        // about a year
            };
            var container = document.getElementById('mytimeline');
            var timeline = new vis.Timeline(container, items, options);
            document.getElementById('dateRangeFilter').onclick = function () {
                var dateFrom = $("#dateFrom").val();
                var dateTo = $("#dateTo").val();
                if (dateFrom.length < 1 || dateTo.length < 1 || dateFrom > dateTo) { //checking if the date to date is after the from date
                    alert("Please select a valid date range");
                } else { //converting the resturn results to a date format accepted by timeline
                var dateFromDay = dateFrom.substr(0, 2);
                var dateFromMonth = dateFrom.substr(3, 2);
                var dateFromYear = dateFrom.substr(6, 4);
                var dateToDay = dateTo.substr(0, 2);
                var dateToMonth = dateTo.substr(3, 2);
                var dateToYear = dateTo.substr(6, 4);
                timeline.setWindow(dateFromMonth + "-" + dateFromDay + "-" + dateToYear, dateToMonth + "-" + dateToDay + "-" + dateToYear);
                }
            };
        }
    });
    $().ready(function () {
        $("#reset").on("click", function () {
            $.datepicker._clearDate("#dateFrom");
            $.datepicker._clearDate("#dateTo");
        });
        $("#dateFrom").datepicker({
            beforeShowDay: $.datepicker.noWeekends,
            dateFormat: "dd/mm/yy"
        });
        $("#dateTo").datepicker({
            beforeShowDay: $.datepicker.noWeekends,
            dateFormat: "dd/mm/yy"
        });
    });
</script>

Answer

elboffor picture elboffor · Jun 29, 2016

I got it working, for the sake of anyone else facing this issue, here's how you do it/get around it.

Declare the variable "items" before the ajax call, Put you event handler before you declare the variable "timeline" Within this, clear the variable "items" ( items.clear(); ) and add the new contents of it ( items.add(); ). you can either build the string in the parethesis or like I did use an ajax call and have the return data inside.

below is the working code that now filters through specific regions:

    var items;
    var timeline;
    $.ajax({
        type: "POST",
        url: 'Ajax.asp?RT=RoadMap', data: {},
        success: function (data) {
            var AllData = JSON.parse(JSON.parse(JSON.stringify(data)));
            document.getElementById('loading').style.display = 'none';
            items = new vis.DataSet();
            items.add(AllData);
            var options = {
                orientation: 'top',
                groupOrder: 'order',
                showCurrentTime: false,
                align: 'left',
                editable: false,
                minHeight: '300px',
                min: new Date(2016, 0, 1),                // lower limit of visible range
                max: new Date(2018, 0, 1),                // upper limit of visible range
                zoomMin: 1000 * 60 * 60 * 24 * 7,         // one week in milliseconds
                zoomMax: 1000 * 60 * 60 * 24 * 365        // about a year
            };
            var container = document.getElementById('mytimeline');
            $("#regionFilter").on("click", function () {
                var regionSelected = $("#regionSelector").val();
                if (siteSelected === "") {
                    alert("Please Select the region you would like to see the information of");
                } else {
                    items.clear(); // note this is the clear function which removes the data but doesn't destroy the timeline
                    $.get("Ajax.asp?RT=RoadMapUpdate&Region=" + regionSelected, function (AjaxReturn) {
                        var AjaxReturn = JSON.parse(JSON.parse(JSON.stringify(AjaxReturn)));
                        items.add(AjaxReturn); // this is where the timeline get's re-populated
                    });
                }
            });
            $("#reset").on("click", function () { // this function is tied to a button I added which resets the filters, it puts wverything back to the way it was at load
                items.clear();
                items.add(AllData);
            });
            timeline = new vis.Timeline(container, items, options);