source: OpenWorkouts-current/ow/static/js/ow.js @ 22eb5de

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

Merge branch 'master' into feature/ui

# Conflicts:
# ow/static/js/ow.js

  • Property mode set to 100644
File size: 11.9 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        url = spec.url,
247        current_month = spec.current_month,
248        y_axis_labels = spec.y_axis_labels;
249
250    // Helpers
251    function select_x_axis_label(d) {
252        /* Given a value, return the label associated with it */
253        return d3.select('.x-axis-b')
254            .selectAll('text')
255            .filter(function(x) { return x == d.name; });
256    };
257
258    function get_y_value(d, filter_by) {
259        return Number(d[filter_by]);
260    };
261
262    function get_y_axis_label(filter_by) {
263        return y_axis_labels[filter_by];
264    };
265
266    // Methods
267    var filters_setup = function filters_setup() {
268        $(filters_selector).on('click', function(e) {
269            var filter_by = 'distance';
270            e.preventDefault();
271            filter_by = $(this).attr('class').split('-')[1]
272            var chart = d3.select(chart_selector);
273            chart.selectAll("*").remove();
274            render(filter_by);
275        });
276    };
277
278    var render = function render(filter_by) {
279        /*
280          Build a d3 bar chart, populated with data from the given url.
281        */
282        var chart = d3.select(chart_selector),
283            margin = {top: 20, right: 20, bottom: 30, left: 50},
284            width = +chart.attr("width") - margin.left - margin.right,
285            height = +chart.attr("height") - margin.top - margin.bottom,
286            g = chart.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
287            x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
288            y = d3.scaleLinear().rangeRound([height, 0]);
289
290        d3.json(url).then(function (data) {
291            x.domain(data.map(function (d) {
292                return d.name;
293            }));
294
295            y.domain([0, d3.max(data, function (d) {
296                return get_y_value(d, filter_by);
297            })]);
298
299            g.append("g")
300                .attr('class', 'x-axis-b')
301                .attr("transform", "translate(0," + height + ")")
302                .call(d3.axisBottom(x))
303
304            g.append("g")
305                .call(d3.axisLeft(y))
306                .append("text")
307                .attr("fill", "#000")
308                .attr("transform", "rotate(-90)")
309                .attr("y", 6)
310                .attr("dy", "0.71em")
311                .attr("text-anchor", "end")
312                .text(get_y_axis_label(filter_by));
313
314            g.selectAll(".bar")
315                .data(data)
316                .enter().append("rect")
317                .attr("class", function(d) {
318                    if (d.id == current_month){
319                        select_x_axis_label(d).attr('style', "font-weight: bold;");
320                        return 'bar current'
321                    }
322                    else {
323                        return 'bar'
324                    }
325                })
326                .attr("x", function (d) {
327                    return x(d.name);
328                })
329                .attr("y", function (d) {
330                    return y(get_y_value(d, filter_by));
331                })
332                .attr("width", x.bandwidth())
333                .attr("height", function (d) {
334                    return height - y(get_y_value(d, filter_by));
335                })
336                .on('mouseover', function(d) {
337                    if (d.id != current_month){
338                        select_x_axis_label(d).attr('style', "font-weight: bold;");
339                    }
340                })
341                .on('mouseout', function(d) {
342                    if (d.id != current_month){
343                        select_x_axis_label(d).attr('style', "font-weight: regular;");
344                    }
345                });
346
347            g.selectAll(".text")
348                .data(data)
349                .enter()
350                .append("text")
351                .attr("class","label")
352                .attr("x", function (d) {
353                    return x(d.name) + x.bandwidth()/2;
354                })
355                .attr("y", function (d) {
356                    /*
357                      Get the value for the current bar, then get the maximum
358                      value to be displayed in the bar, which is used to
359                      calculate the proper position of the label for this bar,
360                      relatively to its height (1% above the bar)
361                     */
362                    var value = get_y_value(d, filter_by);
363                    var max = y.domain()[1];
364                    return y(value + y.domain()[1] * 0.01);
365                })
366                .text(function(d) {
367                    var value = get_y_value(d, filter_by)
368                    if ( value > 0) {
369                        return value;
370                    }
371                });
372
373        });
374    };
375
376    var that = {}
377    that.filters_setup = filters_setup;
378    that.render = render;
379    return that
380
381};
Note: See TracBrowser for help on using the repository browser.