source: OpenWorkouts-current/ow/static/js/ow.js @ 6993c72

currentfeature/docs
Last change on this file since 6993c72 was 6993c72, checked in by Segundo Fdez <segun.2@…>, 5 years ago

Merge branch 'master' into feature/ui

# Conflicts:
# ow/templates/profile.pt

  • Property mode set to 100644
File size: 14.2 KB
Line 
1
2/*
3
4  OpenWorkouts Javascript code
5
6*/
7
8
9// Namespace
10var owjs = {};
11
12
13owjs.map = function(spec) {
14
15    "use strict";
16
17    // parameters provided when creating an "instance" of a map
18    var map_id = spec.map_id;
19    var latitude = spec.latitude;
20    var longitude = spec.longitude;
21    var zoom = spec.zoom;
22    var gpx_url = spec.gpx_url;
23    var start_icon = spec.start_icon;
24    var end_icon = spec.end_icon;
25    var shadow = spec.shadow;
26    var elevation = spec.elevation;
27    var zoom_control = spec.zoom_control;
28
29    // OpenStreetMap urls and references
30    var openstreetmap_url = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
31    var openstreetmap_attr = 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>';
32
33    // Some vars reused through the code
34    var map;
35    var gpx;
36    var elevation;
37    var ow_charts;
38
39    var create_map = function create_map(latitude, longitude, zoom) {
40        /* Create a Leaflet map, set center point and add tiles */
41        map = L.map(map_id, {zoomControl: zoom_control});
42        map.setView([latitude, longitude], zoom);
43        var tile_layer = L.tileLayer(openstreetmap_url, {
44            attribution: openstreetmap_attr
45        });
46        tile_layer.addTo(map);
47    };
48
49    var add_elevation_chart = function add_elevation_chart() {
50        /*
51           Add the elevation chart support to the map.
52           This has to be called *after* create_map and *before* load_gpx.
53        */
54        elevation = L.control.elevation({
55            position: "bottomright",
56            theme: "steelblue-theme", //default: lime-theme
57            width: 600,
58            height: 125,
59            margins: {
60                top: 10,
61                right: 20,
62                bottom: 30,
63                left: 50
64            },
65            useHeightIndicator: true, //if false a marker is drawn at map position
66            interpolation: "linear", //see https://github.com/mbostock/d3/wiki/SVG-Shapes#wiki-area_interpolate
67            hoverNumber: {
68                decimalsX: 3, //decimals on distance (always in km)
69                decimalsY: 0, //deciamls on height (always in m)
70                formatter: undefined //custom formatter function may be injected
71            },
72            xTicks: undefined, //number of ticks in x axis, calculated by default according to width
73            yTicks: undefined, //number of ticks on y axis, calculated by default according to height
74            collapsed: false    //collapsed mode, show chart on click or mouseover
75        });
76
77        var ele_container = elevation.addTo(map);
78        /* document.getElementById('ow-analysis').appendChild(
79            ele_container._container); */
80    };
81
82    var load_gpx = function load_gpx(gpx_url) {
83        /*
84          Load the gpx from the given url, add it to the map and feed it to the
85          elevation chart
86        */
87        var gpx = new L.GPX(gpx_url, {
88            async: true,
89            marker_options: {
90                startIconUrl: start_icon,
91                endIconUrl: end_icon,
92                shadowUrl: shadow,
93            },
94        });
95
96        gpx.on('loaded', function(e) {
97            map.fitBounds(e.target.getBounds());
98        });
99
100        if (elevation) {
101            gpx.on("addline",function(e){
102                elevation.addData(e.line);
103                // ow_charts.addData(e.line);
104            });
105        };
106
107        gpx.addTo(map);
108    };
109
110    var render = function render() {
111        // create the map, add elevation, load gpx
112        create_map(latitude, longitude, zoom);
113        if (elevation) {
114            add_elevation_chart();
115        }
116        // add_ow_charts();
117        load_gpx(gpx_url);
118    };
119
120    var that = {}
121    that.render = render;
122    return that
123
124};
125
126
127owjs.week_chart = function(spec) {
128
129    "use strict";
130
131    // parameters provided when creating an "instance" of the chart
132    var chart_selector = spec.chart_selector,
133        url = spec.url,
134        current_day_name = spec.current_day_name
135
136    // Helpers
137    function select_x_axis_label(d) {
138        /* Given a value, return the label associated with it */
139        return d3.select('.x-axis')
140            .selectAll('text')
141            .filter(function(x) { return x == d.name; });
142    }
143
144    // Methods
145    var render = function render() {
146        /*
147           Build a d3 bar chart, populated with data from the given url.
148         */
149        var chart = d3.select(chart_selector),
150            margin = {top: 17, right: 0, bottom: 20, left: 0},
151
152            width = +chart.attr("width") - margin.left - margin.right,
153            height = +chart.attr("height") - margin.top - margin.bottom,
154            g = chart.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
155            x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
156            y = d3.scaleLinear().rangeRound([height, 0]);
157
158        d3.json(url).then(function (data) {
159            x.domain(data.map(function (d) {
160                return d.name;
161            }));
162
163            y.domain([0, d3.max(data, function (d) {
164                return Number(d.distance);
165            })]);
166
167            g.append("g")
168                .attr('class', 'x-axis')
169                .attr("transform", "translate(0," + height + ")")
170                .call(d3.axisBottom(x))
171
172            g.selectAll(".bar")
173                .data(data)
174                .enter().append("rect")
175                .attr("class", function(d) {
176                    if (d.name == current_day_name){
177                        select_x_axis_label(d).attr('style', "font-weight: bold;");
178                        return 'bar current'
179                    }
180                    else {
181                        return 'bar'
182                    }
183                })
184                .attr("x", function (d) {
185                    return x(d.name);
186                })
187                .attr("y", function (d) {
188                    return y(Number(d.distance));
189                })
190                .attr("width", x.bandwidth())
191                .attr("height", function (d) {
192                    return height - y(Number(d.distance));
193                })
194                .on('mouseover', function(d) {
195                    if (d.name != current_day_name){
196                        select_x_axis_label(d).attr('style', "font-weight: bold;");
197                    }
198                })
199                .on('mouseout', function(d) {
200                    if (d.name != current_day_name){
201                        select_x_axis_label(d).attr('style', "font-weight: regular;");
202                    }
203                });
204
205            g.selectAll(".text")
206                .data(data)
207                .enter()
208                .append("text")
209                .attr("class","label")
210                .attr("x", function (d) {
211                    return x(d.name) + x.bandwidth()/2;
212                })
213                .attr("y", function (d) {
214                    /*
215                      Get the value for the current bar, then get the maximum
216                      value to be displayed in the bar, which is used to
217                      calculate the proper position of the label for this bar,
218                      relatively to its height (1% above the bar)
219                     */
220                    var max = y.domain()[1];
221                    return y(d.distance + y.domain()[1] * 0.02);
222            })
223                .text(function(d) {
224                    if (Number(d.distance) > 0) {
225                        return d.distance;
226                    }
227                });
228
229        });
230    };
231
232    var that = {}
233    that.render = render;
234    return that
235
236};
237
238
239owjs.year_chart = function(spec) {
240
241    "use strict";
242
243    // parameters provided when creating an "instance" of the chart
244    var chart_selector = spec.chart_selector,
245        filters_selector = spec.filters_selector,
246        switcher_selector = spec.switcher_selector,
247        urls = spec.urls,
248        current_month = spec.current_month,
249        current_week = spec.current_week,
250        y_axis_labels = spec.y_axis_labels,
251        filter_by = spec.filter_by,
252        url = spec.url;
253
254    // Helpers
255    function select_x_axis_label(d) {
256        /* Given a value, return the label associated with it */
257        return d3.select('.x-axis-b')
258            .selectAll('text')
259            .filter(function(x) { return x == d.name; });
260    };
261
262    function get_y_value(d, filter_by) {
263        return Number(d[filter_by]);
264    };
265
266    function get_y_axis_label(filter_by) {
267        return y_axis_labels[filter_by];
268    };
269
270    function get_name_for_x(d) {
271        if (d.week == undefined || d.week == 0) {
272            return d.name;
273        }
274        else {
275            return d.id.split('-')[2];
276        }
277    }
278
279    // Methods
280    var filters_setup = function filters_setup() {
281        $(filters_selector).on('click', function(e) {
282            e.preventDefault();
283            filter_by = $(this).attr('class').split('-')[1]
284            var chart = d3.select(chart_selector);
285            chart.selectAll("*").remove();
286            render(filter_by, url);
287        });
288    };
289
290    var switcher_setup = function switcher_setup() {
291        $(switcher_selector).on('click', function(e) {
292            e.preventDefault();
293            url = $(this).attr('class').split('-')[1]
294            var chart = d3.select(chart_selector);
295            chart.selectAll("*").remove();
296            render(filter_by, url);
297        });
298    };
299
300    var render = function render(filter_by, url) {
301        /*
302          Build a d3 bar chart, populated with data from the given url.
303        */
304        var chart = d3.select(chart_selector),
305            margin = {top: 20, right: 20, bottom: 30, left: 50},
306            width = +chart.attr("width") - margin.left - margin.right,
307            height = +chart.attr("height") - margin.top - margin.bottom,
308            g = chart.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
309            x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
310            y = d3.scaleLinear().rangeRound([height, 0]);
311
312        d3.json(urls[url]).then(function (data) {
313            x.domain(data.map(function (d) {
314                return get_name_for_x(d);
315                // return d.name;
316            }));
317
318            y.domain([0, d3.max(data, function (d) {
319                return get_y_value(d, filter_by);
320            })]);
321
322            g.append("g")
323                .attr('class', 'x-axis-b')
324                .attr("transform", "translate(0," + height + ")")
325                .call(d3.axisBottom(x))
326
327            g.append("g")
328                .call(d3.axisLeft(y))
329                .append("text")
330                .attr("fill", "#000")
331                .attr("transform", "rotate(-90)")
332                .attr("y", 6)
333                .attr("dy", "0.71em")
334                .attr("text-anchor", "end")
335                .text(get_y_axis_label(filter_by));
336
337            g.selectAll(".bar")
338                .data(data)
339                .enter().append("rect")
340                .attr("class", function(d) {
341                    var sel_week = current_month + '-' + current_week;
342                    if (d.id == current_month || d.id == sel_week){
343                        /* Bar for the currently selected month or week */
344                        select_x_axis_label(d).attr('style', "font-weight: bold;");
345                        return 'bar current';
346                    }
347                    else {
348                        if (!current_week && d.id.indexOf(current_month) >=0 ) {
349                            /*
350                               User selected a month, then switched to weekly
351                               view, we do highlight all the bars for weeks in
352                               that month
353                            */
354                            select_x_axis_label(d).attr('style', "font-weight: bold;");
355                            return 'bar current';
356                        }
357                        else {
358                            /* Non-selected bar */
359                            return 'bar';
360                        }
361
362                    }
363                })
364                .attr("x", function (d) {
365                    return x(get_name_for_x(d));
366                })
367                .attr("y", function (d) {
368                    return y(get_y_value(d, filter_by));
369                })
370                .attr("width", x.bandwidth())
371                .attr("height", function (d) {
372                    return height - y(get_y_value(d, filter_by));
373                })
374                .on('mouseover', function(d) {
375                    if (d.id != current_month){
376                        select_x_axis_label(d).attr('style', "font-weight: bold;");
377                    }
378                })
379                .on('mouseout', function(d) {
380                    if (d.id != current_month){
381                        select_x_axis_label(d).attr('style', "font-weight: regular;");
382                    }
383                })
384                .on('click', function(d) {
385                    window.location.href = d.url;
386                });
387
388            if (url == 'monthly') {
389                g.selectAll(".text")
390                    .data(data)
391                    .enter()
392                    .append("text")
393                    .attr("class","label")
394                    .attr("x", function (d) {
395                        return x(get_name_for_x(d)) + x.bandwidth()/2;
396                    })
397                    .attr("y", function (d) {
398                        /*
399                          Get the value for the current bar, then get the maximum
400                          value to be displayed in the bar, which is used to
401                          calculate the proper position of the label for this bar,
402                          relatively to its height (1% above the bar)
403                        */
404                        var value = get_y_value(d, filter_by);
405                        var max = y.domain()[1];
406                        return y(value + y.domain()[1] * 0.01);
407                    })
408                    .text(function(d) {
409                        var value = get_y_value(d, filter_by)
410                        if ( value > 0) {
411                            return value;
412                        }
413                    });
414            }
415
416            if (url == 'weekly') {
417                g.selectAll(".tick")
418                    .each(function (d, i) {
419                        /*
420                          Remove from the x-axis tickets those without letters
421                          on them (useful for the weekly chart)
422                        */
423                        if (d !== parseInt(d, 10)) {
424                            if(!d.match(/[a-z]/i)) {
425                                this.remove();
426                            }
427                        }
428                    });
429            }
430        });
431    };
432
433    var that = {}
434    that.filters_setup = filters_setup;
435    that.switcher_setup = switcher_setup;
436    that.render = render;
437    return that
438
439};
Note: See TracBrowser for help on using the repository browser.