-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
executable file
·1015 lines (981 loc) · 51.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="msApplication-ID" content="57039gregstoll.com.MarriageMap">
<meta name="msApplication-PackageFamilyName" content="57039gregstoll.com.MarriageMap_mrfc7nnpdd326">
<link rel="canonical" href="https://gregstoll.com/marriagemap/" />
<title>Same-sex marriage status in the United States</title>
<!--#include virtual="/bootstraphead.html"-->
<script type="text/javascript">
var isIE = false;
</script>
<!--[if lt IE 9]><script type="text/javascript" src="excanvas.compiled.js"></script>
<script type="text/javascript">
isIE = true;
</script>
<![endif]-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<!-- Combo-handled YUI CSS files: -->
<link rel="stylesheet" type="text/css" href="yui/slider.css">
<!-- Combo-handled YUI JS files: -->
<script type="text/javascript" src="yui/slider-min.js"></script>
<script src="mapdata.js" type="text/javascript"></script>
<!-- <script src="marriagedata.js" type="text/javascript"></script> -->
<style type="text/css">
canvas { border: 1px solid black; }
/* Inspired by http://demos.greghoustondesign.com/piechart/ */
.canvasWrapper {
position: relative;
}
.canvasWrapper img {
left: 0px;
top: 0px;
position: absolute;
}
img {
border: medium none;
}
#slider-bg {
/* we'll reset this width later */
width: 30px;
height: 30px;
}
#slider-bg img.slider-background {
left: 0px;
top: 0px;
position: absolute;
/* we'll reset this width later */
width: 30px;
height: 28px;
z-index: -1;
}
td {
border: 0px;
margin: 0px;
padding: 0px;
}
h1 {
font-size: x-large;
}
.compact * {
border: 0px;
margin: 0px;
padding: 0px;
}
.importantEntry {
background-color: #ecf8b9;
}
form label {
font-weight: normal;
}
</style>
</head>
<body>
<!--#include virtual="/navbar.html"-->
<div class="container">
<h1>Same-sex marriage in the United States</h1>
<table>
<tr><td><div id="pendingDiv" style="display: none; margin-top:-5px;"><span>On the horizon: <b><a id="expandContractHorizon" href="javascript:expandContractHorizon();">+</a></b></span><ul style="display: none; margin-top: 0px;" id="pendingUl"></ul></div></td></tr>
<tr><td style="width: 850px; height: 495px;">
<div class="canvasWrapper">
<canvas id="mapCanvas" width="850" height="495"></canvas>
<img width="800" height="495" src="images/spacer.gif" id="imageMapMap" usemap="#mapMap" style="width: 800px; height: 495px;" alt="">
</div></td><td style="vertical-align: bottom;">
<form class="compact" action="javascript:void(0);"><table>
<tr><td><label for="cartogramCheckbox">Cartogram </label><input type="checkbox" id="cartogramCheckbox"></td></tr>
<tr><td>Animation speed: <select id="animationSpeed" name="animationSpeed">
<option value="0">Very slow</option>
<option value="1">Slow</option>
<option value="2">Medium</option>
<option value="3" selected>Fast</option>
<option value="4">Very fast</option>
</select></td></tr>
<tr><td><label for="courtOverturnedBanGradient">Rainbow color for court-overturned bans </label><input type="checkbox" id="courtOverturnedBanGradient" checked="checked"></td></tr>
</table></form>
</td></tr></table>
<table>
<tr>
<td style="vertical-align: top;">
<p style="vertical-align: top; margin: 3px;">Date: <span id="slider-value"></span> <button type="button" onclick="startAnimation();">Play animation</button> <button type="button" onclick="stopAnimation();">Stop</button></p>
</td>
<td id="slider-td" style="vertical-align: top; height: 30px;">
<div id="slider-bg" class="yui-h-slider" tabindex="-1">
<div id="slider-thumb" class="yui-slider-thumb"><img src="yui/thumb-n.gif" alt="slider thumb"></div>
<img class="slider-background" src="yui/bg-h.gif" id="slider-background" alt="slider background">
</div>
</td>
</tr></table>
<div id="stateData"></div>
<div>
<!-- <script type="text/javascript">
google_ad_client = "pub-6170882740725599";
/* marriagemap, 300x250, created 12/2/09 */
google_ad_slot = "5182049633";
google_ad_width = 728;
google_ad_height = 90;
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script> -->
</div>
<map id="mapMap" name="mapMap">
<area href="#AL" shape="poly" coords="546,316,567,383,528,389,528,401,516,397,514,318" alt="Alabama" title="Alabama" />
<area href="#AK" shape="poly" coords="128,389,130,459,150,465,173,489,173,501,155,499,134,471,99,465,85,481,10,491,57,465,34,440,44,399,61,381,91,371" alt="Alaska" title="Alaska" />
<area href="#AZ" shape="poly" coords="112,336,161,369,193,375,208,275,136,263,132,277,126,277,118,295,128,310" alt="Arizona" title="Arizona" />
<area href="#AR" shape="poly" coords="416,293,416,342,424,357,469,357,481,316,487,299,475,295" alt="Arkansas" title="Arkansas" />
<area href="#CA" shape="poly" coords="22,138,77,153,61,206,118,287,118,293,126,308,114,334,77,330,34,283,10,165" alt="California" title="California" />
<area href="#CO" shape="poly" coords="218,199,314,210,310,281,210,271" alt="Colorado" title="Colorado" />
<area href="#CT" shape="poly" coords="695,157,695,175,718,165,716,153" alt="Connecticut" title="Connecticut" />
<area href="#DE" shape="poly" coords="675,204,679,230,691,230,687,216" alt="Delaware" title="Delaware" />
<area href="#FL" shape="poly" coords="622,385,660,463,644,495,628,495,607,442,585,401,563,412,530,399,530,391,567,385,567,391" alt="Florida" title="Florida" />
<area href="#GA" shape="poly" coords="546,312,583,310,626,354,620,387,567,389" alt="Georgia" title="Georgia" />
<area href="#HI" shape="poly" coords="185,430,183,469,220,499,287,501,291,473,248,432" alt="Hawaii" title="Hawaii" />
<area href="#ID" shape="poly" coords="142,40,130,91,136,97,122,118,116,161,191,175,199,132,175,130,169,108,161,112,163,89,148,61,155,42" alt="Idaho" title="Idaho" />
<area href="#IL" shape="poly" coords="471,187,459,224,479,246,475,259,495,281,505,279,514,246,512,193,501,177,469,183" alt="Illinois" title="Illinois" />
<area href="#IN" shape="poly" coords="512,193,512,265,536,259,552,240,546,189" alt="Indiana" title="Indiana" />
<area href="#IA" shape="poly" coords="391,167,385,183,399,220,454,220,463,208,471,191,459,169" alt="Iowa" title="Iowa" />
<area href="#KS" shape="poly" coords="312,228,306,283,414,285,414,246,410,242,412,234,399,228" alt="Kansas" title="Kansas" />
<area href="#KY" shape="poly" coords="493,291,575,281,593,263,579,244,554,238,538,263,512,265" alt="Kentucky" title="Kentucky" />
<area href="#LA" shape="poly" coords="428,414,434,389,424,373,426,359,471,359,471,369,465,391,487,391,497,403,503,424,465,428" alt="Louisiana" title="Louisiana" />
<area href="#ME" shape="poly" coords="711,93,722,126,726,132,762,89,754,75,742,51,722,46" alt="Maine" title="Maine" />
<area href="#MD" shape="poly" coords="622,214,622,224,642,216,660,226,660,234,671,236,679,250,689,228,677,228,675,206" alt="Maryland" title="Maryland" />
<area href="#MA" shape="poly" coords="693,144,695,159,722,153,728,159,746,161,746,144,726,136" alt="Massachusetts" title="Massachusetts" />
<area href="#MI" shape="poly" coords="463,97,471,112,505,126,522,189,565,185,573,163,550,108,493,71" alt="Michigan" title="Michigan" />
<area href="#MN" shape="poly" coords="381,67,387,122,385,124,391,132,391,167,461,167,461,159,436,142,434,128,442,108,473,81,410,73,405,61" alt="Minnesota" title="Minnesota" />
<area href="#MS" shape="poly" coords="483,320,512,316,516,401,497,401,487,389,465,389,473,363,471,352" alt="Mississippi" title="Mississippi" />
<area href="#MO" shape="poly" coords="399,220,399,228,414,244,414,293,481,291,477,299,485,299,495,283,475,259,477,250,454,222" alt="Missouri" title="Missouri" />
<area href="#MT" shape="poly" coords="157,40,153,59,165,87,161,108,169,104,177,128,199,130,201,124,291,134,297,63" alt="Montana" title="Montana" />
<area href="#NE" shape="poly" coords="289,173,285,208,312,210,312,224,403,228,391,183,363,177" alt="Nebraska" title="Nebraska" />
<area href="#NV" shape="poly" coords="77,155,153,169,132,275,124,275,120,291,61,208" alt="Nevada" title="Nevada" />
<area href="#NH" shape="poly" coords="705,97,701,142,724,136,709,91" alt="New Hampshire" title="New Hampshire" />
<area href="#NJ" shape="poly" coords="681,175,679,191,685,195,677,204,687,216,699,189,693,185,693,179" alt="New Jersey" title="New Jersey" />
<area href="#NM" shape="poly" coords="208,271,295,281,285,371,208,367,206,377,191,373" alt="New Mexico" title="New Mexico" />
<area href="#NY" shape="poly" coords="618,150,607,173,671,161,679,173,693,177,693,183,699,187,720,171,697,173,695,157,695,142,683,106,660,108,640,140" alt="New York" title="New York" />
<area href="#NC" shape="poly" coords="599,279,567,312,607,303,636,306,652,318,695,283,683,263" alt="North Carolina" title="North Carolina" />
<area href="#ND" shape="poly" coords="297,65,293,118,387,122,379,67" alt="North Dakota" title="North Dakota" />
<area href="#OH" shape="poly" coords="554,238,577,242,583,248,607,206,603,181,573,189,563,187,548,189,552,234" alt="Ohio" title="Ohio" />
<area href="#OK" shape="poly" coords="295,281,414,285,420,346,365,338,338,330,338,295,293,293" alt="Oklahoma" title="Oklahoma" />
<area href="#OR" shape="poly" coords="51,67,22,122,22,138,116,159,120,116,132,99,128,87,83,87,61,81,61,71" alt="Oregon" title="Oregon" />
<area href="#PA" shape="poly" coords="601,179,607,216,673,204,683,195,677,189,679,173,671,163" alt="Pennsylvania" title="Pennsylvania" />
<area href="#RI" shape="poly" coords="722,153,726,159,720,165,716,155" alt="Rhode Island" title="Rhode Island" />
<area href="#SC" shape="poly" coords="583,308,628,354,650,320,636,306,607,301" alt="South Carolina" title="South Carolina" />
<area href="#SD" shape="poly" coords="293,118,387,122,383,126,389,132,389,165,387,181,361,175,318,171,289,171,291,155,291,136" alt="South Dakota" title="South Dakota" />
<area href="#TN" shape="poly" coords="483,318,567,312,599,277,489,291" alt="Tennessee" title="Tennessee" />
<area href="#TX" shape="poly" coords="293,291,285,373,232,367,261,412,281,426,295,412,312,414,346,475,373,485,373,452,430,416,434,389,424,350,410,342,338,330,336,293" alt="Texas" title="Texas" />
<area href="#UT" shape="poly" coords="155,171,193,177,189,197,218,199,208,273,138,261" alt="Utah" title="Utah" />
<area href="#VT" shape="poly" coords="683,104,693,142,701,142,703,102" alt="Vermont" title="Vermont" />
<area href="#VA" shape="poly" coords="593,263,575,281,683,261,671,238,658,234,660,226,650,220,640,220,622,234,618,259" alt="Virginia" title="Virginia" />
<area href="#WA" shape="poly" coords="48,65,61,71,61,81,93,87,134,91,142,40,75,20,51,28" alt="Washington" title="Washington" />
<area href="#WV" shape="poly" coords="648,220,640,220,632,236,622,234,618,252,609,261,595,265,585,252,589,234,603,222,605,204,607,218,624,216,624,222,640,214,646,216" alt="West Virginia" title="West Virginia" />
<area href="#WI" shape="poly" coords="444,110,442,118,436,124,436,142,456,157,459,179,467,183,503,179,510,132,503,130,497,122,465,108,456,102" alt="Wisconsin" title="Wisconsin" />
<area href="#WY" shape="poly" coords="204,126,189,197,285,208,291,132" alt="Wyoming" title="Wyoming" />
<area href="#DE" shape="rect" coords="750,230,809,246" alt="Delaware" title="Delaware" />
<area href="#MD" shape="rect" coords="750,246,807,267" alt="Maryland" title="Maryland" />
<area href="#DC" shape="rect" coords="735,270,807,285" alt="District of Columbia" title="District of Columbia" />
<area href="#NH" shape="rect" coords="573,28,667,51" alt="New Hampshire" title="New Hampshire" />
<area href="#NJ" shape="rect" coords="736,208,807,228" alt="New Jersey" title="New Jersey" />
<area href="#MA" shape="rect" coords="577,75,658,95" alt="Massachusetts" title="Massachusetts" />
<area href="#CT" shape="rect" coords="740,189,811,206" alt="Connecticut" title="Connecticut" />
<area href="#WV" shape="rect" coords="730,289,809,306" alt="West Virginia" title="West Virginia" />
<area href="#VT" shape="rect" coords="618,53,663,73" alt="Vermont" title="Vermont" />
<area href="#RI" shape="rect" coords="734,165,811,187" alt="Rhode Island" title="Rhode Island" />
<area href="javascript:flashStates('Mar');" shape="rect" coords="670,390,753,401" alt="Flash states with marriage" title="Flash states with marriage legal" />
<area href="javascript:flashStates('CU');" shape="rect" coords="670,401,765,412" alt="Flash states with civil unions" title="Flash states with civil unions legal" />
<area href="javascript:flashStates('CULite');" shape="rect" coords="670,412,831,424" alt="Flash states with civil unions with some rights legal" title="Flash states with civil unions with some rights legal" />
<area href="javascript:flashStates('None');" shape="rect" coords="670,424,745,436" alt="Flash states with none/unclear" title="Flash states with none/unclear" />
<area href="javascript:flashStates('NoMar');" shape="rect" coords="670,436,753,447" alt="Flash states with marriage illegal" title="Flash states with marriage illegal" />
<area href="javascript:flashStates('NoCU');" shape="rect" coords="670,447,768,458" alt="Flash states with civil unions illegal" title="Flash states with civil unions illegal" />
<area href="javascript:flashStates('NoMarConst');" shape="rect" coords="670,458,831,470" alt="Flash states with marriage illegal in constitution" title="Flash states with marriage illegal in constitution" />
<area href="javascript:flashStates('NoCUConst');" shape="rect" coords="670,470,831,481" alt="Flash states with civil unions illegal in constitution" title="Flash states with civil unions illegal in constitution" />
</map>
<p>Also available <a href="http://apps.microsoft.com/webpdp/en-us/app/marriage-map/f5f57402-2472-4fc4-a27a-0320fb6294d9">on the Windows Store</a>, on the Windows Phone Marketplace: <a href="http://www.windowsphone.com/s?appid=07d33830-0e19-42b9-b371-abed7f1fcebe"><img src="DownloadWPSmall.png" title="Download it on the Windows Phone Marketplace" alt="Download it on the Windows Phone Marketplace"></a>, and on the HP TouchPad: <a href="http://developer.palm.com/appredirect/?packageid=com.gregstoll.marriagemap"><img alt="Download it on the HP App Catalog" title="Download it on the HP App Catalog" src="appcatalog.png"></a></p>
<p>Here's <a href="http://terrymun.com/playground/data-in-equality/">another nice visualization</a> based on this data - check it out!</p>
<h1 id="faq" style="clear: both;">FAQ:</h1>
<ul>
<li><b>What is this?</b> This is an interactive map showing the
legality of same-sex (gay) marriage and civil unions in the United States.</li>
<li><b>How can I find more information about a state?</b> Click on the state to get a timeline of important events regarding same-sex marriage law.</li>
<li><b>I'm having some trouble telling the colors apart.</b> Click on a category in the legend to have those states flash briefly.</li>
<li><b>What's a cartogram?</b> A cartogram is a kind of map that shows states
roughly in proportion to their population, and so it's more representative
of how many people in the US are living under which laws. In this case,
I based the cartogram
on <a href="http://en.wikipedia.org/wiki/File:Cartogram-2008_Electoral_Vote.svg">this Wikipedia cartogram of the 2008 election</a>. Ideally the cartogram would
change based on what year we're showing to keep up with population. Also note
that small states are slightly overrepresented since every state gets at least
3 electoral votes.</li>
<li><b>What's the deal with Colorado?</b> In the past, some states like Colorado and Nevada had civil unions, but marriage was against the constitution. I went with the green color instead of the dark red to emphasize that
same-sex couples did have some rights, which seems more important than the fact
that marriage was off limits.</li>
<li><b>How did you determine the difference between "Civil unions" and "Civil unions with some rights included in marriage"?</b> I mostly relied on the determination made by the <a href="http://www.hrc.org">Human Rights Campaign</a> - <a href="http://hrc-assets.s3-website-us-east-1.amazonaws.com/files/assets/resources/marriage-equality.pdf">here's a PDF map</a> of the states that currently recognize same-sex marriage and civil unions.</li>
<li><b>Where can I find more information about interstate relationship recognition, hospital visitation laws, etc.?</b> The Human Rights Campaign maintains <a href="https://www.hrc.org/state_maps">a number of maps</a> covering these issues. Another good resource is Lambda Legal's <a href="http://www.lambdalegal.org/pending-marriage-equality-cases">map of pending marriage equality cases</a>.</li>
<li><b>How does the map work?</b> I'm using the <a href="http://en.wikipedia.org/wiki/Canvas_%28HTML_element%29">HTML Canvas</a> to dynamically color the map. The map itself was adapted from <a href="http://en.wikipedia.org/wiki/File:Map_of_USA_with_state_names.svg">this Wikipedia map</a>, and the clickable regions were taken from that same page, saving me a lot of time and trouble.<br>
<li><b>How did you find this data?</b> I did a lot of online research - mostly starting with <a href="http://en.wikipedia.org/wiki/Same-sex_marriage_legislation_in_the_United_States_by_state">the Wikipedia page</a>, the <a href="https://en.wikipedia.org/wiki/Marriage_Law_Project">Marriage Law Project at The Catholic University of America</a>, and <a href="http://www.alliancealert.org/category/6-family-marriage/">alliancealert.org</a> (formerly domawatch.org).</li>
<li><b>The labels are all in the wrong place - what's up?</b> Try hitting Shift+Reload or Shift+Refresh to reload the images.</li>
<li><b>Are the source files available?</b> Yes - aside from the Javascript on this page, the other files are <a href="marriagedata.js.txt">marriagedata.js</a>, which contains all of the same-sex marriage data, and <a href="mapdata.js.txt">mapdata.js</a> which contains most of the drawing logic. I apologize upfront for
the ugly hacks therein :-)</li>
<li><b>How can I contact you?</b> Just email me at greg@gregstoll.com.</li>
</ul>
<p>Map colors based on <a href="http://www.ColorBrewer.org">www.ColorBrewer.org</a>, by Cynthia A. Brewer, Penn State.</p>
<script type="text/javascript">
function expandContractHorizon() {
var linkText, pendingUl;
pendingUl = $('#pendingUl');
if (pendingUl.css('display') === 'none') {
linkText = '-';
pendingUl.fadeIn();
} else {
linkText = '+';
pendingUl.fadeOut();
}
$('#expandContractHorizon').text(linkText);
}
var mapTypes = ['Mar', 'CU', 'CULite', 'None', 'NoMar', 'NoCU', 'NoMarConst', 'NoCUConst'];
var mapColors = {
//'Mar': 'rgb(26, 152, 80)',
'Mar': 'rgb(20, 118, 255)',
//'CU': 'rgb(102, 189, 99)',
'CU': 'rgb(26, 152, 80)',
'CULite': 'rgb(166, 217, 106)',
//'None': 'rgb(255, 255, 191)',
'None': 'rgb(222, 222, 222)',
'NoMar': 'rgb(254, 224, 139)',
'NoCU': 'rgb(253, 174, 97)',
'NoMarConst': 'rgb(244, 109, 67)',
'NoCUConst': 'rgb(215, 48, 39)'
};
function getCursorPosition(e) {
/* returns Cell with .row and .column properties */
var x;
var y;
var canvas = document.getElementById('mapCanvas');
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
return [x, y];
}
function getFlashingColor(origColor) {
var rgbRe = /rgb\((\d+), (\d+), (\d+)\)/;
var rgbMatch = rgbRe.exec(origColor);
if (rgbMatch.length == 4) {
var r = parseInt(rgbMatch[1]);
var g = parseInt(rgbMatch[2]);
var b = parseInt(rgbMatch[3]);
var hsl = rgbToHsl(r, g, b);
if (hsl[2] < .5) {
hsl[2] = hsl[2] * 1.25 + .25;
} else {
hsl[2] = (hsl[2] - .25) / 1.25;
}
var newRgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
var newR = newRgb[0];
var newG = newRgb[1];
var newB = newRgb[2];
if (Math.abs(r - newR) + Math.abs(g - newG) + Math.abs(b - newB) < 80) {
// Colors are too close - use something distinguishable.
// Hopefully this won't happen anymore.
newR = 128;
newG = 128;
newB = 128;
}
return "rgb(" + newR + ", " + newG + ", " + newB + ")";
}
return origColor;
}
var mapDescriptions = {
'Mar': 'Marriage is legal',
'CU': 'Civil unions are legal',
'CULite': 'Civil unions that have some rights included in marriage are legal',
'None': 'No applicable law or unclear',
'NoMar': 'Marriage forbidden by statute',
'NoCU': 'Marriage or civil unions forbidden by statute',
'NoMarConst': 'Marriage forbidden by state constitution',
'NoCUConst': 'Marriage or civil unions forbidden by state constitution'
}
// It would be nice if we didn't have to repeat this data multiple times
// (see the area elements), but such is life. Also, I doubt these will
// change anytime soon.
var stateNames = {'AL': 'Alabama', 'AK': 'Alaska', 'AZ': 'Arizona', 'AR': 'Arkansas', 'CA': 'California', 'CO': 'Colorado', 'CT': 'Connecticut', 'DC': 'District of Columbia', 'DE': 'Delaware', 'FL': 'Florida', 'GA': 'Georgia', 'HI': 'Hawaii', 'ID': 'Idaho', 'IL': 'Illinois', 'IN': 'Indiana', 'IA': 'Iowa', 'KS': 'Kansas', 'KY': 'Kentucky', 'LA': 'Louisiana', 'ME': 'Maine', 'MD': 'Maryland', 'MA': 'Massachusetts', 'MI': 'Michigan', 'MN': 'Minnesota', 'MS': 'Mississippi', 'MO': 'Missouri', 'MT': 'Montana', 'NE': 'Nebraska', 'NV': 'Nevada', 'NH': 'New Hampshire', 'NJ': 'New Jersey', 'NM': 'New Mexico', 'NY': 'New York', 'NC': 'North Carolina', 'ND': 'North Dakota', 'OH': 'Ohio', 'OK': 'Oklahoma', 'OR': 'Oregon', 'PA': 'Pennsylvania', 'RI': 'Rhode Island', 'SC': 'South Carolina', 'SD': 'South Dakota', 'TN': 'Tennessee', 'TX': 'Texas', 'UT': 'Utah', 'VT': 'Vermont', 'VA': 'Virginia', 'WA': 'Washington', 'WV': 'West Virginia', 'WI': 'Wisconsin', 'WY': 'Wyoming'};
var currentMapStatus = {};
var useCartogram = false;
var selectedPostalCode = undefined;
if (!Array.prototype.map)
{
Array.prototype.map = function(fun /*, thisp*/)
{
var len = this.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = new Array(len);
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
res[i] = fun.call(thisp, this[i], i, this);
}
return res;
};
}
if(!Object.keys) Object.keys = function(o){
if (o !== Object(o))
throw new TypeError('Object.keys called on non-object');
var ret=[],p;
for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
return ret;
}
var ctx;
function compareYear(year1, year2) {
if (year1[0] < year2[0] || (year1[0] == year2[0] && year1[1] < year2[1])) {
return -1;
} else if (year1[0] == year2[0] && year1[1] == year2[1]) {
return 0;
} else {
return 1;
}
}
function getStateStatus(stateName, year) {
var status = 'None';
var courtOverturnedBan = 0;
var stateMarriageData = marriagedata[stateName];
for (var i = 0; i < stateMarriageData.length; ++i) {
var testYear = stateMarriageData[i][0].split('-').map(function(x) { return parseInt(x, 10);});
if (compareYear(testYear, year) <= 0) {
status = stateMarriageData[i][1];
if (stateMarriageData[i].length > 3 && stateMarriageData[i][3].hasOwnProperty('pending') && stateMarriageData[i][3]['pending'].hasOwnProperty('courtOverturnedBan')) {
courtOverturnedBan = stateMarriageData[i][3]['pending']['courtOverturnedBan'];
}
} else {
// Assumes the marriage data is in sorted order.
break;
}
}
return [status, courtOverturnedBan];
}
var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var shortMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
function showStateData(postalCode, stateName) {
var htmlData = [];
htmlData.push('<h1>' + stateName + ':</h1>');
var data = marriagedata[postalCode];
if (data.length > 0) {
htmlData.push('<ul>');
}
for (var i = 0; i < data.length; ++i) {
var dateParts = data[i][0].split('-').map(function(x) { return parseInt(x, 10);});
htmlData.push('<li><b><a href="#" onclick="goToDate(' + dateParts + '); return false;">' + monthNames[dateParts[1]-1] + ' ' + dateParts[0] + '</a></b>: ' + '<span style="background-color: ' + mapColors[data[i][1]] + '">' + mapDescriptions[data[i][1]] + '</span> - ' + data[i][2]);
}
if (data.length > 0) {
htmlData.push('</ul>');
}
$('#stateData').html(htmlData.join('\n'));
selectedPostalCode = postalCode;
updateHash(slider.getRealValue(), postalCode, useCartogram);
}
function updateMapTitles() {
var areas = $('#mapMap area');
for (var i = 0; i < areas.length; ++i) {
var elem = areas[i];
if (elem.hash.length == 3) {
var postalCode = elem.href.substr(elem.href.length - 2);
var title = elem.title.split('-')[0];
if (title[title.length - 1] != ' ') {
title = title + ' ';
}
title += '- ' + mapDescriptions[currentMapStatus[postalCode][0]];
elem.title = title;
}
}
}
function getHash(year, postalCode, useCartogram) {
var newHash = "";
//newHash = "year=" + year[0] + "-" + year[1];
if (postalCode != undefined) {
if (newHash != "") newHash += "&";
newHash += "state=" + postalCode;
}
if (useCartogram) {
if (newHash != "") newHash += "&";
newHash += 'cartogram=1';
}
return newHash;
}
function updateHash(year, postalCode, useCartogram) {
var hash = getHash(year, postalCode, useCartogram);
if (hash != location.hash) {
location.hash = hash;
}
}
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param {Number} r The red color value
* @param {Number} g The green color value
* @param {Number} b The blue color value
* @return {Array} The HSL representation
*/
var rgbToHsl = function(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
};
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param {Number} h The hue
* @param {Number} s The saturation
* @param {Number} l The lightness
* @return {Array} The RGB representation
*/
var hslToRgb = function(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
};
function flashStates(type) {
return function() {
var numTimesLeft = 2;
var useFlashingColor = true;
function flashMap() {
if (useFlashingColor) {
redrawMap(slider.getRealValue(), type);
} else {
redrawMap(slider.getRealValue());
}
if (useFlashingColor) {
useFlashingColor = false;
} else {
useFlashingColor = true;
--numTimesLeft;
}
if (numTimesLeft > 0) {
setTimeout(flashMap, animationTimeout);
}
}
flashMap();
}();
}
function getPendingStatus(postalCode, year) {
var stateMarriageData = marriagedata[postalCode];
var curPending = undefined;
var i, props, testYear, testPropYear, eventHasExpired;
for (i = 0; i < stateMarriageData.length; ++i) {
testYear = stateMarriageData[i][0].split('-').map(function(x) { return parseInt(x, 10);});
if (compareYear(testYear, year) <= 0) {
if (stateMarriageData[i].length >= 4) {
props = stateMarriageData[i][3];
if (props.hasOwnProperty('pending')) {
if (props.hasOwnProperty('clear') && props['clear']) {
curPending = undefined;
} else {
eventHasExpired = false;
// See when this expires (if ever)
if (props['pending'].hasOwnProperty('date')) {
testPropYear = props['pending']['date'].split('-').map(function(x) { return parseInt(x, 10);});
// if it expires this month, still show it
if (compareYear(testPropYear, year) < 0) {
eventHasExpired = true;
}
}
if (!eventHasExpired) {
curPending = props['pending'];
}
}
}
}
} else {
// Assumes the marriage data is in sorted order.
break;
}
}
return curPending;
}
function updatePending(year) {
var pendingData = {}, postalCode, statePending, i, stateKeys, htmlData = [];
// adjust to the previous
for (postalCode in stateSvgPaths) {
statePending = getPendingStatus(postalCode, year);
if (statePending && statePending !== undefined) {
pendingData[postalCode] = statePending;
}
}
stateKeys = Object.keys(pendingData);
if (stateKeys.length > 0) {
$('#pendingDiv').css('display', 'block');
$('#pendingUl').empty();
stateKeys.sort();
for (i = 0; i < stateKeys.length; i++) {
postalCode = stateKeys[i];
htmlData.push('<li><b><a href="javascript:showStateData(\'' + postalCode + '\', \'' + stateNames[postalCode] + '\');">' + stateNames[postalCode] + '</a></b>: ' + pendingData[postalCode]['description'] + '</li>');
}
$('#pendingUl').append(htmlData.join('\n'));
} else {
$('#pendingDiv').css('display', 'none');
}
}
function redrawMap(newYear, flashType) {
// A full redraw looks better, and is fast enough.
// let's try full redraw.
for (var stateName in stateSvgPaths) {
var newStatus = getStateStatus(stateName, newYear);
currentMapStatus[stateName] = newStatus;
}
clearMap();
updateMapTitles();
var courtOverturnedBanGradient = $('#courtOverturnedBanGradient')[0].checked;
drawMap(flashType, useCartogram, courtOverturnedBanGradient);
return;
// This is the code for incremental redraw that
// is theoretically faster, but causes lines (especially
// state boundaries and the lines to state names) to become
// darker over time.
/*var changedStates = [];
for (var stateName in stateSvgPaths) {
var newStatus = getStateStatus(stateName, newYear);
if (newStatus != currentMapStatus[stateName]) {
changedStates.push(stateName);
currentMapStatus[stateName] = newStatus;
drawState(stateName, useCartogram, mapColors[currentMapStatus[stateName]], false);
}
}
for (var i in changedStates) {
drawStateName(changedStates[i]);
}
var translation = scalePoint([0, -131.9412]);
for (var i = 0; i < stateLabelPaths.length; ++i) {
drawSvgPath(stateLabelPaths[i], translation, "black", .5);
}*/
}
function clearMap() {
ctx.clearRect(0, 0, document.getElementById('mapCanvas').width, document.getElementById('mapCanvas').height);
}
var legendImage;
function drawMap(flashType, useCartogram, courtOverturnedBanGradient) {
var courtOverturnedBan;
var flashingColor = flashType ? getFlashingColor(mapColors[flashType]) : "";
for (var stateName in stateSvgPaths) {
courtOverturnedBan = courtOverturnedBanGradient ? currentMapStatus[stateName][1] : 0;
if (currentMapStatus[stateName][0] == flashType) {
drawState(stateName, useCartogram, flashingColor, false, 1.0, courtOverturnedBan);
} else {
drawState(stateName, useCartogram, mapColors[currentMapStatus[stateName][0]], false, 1.0, courtOverturnedBan);
}
}
for (var stateName in statenamepositions) {
drawStateName(stateName, useCartogram);
}
var translation = scalePoint([0, -131.9412]);
//var translation = scalePoint([-43.12533, -131.9412]);
if (!useCartogram) {
for (var i = 0; i < stateLabelPaths.length; ++i) {
drawSvgPath(stateLabelPaths[i], translation, "black", .5);
}
}
translation[0] += 10;
if (!useCartogram) {
drawSvgPath(insetBox, translation, "black", 1, DRAW_SVG_NOFILL);
}
if (!legendImage) {
legendImage = new Image();
legendImage.onload = function() {
ctx.save();
ctx.translate(translation[0], translation[1]);
var legendX = scaleValue(810);
var legendY = scaleValue(600);
if (isIE) {
// TODO - why?
legendX *= .912;
legendY *= .93;
}
ctx.drawImage(legendImage, legendX, legendY, scaleValue(legendImage.width), scaleValue(legendImage.height));
ctx.restore();
};
legendImage.src = 'images/legend.png';
} else {
ctx.save();
ctx.translate(translation[0], translation[1]);
var legendX = scaleValue(810);
var legendY = scaleValue(600);
if (isIE) {
// TODO - why?
legendX *= .912;
legendY *= .93;
}
ctx.drawImage(legendImage, legendX, legendY, scaleValue(legendImage.width), scaleValue(legendImage.height));
ctx.restore();
}
// Draw the color boxes for the legend.
ctx.save();
ctx.translate(translation[0], translation[1]);
var curY = scaleValue(600);
for (var i = 0; i < mapTypes.length; ++i) {
var mapType = mapTypes[i];
ctx.fillStyle = mapColors[mapType];
ctx.fillRect(scaleValue(790), curY, 15, 13);
curY += scaleValue(13);
}
ctx.restore();
}
function goToDate(year, month) {
var realValue = slider.getRealValue();
// Round up to the next bucket, since we index by end year.
if (month % monthGroupInterval != 0) {
month += monthGroupInterval - (month % monthGroupInterval);
}
if (realValue[0] != year || realValue[1] != month) {
slider.setValue(pixelsPerMonthGroup*((year - startYear)*monthGroupsPerYear + Math.floor((month-1)/monthGroupInterval)), true);
} else {
// Here the date has not changed, but we still want to update
// the hash and animation data.
selectedPostalCode = undefined;
updateHash(realValue, undefined, useCartogram);
showAnimationData(realValue);
}
}
// IE canvas is slower, so make animation faster.
animationTimeout = isIE ? 500: 1000;
function advanceYear() {
if (stopAnimating) {
// Stop, and reset the flag.
stopAnimating = false;
isAnimating = false;
} else {
slider.setValue(slider.getValue() + pixelsPerMonthGroup);
if (slider.getValue() + pixelsPerMonthGroup < maxSliderValue) {
setTimeout(advanceYear, animationTimeout);
} else {
isAnimating = false;
}
}
}
var stopAnimating = false;
var isAnimating = false;
function startAnimation() {
isAnimating = true;
if (Math.floor(slider.getValue()/pixelsPerMonthGroup) == Math.floor(maxSliderValue/pixelsPerMonthGroup)) {
slider.setValue(0);
}
setTimeout(advanceYear, animationTimeout);
}
function stopAnimation() {
stopAnimating = true;
}
function showAnimationData(endYear) {
var htmlData = [];
// Find all changes ending in the endYear bucket.
for (var postalCode in marriagedata) {
if (!marriagedata.hasOwnProperty(postalCode)) continue;
if (endYear in stateDateDataHash[postalCode]) {
var data = marriagedata[postalCode];
for (var j in stateDateDataHash[postalCode][endYear]) {
if (!stateDateDataHash[postalCode][endYear].hasOwnProperty(j)) continue;
var i = stateDateDataHash[postalCode][endYear][j];
var dateParts = data[i][0].split('-').map(function(x) { return parseInt(x, 10)});
var isImportant = false;
if ((i == 0 && data[i][1] != 'None') ||
(i > 0 && data[i-1][1] != data[i][1])) {
isImportant = true;
}
htmlData.push('<li' + (isImportant ? ' class="importantEntry"' : '') + '><b><a href="javascript:showStateData(\'' + postalCode + '\', \'' + stateNames[postalCode] + '\')">' + stateNames[postalCode] + '</a></b>: ' + monthNames[dateParts[1]-1] + ' ' + dateParts[0] + ': <span style="background-color: ' + mapColors[data[i][1]] + '">' + mapDescriptions[data[i][1]] + '</span> - ' + data[i][2] + '</li>');
}
}
}
if (htmlData.length > 0) {
$('#stateData').html('<ul>' + htmlData.join('\n') + '</ul>');
} else {
$('#stateData').html('');
}
}
function updateCartogramFromValue(newValue) {
useCartogram = newValue;
$('#mapMap').disabled = useCartogram;
$('#mapMap area').disabled = useCartogram;
$('#mapMap area').visible = !useCartogram;
if (useCartogram) {
$('#imageMapMap')[0].style.width = '0px';
$('#imageMapMap')[0].style.height = '0px';
} else {
$('#imageMapMap')[0].style.width = '800px';
$('#imageMapMap')[0].style.height = '495px';
}
/*$('#imageMapMap').disabled = useCartogram;
$('#imageMapMap').visible = !useCartogram;*/
}
function updateCartogramFromCheckbox() {
updateCartogramFromValue($('#cartogramCheckbox')[0].checked);
updateHash(slider.getRealValue(), selectedPostalCode, useCartogram);
}
function updateCartogram() {
updateCartogramFromCheckbox();
redrawMap(slider.getRealValue());
}
function updateAnimationSpeed() {
var val = parseInt($("#animationSpeed").val());
switch (val) {
case 0:
animationTimeout = isIE ? 3500: 4000;
break;
case 1:
animationTimeout = isIE ? 2500: 2000;
break;
case 2:
animationTimeout = isIE ? 750: 1000;
break;
case 3:
animationTimeout = isIE ? 500: 500;
break;
case 4:
animationTimeout = isIE ? 0: 0;
break;
}
}
var slider;
var startYear = 1990;
// This must be a multiple of 12.
var monthGroupsPerYear = 4;
var monthGroupInterval = 12/monthGroupsPerYear;
var pixelsPerMonthGroup = 8;
// If you change this, you'll need to change values in the CSS section
// at the top.
//var curYear = [(new Date()).getFullYear(), Math.floor((new Date()).getMonth()/monthGroupInterval)*monthGroupInterval + monthGroupInterval];
var curYear = [2015, 6];
var endYear = curYear;
// Take the latest time that something happened.
for (var postalCode in marriagedata) {
if (marriagedata[postalCode].length > 0) {
var latestDateParts = marriagedata[postalCode][marriagedata[postalCode].length - 1][0].split('-').map(function(x) { return parseInt(x, 10);});
// Round up to the next bucket, since we index by end year.
if (latestDateParts[1] % monthGroupInterval != 0) {
latestDateParts[1] += monthGroupInterval - (latestDateParts[1] % monthGroupInterval)
}
if (compareYear(endYear, latestDateParts) == -1) {
endYear = latestDateParts;
}
}
}
var maxSliderValue = pixelsPerMonthGroup * (monthGroupsPerYear*(endYear[0] -startYear) + (endYear[1]/monthGroupInterval) - 1) + 6;
var stateDateDataHash = {};
var marriagedata = {};
$(document).ready(function() {
// Code:
// Mar - same-sex marriage allowed
// CU - same-sex civil unions allowed
// CULite - some same-sex rights
// None - none/unclear
// NoMar - no same-sex marriage by statute
// NoCU - no same-sex civil unions by statute
// NoMarConst - no same-sex marriage in constitution
// NoCUConst - no same-sex civil unions in constitution
// References:
// http://marriagelaw.cua.edu/law/states/AL.cfm
// http://www.domawatch.org/stateissues/alaska/index.html
// http://ballotpedia.org/wiki/index.php/Marriage-related_ballot_measures_and_initiatives
$.getJSON('marriagedata.js?random=' + Math.random(), function(data) {
marriagedata = data;
doRestOfStartUp();
});
});
function doRestOfStartUp() {
var canvas = document.getElementById('mapCanvas');
ctx = canvas.getContext('2d');
$('#slider-bg').parent().css('width', maxSliderValue + 26);
$('#slider-bg').css('width', maxSliderValue + 26);
$('#slider-background').css('width', maxSliderValue + 26);
// Update animation speed.
updateAnimationSpeed();
$("#animationSpeed").change(updateAnimationSpeed);
$("#cartogramCheckbox").click(updateCartogram);
$("#courtOverturnedBanGradient").click(function() { redrawMap(slider.getRealValue()); });
// Initialize map status
for (var stateName in stateSvgPaths) {
currentMapStatus[stateName] = ['None', 0];
}
// Initialize onclicks for areas
var areas = $('#mapMap area');
for (var i = 0; i < areas.length; ++i) {
var elem = areas[i];
if (elem.hash.length == 3) {
elem.onclick = function() {
if (!useCartogram) {
var postalCode = this.href.substr(this.href.length - 2);
showStateData(postalCode, stateNames[postalCode]);
return false;
}
}
}
}
canvas.addEventListener('click', function(e) {
var pos, postalCode, i, l, data;
if (useCartogram) {
var pos = getCursorPosition(e);
// correct translation
pos[0] *= 1.0/0.6;
pos[1] *= 1.0/0.6;
pos[0] -= 25;
pos[1] += 100;
pos[0] -= pos[0] % 25;
pos[1] = (pos[1] - 2 - ((pos[1] - 2) % 25)) + 2;
//alert(pos);
for (postalCode in cartogramBoxes) {
if (cartogramBoxes.hasOwnProperty(postalCode)) {
data = cartogramBoxes[postalCode];
l = data.length;
for (i = 0; i < l; i += 1) {
if (data[i][0] === pos[0] && data[i][1] === pos[1]) {
//alert('selecting ' + postalCode);
showStateData(postalCode, stateNames[postalCode]);
return;
}
}
}
}
//alert(pos);
}
}, false);
// Initialize stateDateDataHash
for (var postalCode in marriagedata) {
stateDateDataHash[postalCode] = {};
var data = marriagedata[postalCode];
for (var i = 0; i < data.length; ++i) {
// See which bucket this should go in.
var dateParts = data[i][0].split('-').map(function(x) { return parseInt(x, 10);});
// Round up to the next bucket, since we index by end year.
if (dateParts[1] % monthGroupInterval != 0) {
dateParts[1] += monthGroupInterval - (dateParts[1] % monthGroupInterval)
}
if (!(dateParts in stateDateDataHash[postalCode])) {
stateDateDataHash[postalCode][dateParts] = [];
}
stateDateDataHash[postalCode][dateParts].push(i);
}
}
// Initialize slider
var bg="slider-bg", thumb="slider-thumb",
valuearea="slider-value", textfield="slider-converted-value"
// The slider can move 0 pixels up
var topConstraint = 0;
slider = YAHOO.widget.Slider.getHorizSlider(bg,
thumb, 0, maxSliderValue, pixelsPerMonthGroup);
// The amount the slider moves when the value is changed with the arrow
// keys
slider.keyIncrement = pixelsPerMonthGroup;
slider.animate = false;
slider.getRealValue = function() {
var realValue = Math.round(this.getValue() / pixelsPerMonthGroup);
return [startYear + Math.floor(realValue/monthGroupsPerYear), (realValue % monthGroupsPerYear) * monthGroupInterval + monthGroupInterval];
}
slider.subscribe("change", function(offsetFromStart) {
// use the scale factor to convert the pixel offset into a real
// value
var actualValue = slider.getRealValue();
var mult = (actualValue[1] / monthGroupInterval) - 1;
var monthNames = shortMonthNames[mult * monthGroupInterval] + '-' + shortMonthNames[(mult + 1) * monthGroupInterval - 1];
var printedValue = monthNames + ' ' + actualValue[0];
$('#slider-value').html(printedValue);
// Update the title attribute on the background. This helps assistive
// technology to communicate the state change
$('#slider-thumb').attr('title', printedValue);
$('#slider-bg').attr('title', printedValue);
redrawMap(actualValue);
selectedPostalCode = undefined;
updateHash(actualValue, undefined, useCartogram);
showAnimationData(actualValue);
});
updatePending([(new Date()).getFullYear(), (new Date()).getMonth() + 1]);
if (location.hash.length > 1) {
var hashVals = location.hash.substr(1).split('&').map(function(x) { return x.split('=')});
var dateToSet = curYear;
var stateToSet = undefined;
var tempUseCartogram = false;
for (var i in hashVals) {
if (hashVals[i][0] == 'year') {
dateToSet = hashVals[i][1].split('-').map(function(x) { return parseInt(x, 10);});
} else if (hashVals[i][0] == 'state') {
stateToSet = hashVals[i][1];
}
else if (hashVals[i][0] == 'cartogram') {
tempUseCartogram = (hashVals[i][1] !== 0);
}
}
updateCartogramFromValue(tempUseCartogram);
goToDate(dateToSet[0], dateToSet[1]);
if (stateToSet != undefined) {
// Wait for the location.hash to change.
var expectedHash = '#' + getHash(dateToSet, undefined, tempUseCartogram);
waitForHashThenChangeState(expectedHash, stateToSet);
}
} else {
goToDate(curYear[0], curYear[1]);
}
}
function waitForHashThenChangeState(expectedHash, stateToSet) {
if (location.hash === expectedHash || (expectedHash == '#' && location.hash == '')) {
showStateData(stateToSet, stateNames[stateToSet]);
return;
}
setTimeout(function() {waitForHashThenChangeState(expectedHash, stateToSet);}, 750);
}
var oldUrl = undefined;
function saveCanvasImage() {
var img = document.getElementById('exportCanvasImg');
var canvas = document.getElementById('mapCanvas');
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement#Example.3A_Getting_a_file_representing_the_canvas
canvas.toBlob(function(blob) {
var url = URL.createObjectURL(blob);
img.onload = function() {
if (oldUrl !== undefined) {
URL.revokeObjectURL(oldUrl);