Digital humanities


Maintained by: David J. Birnbaum (djbpitt@gmail.com) [Creative Commons BY-NC-SA 3.0 Unported License] Last modified: 2015-11-07T20:19:51+0000


SVG assignment #3 answers

Overview

The basic task of SVG assignment 2 was to create an SVG bar graph of the democratic results of the 2012 US presidential election. See the assignment page for a more detailed description, suggestions, and a link to the input data in XML form. See also our posted solution. For SVG assignment 3 we asked you to enhance your answer to #2 by using variables, and also by including additional information.

Sample solution

The XSLT that we used to produce our JavaScript-enhanced enhanced output is below. Note the extensive use of variables and calculated values. This output embeds the SVG inside HTML (that is, it isn’t stand-alone SVG of the sort that we’ve been creating so far), and it needs the CSS and JavaScript for completely correct display and interactive functionality.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all">
    <xsl:output indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="sorted" as="node()+">
            <xsl:for-each select="//state">
                <xsl:sort select="candidate[@party='Democrat'] div sum(candidate)"
                    order="descending"/>
                <xsl:copy-of select="current()"/>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="barInterval" select="15"/>
        <xsl:variable name="barHeight" select="300"/>
        <html>
            <head>
                <title>Election results</title>
                <link rel="stylesheet" type="text/css" href="http://www.obdurodon.org/css/style.css"/>
                <link rel="stylesheet" type="text/css" href="style.css"/>
                <link rel="stylesheet" type="text/css" href="election.css"/>
                <script type="text/javascript" src="election.js">//</script>
            </head>
            <body>
                <h1>Results of 2012 US presidential election</h1>
                <p>Data scraped from <a
                        href="http://en.wikipedia.org/wiki/United_States_presidential_election,_2012"
                        >http://en.wikipedia.org/wiki/United_States_presidential_election,_2012</a>.
                    Click on a bar to see the votes for that state.</p>
                <div id="svg-wrap">
                    <svg xmlns="http://www.w3.org/2000/svg" height="375">
                        <g transform="translate(30, 330)">
                            <line x1="20" x2="20" y1="0" y2="-320" stroke="black" stroke-width="1"/>
                            <line x1="20"
                                x2="{count(//state)*$barInterval + sum(//state/@elec)*2 + 20}"
                                y1="0" y2="0" stroke="black" stroke-width="1"/>
                            <text x="10" y="5" text-anchor="end">0%</text>
                            <text x="10" y="{5 - $barHeight div 2}" text-anchor="end">50%</text>
                            <text x="10" y="{5 - $barHeight}" text-anchor="end">100%</text>
                            <xsl:for-each select="$sorted">
                                <xsl:variable name="statePos" select="position()-1"/>
                                <xsl:variable name="xPosition"
                                    select="$statePos*$barInterval + sum($sorted[position() lt ($statePos + 1)]/@elec)*2 + 22"/>
                                <xsl:variable name="totalVotes" select="sum(candidate)"/>
                                <xsl:variable name="elec" select="@elec"/>
                                <xsl:variable name="acro" select="@acro"/>
                                <g id="{$acro}" class="wrapper">
                                    <text x="{$xPosition + ($elec)}" y="20" text-anchor="middle">
                                        <xsl:value-of select="$acro"/>
                                    </text>
                                    <text x="{$xPosition + ($elec)}" y="35" text-anchor="middle">
                                        <xsl:value-of select="$elec"/>
                                    </text>
                                    <xsl:for-each select="candidate">
                                        <xsl:variable name="percentage"
                                            select="current() div $totalVotes"/>
                                        <xsl:variable name="color">
                                            <xsl:choose>
                                                <xsl:when test="@party='Democrat'">blue</xsl:when>
                                                <xsl:when test="@party='Republican'">red</xsl:when>
                                                <xsl:when test="@party='Libertarian'"
                                                  >yellow</xsl:when>
                                                <xsl:when test="@party='Green'">green</xsl:when>
                                            </xsl:choose>
                                        </xsl:variable>
                                        <rect x="{$xPosition}"
                                            y="{-($percentage+(sum(../candidate[@party lt current()/@party]) div $totalVotes))*$barHeight}"
                                            stroke="black" stroke-width=".5" fill="{$color}"
                                            width="{$elec*2}" height="{($percentage*$barHeight)}"/>
                                    </xsl:for-each>
                                </g>
                            </xsl:for-each>
                            <line x1="20"
                                x2="{count(//state)*$barInterval + sum(//state/@elec)*2 + 20}"
                                y1="-{$barHeight div 2}" y2="-{$barHeight div 2}" stroke="black"
                                opacity="0.5" stroke-dasharray="8 4" stroke-width="1"/>
                        </g>
                    </svg>
                </div>
                <h2>Votes for <span id="current-state">PA</span></h2>
                <table id="results" border="1">
                    <tr>
                        <th>Party</th>
                        <th>Votes</th>
                        <th>Percent</th>
                    </tr>
                    <xsl:for-each select="//state">
                        <xsl:variable name="total" select="sum(candidate)"/>
                        <xsl:variable name="elec" select="@elec"/>
                        <tbody id="tbody-{@acro}">
                            <xsl:if test="not(@acro = 'PA')">
                                <xsl:attribute name="style">display: none;</xsl:attribute>
                            </xsl:if>
                            <xsl:for-each select="candidate">
                                <xsl:sort select="@party" order="descending"/>
                                <xsl:variable name="pct" select=". div $total" as="xs:double"/>
                                <tr class="{@party}">
                                    <xsl:if test="($pct * 100) gt 50">
                                        <xsl:attribute name="style"
                                            >font-weight:bold;</xsl:attribute>
                                    </xsl:if>
                                    <td>
                                        <xsl:value-of select="@party"/>
                                    </td>
                                    <td>
                                        <xsl:value-of select="format-number(.,'#,###')"/>
                                    </td>
                                    <td>
                                        <xsl:value-of select="format-number($pct,'0.00%')"/>
                                    </td>
                                </tr>
                            </xsl:for-each>
                            <tr style="font-weight: bold;">
                                <td>Total</td>
                                <td>
                                    <xsl:value-of select="format-number($total,'#,###')"/>
                                </td>
                                <td>Electoral: <xsl:value-of select="@elec"/></td>
                            </tr>
                        </tbody>
                    </xsl:for-each>
                    <tr style="font-weight: bold; visibility:hidden">
                        <td>Republican</td>
                        <td>10,000,000</td>
                        <td>Electoral: 55</td>
                    </tr>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>