Public
Edited
Apr 6, 2023
1 fork
4 stars
Insert cell
Insert cell
bills = ({
'house': [
{
label: 'Theoretical party line vote',
sublabel: '102 yes votes from Republicans and 48 nos from Democrats.',
votes: { yes: {R: 102, D: 0}, no: {R: 0, D: 48 }, absent: {R: 0, D: 0} },
potentialVotes: { yes: {R: 0, D: 0}, no: {R: 0, D: 0 } }
},
{
label: 'HB 372 – Constitutional right to hunt and trap',
sublabel: 'House vote 64-34. Senate vote forthcoming.',
votes: { yes: {R: 64, D: 0}, no: {R: 4, D: 30 }, absent: {R: 0, D: 2} },
potentialVotes: { yes: {R: 34, D: 0}, no: {R: 0, D: 16 } }
},
{
label: 'HB 517 – Expanded Legislative power over universities',
sublabel: 'House vote 61-37. Senate vote forthcoming.',
votes: { yes: {R: 61, D: 0}, no: {R: 7, D: 30 }, absent: {R: 0, D: 2} },
potentialVotes: { yes: {R: 34, D: 0}, no: {R: 0, D: 16 } }
},
{
label: 'HB 551 – Constitutional right to carry concealed firearms',
sublabel: 'House vote 65-33. Senate vote forthcoming.',
votes: { yes: {R: 65, D: 0}, no: {R: 3, D: 30 }, absent: {R: 0, D: 2} },
potentialVotes: { yes: {R: 34, D: 0}, no: {R: 0, D: 16 } }
},
{
label: 'HB 915 – Makes state supreme court justices appointed',
sublabel: 'House vote 59-39. Senate vote forthcoming.',
votes: { yes: {R: 59, D: 0}, no: {R: 9, D: 30 }, absent: {R: 0, D: 2} },
potentialVotes: { yes: {R: 34, D: 0}, no: {R: 0, D: 16 } }
},
{
label: 'HB 965 – Strips lawyer licensing from state supreme court jurisdiction',
sublabel: 'House vote 45-55. Received too few votes to advance to Senate.',
votes: { yes: {R: 45, D: 0}, no: {R: 23, D: 32 }, absent: {R: 0, D: 0} },
potentialVotes: { yes: {R: 0, D: 0}, no: {R: 0, D: 0 } }
},
{
label: 'SB 272 – Enshrines county sheriff powers in Constitution',
sublabel: 'Senate vote 22-28. House vote forthcoming.',
votes: { yes: {R: 22, D: 0}, no: {R: 12, D: 16 }, absent: {R: 0, D: 0} },
potentialVotes: { yes: {R: 68, D: 0}, no: {R: 0, D: 32 } }
},
{
label: 'SB 534 – Forbids consideration of political data in redistricting',
sublabel: 'House vote 31-19, including one Democrat who said she had misvoted. Senate vote forthcoming.',
votes: { yes: {R: 30, D: 1}, no: {R: 4, D: 15 }, absent: {R: 0, D: 0} },
potentialVotes: { yes: {R: 68, D: 0}, no: {R: 0, D: 32 } }
},
{
label: 'SB 563 – Establishes a mental health trust fund',
sublabel: 'Senate vote 40-10. House vote forthcoming.',
votes: { yes: {R: 29, D: 11}, no: {R: 5, D: 5 }, absent: {R: 0, D: 0} },
potentialVotes: { yes: {R: 68, D: 0}, no: {R: 0, D: 32 } }
},
]
})
Insert cell
graphic = {
const width = 600
const height = 1200
const mark = (vote, i, sign) => `<g transform="translate(${sign*Math.floor(i/4)*12 + (i >= 100 ? 8 : 0)},${i%4*12})"><circle
r="5"
cx="0" cy="0"
fill="${fill(vote)}"
fill-opacity="0.7"
stroke="${stroke(vote)}"
/>
</g>`
const houseVotes = bills.house.map((bill, i) => {
const yesVotes =
[].concat(
[...Array(bill.votes.yes.R).keys()].map(d => ({party: 'R', type: 'counted'}))
).concat(
[...Array(bill.votes.yes.D).keys()].map(d => ({party: 'D', type: 'counted'}))
).concat(
[...Array(bill.potentialVotes.yes.R).keys()].map(d => ({party: 'R', type: 'potential'}))
).concat(
[...Array(bill.potentialVotes.yes.D).keys()].map(d => ({party: 'D', type: 'potential'}))
)
const noVotes =
[].concat(
[...Array(bill.votes.no.R).keys()].map(d => ({party: 'R', type: 'counted'}))
).concat(
[...Array(bill.votes.no.D).keys()].map(d => ({party: 'D', type: 'counted'}))
).concat(
[...Array(bill.votes.absent.R).keys()].map(d => ({party: 'R', type: 'absent'}))
).concat(
[...Array(bill.votes.absent.D).keys()].map(d => ({party: 'D', type: 'absent'}))
).concat(
[...Array(bill.potentialVotes.no.R).keys()].map(d => ({party: 'R', type: 'potential'}))
).concat(
[...Array(bill.potentialVotes.no.D).keys()].map(d => ({party: 'D', type: 'potential'}))
)
return `<g transform="translate(210, ${50+i*120})">
<g class="nos" transform="translate(0,10)">
${noVotes.map((vote, i) => mark(vote, i, -1))}</g>

<text y=-40 x=-140 font-size=13 font-weight="bold">${bill.label}</text>
<text y=-25 x=-140 font-size=11 >${bill.sublabel}</text>

<line x1="10" x2="10" y1="-12" y2="55" stroke-width="2" stroke="black" />

<text x="15" y="-3" text-anchor="start">YES votes</text>
<g class="yeses" transform="translate(20,10)">
${yesVotes.map((vote, i) => mark(vote, i, 1))}
</g>

<text x="318" y="-3" text-anchor="middle">100 yes</text>
<text x="5" y="-3" text-anchor="end">NO votes</text>
<line x1="318" x2="318" y1="0" y2="55" stroke-width="1" stroke="black" stroke-dasharray="2"/>
</g>
`})


return html`<svg width=${width} height=${height} viewBox="0 0 ${width} ${height}"
font-family="Arial, sans-serif" font-size="10"
>
<g>${houseVotes}</g>
</svg>`
}
Insert cell
stroke = vote => vote.party === 'R' ? '#d73027' : '#4575b4'
Insert cell
fill = vote => {
if (vote.type === 'absent') return 'gray'
if (vote.type === 'potential') return 'white'
else return vote.party === 'R' ? '#d73027' : '#4575b4'
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more