<% osm = @trans.t.osm misc = @trans.t.misc taginfo = @trans.t.taginfo page = @trans.t.pages.relation %> var create_flexigrid_for = { overview: function(rtype) { create_flexigrid('grid-overview', { url: '/api/4/relation/stats?rtype=' + encodeURIComponent(rtype), colModel: [ { display: '<%= h(page.overview.member_type) %>', name: 'type', width: 100, sortable: true }, { display: '<%= h(page.overview.member_count) %>', name: 'count', width: 260, sortable: true, align: 'right' } ], usepager: false, useRp: false, preProcess: function(data) { return { total: 4, page: 1, rows: jQuery.map(data.data, function(row, i) { return { 'cell': [ fmt_type_image(row.type), fmt_with_ts(row.count) ]}; }) }; } }); }, roles: function(rtype) { create_flexigrid('grid-roles', { url: '/api/4/relation/roles?rtype=' + encodeURIComponent(rtype), colModel: [ { display: '<%= h(osm.relation_member_role) %>', name: 'role', width: 250, sortable: true }, { display: ' <%= h(osm.relation_members) %>', name: 'count_all_members', width: 250, sortable: true, align: 'center' }, { display: ' <%= h(osm.relation_member_nodes) %>', name: 'count_node_members', width: 250, sortable: true, align: 'center' }, { display: ' <%= h(osm.relation_member_ways) %>', name: 'count_way_members', width: 250, sortable: true, align: 'center' }, { display: ' <%= h(osm.relation_member_relations) %>', name: 'count_relation_members', width: 250, sortable: true, align: 'center' }, ], searchitems: [ { display: '<%= h(osm.relation_member_role) %>', name: 'role' } ], sortname: 'count_all_members', sortorder: 'desc', preProcess: function(data) { data.rows = jQuery.map(data.data, function(row, i) { return { 'cell': [ fmt_role(row.role), fmt_value_with_percent(row.count_all_members, row.count_all_members_fraction), fmt_value_with_percent(row.count_node_members, row.count_node_members_fraction), fmt_value_with_percent(row.count_way_members, row.count_way_members_fraction), fmt_value_with_percent(row.count_relation_members, row.count_relation_members_fraction) ] }; }); return data; } }); }, wiki: function(rtype) { create_flexigrid('grid-wiki', { url: '/api/4/relation/wiki_pages?rtype=' + encodeURIComponent(rtype), colModel: [ { display: '<%= h(misc.language) %>', name: 'lang', width: 150, sortable: false }, { display: '<%= h(page.wiki_pages.wiki_page) %>', name: 'title', width: 160, sortable: false, align: 'right' }, { display: '<%= h(misc.description) %>', name: 'description', width: 500, sortable: false }, { display: '<%= h(misc.image) %>', name: 'image', width: 300, sortable: false } ], usepager: false, useRp: false, preProcess: function(data) { return { total: data.size, page: 1, rows: jQuery.map(data, function(row, i) { return { 'cell': [ fmt_language(row.lang, row.language, row.language_en), link_to_wiki(row.title), html_escape(row.description), fmt_wiki_image_popup(row.image) ]}; }) }; } }); }, projects: function(rtype) { create_flexigrid('grid-projects', { url: '/api/4/relation/projects?rtype=' + encodeURIComponent(rtype), colModel: [ { display: '<%= h(taginfo.project) %>', name: 'project_name', width: 280, sortable: true }, { display: '<%= h(page.projects.description) %>', name: 'description', width: 600, sortable: false, align: 'left' } ], searchitems: [ { display: '<%= h(taginfo.project) %>/<%= h(osm.value) %>', name: 'project_value' } ], sortname: 'project_name', sortorder: 'asc', preProcess: function(data) { data.rows = jQuery.map(data.data, function(row, i) { return { 'cell': [ link_to_project(row.project_id, row.project_name, row.project_icon_url), project_tag_desc(row.description, row.icon_url, row.doc_url) ] }; }); return data; } }); } }; // Marimekko chart based on http://bl.ocks.org/1005090 function create_role_chart(data) { if (data.length == 0) { return; } var width = 800, height = 360, margin = 20; var x = d3.scale.linear() .range([0, width - 3 * margin]); var y = d3.scale.linear() .range([0, height - 2 * margin]); var z = d3.scale.category10(); var n = d3.format(",d"), p = d3.format("%"); var svg = d3.select("div.canvas").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + 2 * margin + "," + margin + ")"); var offset = 0; // Nest values by member type. We assume each member type+role is unique. var member_types = d3.nest() .key(function(d) { return d.type; }) .entries(data); // Compute the total sum, the per-type sum, and the per-role offset. // You can use reduce rather than reduceRight to reverse the ordering. // We also record a reference to the parent type for each role. var sum = member_types.reduce(function(v, p) { return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) { d.parent = p; return (d.offset = v) + d.value; }, 0)); }, 0); // Add x-axis ticks. var xtick = svg.selectAll(".x") .data(x.ticks(10)) .enter().append("g") .attr("class", "x") .attr("transform", function(d) { return "translate(" + x(d) + "," + y(1) + ")"; }); xtick.append("line") .attr("y2", 6) .style("stroke", "#000"); xtick.append("text") .attr("y", 8) .attr("text-anchor", "middle") .attr("dy", ".71em") .text(p); // Add y-axis ticks. var ytick = svg.selectAll(".y") .data(y.ticks(10)) .enter().append("g") .attr("class", "y") .attr("transform", function(d) { return "translate(0," + y(1 - d) + ")"; }); ytick.append("line") .attr("x1", -6) .style("stroke", "#000"); ytick.append("text") .attr("x", -8) .attr("text-anchor", "end") .attr("dy", ".35em") .text(p); // Add a group for each member type. var member_types_svg = svg.selectAll(".member_types") .data(member_types) .enter().append("g") .attr("class", "member_types") .attr("xlink:title", function(d) { return d.key; }) .attr("transform", function(d) { return "translate(" + x(d.offset / sum) + ")"; }) .call(function(c) { c.append("line") .attr("x1", 0) .attr("y1", -9.5) .attr("x2", function(d) { return x(d.sum/sum); } ) .attr("y2", -9.5) .style("stroke", "#000"); c.append("text") .attr("x", 0) .attr("y", -6) .attr("text-anchor", "start") .text(function(d) { return x(d.sum/sum/2) > 6 ? '<' : ''; }); c.append("text") .attr("x", function(d) { return x(d.sum/sum); } ) .attr("y", -6) .attr("text-anchor", "end") .text(function(d) { return x(d.sum/sum/2) > 6 ? '>' : ''; }); c.append("text") .attr("x", function(d) { return x(d.sum/sum/2); } ) .attr("y", -6) .attr("text-anchor", "middle") .style("stroke", "#ddddd4") .style("stroke-width", 4) .style("fill", "#000") .text(function(d) { return x(d.sum/sum/2) > 20 ? texts.osm[d.key] : ''; }); c.append("text") .attr("x", function(d) { return x(d.sum/sum/2); } ) .attr("y", -6) .attr("text-anchor", "middle") .style("fill", "#000") .text(function(d) { return x(d.sum/sum/2) > 20 ? texts.osm[d.key] : ''; }); }) // Add a rect for each role. var roles = member_types_svg.selectAll(".role") .data(function(d) { return d.values; }) .enter().append("a") .attr("class", "role") .attr("xlink:title", function(d) { if (d.role == '...') { return "" + d.value + " member " + d.parent.key + " with other roles"; } else { return "" + d.value + " member " + d.parent.key + " with role '" + d.role + "'"; } }) .call(function(c) { c.append("rect") .attr("y", function(d) { return y(d.offset / d.parent.sum); }) .attr("height", function(d) { return y(d.value / d.parent.sum); }) .attr("width", function(d) { return x(d.parent.sum / sum); }) .style("fill", function(d) { return z(d.role); }); c.append("text") .attr("x", function(d) { return x(d.parent.sum / sum / 2); } ) .attr("y", function(d) { return y(d.value / d.parent.sum / 2); } ) .attr("dy", function(d) { return y(d.offset / d.parent.sum) + 4; }) .attr("text-anchor", "middle") .style("fill", "#fff") .text(function(d) { if (x(d.parent.sum / sum) > 40 && y(d.value / d.parent.sum) > 12) { return d.role == '' ? '(empty)' : d.role; } else { return ''; } }); }); } function page_init() { up = function() { window.location = '/relations'; }; activate_josm_button(); page_init2(); }