Search code examples
javascripthtmljsonajaxtimeline

Use static JSON string in AJAX query instead of a URL


I am trying to create a dynamic timeline widget in a HTML file as shown in the picture:

IMAGE1

It works fine when I parse the data from a JSON URL. This part is shown below :

    var filename = "snow-patrol.json",
    bandId = filename.replace(".json","");

$.ajax({
    type: "GET",
    url: filename,
    dataType: "json",
    success: function(data){
        init(data);
    }
});

Now, I am trying to use a static JSON string in the AJAX query instead of using a URL:

    $.ajax({
    type: "GET",
    url: filename,
    data: JSON.stringify({"dummy" : "","yearStarted" : 1994, "row" : [{"id" : "garyL","name" : "One","yearJoined" : 2007,"yearLeft" : 2015},{"id" : "markM","name" : "Two","yearJoined" : 2001,"yearLeft" : 2005}]}),
    dataType: "json",
    success: function(data){
        init(data);
    }
});

So, in the data: JSON.stringify part, I am using the JSON string but the widget (timeline) does not work. It only works if I have a working URL. Is there a way to use a static JSON string instead of having to use a link in the AJAX query? Everything else works fine. The data used in this AJAX call is being used in other queries in my page as shown in the snippet below (it does not work because of the cross origin thing for the JSON link).

var BAND_TIMELINE = (function() {

    var filename = "snow-patrol.json",
        bandId = filename.replace(".json","");

    $.ajax({
        type: "GET",
        url: filename,
        dataType: "json",
        success: function(data){
            init(data);
        }
    });

    function init(data) {
        THE_BAND.displayBand(data);
        TIMELINE.displayTimescale(data);

        $(".bar").each(function() {
            $(this)
                .data("origWidth", $(this).width())
                .width(0)
                .animate({
                    width: $(this).data("origWidth")
                }, 3000);
        });
    }

})();	


////
var THE_BAND = (function() {

    var presentYear = new Date().getFullYear();

    function displaydummy(dummy) {
        $('.band-name').text(dummy);
    }

    function displayBandDetails(data) {
        displaydummy(data.dummy);
        listrow(data);
    }

    function listrow(data) {
        var yearBandStarted = TIMELINE.getYearStarted(data),
            row = data.row,
            $rowList = $(".band-members"),
            barPosition = {};

        for (var member in row) {
            if (row.hasOwnProperty(member)) {
                var person = row[member],
                    yearsInBand = getYearsActive(person);

                $rowList.append('<li class="bar" id = "' + person.id + '">' + person.name +
                                        ' <em>(' + yearsInBand + ')</em></li>');

                barPosition = calculatePositionOnTimeline(person, yearBandStarted);

                if (barPosition.left) {
                    $('#' + person.id).css({left: barPosition.left + '%'});
                }
                $('#' + person.id).width(barPosition.width + '%');
            }
        }
    }

    function getYearsActive(person) {
        var yearsActive = "";

        if (!person.yearLeft) {
            yearsActive = person.yearJoined + " - present";
        } else {
            yearsActive = person.yearJoined + " - " + person.yearLeft;
        }

        return yearsActive;
    }

    function calculatePositionOnTimeline(person, yearBandStarted) {
        var yearsInBand = 1,
            widthPerYear = getWidthPerYear(yearBandStarted),
            barPosition = "",
            barProperties = { "left" : 0, "width" : 0};

        if (person.yearLeft) {
            yearsInBand += person.yearLeft - person.yearJoined;
        } else if (person.yearJoined < presentYear) {
            yearsInBand += presentYear - person.yearJoined;
        }

        barProperties.width = widthPerYear * yearsInBand;

        if (person.yearJoined > yearBandStarted) {
            var yearsFromStart = person.yearJoined - yearBandStarted;
            barProperties.left = (widthPerYear * yearsFromStart);
        }

        return barProperties;
    }

    function getWidthPerYear(yearBandStarted) {
        var present = new Date().getFullYear(),
            numberOfYears = (present - yearBandStarted) + 1,
            timelineWidth = $(".timeline").width(),
            widthPerYear = ((timelineWidth/numberOfYears)/timelineWidth)*100;

        return widthPerYear;
    }

    return {
        displayBand : displayBandDetails
    };

})();	

/////
var TIMELINE = (function() {

    function displayTimelineScale(data) {
        var $timelineScale = $(".years"),
            presentYear = new Date().getFullYear(),
            yearZero = getYearStartPoint(data),
            year = yearZero;

        while (year <= presentYear) {
            if (year === yearZero) {
                $timelineScale.append('<li class="start">' + trimYear(year.toString()) + '</li>');
            } else if (year === presentYear) {
                $timelineScale.append('<li class="present">' + trimYear(year.toString()) + '</li>');
            } else {
                $timelineScale.append("<li>" + trimYear(year.toString()) + "</li>");
            }
            year++;
        }

        // widths are set as percentages to allow for a flexible widths chart
        // NOTE: there is a limit to how flexible the width can be as more years = more space needed
        $('ul.years li').width(getWidthPerYear(yearZero) + '%');
    }

    function getYearStartPoint(data) {
        var row = data.row,
            startAtYear = row[0].yearJoined;

        for (var i = 0; i < row.length; i++) {
            for (var j = 1; j < row.length; j++) {
                var personA = row[i],
                    personB = row[j];

                if (personB.yearJoined < personA.yearJoined && personB.yearJoined < startAtYear) {
                    startAtYear = personB.yearJoined;
                } else if (personA.yearJoined < personB.yearJoined && personA.yearJoined < startAtYear) {
                    startAtYear = personA.yearJoined;
                }
            }
        }

        return startAtYear;
    }

    function getWidthPerYear(yearStarted) {
        var present = new Date().getFullYear(),
            numberOfYears = (present - yearStarted) + 1,
            borderPadding = numberOfYears,
            timelineWidth = $(".timeline").width(),
            widthPerYear = (((timelineWidth-borderPadding)/numberOfYears)/timelineWidth)*100;

        return widthPerYear;
    }

    function trimYear(yearStr) {
        var trimmedYear = "";

        if (yearStr.length === 4) {
            trimmedYear = "'" + yearStr.slice(2,4);
        } else if (yearStr.length === 3 && yearStr.startsWith("'")) {
            trimmedYear = yearStr;
        } else if (yearStr.length === 2) {
            trimmedYear = "'" + yearStr;
        }

        return trimmedYear;
    }

    return {
        displayTimescale : displayTimelineScale,
        getYearStarted : getYearStartPoint
    };
})();
/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font-weight: 400;
    font: inherit;
    vertical-align: baseline;
}
strong {
    font-weight: bold;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}

/* --- General style --- */


body {
    font: 400 1em/1.15 "Fira Sans Light", "Helvetica Neue", Helvetica, Arial, sans-serif;
    background: #fefefe;
    padding: 0 10px;
}
h1 {
    padding-top: 1.25%;
    padding-bottom: 1.5%;
    font: 400 1.5em/1 "Patua One", Georgia, "Times New Roman", serif;
    font-weight: bold;
    color: #333;
}
p {
    padding-top: 0.8%;
    padding-bottom: 0.8%;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

::selection {
    background: #ffb50d;
}
::-moz-selection {
    background: #ffb50d;
}

.description {
    clear: both;
    margin: 45px 0;
}

.band-name {
    background-color: #203e74;
    color: transparent;
    text-shadow: 0px 2px 5px rgba(255,255,255,0.6);
    -webkit-background-clip: text;
    -moz-background-clip: text;
    background-clip: text;
}

/* --- Timeline Style --- */

.years {
    list-style-type: none;
    padding: 0;
    display: block;
}

.years li {
    font-size: 0.85em;
    border-right: 1px solid #fff;
    background: #f3f3f3;
    float: left;
    margin: 0;
    padding: 10px 0;
    text-align: center;
}
.years.top li {
    border-bottom: 1px solid #000;
}
.years.bottom li {
    border-top: 1px solid #000;
}

.years .start {
    border-left: 1px solid #fff;
}
.years .present {
    border-right: none;
}

.band-members {
    clear: both;
    list-style: none;
    margin: 0;
    padding: 15px 0;
    margin-left: -1px;
    height: 330px;
}

.band-members li {
    color: #f3f3f3;
    text-shadow: 0px 2px 3px #565656;
    border: 2px solid #ddd;
    position: relative;
    left: -2px;
    -moz-border-radius: 25px;
    -webkit-border-radius: 25px;
    border-radius: 25px;
    -moz-box-shadow: 2px 2px 3px #696969;
    -webkit-box-shadow: 2px 2px 3px #696969;
    box-shadow: 2px 2px 3px #696969;
    margin-bottom: 5px;
    padding: 3px 0;
    text-align: center;
}

.band-members em {
    font-family: "Fira Sans Light Italic", "Helvetica Neue", Helvetica, Arial, sans-serif;
    padding-left: 0;
    display: inline-block;
}

#garyL {
    background: #f2374d;
    background: -webkit-linear-gradient(top, #cf061d, #f2374d);
    background:    -moz-linear-gradient(top, #cf061d, #f2374d);
    background:     -ms-linear-gradient(top, #cf061d, #f2374d);
    background:      -o-linear-gradient(top, #cf061d, #f2374d);
    background:         linear-gradient(to bottom, #cf061d, #f2374d);
}

#markM, #paulW {
    background: #fcbf17;
    background: -webkit-linear-gradient(top, #fcbf17, #fdd66a);
    background:    -moz-linear-gradient(top, #fcbf17, #fdd66a);
    background:     -ms-linear-gradient(top, #fcbf17, #fdd66a);
    background:      -o-linear-gradient(top, #fcbf17, #fdd66a);
    background:         linear-gradient(to bottom, #fcbf17, #fdd66a);
}

#michaelM, #jonnyQ {
    background: #6c9bde;
    background: -webkit-linear-gradient(top, #2779eb, #6c9bde);
    background:    -moz-linear-gradient(top, #2779eb, #6c9bde);
    background:     -ms-linear-gradient(top, #2779eb, #6c9bde);
    background:      -o-linear-gradient(top, #2779eb, #6c9bde);
    background:         linear-gradient(to bottom, #2779eb, #6c9bde);
}

#nathanC {
    background: #73b84d;
    background: -webkit-linear-gradient(top, #24a624, #73b84d);
    background:    -moz-linear-gradient(top, #24a624, #73b84d);
    background:     -ms-linear-gradient(top, #24a624, #73b84d);
    background:      -o-linear-gradient(top, #24a624, #73b84d);
    background:         linear-gradient(to bottom, #24a624, #73b84d);
}

#tomS {
    background: #7ba6ad;
    background: -webkit-linear-gradient(top, #4a95ab, #7ba6ad);
    background:    -moz-linear-gradient(top, #4a95ab, #7ba6ad);
    background:     -ms-linear-gradient(top, #4a95ab, #7ba6ad);
    background:      -o-linear-gradient(top, #4a95ab, #7ba6ad);
    background:         linear-gradient(to bottom, #4a95ab, #7ba6ad);
}

#johnnyM {
    background: #9c79bd;
    background: -webkit-linear-gradient(top, #8952bd, #9c79bd);
    background:    -moz-linear-gradient(top, #8952bd, #9c79bd);
    background:     -ms-linear-gradient(top, #8952bd, #9c79bd);
    background:      -o-linear-gradient(top, #8952bd, #9c79bd);
    background:         linear-gradient(to bottom, #8952bd, #9c79bd);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<section class="bands">
    <div class="timeline">
        <ul class="years top"></ul>
        <ul class="band-members"></ul>
        <ul class="years bottom"></ul>
    </div>
</section>


Solution

  • Why not just pass the whole object to your init function?

    You don't need AJAX if you're going to use a static JSON object.

    init({"dummy" : "","yearStarted" : 1994, "row" : [{"id" : "garyL","name" : "One","yearJoined" : 2007,"yearLeft" : 2015},{"id" : "markM","name" : "Two","yearJoined" : 2001,"yearLeft" : 2005}]});