@andyreagan/hedotools 3.0.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4042 +1,27 @@
1
- hedotools.shifter = function() {
2
- // for the word type selection
3
- var shiftselencoder = hedotools.urllib.encoder().varname("wordtypes");
4
- var shiftseldecoder = hedotools.urllib.decoder().varname("wordtypes").varresult("none");
5
- // initialize that we have't selected a shift
6
- var shiftTypeSelect = false;
7
- var shiftType = -1;
8
-
9
- // put the status of the viz into the bar
10
- var viz_type = hedotools.urllib.encoder().varname("viz");
11
- var viz_type_decoder = hedotools.urllib.decoder().varname("viz").varresult("wordshift");
12
- var viz_type_use_URL = false;
13
- var _viz_type_use_URL = function(_) {
14
- var that = this;
15
- if (!arguments.length) return viz_type_use_URL;
16
- viz_type_use_URL = _;
17
- return that;
18
- }
19
-
20
- // set a special variable to make sure all necessary things
21
- // have been set before shifting
22
- // (this is a double check on the page loading)
23
- var loadsremaining = 4;
24
-
25
- // will need a figure.
26
- // this needs to be set by setfigure() before plotting
27
- var figure = d3.select("body");
28
-
29
- var widthsetexplicitly = false;
30
- var getfigure = function() {
31
- return figure;
32
- }
33
- var setfigure = function(_) {
34
- var that = this;
35
- console.log("setting figure for wordshift");
36
- figure = _;
37
- // wrap another relative parent div in there, for the overlay button to pad off of
38
- figure = figure.append("div").attr({
39
- "class": "outwrapper"
40
- }).style({
41
- "position": "relative"
42
- });
43
- if (!widthsetexplicitly) {
44
- grabwidth();
45
- }
46
- return that;
47
- }
48
-
49
- var show_x_axis_bool = false;
50
- var show_x_axis = function(_) {
51
- var that = this;
52
- if (!arguments.length) return show_x_axis_bool;
53
- show_x_axis_bool = _;
54
- // give a litter extra space for it
55
- axeslabelmargin.bottom = axeslabelmargin.bottom + 10;
56
- return that;
57
- }
58
-
59
- var splitstring = function(_, w, f) {
60
- // take an array of strings _
61
- // a formatter f
62
- // and a max width w (in pixels)
63
- //
64
- // return the strings split into an array
65
- var font = f || (topFontSizeArray[topFontSizeArray.length - 1] + "px " + fontString);
66
- // console.log(w);
67
- // console.log(f);
68
- var splitar = [];
69
- var newar;
70
- for (var i = 0; i < _.length; i++) {
71
- if (_[i].width(font) < w) {
72
- newar = [_[i]];
73
- } else {
74
- var tmp = _[i].split(" ");
75
- // chop words off until it's long enough
76
- // this is better if we know that they're
77
- // not going to be way too long
78
- // right now a max of two lines
79
-
80
- // a more general approach would be to march forward...
81
- // but this could be a lot of .width() calculations
82
- // really need to keep those at a min
83
- var leng = false;
84
- var numi = 0;
85
- while (!leng) {
86
- numi += 1;
87
- // console.log(numi);
88
- var wt = tmp.slice(0, tmp.length - numi).join(" ");
89
- // console.log(wt);
90
- if (wt.width(font) < w) {
91
- newar = [wt, tmp.slice(tmp.length - numi, tmp.length).join(" ")];
92
- leng = true;
93
- }
94
- }
95
- }
96
- // console.log("adding newar to splitar");
97
- // console.log(newar);
98
- // console.log(splitar);
99
- splitar = splitar.concat(newar);
100
- // console.log(splitar);
101
- }
102
- return splitar;
103
- }
104
-
105
- // set the ones we can
106
- // since the height is fixed, do all that
107
- // but just initialize the width-related variables
108
-
109
- // full width and height. we'll draw the outer svg this big
110
- var fullwidth = 400;
111
- var fullheight = 550 // 650; // make sure to change num words too
112
-
113
- var margin = {
114
- top: 0,
115
- right: 0,
116
- bottom: 0,
117
- left: 0
1
+ // hedotools.shifter the wordshift graph.
2
+ //
3
+ // As of v4.5 this is no longer implemented here; it lives in its own package,
4
+ // @andyreagan/d3-shifterator (extracted from this repo's old shifter.v4.js).
5
+ // We instantiate that package's factory once and expose it as the shared
6
+ // `hedotools.shifter` singleton that the dashboard modules (barchart, lens,
7
+ // map, sankey) drive via .shift(refF, compF, lens, words) and
8
+ // .setfigure(...).setText(...).plot().
9
+ //
10
+ // Load order on the page (and in bundle.sh): D3 v4, then the d3-shifterator
11
+ // UMD bundle (which defines the global `shifterator`), then this file.
12
+ //
13
+ // One compatibility shim: the dashboard modules call
14
+ // setfigure(d3.select('#shift01'))
15
+ // passing a d3 SELECTION (the old hedotools.shifter API). d3-shifterator's
16
+ // setfigure expects a selector string or node (it runs d3.select() on its
17
+ // argument). Normalize a selection down to its node so both styles work.
18
+ hedotools.shifter = (function () {
19
+ var instance = shifterator.shifterator();
20
+ var setfigure = instance.setfigure;
21
+ instance.setfigure = function (_) {
22
+ var arg = (_ && typeof _.node === "function") ? _.node() : _;
23
+ setfigure.call(instance, arg);
24
+ return instance;
118
25
  };
119
-
120
- // the width and height that we're going to use
121
- var boxwidth = fullwidth - margin.left - margin.right;
122
- var boxheight = fullheight - margin.top - margin.bottom;
123
-
124
- // margin inside
125
- var axeslabelmargin = {
126
- top: 0,
127
- right: 3,
128
- bottom: 25,
129
- left: 23
130
- };
131
-
132
- // inner width and height
133
- // used for the axes
134
- var figwidth = boxwidth - axeslabelmargin.left - axeslabelmargin.right;
135
- var figheight = boxheight - axeslabelmargin.top - axeslabelmargin.bottom;
136
- var leftOffsetStatic = axeslabelmargin.left;
137
-
138
- // individual bar height, and number of words
139
- // need to be tuned to the height of the plot
140
- var iBarH = 11;
141
- var numWords = 28; // 37 with height 650 // 23 with height 500
142
- // I should be able to compute this?
143
-
144
- // max length of words to plot
145
- var maxChars = 20;
146
-
147
- // all inside the axes
148
- var yHeight = (7 + 17 * 3 + 14 + 5 - 13); // 101
149
- // where to draw the line below the summary bars
150
- var barHeight = (7 + 17 * 3 + 15 - 13); // 95
151
- var figcenter = figwidth / 2;
152
-
153
- // pull the width, set the height fixed
154
- var grabwidth = function() {
155
- // console.log("setting width from figure");
156
- // console.log(parseInt(figure.style("width")));
157
- // use d3.min to set a max width of fullwidth
158
- fullwidth = d3.min([parseInt(figure.style("width")), fullwidth]);
159
- boxwidth = fullwidth - margin.left - margin.right;
160
- figwidth = boxwidth - axeslabelmargin.left - axeslabelmargin.right;
161
- figcenter = figwidth / 2;
162
- }
163
-
164
- var setWidth = function(_) {
165
- if (!arguments.length) return fullwidth;
166
- widthsetexplicitly = true;
167
- fullwidth = _;
168
- boxwidth = fullwidth - margin.left - margin.right;
169
- figwidth = boxwidth - axeslabelmargin.left - axeslabelmargin.right;
170
- figcenter = figwidth / 2;
171
- }
172
-
173
- // pull the width, set the height fixed
174
- var setHeight = function(_) {
175
- var that = this;
176
- if (!arguments.length) return fullheight;
177
- fullheight = _;
178
- boxheight = fullheight - margin.top - margin.bottom;
179
- figheight = boxheight - axeslabelmargin.top - axeslabelmargin.bottom;
180
- return that;
181
- }
182
-
183
- // will be set by setdata() or shift() functions
184
- var sortedMag;
185
- var sortedType;
186
- var sortedWords;
187
- var sortedWordsRaw;
188
- var sortedWordsEn;
189
- var sortedWordsEnRaw;
190
- var sumTypes;
191
- var refH;
192
- var compH;
193
- var xlabel_text = "Per word average happiness shift";
194
- var ylabel_text = "Word Rank";
195
-
196
- var _sortedMag = function(_) {
197
- var that = this;
198
- if (!arguments.length) return sortedMag;
199
- sortedMag = _;
200
- return that;
201
- }
202
- var _sortedType = function(_) {
203
- var that = this;
204
- if (!arguments.length) return sortedType;
205
- sortedType = _;
206
- return that;
207
- }
208
- var _sortedWords = function(_) {
209
- var that = this;
210
- if (!arguments.length) return sortedWords;
211
- sortedWords = _;
212
- return that;
213
- }
214
- var _sortedWordsRaw = function(_) {
215
- var that = this;
216
- if (!arguments.length) return sortedWordsRaw;
217
- sortedWordsRaw = _;
218
- return that;
219
- }
220
- var _sortedWordsEn = function(_) {
221
- var that = this;
222
- if (!arguments.length) return sortedWordsEn;
223
- sortedWordsEn = _;
224
- return that;
225
- }
226
- var _sortedWordsEnRaw = function(_) {
227
- var that = this;
228
- if (!arguments.length) return sortedWordsEnRaw;
229
- sortedWordsEnRaw = _;
230
- return that;
231
- }
232
- var _sumTypes = function(_) {
233
- var that = this;
234
- if (!arguments.length) return sumTypes;
235
- sumTypes = _;
236
- return that;
237
- }
238
- var _refH = function(_) {
239
- var that = this;
240
- if (!arguments.length) return refH;
241
- refH = _;
242
- return that;
243
- }
244
- var _compH = function(_) {
245
- var that = this;
246
- if (!arguments.length) return compH;
247
- compH = _;
248
- return that;
249
- }
250
- var _xlabel_text = function(_) {
251
- var that = this;
252
- if (!arguments.length) return xlabel_text;
253
- xlabel_text = _;
254
- return that;
255
- }
256
- var _ylabel_text = function(_) {
257
- var that = this;
258
- if (!arguments.length) return ylabel_text;
259
- ylabel_text = _;
260
- return that;
261
- }
262
-
263
- var reset = true;
264
- var _reset = function(_) {
265
- var that = this;
266
- if (!arguments.length) return reset;
267
- reset = _;
268
- return that;
269
- }
270
-
271
- var get_word_index = function(w) {
272
- var ind = -1;
273
- for (var i = 0; i < words.length; i++) {
274
- if (w === words[i]) {
275
- ind = i;
276
- break;
277
- }
278
- }
279
- return ind;
280
- }
281
-
282
- // let's make this just toggle the state
283
- // you can force it to turn on by setting the _reset function
284
- // to set the reset bool to be false, then calling toggle
285
- var resetbuttontoggle = function() {
286
- var that = this;
287
- reset = !reset;
288
- resetButton(reset);
289
- if (reset) {
290
- figure.select("g.help").style("visibility", "visible");
291
- figure.selectAll("text.credit").style("visibility", "visible");
292
- } else {
293
- figure.select("g.help").style("visibility", "hidden");
294
- figure.selectAll("text.credit").style("visibility", "hidden");
295
- }
296
- return that;
297
- }
298
-
299
- var setdata = function(a, b, c, d, e, f) {
300
- var that = this;
301
- // console.log("setting data");
302
- sortedMag = a;
303
- sortedType = b;
304
- sortedWords = c;
305
- sortedWordsRaw = c;
306
- sumTypes = d;
307
- refH = e;
308
- compH = f;
309
- loadsremaining = 0;
310
- return that;
311
- }
312
-
313
- // ******************************************************************************** //
314
- // all of this stuff deals with setting the top text //
315
- // which has become the most haphazard part so far //
316
- // -AR 2015-07-28 //
317
- //
318
- // right now, we can just set the text ourselves completely, or have it set
319
- // automatically
320
-
321
- // have control over:
322
- // -number of bold lines (top N lines, default 1)
323
- // -each line's size
324
- // -each line's color (which, doesn't seem to have an effect)
325
- // -whether custom text is split or not
326
-
327
- // this variable controls whether the top strings are checked for length
328
- // and split, if necessary
329
- // - only used if compatison text is set explicitly
330
- var split_top_strings = true;
331
- var _split_top_strings = function(_) {
332
- var that = this;
333
- if (!arguments.length) return split_top_strings;
334
- split_top_strings = _;
335
- return that;
336
- }
337
-
338
- var numBoldLines = 1;
339
- var setTextBold = function(_) {
340
- var that = this;
341
- if (!arguments.length) return numBoldLines;
342
- numBoldLines = _;
343
- return that;
344
- }
345
-
346
- // only support up to 5 lines....
347
- var colorArray = ["#202020", "#D8D8D8", "#D8D8D8", "#D8D8D8", "#D8D8D8"];
348
- var topFontSizeArray = [16, 12, 12, 12, 12];
349
- // var topFontSizeArray = [20,16,16,16,16];
350
-
351
- var setTextColors = function(_) {
352
- var that = this;
353
- if (!arguments.length) return colorArray;
354
- colorArray = _;
355
- return that;
356
- }
357
-
358
- var bgcolor = "white";
359
- var setBgcolor = function(_) {
360
- var that = this;
361
- if (!arguments.length) return bgcolor;
362
- bgcolor = _;
363
- return that;
364
- }
365
-
366
- var setTopTextSizes = function(_) {
367
- var that = this;
368
- if (!arguments.length) return topFontSizeArray;
369
- topFontSizeArray = _;
370
- return that;
371
- }
372
-
373
- var comparisonText = [""];
374
-
375
- var setText = function(_) {
376
- var that = this;
377
- if (!arguments.length) return _;
378
- comparisonText = _;
379
- return that;
380
- }
381
-
382
- // end of the top text stuff //
383
- // ******************************************************************************** //
384
-
385
- var numwordstoplot = 200;
386
-
387
- var refF;
388
- var compF;
389
- var lens;
390
- var complens;
391
- var stoprange = [4, 6];
392
- var words;
393
- var words_en;
394
- var translate = false;
395
-
396
- var _stoprange = function(_) {
397
- var that = this;
398
- if (!arguments.length) return stoprange;
399
- stoprange = _;
400
- return that;
401
- }
402
-
403
- var _refF = function(_) {
404
- var that = this;
405
- if (!arguments.length) return refF;
406
- refF = _;
407
- // what better place to check for this
408
- // some datasets have less than 200 words
409
- numwordstoplot = d3.min([refF.length, numwordstoplot])
410
- loadsremaining--;
411
- return that;
412
- }
413
-
414
- var _compF = function(_) {
415
- var that = this;
416
- if (!arguments.length) return compF;
417
- compF = _;
418
- loadsremaining--;
419
- return that;
420
- }
421
-
422
- var _lens = function(_) {
423
- var that = this;
424
- if (!arguments.length) return lens;
425
- lens = _;
426
- loadsremaining--;
427
- return that;
428
- }
429
-
430
- var _complens = function(_) {
431
- var that = this;
432
- if (!arguments.length) return complens;
433
- complens = _;
434
- return that;
435
- }
436
-
437
- var _words = function(_) {
438
- var that = this;
439
- if (!arguments.length) return words;
440
- words = _;
441
- loadsremaining--;
442
- return that;
443
- }
444
-
445
- var _words_en = function(_) {
446
- var that = this;
447
- if (!arguments.length) return words_en;
448
- words_en = _;
449
- translate = true;
450
- return that;
451
- }
452
-
453
- var ignoreWords = ["nigga", "niggas", "niggaz", "nigger"];
454
-
455
- var ignore = function(_) {
456
- var that = this;
457
- if (!arguments.length) return ignoreWords;
458
- // refresh the list each time
459
- ignoreWords = ["nigga", "niggas", "niggaz", "nigger"];
460
- ignoreWords = ignoreWords.concat(_);
461
- // console.log(_);
462
- // console.log(ignoreWords);
463
- return that;
464
- }
465
-
466
- var stop = function() {
467
- var that = this;
468
- // first check if all the loads are done
469
- // WARNING
470
- // could not get this loop to stop!
471
- // even when the other variables are set
472
- // while (loadsremaining > 0) { console.log("waiting"); };
473
- for (var i = 0; i < lens.length; i++) {
474
- var include = true;
475
- // check if in removed word list
476
- for (var k = 0; k < ignoreWords.length; k++) {
477
- if (ignoreWords[k] == words[i]) {
478
- include = false;
479
- }
480
- }
481
- // check if underneath lens cover
482
- if (lens[i] > stoprange[0] && lens[i] < stoprange[1]) {
483
- include = false;
484
- }
485
- // include it, or set to 0
486
- if (!include) {
487
- refF[i] = 0;
488
- compF[i] = 0;
489
- }
490
- }
491
- return that;
492
- }
493
-
494
- // stop an individual vector
495
- var istopper = function(fvec) {
496
- for (var i = 0; i < lens.length; i++) {
497
- var include = true;
498
- // check if in removed word list
499
- for (var k = 0; k < ignoreWords.length; k++) {
500
- if (ignoreWords[k] == words[i]) {
501
- include = false;
502
- }
503
- }
504
- // check if underneath lens cover
505
- if (lens[i] > stoprange[0] && lens[i] < stoprange[1]) {
506
- include = false;
507
- }
508
- // include it, or set to 0
509
- if (!include) {
510
- fvec[i] = 0;
511
- }
512
- }
513
- return fvec;
514
- }
515
-
516
- var prefix = true;
517
-
518
- var concatter = function() {
519
- if (prefix) {
520
- // new method, with numbers prefixed
521
- // log everything
522
- // console.log(sortedMag);
523
- // console.log(sortedWords);
524
- // console.log(sortedWordsEn);
525
- // console.log(sortedType);
526
- // console.log(refF);
527
- // console.log(compF);
528
- // console.log(lens);
529
- // console.log(words);
530
- sortedWords = sortedWords.map(function(d, i) {
531
- if (sortedType[i] == 0) {
532
- return ((i + 1) + ". ").concat(d.concat("-\u2193")); // down // increase in happs
533
- } else if (sortedType[i] == 1) {
534
- return ((i + 1) + ". ").concat(d.concat("+\u2193")); // decrease in happs
535
- } else if (sortedType[i] == 2) {
536
- return ((i + 1) + ". ").concat(d.concat("-\u2191")); // up
537
- } else {
538
- return ((i + 1) + ". ").concat(d.concat("+\u2191"));
539
- }
540
- });
541
- if (translate) {
542
- sortedWordsEn = sortedWordsEn.map(function(d, i) {
543
- if (sortedType[i] == 0) {
544
- return ((i + 1) + ". ").concat(d.concat("-\u2193"));
545
- } else if (sortedType[i] == 1) {
546
- return ((i + 1) + ". ").concat(d.concat("+\u2193"));
547
- } else if (sortedType[i] == 2) {
548
- return ((i + 1) + ". ").concat(d.concat("-\u2191"));
549
- } else {
550
- return ((i + 1) + ". ").concat(d.concat("+\u2191"));
551
- }
552
- });
553
- }
554
- } else {
555
- // old method, without numbers prefixed
556
- sortedWords = sortedWords.map(function(d, i) {
557
- // d = ((i+1)+". ").concat(d);
558
- if (sortedType[i] == 0) {
559
- return ((i + 1) + ". ").concat(d.concat("-\u2193"));
560
- } else if (sortedType[i] == 1) {
561
- return ((i + 1) + ". ").concat("\u2193+".concat(d));
562
- } else if (sortedType[i] == 2) {
563
- return ((i + 1) + ". ").concat("\u2191-".concat(d));
564
- } else {
565
- return ((i + 1) + ". ").concat(d.concat("+\u2191"));
566
- }
567
- });
568
- }
569
- }
570
-
571
- var shift = function(a, b, c, d) {
572
- var that = this;
573
- refF = a;
574
- compF = b;
575
- lens = c;
576
- words = d;
577
- loadsremaining = 0;
578
- shifter();
579
- return that;
580
- }
581
-
582
- // var sortedMagFull;
583
- var sortedTypeFull;
584
- var distflag = false;
585
- var plotdist = function(_) {
586
- var that = this;
587
- if (!arguments.length) return distflag;
588
- distflag = _;
589
- return that;
590
- }
591
-
592
- var selfShifter = function() {
593
- var that = this;
594
- /* shift one frequency vectors, against itself
595
-
596
- uses self.refF
597
-
598
- -assume it has been zero-ed for stop words
599
- -lens is of full length
600
- -words is a list of utf8 strings
601
-
602
- return an object with the sorted quantities for plotting the shift
603
- */
604
-
605
- //normalize frequencies
606
- var Nref = 0.0;
607
- var lensLength = d3.min([refF.length, words.length, lens.length])
608
- for (var i = 0; i < lensLength; i++) {
609
- Nref += parseFloat(refF[i]);
610
- }
611
-
612
- // refute refarison happiness
613
- refH = 0.0;
614
- for (var i = 0; i < lensLength; i++) {
615
- refH += refF[i] * parseFloat(lens[i]);
616
- }
617
- refH = refH / Nref;
618
- compH = 0.0;
619
-
620
- // do the shifting
621
- shiftMag = Array(lensLength);
622
- shiftType = Array(lensLength);
623
- var freqDiff = 0.0;
624
- for (var i = 0; i < lensLength; i++) {
625
- freqDiff = refF[i] / Nref;
626
- shiftMag[i] = (parseFloat(lens[i]) - refH) * freqDiff;
627
- // this does just the weighted distribution
628
- // (for LabMT, everything is positive)
629
- // shiftMag[i] = (parseFloat(lens[i]))*freqDiff;
630
- if (freqDiff > 0) {
631
- shiftType[i] = 2;
632
- } else {
633
- shiftType[i] = 0
634
- }
635
- if (parseFloat(lens[i]) > refH) {
636
- shiftType[i] += 1;
637
- }
638
- }
639
-
640
- // +2 for frequency up
641
- // +1 for happier
642
- // =>
643
- // 0 sad, down
644
- // 1 happy, down
645
- // 2 sad, up
646
- // 3 happy, up
647
-
648
- // do the sorting
649
- var indices = Array(lensLength);
650
- for (var i = 0; i < lensLength; i++) {
651
- indices[i] = i;
652
- }
653
- indices.sort(function(a, b) {
654
- return Math.abs(shiftMag[a]) < Math.abs(shiftMag[b]) ? 1 : Math.abs(shiftMag[a]) > Math.abs(shiftMag[b]) ? -1 : 0;
655
- });
656
-
657
- sortedMag = Array(numwordstoplot);
658
- sortedType = Array(numwordstoplot);
659
- sortedWords = Array(numwordstoplot);
660
-
661
- for (var i = 0; i < numwordstoplot; i++) {
662
- sortedMag[i] = shiftMag[indices[i]];
663
- sortedType[i] = shiftType[indices[i]];
664
- sortedWords[i] = words[indices[i]];
665
- }
666
-
667
- if (distflag) {
668
- // declare some new variables
669
- sortedMagFull = Array(lensLength);
670
- sortedTypeFull = Array(lensLength);
671
- for (var i = 0; i < lensLength; i++) {
672
- sortedMagFull[i] = shiftMag[indices[i]];
673
- sortedTypeFull[i] = shiftType[indices[i]];
674
- }
675
- }
676
-
677
- // compute the sum of contributions of different types
678
- sumTypes = [0.0, 0.0, 0.0, 0.0];
679
- for (var i = 0; i < lensLength; i++) {
680
- sumTypes[shiftType[i]] += shiftMag[i];
681
- }
682
- if (translate) {
683
- sortedWordsEn = Array(numwordstoplot);
684
- for (var i = 0; i < numwordstoplot; i++) {
685
- sortedWordsEn[i] = words_en[indices[i]];
686
- }
687
- }
688
-
689
- return that;
690
- }
691
-
692
- var shiftMag;
693
- var shiftType;
694
-
695
- var _shiftMag = function(_) {
696
- var that = this;
697
- if (!arguments.length) return shiftMag;
698
- shiftMag = _;
699
- return that;
700
- }
701
-
702
- var _shiftType = function(_) {
703
- var that = this;
704
- if (!arguments.length) return shiftType;
705
- shiftType = _;
706
- return that;
707
- }
708
-
709
- var shifter = function() {
710
- // console.log("running the shifter");
711
- var that = this;
712
- /* shift two frequency vectors
713
- -assume they've been zero-ed for stop words
714
- -lens is of full length
715
- -words is a list of utf8 strings
716
-
717
- return an object with the sorted quantities for plotting the shift
718
- */
719
-
720
- //normalize frequencies
721
- var Nref = 0.0;
722
- var Ncomp = 0.0;
723
- var lensLength = d3.min([refF.length, compF.length, words.length, lens.length]);
724
- for (var i = 0; i < lensLength; i++) {
725
- Nref += parseFloat(refF[i]);
726
- Ncomp += parseFloat(compF[i]);
727
- }
728
-
729
- // for (var i=0; i<refF.length; i++) {
730
- // refF[i] = parseFloat(refF[i])/Nref;
731
- // compF[i] = parseFloat(compF[i])/Ncomp;
732
- // }
733
-
734
- // compute reference happiness
735
- refH = 0.0;
736
- for (var i = 0; i < lensLength; i++) {
737
- refH += refF[i] * parseFloat(lens[i]);
738
- }
739
- // normalize at the end to minimize floating point errors
740
- refH = refH / Nref;
741
- // console.log(refH);
742
-
743
- // compute reference variance
744
- // var refV = 0.0;
745
- // for (var i=0; i<refF.length; i++) {
746
- // refV += refF[i]*Math.pow(parseFloat(lens[i])-refH,2);
747
- // }
748
- // refV = refV/Nref;
749
- // // console.log(refV);
750
-
751
- // compute comparison happiness
752
- compH = 0.0;
753
- for (var i = 0; i < lensLength; i++) {
754
- compH += compF[i] * parseFloat(lens[i]);
755
- }
756
- compH = compH / Ncomp;
757
-
758
- // do the shifting
759
- shiftMag = Array(lensLength);
760
- shiftType = Array(lensLength);
761
- var freqDiff = 0.0;
762
- for (var i = 0; i < lensLength; i++) {
763
- freqDiff = compF[i] / Ncomp - refF[i] / Nref;
764
- shiftMag[i] = (parseFloat(lens[i]) - refH) * freqDiff;
765
- if (freqDiff > 0) {
766
- shiftType[i] = 2;
767
- } else {
768
- shiftType[i] = 0
769
- }
770
- if (parseFloat(lens[i]) > refH) {
771
- shiftType[i] += 1;
772
- }
773
- }
774
-
775
- // +2 for frequency up
776
- // +1 for happier
777
- // =>
778
- // 0 sad, down
779
- // 1 happy, down
780
- // 2 sad, up
781
- // 3 happy, up
782
-
783
- // do the sorting
784
- var indices = Array(lensLength);
785
- for (var i = 0; i < lensLength; i++) {
786
- indices[i] = i;
787
- }
788
- indices.sort(function(a, b) {
789
- return Math.abs(shiftMag[a]) < Math.abs(shiftMag[b]) ? 1 : Math.abs(shiftMag[a]) > Math.abs(shiftMag[b]) ? -1 : 0;
790
- });
791
-
792
- sortedMag = Array(numwordstoplot);
793
- sortedType = Array(numwordstoplot);
794
- sortedWords = Array(numwordstoplot);
795
-
796
- // console.log(numwordstoplot);
797
- // console.log(indices);
798
-
799
- for (var i = 0; i < numwordstoplot; i++) {
800
- sortedMag[i] = shiftMag[indices[i]];
801
- sortedType[i] = shiftType[indices[i]]
802
- var tmpword = words[indices[i]];
803
- // add 1 to maxChars, because I'll add the ellipsis
804
- if (tmpword.length > maxChars + 2) {
805
- var shorterword = tmpword.slice(0, maxChars);
806
- // check that the last char isn't a space (if it is, delete it)
807
- if (shorterword[shorterword.length - 1] === " ") {
808
- sortedWords[i] = shorterword.slice(0, shorterword.length - 1) + "\u2026";
809
- } else {
810
- sortedWords[i] = shorterword + "\u2026";
811
- }
812
- } else {
813
- sortedWords[i] = tmpword;
814
- }
815
- }
816
-
817
- if (distflag) {
818
- // declare some new variables
819
- sortedMagFull = Array(lensLength);
820
- sortedTypeFull = Array(lensLength);
821
- for (var i = 0; i < lensLength; i++) {
822
- sortedMagFull[i] = shiftMag[indices[i]];
823
- sortedTypeFull[i] = shiftType[indices[i]];
824
- }
825
- }
826
-
827
- // compute the sum of contributions of different types
828
- sumTypes = [0.0, 0.0, 0.0, 0.0];
829
- for (var i = 0; i < lensLength; i++) {
830
- sumTypes[shiftType[i]] += shiftMag[i];
831
- }
832
-
833
- // slice them
834
- // sortedMag = sortedMag.slice(0,numwordstoplot);
835
- // sortedWords = sortedWords.slice(0,numwordstoplot);
836
- // sortedType = sortedType.slice(0,numwordstoplot);
837
-
838
- if (translate) {
839
- sortedWordsEn = Array(numwordstoplot);
840
- for (var i = 0; i < numwordstoplot; i++) {
841
- sortedWordsEn[i] = words_en[indices[i]];
842
- }
843
- }
844
-
845
- // // return as an object
846
- // return {
847
- // sortedMag: sortedMag,
848
- // sortedType: sortedType,
849
- // sortedWords: sortedWords,
850
- // sumTypes: sumTypes,
851
- // refH: refH,
852
- // compH: compH,
853
- // };
854
-
855
- sortedWordsRaw = sortedWords;
856
- sortedWordsRawEn = sortedWordsEn;
857
- concatter();
858
-
859
- // allow chaining here too
860
- return that;
861
- }
862
-
863
- var dualShifter = function() {
864
- var that = this;
865
- /* shift two frequency vectors
866
- -assume they've been zero-ed for stop words
867
- -lens is of full length
868
- -words is a list of utf8 strings
869
-
870
- return an object with the sorted quantities for plotting the shift
871
- */
872
-
873
- //normalize frequencies
874
- var Nref = 0.0;
875
- var Ncomp = 0.0;
876
- var lensLength = d3.min([refF.length, compF.length, words.length, lens.length]);
877
- for (var i = 0; i < lensLength; i++) {
878
- Nref += parseFloat(refF[i]);
879
- Ncomp += parseFloat(compF[i]);
880
- }
881
-
882
- // for (var i=0; i<refF.length; i++) {
883
- // refF[i] = parseFloat(refF[i])/Nref;
884
- // compF[i] = parseFloat(compF[i])/Ncomp;
885
- // }
886
-
887
- // compute reference happiness
888
- refH = 0.0;
889
- for (var i = 0; i < lensLength; i++) {
890
- refH += refF[i] * parseFloat(lens[i]);
891
- }
892
- // normalize at the end to minimize floating point errors
893
- refH = refH / Nref;
894
- // console.log(refH);
895
-
896
- // compute reference variance
897
- // var refV = 0.0;
898
- // for (var i=0; i<refF.length; i++) {
899
- // refV += refF[i]*Math.pow(parseFloat(lens[i])-refH,2);
900
- // }
901
- // refV = refV/Nref;
902
- // // console.log(refV);
903
-
904
- // compute comparison happiness
905
- compH = 0.0;
906
- for (var i = 0; i < lensLength; i++) {
907
- compH += compF[i] * parseFloat(complens[i]);
908
- }
909
- compH = compH / Ncomp;
910
-
911
- // do the shifting
912
- shiftMag = Array(lensLength);
913
- shiftType = Array(lensLength);
914
- var freqDiff = 0.0;
915
- for (var i = 0; i < lensLength; i++) {
916
- // shiftMag[i] = (parseFloat(complens[i])-compH)*compF[i]/Ncomp - (parseFloat(lens[i])-refH)*refF[i]/Nref;
917
- shiftMag[i] = parseFloat(complens[i]) * compF[i] / Ncomp - parseFloat(lens[i]) * refF[i] / Nref;
918
- if (compF[i] / Ncomp > refF[i] / Nref) {
919
- shiftType[i] = 2;
920
- } else {
921
- shiftType[i] = 0
922
- }
923
- // if (parseFloat(complens[i])-compH > parseFloat(lens[i])-refH) { shiftType[i] += 1;}
924
- // this means the word is in the reference, but not comparison
925
- if (refF[i] > 0 && compF[i] == 0) {
926
- // compare the happiness to ref avg
927
- if (parseFloat(lens[i]) > refH) {
928
- shiftType[i] += 1;
929
- }
930
- }
931
- // this means the word is in the reference, but not comparison
932
- else if (refF[i] == 0 && compF[i] > 0) {
933
- // compare the happiness to comp avg
934
- if (parseFloat(complens[i]) > compH) {
935
- shiftType[i] += 1;
936
- }
937
- }
938
- // if it's in both, color by the difference
939
- else {
940
- if (parseFloat(complens[i]) > parseFloat(lens[i])) {
941
- shiftType[i] += 1;
942
- }
943
- }
944
- }
945
-
946
- // +2 for frequency up
947
- // +1 for happier
948
- // =>
949
- // 0 sad, down
950
- // 1 happy, down
951
- // 2 sad, up
952
- // 3 happy, up
953
-
954
- // do the sorting
955
- var indices = Array(lensLength);
956
- for (var i = 0; i < lensLength; i++) {
957
- indices[i] = i;
958
- }
959
- indices.sort(function(a, b) {
960
- return Math.abs(shiftMag[a]) < Math.abs(shiftMag[b]) ? 1 : Math.abs(shiftMag[a]) > Math.abs(shiftMag[b]) ? -1 : 0;
961
- });
962
-
963
- sortedMag = Array(numwordstoplot);
964
- sortedType = Array(numwordstoplot);
965
- sortedWords = Array(numwordstoplot);
966
-
967
- for (var i = 0; i < numwordstoplot; i++) {
968
- sortedMag[i] = shiftMag[indices[i]];
969
- sortedType[i] = shiftType[indices[i]]
970
- var tmpword = words[indices[i]];
971
- // add 1 to maxChars, because I'll add the ellipsis
972
- if (tmpword.length > maxChars + 2) {
973
- var shorterword = tmpword.slice(0, maxChars);
974
- // check that the last char isn't a space (if it is, delete it)
975
- if (shorterword[shorterword.length - 1] === " ") {
976
- sortedWords[i] = shorterword.slice(0, shorterword.length - 1) + "\u2026";
977
- } else {
978
- sortedWords[i] = shorterword + "\u2026";
979
- }
980
- } else {
981
- sortedWords[i] = tmpword;
982
- }
983
- }
984
-
985
- if (distflag) {
986
- // declare some new variables
987
- sortedMagFull = Array(lensLength);
988
- sortedTypeFull = Array(lensLength);
989
- for (var i = 0; i < lensLength; i++) {
990
- sortedMagFull[i] = shiftMag[indices[i]];
991
- sortedTypeFull[i] = shiftType[indices[i]];
992
- }
993
- }
994
-
995
- // compute the sum of contributions of different types
996
- sumTypes = [0.0, 0.0, 0.0, 0.0];
997
- for (var i = 0; i < lensLength; i++) {
998
- sumTypes[shiftType[i]] += shiftMag[i];
999
- }
1000
-
1001
- // allow chaining here too
1002
- return that;
1003
- }
1004
-
1005
- var nbins = 100;
1006
- var dist;
1007
- var cdist;
1008
- var ntypes = 4;
1009
- var nwords;
1010
- var computedistributions = function() {
1011
- var that = this;
1012
- // bin the distribution of words into a distribution
1013
- // and cumulative
1014
- // there are four types of contributions here (the way
1015
- // the sum has been broken down), so do the distribution
1016
- // for the total, and each of the four bins
1017
-
1018
- // nwords = sortedMagFull.length;
1019
- // nwords = 2000;
1020
- var a = 1;
1021
- nwords = -1;
1022
- while (a > Math.pow(10, -6)) {
1023
- nwords++;
1024
- a = Math.abs(sortedMagFull[nwords]);
1025
- }
1026
- // console.log(nwords);
1027
-
1028
- dist = Array(nbins);
1029
- cdist = Array(nbins);
1030
-
1031
- // compute the size of each bin
1032
- // should be a fast way to do this
1033
- // when it doesn't round evenly
1034
- var binsize = Math.floor(nwords / nbins);
1035
- // console.log(binsize);
1036
-
1037
- // loop over each bin, initialize it to zero
1038
- // then add each of the types to it
1039
- for (var i = 0; i < nbins; i++) {
1040
- dist[i] = Array(ntypes + 1);
1041
- cdist[i] = Array(ntypes + 1);
1042
- for (var j = 0; j < ntypes + 1; j++) {
1043
- dist[i][j] = 0;
1044
- cdist[i][j] = 0;
1045
- }
1046
- // fast, with the sum
1047
- // console.log(i*binsize);
1048
- // console.log((i+1)*binsize);
1049
- dist[i][4] = d3.sum(sortedMagFull.slice(i * binsize, (i + 1) * binsize));
1050
- // slower, by type
1051
- for (var j = i * binsize; j < (i + 1) * binsize; j++) {
1052
- dist[i][sortedTypeFull[j]] += sortedMagFull[j];
1053
- }
1054
- }
1055
-
1056
- // now get the cumulative
1057
- for (var j = 0; j < ntypes + 1; j++) {
1058
- cdist[0][j] = dist[0][j];
1059
- }
1060
- for (var i = 1; i < nbins; i++) {
1061
- for (var j = 0; j < ntypes + 1; j++) {
1062
- cdist[i][j] = cdist[i - 1][j] + dist[i][j];
1063
- }
1064
- }
1065
-
1066
- // console.log(dist);
1067
- // console.log(cdist);
1068
- // console.log(cdist[cdist.length-1]);
1069
- return that;
1070
- }
1071
-
1072
- // declare a boat load of private variables
1073
- // to be accessed by the other methods
1074
- var canvas;
1075
- var maxWidth;
1076
- var x;
1077
- var y;
1078
- var topScale;
1079
- var bgrect;
1080
- var xlabel;
1081
- var topbgrect;
1082
- var ylabel;
1083
- var sepline;
1084
- var zoom;
1085
- var axes;
1086
- var fontString = "Latex default, serif";
1087
- var _fontString = function(_) {
1088
- var that = this;
1089
- if (!arguments.length) return fontString;
1090
- fontString = _;
1091
- return that;
1092
- }
1093
- // the inspector computed width of ∑+↓ rendering in latex default (cmr10)
1094
- var sumTextWidth = 34.1562;
1095
- // these are set explicitly on the elements
1096
- var bigshifttextsize = 12;
1097
- var xaxisfontsize = 12;
1098
- var xylabelfontsize = 16;
1099
- var wordfontsize = 12;
1100
- var distlabeltext = 8;
1101
- var creditfontsize = 8;
1102
- var resetfontsize = 12;
1103
- // [16,10,20,10,8,8,13];
1104
- var setFontSizes = function(_) {
1105
- var that = this;
1106
- if (!arguments.length) return [bigshifttextsize, xaxisfontsize, xylabelfontsize, wordfontsize, distlabeltext, creditfontsize, resetfontsize];
1107
- bigshifttextsize = _[0];
1108
- xaxisfontsize = _[1];
1109
- xylabelfontsize = _[2];
1110
- wordfontsize = _[3];
1111
- distlabeltext = _[4];
1112
- creditfontsize = _[5];
1113
- resetfontsize = _[6];
1114
- return that;
1115
- }
1116
- var typeClass = ["negdown", "posdown", "negup", "posup"];
1117
- var colorClass;
1118
- var shiftrects;
1119
- var shifttext;
1120
- var flipVector;
1121
- var maxShiftSum;
1122
- var summaryArray;
1123
- var toptext;
1124
- var toptextheight;
1125
- var credit;
1126
- var help;
1127
- var logo = false;
1128
- var logowidth = 0;
1129
-
1130
- var drawlogo = function() {
1131
- var that = this;
1132
- logo = true;
1133
- var logosize = d3.min([toptextheight - 10, 80]);
1134
- logowidth = logosize + 40; // add some extra space
1135
- // not working yet
1136
- canvas.append("image")
1137
- .attr({
1138
- "x": (boxwidth - logosize - 10),
1139
- "y": "0",
1140
- "width": logosize,
1141
- "height": logosize,
1142
- "xlink:href": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAIAAAAErfB6AAABFWlDQ1BpY20AAHheY2Bg4slJzi1mEmBgyM0rKQpyd1KIiIxSYL/DwMggycDMoMlgmZhcXOAYEODDgBN8uwZUDQSXdUFmocsSAFwpqcXJQPoPEMclFxSVMDAwxgDZ3OUlBSB2BpAtkpQNZteA2EVABwLZE0DsdAh7CVgNhL0DrCYkyBnIPgNkO6QjsZOQ2FB7QYA52QjKoiIoSa0AupmBwc2JgQEUphBRRFghxJjFgNgYGBdLEGL5ixgYLL4CxScgxJJmMjBsb2VgkLiFEFNZwMDA38LAsO18cmlRGUSMQQqITzOeZE5mncSRzf1NwF40UNpE8aPmBCMJ60lurIHlsW+zC6pYOzfOqlmTub/28uGXBv//AwDeQVN9kuwu9QAAIABJREFUeF7tfXd4VNed9vRepWka9d4rSEINkGi2McYmrskmTtnsOpvn2+zn7O63yZPv2WTzx26SzW6ezZfkcYptbGywTUwzCAwCUUyX6KCGeh2NNCozmj7zveceMRYaQWSQhCT0xhmubjn33POe3+/3/s4991623+9nLWHxghO8agmLCUsEL3IsEbzIsUTwIscSwYscSwQvciwRvMixRPAixxLBixxLBC9yLBG8yLFE8CLHEsGLHEsEL3IsEbzIwQte9dgg+EY4O2jNgsfjQfAUcxr8fpYvaAObzebevWbB4/EgeArLZE/JevCqhY7H2UWD9kXokyfhsSDY6/Ox2Byfz8vhwAP7mWlobPxwOBzKsM/ng3fGSu6iY/yxINjt81ltowIBXyAQcNhIHIgr9rH8Xq8XNoz/Ec79PixwQPHi4vixIHjb++/VXq5NTk5Zu3ZtQlwC+PWBTjbX4XSePnPaYrEYjca8vDyRQBB87ELHY0Hw0aNVbq/X7b5eV1f3kx//RCFXEBft83d2dr677T1NaOiQZaitrWPTxqdCFLLgwxc0FvNAB53ybbPZdKqQsBCNUiQZNQ+6bWN8ll/E4QrZHL6f7R61dTS1JMfGdbe02izDi090LX6CJRLJV77ylX6Tqa+31xgWJhGLEYYRcbFVp9VmZ2VjsbWltb2tnc/nB5Wx4LGYCYZIhjzGQk5Ozj/90z9FRUU988wzSqUSK8EuxJRCId+wYQPEl16v//KXX9FqQ4PKWPBYtI+uBF+Xx+PhciGSiRvGLwwX//q83pu36gx6gzpEhQ7BWXR50mP8bNKU173ogvDS3aRFjiWCFzlmPg+GhEEs83q9+KVrEAWY8SMWoh4iH5tD4h+Hw2bWzTDIiJTPZ7Va//SnP924cSMxMXF4ZMQQFdPR2WG12mJiYgwGg1Qq0Wo0CqlMJBQ6nS6vx2O12aqqqpwOR/GKgry83IiICARpGq0XOmaeYPBK4zrh9Y6OpcO/aDD8A7Ej4PFA9my0Hz2pXC5ft26d3W7HuXhcrpDHU8sVMrGE7fUerzrqcrn1Bn1TYyM0F/ZHHqVWq9EnHA77rRvX+vs3feMb3+DxFskQ0MyLrECBLgZSqZSYgh96lcXhstxut6l/YHR4JD4hViCc+bwTZ6egJkgNms3mer0+LpvjhWgmQ1pum23M7nKOOexY4HLwP7InekOYNlSn0wkEgkVjwTNPMFoQTTM0NLRz5866urpvfetbqampLD8Z4oc/rDpaXXPxYmtr6w9+8H+SkhOCD39I3LkvRJgOcIzuRdYQp4F+5kNogJV7sB57ou8xzsRPbjixuajoHVpnnOBAU9O60Y4ILxLYAZWn9cdKuvDwdZgtR1RTU/PrX/9aKBSGhIQkJSXxefDb7PaOrrNnzoxaR202W3Nzy2wQHAj8gabBgsdDGgtBH1Sz8A9pXGYH5q4/1AChmPRAuPe7jp0lMFXyjI2NgUg0UWAEDaSO2cbG7GMIMeTGF9LyCfQ/GGaFYDpUBOeMSIa6YtnrJapKJpUg1A0PDcNJCkXC4ANnCzyOFx6YqD82DNXPWDXDN5m5Q/5gkz8ZkQAQrx7oKDMIyis4QyO8/fbbp06d0uv1v/jFLwI7dHR0/O53v6uvr1+/fv23v/1tqmAesiazQjDqVFhY+KMf/QgEZ2dnkx6KGOxjabWa8vLVf/zjn5RKZWxMLPWRcwCr3T48ila1upzOAcsgfDKUM5QXKqbRan0er1gklMnkQqEA/lksFsHavfCQd1p2BqmmbrmtrW3r1q0ikainp6ezszM+Pp5ura2tbW9vj46OBvdf/vKXVSrVfCSYehVQuHHjRhps8CflEnxv3PgUric0NNRg0E6fXR+Jk5O1AtHlzCbwQZqNRFq22+3zeLwet3toeNhisQwNDZvNA6b+voaGRrFEAkYtg4N8AVQ8l8/xDlksiHcioRh+0u9liSSSAduIVCbj8VFTvkQsLsjPj42NlYn4QsguLgerocfgnVBzDpGNjOdnMKlu9wEOiYqKSkhI6O/vF4vFt27diouLo5saGhqoZ0ZQg/+jCQiMnpb/YCF5FocqAyUTvcDiwvFRjQPRipWkjaY98At6ybXeDca5klOM2WwwOCQ53d3dFy7Umkz9IyMjOCnyH8QCMmGD5UdqhCDsdrmwv8vthim7naNcLkcuVbjdHoFA6LC7iJvx+yAasA9R+yYTGtTn8/IEXL1ehxwaTCCNDjOEKRQKcI1e8EUJphaMo8DlP//zP8OCf/7zn69atYpuHRgYeOONNy5duvS9732vpKSE7ozCA7zOL4IBGnKodVmtNqhokQiuEQZEGoXLeyiCkfM4HI6rV68iaGEBWe/o6CgsWICIwGYPDg7CB+LUoBk7w5rx63Q6sSdODdMZMHW6nI7QUB2sXCqVOZ0emVTmHnOAKyQCoBDtAovHJfBFPI/HTWKnzep2uQVCIZiWKeS5ebnp6elwpNMkmFokSEKt0IFOnz69Z8+eH/zgB0jM6A5Yia4JB56RkYFTU2omGu68IJj2OyygNmgp5EuVlZVHq463tLRiGY2OtsMFvPDi8/n5edQC7lNvpigoI0IwdqIluz0emCmMoLunp7bmIoyKxFeXC54WoRTNNGA22x0OqUTqcDrg63BShDooGtRHJBYb9Hrkw0cP7kVpf/XVV8USmUgqaWnt4PEFLoej39SPrgPbQm8AqZ0dHQqROESlhtvnCQRcZhgH3dQ0ZA7VhOJaVq5cCX8Lrzvele9QGPgNXAslOHBd+BP1oTk3XUkzTGwKpEnopvv27SsrK0OXmsj09DHzMRiVQBOjimijDz/8cPv27TCaVSsrvvWtb4aHh8NWmpqazp479/d//73s7IxNm55GA6GZpswHaHsxrpi4WYfDBbd5/vyFjs5OOFuP15uSkhISokXuOjpqg/lCsXd2duGQcGM4WhxOlQyL+llGYxhohqEgrNIAfKmmdue7bykU8ujIqGWFhR64Zs7pvLw8iVyGYvHf6MjIjbo6lVKBkG5u7bKYB9o7OtFvbGM2IRIAiSxaKUW+d/v2beT6MOLc3FxcSHJyMvw2jZqUjIkqCQvoNMR1ITYwv9h5Yieg3Z1yj0KQau7atQtdMzMz8wGopZh5gtENUfVDhw698847zc3NL7/88pNPPhkVGQOdArpwaTDcLVuexaY9e3f/9Kc/LS4u/tnPfgafOakcxhFQ78K22ey36hrQlMPDI13dXWqVmguRxOFdu3bD1NdHRqO4nLS0tIiIiPSMVJxdqVRADMOakZL19PampqaQkW+0HTUjpmCJSOx2OFEmCIZuGhwessHcZVKIHCF8eEjINacrQh+m02i4Wbl+H67LPToyeuXqje7uLshdtptEH61Wi1/0nuPHjx8+fBgpQ3l5Ofy2Wq2m5jjxinBqSj+WAz1gknun1La0tHz66afw4TCJ1157DcXSVp245zQx8wSjftD6H3/8MS77rbfegvvCNUCU+rx+LjNKhCRZKBKkpaXGxsVs2LC+tvbSlDGMkMBmDw8P19XVX7l6CwaE1lcpVVKJ2AxlbDa7vZ4wvWFFYWFubo7BoINhNTY1J8THi4QCHMhYBulPXV1d8fFxsF3a2Ez6y4b5qBQK4sDFEtLWLBa0FcxLCL/IxAJ0A6mfo+RBXrNdUDo8NqSDXKUSSMTPPv/cmvXr6m9evXDhPEI7zBAxQqVSw1HVN9SfOXM2MzPjqaeegkqC+50Y/8AoGuedrVtv3Lz55S9/JSUlGU00YTsLARhNR6kNCwt79tlnob/QhwJm/QAczxjBgdtHY2Nj3//+9wsKCr773e+iIwd2CEgqSjOAcJiTtyw7Nw/X7vISPvA/koCy2Wjrvr6+U5+d7jeZELkdDo9cLvV47R2d/XDC8XEpK1c+l5eTYQwz0IjlhTgHdT7X6NCALMyIRIkLEjmcUJVCLOANDY+SOdFcMpUSxupl81wez+jY2JBlAL2ERjuFXN58uznaEIajULcenN4yyBJwvRwW0WxMlW12m3XIgi5s1Gt02tLMnIyLNbW3m1oHh4bHxlw6rTYuISUyJg453R/e2rpr34G//du/jYmORI6F3krmW4MhDnddxdrLF2p/9V+/3vzsc2lpyW6Pt+5WfU93N7R9Te1ZmUyKK/rmN78JTwCvdn+BMh3MGMG0HuihSOERGl9//XVIm6C9JoNqEtgqGWNixoQR2CDHzl+40NvTA9+L8Ay5ZB9D9O01hmuzszNLy8oM+vDUlFSxgIga2Cg6N0OKH+EVmQbEFO+O3gH3EeHhHV3dRgNCNSGSRx5uYJ8+c04iliBVtjvsHDhvNksmlfaaTHDfpPv5WQMWS1JKslgq8fpZyOaYQU6WuX9QKpGIRSJGLvlV6pDVqysiIpqRI9y4caujowvJd0xMFPEdHA7C8/vvv6/Vap54ckNsTDS5QQrPweFERkX96te/PnSo6pMDlUePHkVXBpFisQSZ2HPPbUlKSkD9Yb7UWB/Maidi5gmGU/2Hf/gHmmDARwXtOAVwKPpvT3dvW3v7uXPnUBQUE70wmC+YgJIqK30hOyddLBZ6PL7r12/19PTFRYeDXapiIOtwRvQGNCtCYEC5YMFoNDadq0XvAXOM5iKDJmhWxGmPxwkPwXQzNg+Hy+XEiTDNiquAYiKFUBnP3NyEpuUL+KgYVnG4fLgNONXBgYEVK1YkJMb39vSdPHWyvaODDMrKZAif6G1mc/+A2bR69arluXmoHhkTRRfzs9ZtWFu6shhXMWYb0+m12IS2Eor41FzhDmkHnTJ4fSFwf/zjHwevfWCglXG1ULNoBeBe7oUSQEensAss9ebNusNHjty4ccNmtcKLOl3O7q7u0NDQFSsK4Q9WFBZlZWcwCS4MgQs53dvTHxFuQFH0FDgXWEFIg+ZE0CLBjxkiwC+fL+jq7TfodXzG1gE/myuVyW9eqnG5HHqDsXTlSh+Y53Bgf+FhBhRIB0Z0Wg0Zk2EGrUgm7/d1tHdERISr1UqckYxp+1mffXYmMTGBjnugxyQnJYEbi2WosaFRIpVAt6Ny/b297W1tiNZK7IH0GpfNYaNrisQirTbUYNBDzIvEEHbEkxD9xwQdVIPWf365aGA6npk0ItNFYQTNcMjnzre1tyEFQr4xZrcjzUVDfPvbf5OengJTaGlpa2xo1upCIY1xIKDT6QfNI1arTTHhQQQ0B/LgxMREOkRA+z79RUeBqUk0alSR2J+fFREeBp/hdLr6TCaH08kTiSGq6RMP2AdHxURH83g4lpg0TB8uGcFSFaLW67U+L3lIDdtGbHa0v1yuIMkxk9mOjI7ExcdnZ+dA20NgwoJxnQqZbMDUX3frFvpWfkFBUnIyqsS7I0QCw3lccrrPm3F863yz4OmA2BDTMUdGbSdOfbZn926IT3hI6gPh2CGwv/7q1xC36B0npM5IkwYtA5DK5OrZbD5PAOfmdTsgfSnlgcLRIejdt4nrvSDE75dLxeT+IHEa3CvXbp47cUytUnZ2dT+zeTNPyCdCXygQ8oSgjukH4+xime1DQ5OeEaJWCwTwIsxV+P3Nze1QkUajnimWJD9VVceMYcawMD26VFp6OvRmW1sbUt2kpMTu7m6k13aX0+31ooPCTz+cZU4Xcz0xhVFSbJvV1tjYWH3i5I2bt5QKJXrz6MhIT093aWnpSy+91NR0G6lRUVEhuYXHYgn4vPi46CNVVWmpiSJEKeaOLjKftuYG6tAmEozlYLemCVGQGwPjexCbQLiVSKUulxOSDfqaPOfA9imk0omj44Ey6POI6BmEdTrTiA214QNZScnxzLn8+H9Pbw/0F2IB45tY4cawF57/Ulx09K4d2y/V1oJdp9ttdzoszHBedlra52e6g9l4v8AcEeyBPKWhl8Vqb+9EstjV2Wnp6dEp5Mg9RHyeMSr8f/3938XGxnG8LHEq/8SJz7wuD48M45HDVQppRJhu2GKRGY2kQdksXajcZdeTgWLGIQcYndKnkbuA466QeEbskZOe9Nff+Q4y1+KSEjr9irFsapyT4fUw445Q4UjluRwIIDInhOVLjI+QiUkNQbrL7e3u6FqRv0wsRPhHgCYFjg4Nnj1zqr7pJvpTVGS0OlTb12fua+++XnNlbGhkef7ywO2K4JPOFObOgnHBECC9vX2HDh1GOu/1esQiocvp6O7uksikqRlpMVExaCqiVhQKg05nGbTA15EDmTvwKSnJHR0dYQZDIG1ALkF5nWSvwQjejEOWLV9OF+6suWuHiSAztoggJF0UHggCiARmDqKKfHwHNht5dkZ6BjMBjewIzpAIfPLJJ5WVB9A7tXq9WCIx9/eHhmiGh0Y627vMA2apTArBP6vsAnMUg4me8vluNzV//PEuBFoEu46OdoTA2NgYk7kfwurUyZPZ2dmRERGQLzBIkUg4MDAYEqImc2tJ0/uZZFFMb5cGin3IcQAcPh2lSvUgmQmCve7kWsSPfN45yALNCWlpSNv27t27Z88eOJjo6Ois7Oy//vZrEqkCitLl8bhcHpfHAQkGD4Rs6iEz3ftjdi040HYet7f6+Inq6uOwxeXLlw0Pj4DaNeVlTqejrbOjublZq9Hu3b07Kz0DehbuUKtDisKDxoZBkxKYVy/Q7CtQOOUGCw/GceDwKUFrzgxokOVLly7t3r27rq6OPscG2ugsA3pqmouTfsAUCEd1+PDhjz76CEYcGRm5fsMTeXl5SpV6zdo1MrnyzTffVqtEVqt1ZGS4v78fBxYVFdGTzoY1z64F0wtGd25qan3zrbeMRmNycrLH40W3XbNujUqtVKnUmtAQpL9olNqLNWgOZniBGLGYpIYkIWQ8HlpyihuLZO1DWDA9dsoSsJLeFQBu3br5ox/9CJW0Wkeh8KEEmbGzz7P8QDm0Q1y5cuU3v/kN2NVoNFu2bFm/foNCqSLTgDz+8AijRCKDhNRq1bR86ABIbjrL4GGu5V6YRYLBLi7Y6XSePHVq9559+rCw2JgYuUIhEgrdHrdepyNZEJskqU6Ho6+nVywQNtTXr1m7FgkLujLoJNGOCd6z8QzE/REw7uvXr7/55h+6ujv0Bh2fz122bHlOTjaujMud2vmhp27durW2thad+OWXXyaPpwqFRHSBPS4Z21GpddDs589/Ru8VDg0N2Ww2ZHfwT7Mx234WWw5NhEa6fPnKiRMnhSJRSnIKLl6tUlVUrMzLyam5WGO3j6EHkIlaT28E91KpZMBs3r//wCRRNMsqZBLGeSVDmxyOy+U6dLCyra1Vr9PDe4DUttYWZLf3MjWsh7uCaeI3MzNz3bp1ROQzKozqalP/IBLCjRvXv/jii2gN7CoUCusb6mH0XV3kTvaMg/vD//sjL9H15MroxAl0Ny/DjcdLxCNEgdfH4jETqaYDtxfZBDnQOjZ26rMz23d8oArRGKKiBSJRUlJCTlaGWMCXS4VKmdjU26fXanGIUCBISkmGAGnrbD93/tyqVauUSgVpEzJ8PJUIni3gsj1ED5LRSbbb5z+0f9+Od7fy2RypSMz2c3lcQUPD7YLCYp0ujLnHGHQ8A0Qig8GAhF6pVDIhhFHgPl9vT/eYbUSvD5VKRDFx0WK5pLOr0zJisdpsDpejoakhKSEJKTKOCET3hwf3X//1J2P2McR8xiVy6VNipHC/v8/Uf/z4id7eXkQIiVg0zROiO6ByZvPg4SNV16/fiIiIkCvkoRotREV4eBgYxTlguBKJZNRqgzWoVCochQQDahOiw2KxwL/Bs9EcMaj42QaZGoSgjyVzv/l//vuXUrFIG6oRCkXo6BKplMvjy+XKjIx0ZqhrCqANEXSysrLuvtfr7+rqRAsbjeQdEoyXYIeHRyIwt7W2KZUqp9NF/rPb0VxQ4zOoq7mvv/6/33ln69tvvXXzxo242FikLsRyyFRFe+X+yupjx/Z/ckAmlWZmpk+3udns/oHBQ59+evbsWblcptXqeFxuYUFBRkZqbe1lKBOtJhT7gD8EHjgoGnhQuEKhgMJCzDt58mRsbGxiYuJsqMr7gkyFR6OjBdDc723bVl19DKERybeXzB7kqdTqoZGRvt7+spVlEsnUQ+5UCQb0IP2FN0ZX1uv1NJUiK5lp9wq5vKenBytGRkZxEAjGpqioqGA5+cDgbn560+9++zuf13O7qQliLjUllZlXxmpquH3w4EFUSKfRDA4MrFxVdp9uRSUJdVC9JnNl5cGGhkaVitw8CQvTFxeXREcapRIJrOHy5ctMJxUiCvCZmacBFnFJaM20tLSrV68i5V2+nAz03HWa2QcRdMw78c6ePr317bfhMGNi4zLTUltb2xB3SsrKbGN2qIoVxUVhBjIIQxEggy4EHCy9NCwD6M30ckhCRd7BRtZbhkbQb3p7+6xWG58v8Lpddrtdp9NRUT2p8EDOhl/4uaamppGRERoF6BnpID8UABbonzgXD/9oQ0PhpZUKpUJOJr8hhGKDQChob2tDtdDvhoeHmTda3BO0OCy43O6LFy52d3dDMYWFhWFLfn6+TquBHPZ5fZHhxq4u44VLl8tKSxDZZaJxXzSxt6L/vvHGG2jZuWcXgP7wuFy3bl7/7f/7lc06rDcYv/6Nb42a+65cvixVqJbl5fGFouvXb509czY3J5NQNVUmPdHx0EubZBuIg3Dwff3mjo6uhPhEkVB8oLISbIUqZQiIcGCgDX6eFh44FkXRaTPIrNBEWI92Ligo2Lx5M+Iddoayq66uRgnQa/CFSOeQp5FJ9PFxcXwuf9XKlVB9qBqxYJ8/Njr6r7/5zY629oa6+uioaAiMiVUMBk6PExw5fPhYdTX+RDeEFa5etVKLc5ACvehn4KywMB/u6fzFS+hmQWWMA3aMQ+bcPxOA4O7u3t/++n9GhywquSwzKysuKamltbW/30xmVrPZUPvwalCCWIM2pd36AWC12ZuaWjhsrk6rW7Yst2hFsUqphgQxm82g59atWzDEYKlFXXdHRwfCH/NAs+PChQtIuKnvhObftWvX/v37QXxDQwMcIZmq97P/+NmKoqKKiorS0hJ4TuJNIDHYLC6bGxsbA5s39Zu++rWvGsL0k042EUy+6zpWffzixYsaLeqsF4slSUkIo4noqziQS2a6kQAHISeRyto6upAQq+Vk5DYYqCtz13bGlOT0AfWAgNXcVK8JUYeEhH7la18XiMTnPzuFVFUdErpuwxMhGg3aDu4xOTkxMhIqaRzBRd0fF2uucLi89PRU5lY/F2ELDdhv6kGGhQWTqT80NERvMDDp8+eFg2Bwhn6wd+8+iDj6hHtKSgrjLFnkWSs+f3BwEHQAcL2wXu6Pf/ITeGOZQk5u3RB5AYdO7qz52X7QkpWTtXpteXhkRGCm3ET4/QhMJG4hj7rZ0Lhnf6WfzcvMzoH8TktLH3M4BywWeAnqp3AZ4AzFyGWSpLiYe7GLfWk/nTN2qRXiFwbx03/7t+6uTrFU6vR4X/nKV+EAr1+9+umhT6UKZXh0dNayPJlMKuDzTh49ajKb165dGxxi7g9qanX1dZah4ezsLLmcuFaETtsYmbhvszsQ49GlkF60tneEanQhoaE+8gAzashhHu8g1qfWhAyaB8hsAjY7Li6uqKgIkZQJ7WxjhLG9o6N/YECr05WuXKlWh47HOewamMeL1iW1YO6c8JAVKBTMn1PcTCOEcbjYbWhoeM/efS63p6i4VCQUpaWm5uVlD1mGT585C7eckpzEF5Bgj0qQX5xlri3zfqBmgWuH0HXYx+z2sezs7MzMTDg2wh+jPuwOe6hWg6CD5bzc3JLSkn2VB+BIkQ4xbTMtBCaehodHRMUkCIR8KmyaW1pMJpMxLGzVqlVwFUMWi9fnGxkdvVVXZzDoQ0LUjPgjJI3PcWJzXnzxpbNnz6BHop5hhvG7amhbpHOvvvr1q9eviQTCcGM48cSBoUoYO9w6AkBXZwdsX4AMRkg8Ns0c7iHbydXhNLv37L105Wp2dg48sE4bmpeTJRIKxSJRVGQ45PTYmE0pl5G5EAzmzDSnD+ozoOwgTNBkq1evBsegE6oCqXx/Xx+ua3lBQXRMDNI8AZ/vsNthhWAF+0989uT+oG4JTYa2JYPsxF2yRketIDI1JcVoNKpUKr6Aj2CP3eBpW1tboyKjdDoyt56hlvYkHMRRyKRIN9C94IeZTYQjJnsnQTDCGE6mlpIpbCxiWMC5c+eOHj16/vz527dvux1OJOOq0NDSstLXXntNH2b0kxnkU4ksxr2gCaqPVccmJETHRBvDjMkJMXBiuAwehy2XyVaVlSBmoNckJiSQgZRHIZ3uD+o2KceQr6CWKgA0C3p8fX1dZ2cnF0mMQEjmfeC62JxVq1eP2Gx79u5hZtXTSR1/GdgNZTI7k/+7ySQTtnlgMCIyAiwSMliczPT0zo5OqpsQUOvq62PjojVQ1MzDsV6fx+32kuzyDiNUjTJXQB6j9bHG72uRp4fgL6Fm/uVf/mXv3r3//u//3tzcDGkORl94/ktFK4oglY4eO7Z9x/blyHN0OqSrQRWGT/A2N7d8/PEugUgUqtVyefycnCyFVIw2Q45LehqbJLtIv0LUapKAzc6T8w8JaliBhYk1hBw9f+48WkqhVD61cSN0DXljC5sNuhOTEgoLC9VqNX16cZqgp8DZyNRKDntgwAI9lRgfx+fTWSV+oUgYGhIK20VoQ/dqbGzg8bjQUCQ6+Hww9+9//3WsLCkqpqVNKJP6WuIXnC7nf/7nL7q6u+EYOJ9++unvf/97hAdUF+56y5Yt5RVrtjz//Ouvv/7HP/4xISHxb/7m29evX58yzrhdLtg9fTJToVAghb1w4SJ5moOZrkw66p3/aKvNQ3bvBdp2RH9BFSoU0FYQMsQN3gGXy4OKhsVPPwZPAjiGvE1LTQGpjMQh8+K9Xh9OV1FRLpFKNVqNw+lEttPe3gZ1Dd/rdrtg1jdu3BgaGrrPeW83NSFfvXHzumXIwm088VY6AAAXqElEQVRpaUG7l5WV/eM//iMcN+NFx5UFJFx6enr1ieMdHe0Vq1fT2YoTce78+W3btiF4REaTh6OLi1egRWovnNNqQqVSCTokfBJ5gxKZtDQ+pjOphHkLOjRXU1Nz8sQJr9uD1CA7N4fEt3GroW8WGB8teoDrIkPebJYQ8ZyZ0UCPhwy6dvWazWpNTkyETx4dGeVzeQODZr1OH2YwwG1AJQxaBjvaO6IjI2FONLIEyhzvJSxWS2vLjZs3EdETExI5kG3Lli374Q9/iHwGqooEf+bGGPw8jklISNj01MYjhz6tOnbc6fG5vX6Xl9xwcfv89Y3NNZeuCaVyy6jN4XRB9CM+JSfF5+bldXZ1Q5ASUtk8+h/1IYGqzF8wVoHe7WGxnB43EbQut1ypDAkN4XO5zIzO8Vakg6wPfEcEQRT/8TlsMkHa5yWvb/L7mhtu8zmC2KhoLotdnF8QHx2vC9HKxfIrNVfaWzrJ45RsriFU73a49+/fD+ImnZqNPkfeP+K9eukShNTw4GCIUkkyhJycnOCnNwHqBJ599tnYuNj/+q//dnvIA2KwRwgrp8t95dq1lrY2sUSamJT4wgsvqMmD7qR89K3k5OQHdlzzAUzV/TbbGDQUnLBlaCg2NnaW4gt8AFFDPp/d7ujtNSUlxopFYrhRmPbyZblkOEil7usztbW2jY7Y0LwlxSXpaeloXchhKpADRVG12NfXC8ms1WhKS0oRvMljteXl5RPO+DnQQXBV2Ok73/k76CzkiMQjkbXswYFBiLLe3l63k7zaQqGQkzSZ2YReBU8ynecb5jfYDqejt68PbYqrQxjCqtnotdTDo2Eh6DIyUpHIksnXzDPMWm1oZka6SCxG+AedjY1N2F+ukK0uX40/IYxcLtekbgf5DckMGQRJVFRUhJK53/3ud4uLi5lZZJNdDdbgNPhNTEpau3YtehOzkuVyuU+cOnnj+o1QjQZJgkgk7Ovri4uNJRoENDOBgZ54YbjlSWDejoYQ63Q4r1+5giQ4NT2tuKSEMjEbV4TQC6pAiUrFtDB5SIkIGETLkJAQ6ACctLOzy24fQyRWqpTh4cYzZ04PDAxgq8FgoKkXvSP5wQcfIDuHXkbYRUKPOnN/9atfkWT5HgO/9JJwZehZ+APXCP/c3dNz4EAlCoKZlpQUb3zqKSjyK1evhEdEiEUiHjP4PEttMRegH71js9taW2ov1kJh5S7LS0tPH984CxdFtRIdVhpXbPSePIK0gCcRSYeGhxnNNSKTK6IiI3lcriEs7Nq1a7BjcKzVakHtzp07wa7ZbEZHyc/Pp2EXZfFiYmLuZN/TAti+fbvZarPBadNnLPkCQXn56hs3btbU1JaUFCkkU4TzhYjevl4kJ3KFHAkCNYBZ6rLU4d2r8MioyKqjR7EZNN28cSPcGAZPnpWV6XRuef/99//whz9AHQ8ODsIHpKSkuN3uwoJC2C7Jmxl8ARFI9xsZGm5pbg5RqWJx2T6fXqdFKZAJOdlZUPD0tZ8LHfQa7GN2cmlcXlRUNFrpXk7u4REo1u/33r0FYIslosjIiIaGBubFaeSFE1ACcL0FBQVqtfr06dOQ01iJIIucFuYaHR0dmDdCLHi699WZW0xQetve3drU1IReY9Rp4uISIOhRFE0PDaEL/6slTFOTXMjn8zhdEFloNYVSMUnLzBICD5+hM1G3in/5fD+H5+7uaQ0JVXq97uaWVjjzhMRYFosLkwWj1HzlcnnoVO0/3VkT9JRW6+iVy5eh9+ArHHb7q69GeD1ePu+ux78WBxB9kCY4HI6IiIi5YXci6PgJc4+Ldfr0Z9u3v69WhdrtdqlEgdALPxyfAElL9gTZ0FmTj5+ALzAtBrYOw/35z3+Ocxw8ePDkyZOf7Kt84YUXv/71VyMjw4P3X9BAvgGZikuGyJh7grlcLqQ1GK2srNy+fZtQKFAq1YWFKwyGMK/Hl5ObG7CmQOYWWJiELzbvCZcKP4C8GdkzEqSTJ85UVx87d+7sa6+99sQT6+mIOUAjFjD3TfPwoL4ROQIUaUx0TELCzL/U+i8CdYBCpk9IIKYCK1asoO9lcrmcAsHnb2JmQjLB1Lf7pk9w4HjaU0Dzq6++mpaatWPHDtTm3Xe3ob9v2LBBqwtlXntDvtz6SGbNPSQou7AetC8WJFLJI7kKdK9f/vKXjY2NMCS93lhevmb58jzGWvzMbXUfCAnsTMXUhKPvwoPUnvYXXHlRcWFiYrzZPNBv6v9o5876+oYtW57NzcuB5n/gQdpHC1pnn5c8UgVzgTR9JATDfvLy8mQyWVpaelxsYm52DtqbVm18IHX8zsJfxheuPXW/WKDCiiba8fGxEZERVVVV727bVt9Q9/LLL5O9yDunFpiLpmFleGS4vb0d1kxuhD8KggcHLRABRmM4mC4rLeYwL45B7QL51F173xcPQvBE06QP2Ym4Qug6nf7F06fPfLxrv83ufe65TUqVgs3yYTscNp+DzGwBGDQuDbx2dnbS5DI8PHwu/ZDTTfLgUav1D2++LRAKxBJJ/ooivjDAEa0JZXe6tZpBC/PTd+tueOKJPpPpt797o6urm83leMk8F/IW0AUBWDACcF1dHQhGchkbGxt8F3z2gC7lcLmOHKnqN5thOfn5+RpNcGoLar9An5sZggNmLZFINqxfs3JlidPl3PnnP1+9etXnQ0jDtoURjynBYBcpCpwzAhCNR3MDKFOwe7GmBqHhiSeeyMzMmDiH5MEwMwTTeExZlkhFxcUrkDWhuu+9t/3QocP9/Wb4PSqt57K9HgCoXk9PD3l/okSiCSXzZGfbRTM5DmkZr893/MTJ8+cvREZFrVu3NikxnkfC38M214xZ8IS/yGs3i4pWvPzSS6mp6WfOnHv33fcbGpvo6Mw8JxiVvH79+uDgIFR0mDEMOnYOKoxT4Lznz5/ft28fZHt6Wlp2VhaaFMnIvbLb6WM2VC555zKHzYqICH/h+S0lJaUWy8if/vinW7duzXN2AdQQ+pnWEworaPvMA9QODw+D2k8+2RcRHlFSUpK/fBmoDd7zwTDjOQCaBs1DHrWAYUulsjUVq1QK1dXLF3bu/POqVf1lZWXzfHgLMRi/qGRiYiL1n0G7zCQQ7Lfv2MG8Q1WXuwy6ajn5hM/MhYUZJ5jNhV8hN6zH/xZwBStL8wVc1tGjxw4drDIYwlOS0XDY7J+H31N3OBwwKQAZARAQjzMOt5c8iTw0PHzo4KGW9q5wYzjiblpy0oyfbTaMaYo6Ll+eV1xcPDI8snvXnoYGMlsseJ95ArPZ3N/fTwmm2jB4n4cHigW7e/fuu3rtGmLBpmc2JSUlzkZfmiNvyeFwly3L3fDEBoVC+dZbb7e2tgXvMx8AapH4QjxHRETgd/ZUodVq27//QH19g9FozMjI0Ot0sxQK5ohg9E25TFpRUZ6SkowkZNeu3WbzAGMesx7kvhCgdywWi1wuJx+7YzCDioH6LZRptVr37N17+coVOLvkpOSiFSsCbymeccwRwdQlS6WSwsKCl195ZXR09MCByr6+XmYTwaT9HxW6urrI+yrIlFXyrZPgHR4GCOe4UpvNduHiBWTbIqFw09NPl5QW8/hkDv0sBfs5Ipg8Z4uTsVkSiWj5sryi4qKOzo7339/e3d0dvPMjBEQWzFej0cTGxjJPeI7fWZkpjI2NHT9+HM7ZZrUhI1qWlwuayQMDwbvOEObKgslQ13gKBY4LCpYjl+/q7v7tb3/X29s7fyz48uXLqA8cDBQWqGVGG2asiVwu9+EjR2pqank8PqLV2jUVfPrlM4aGWWJizkQWSZzIM8pcMqc8JES1Zm3FqtXlPg73/Q93mi3DyBqYR56CD50LoJXRyejstcjISPhniYTMXwze8wGAjMjt89ud7qPHTx48XDVqd67b8GTF6jKxgMfnsoU8DnnYl/lvNjDXYw50BA4LEol4zZq15eUV7e0dH+/a3WvqZzZP2n1O4XK64Ja9zKdHIbKCd3gw0NB7/mLN0WPHQjXaTZs2FRWtmO0h7gDm+m42DWn0mnk8HuIxdM2FCxccTucrL72o0WqCjph1BJT8mH2MzjSCHaN6M+ec/X19/dXV1TjL2jVk8s2c3oIMXjWroFGNhjc+jyuTy8rLV1dUVJhMfTs++LC9rd1LbiDPaeJEFQDqgyQYEtrtdmMBTAft+MVAB0mA7u7et99+u6+vD+nQihUFPC6Ju8H7zxLmmmAKOgTI3JNghxuNq1evKistczqdH3z4UWtrK67fw7yPL/jA2UDgjRy3b99G58Of0eSjSQ/l2wKvLDIPmCGsICezMjPXb1gn4PMRoXDVQUfMFh4NwRT0JUL4USjkxcVFy5cvHxwc+M1vfnPixAkQPGdRCsC50L3MZjMIViqV9L1iDwPq3iHId+z4oLamNi0t7Utf2jKDcX36eJQzW0EgvBi6s9/HkkulRSsKYUcnqqs+/fSwUIhUKv/h74ZOB9SXDg0N1dfXY1EkEpNP0j1g90J3JQeiwJaW1o8//hiFP/30xvyCfKWSfNSOPef3Vx4lwVwOi3m0afyLnxIhf035Spbfd+jTwx/+eReLy8vNzSVDPCwW0omgo2cMOAXiLswXy3p9mMvpUYeEgmDmNek0PE+zldA/6Qsmec3Nrdve3Y6iYLvr15aP6zXyYO3kY2Ybj9JFBxC4bPxLp+3x+DxorqPV1fDV9ItFsweq+CCCkPs6HciDo7QaQnDwnn8JzFRhPxu2u2vXbrFYlJuX89yWTRPU+CMYdX+UFjw12OziohVIJOrr6/bs3qNSKvOXL5vVfg8u4UjhogGFXB0REf7AaQzYNZsHdu7cOTJiTUpMXreuXPQo4u5EzBeCqcXAApi3CvHz8nLR3DGxsTAFGFZWeioJ1Xdy6MkHPxzALsrs7OyECIK16Q0GxhCna200F8ICU0hP1ZEqk8mck52z6ZmnyTtC7/mJ3TnCvHDRAaAtSGuw2fBvFeWrMzMzoH8+/PCjmpoa+OqHz02nBEi12+0Iww6HQywWa7UaatPBe04JSiD2t1gsH+74qKuruyC/cNOmp5nvipDR96Aj5hTzi2CA+XwyMWWRWLRq5crNzzyDNnpn6zuXLl0K3nmmMDIyAnqY14Tx5F9wJiW14Obm5u3bt3d398bFJTzxxHqFUuHzeZl3qYx/XetRYd7FYNK4zHscYRtikTB/eZ7P66m5cOHAgUqny11YkD/j43x0iAMRAUYcExstk0uxhvmoCs157kX2eEaEow4fPnLp8mWX01VQWFBRUc689BCWzfH5Iap9j9aG5h3BkzIinoC/qqyEIxDv/PPH732wExyvLC1m7p/6ubwZ0y/IkcbGxhAFoqMjmNe2kpX3farA73W72ByOw+nZu++TC5eu8EWSijUbipZlSSUSHE54JR+/m7sx53th/qnoIKC1c7Iz1WrV2dOnDx46JBYKcnOyhCLynpEZAQ2ikHKIxElJSViexvwKYqEer6+qqqrx9m045FWryvPz88SQiIzFP2JlNQELgGBALOQnxceKBQKPy7ntvfecLldJSbFghnwfHPK1a9esVis4DgkJocNnNDkO2vdzeH2sxsbbx44dC4+KTk3PyMvJ5DOfWpwlqf/AmHcia0pw/SykGzFR4evWrlGHav709taDhw67XC5sCmQpdPmuw+6LgE7u7u5ubGwUiUTx8fF0UOI+5ZCHiJgnrNo7u/cdqOTyhQa9vqy4SCISks+/k8d2CJYs+IuBw/FzyDgROzYm+oWXXjpy5Ojho9X9pr5NT29Uq9WUFbTphDGjaYF2DpPJBKGkUChiYmLoTaT70EM33bx5649bt2G5sKBw/dpymUTkg/pnhFXQEY8YC4NgZliYMIh/U5KTuTxB5aHDN2/dunnj+rPPPltcXExv+f1FvzoRgT1BMJwB/tTpdPfvIvQUXV1db731lliuBrvlq0rEIrALSUW+YjIPPeKCcNH09XnUAZLxrISEuFe/9lfr161TqdQffvjhiRMnEJXJHl9kUIH2Bp/XZ+ozoWybzYbSgndjEAgBrL4+0/4DlQKhsKioqLxipZj5Zif5jhkz+nX3UfMCC8KCyXQ9OsaFf8R8IoLEKtnaijWaEF3lwco/79ztdHrXVJRTO8ZWhEk66XVSQRPhgzv1sRxjzrprdT6P32CIUGt147ntXUAyi3QWCxyHw7Xjo10mkzkrc/nqokIpn0dUFUqCnXDmaUsuDBc9RbMTsMk3UVmsA5WVB/YfEAoExSVFPB6XTJmYRjCmXPb09Po8PmNYuFgi4fOmTFvJS9A9PjLJZP/+A21trQaDcXn+MqlURH32/NFTU2KhEDw1+HxeTm6WWCKurj5+/PgJpDpr1paLROS9vME7BwPCqKe7BwrL7/MhlAqFgjvDU5N2Y3u9vs9OnTp8+HBkVMzmzZuio8PpO52xdYng2QIslVE37KSkRLRzZWXl2XPn+s29W7ZskcvlaHeAeux7cQCjJB+eNJu8zOuCJk0godaJX5fLc+r06e07dkRFRb/yyosx0TE06M5zaikWRh48JdC85Ivl5Asi7MSE+C1bnouJiTb3m998800I3YCovicNfr/D6XST97QqBAKBVqedOMpN71zh1+VyHzp0ZN/eT/R64/Nfeh6pFHH/zCdXPi9qHmMBExwArJTL44QZjU9v3JiQmDg2NvbRRx/RKTjM1qnFLRgaHRnp7CRfXpfL5CqlknfnXZsAtWZ4iOMnThw6eFguV73w/AtwFehRfpaXxZ6/zzdPwqIgmEyGYgn4HL1eV7GmorCw0DI0tH3H9tY2MgM3eH8KhFWP19vc0ux0OSUyCQL5xDzHx6gqxPUDBw4YwvQvvfRCeloKBBy500XC74LBQiYYPpL5j7yNhsd8y4LLlsrlRaWlpatWmswDv33j95+dPWO1231eMghBhxh9PvxCFLsRXhtuNwjkQjvLJQuVxyfFoRzmc0k+p8fv8vrOX7x05NhxqVzxlVeez0pPFpIZzSweh80jMWHBaJfFYMETgXSZL+CXlpQ9t+W5kBD1nr17d+/ZA6cNiyQDYXRwA/buZ3nc7traGpvVahmyJCYkhqiZz+ZjBw40s+fkqc8OV1XhqGc2b45PiKcBd2FE3bux2Aj2s3ywZ6Q8WZlZT298Wq/Xd3d3VVUdRS6ErVQZ4RcUmvtNA6Z+AY8Hy+zt7j57+rO+nh5IKhTR1dV97Fg1wvDGp5/KyswgbmKBSKpgzPADzo8cXvo1XfLxRT+suae3+5NP9jfebFyxovDJpzZIpRKnw97W3nriRPW1q3XNzc0ymVSj0fB4PIVCCdPXGsLlCkVHRwc2Pf/88yvLSpFq88fzsXEHMPmU8xuLjWDmO+h0AaZMKOkz9e76cPfg4GB0TERWVubJk8dPfXZyeHhIrwmTSKRIs7zMx91VKpVQJLI6XHaHQyqVQpCXlpUKBQIEXjIguWCxaAmmX1Rm5t+w+7pMR48e7epuHxggL0ni8UicFvHIB76lUpnL5bKPjUEa5+Rk95iHek19Tz7x5Jq15UiO0TZslh8WPOksCwiLkODA9dDPopM7AV6f1WqrvVRLPgDY2NDX1yORiN0OckNCr9PBXtEGFsugRCodc3tTUlM3P7NJLpeRUUvGI8+/97V9ASzssehg3G1sNJFi+bkcuUJaWJiv0YRcvXrVarVLJHJkOk632+X1cN0uCGyb08ER8KMjIzc9tUEuFYPUhSusJmKxWfC9EJigc/Pmzd27d5tMJogmPp+P9R7mAzajo6ObN29eu3ZtSAiTLzFT7z4/fsFisaVJUwIU0nlS+E1JSdmwYQN4Rc+WSMhHVbAApmNjY8vKytTqe93zX6hYbC56SgSe4acjzEKhELIZZFutVqwfGRlBGF63fj19LJgiqIyFisfFRVME7hGdPXu2vb0dnrmhoSEyMjIjI6OwsBAGvZiopXi8CMbFAoEXaMCme3p6EHRhwXSHxRF3J+KxIxjxmHrsgLGCZkRi/C4y50zxeBH8GOKxUNGPM5YIXuRYIniRY4ngRY4lghc5lghe5FgieJFjieBFjiWCFzmWCF7kWCJ4kWOJ4EWOJYIXOZYIXuRYIniRY4ngRQ0W6/8DJqqWL+oHLu0AAAAASUVORK5CYII=",
1143
- })
1144
- .on("click", function() {
1145
- window.open("http://hedonometer.org", "_blank");
1146
- });
1147
- }
1148
-
1149
- var xAxis;
1150
- var distgroup;
1151
- var my_shift_id = "shiftsvg";
1152
- var _my_shift_id = function(_) {
1153
- var that = this;
1154
- if (!arguments.length) return my_shift_id;
1155
- my_shift_id = _;
1156
- return that;
1157
- }
1158
-
1159
- var word_paragraph = function(i) {
1160
- var this_type = sortedType[i];
1161
- return "The word \"" +
1162
- (sortedWordsRaw[i]) +
1163
- "\", shown as \"" +
1164
- (sortedWords[i]) +
1165
- "\", is a " +
1166
- (((this_type == 1) || (this_type == 3)) ? "more happy word (+)" : "less happy word (-)") +
1167
- " than the reference average, and was used " +
1168
- ((this_type > 1) ? "more frequently (\u2191)" : "less frequently (\u2193)") +
1169
- " in the comparion, bringing the comparison happiness " +
1170
- (((this_type == 0) || (this_type == 2)) ? "up" : "down") +
1171
- " by " +
1172
- (Math.abs(sortedMag[i] / (Math.abs(refH - compH))).toFixed(2)) +
1173
- "%.";
1174
- }
1175
-
1176
- var word_list = function(i) {
1177
- var this_type = sortedType[i];
1178
- var sign = ((this_type == 1) || (this_type == 3)) ? "+" : "-";
1179
- var morelesshappy = ((this_type == 1) || (this_type == 3)) ? "more" : "less";;
1180
- var frequency = (this_type > 1) ? "\u2191" : "\u2193";
1181
- var morelessfreq = (this_type > 1) ? "more" : "less";
1182
- var updown = (sortedMag[i] > 0) ? "up" : "down";
1183
- var risefall = (sortedMag[i] > 0) ? "rise" : "fall";
1184
- var leftright = (sortedMag[i] > 0) ? "right" : "left";
1185
- var index = my_shifter.get_word_index(sortedWordsRaw[i]);
1186
- return "The word \"" +
1187
- (sortedWordsRaw[i]) +
1188
- "\" is shown as \"" +
1189
- (sortedWords[i]) +
1190
- "\". Let's break that down: <br>" +
1191
- "<ul>" +
1192
- // "<li>The "+sign+" means "+sortedWordsRaw[i]+" is a "+morelesshappy+" happy word ($h_{\\textrm{avg}} {("+sortedWordsRaw[i]+")}=$"+lens[index].toFixed(2)+")"+
1193
- "<li>The " + sign + " means " + sortedWordsRaw[i] + " is a " + morelesshappy + " happy word" +
1194
- " than the reference average ($h_{\\textrm{avg}} {(\\textrm{" + sortedWordsRaw[i] + "})}=" + lens[index].toFixed(2) + "$ and $h^{\\textrm{(ref)}}_{\\textrm{avg}}=" + refH.toFixed(2) + "$).</li><li>The " +
1195
- ((this_type > 1) ? "\u2191 means used more" : "\u2193 means used less") +
1196
- " frequently in the comparison text than reference text (" + commaSeparateNumber(compF[index]) + " times to " + commaSeparateNumber(refF[index]) + " times, such that " +
1197
- "$p_\\textrm{" + sortedWordsRaw[i] + "}^{\\textrm{(comp)}} = " + (compF[index] / d3.sum(compF)).toFixed(3) + "$ and " + "$p_\\textrm{" + sortedWordsRaw[i] + "}^{\\textrm{(ref)}}=" + (refF[index] / d3.sum(refF)).toFixed(3) + "$" +
1198
- ").</li><li>Together" +
1199
- // ((this_type > 1) ? " (more" : " (less")+
1200
- // ", "+
1201
- // (((this_type == 1) || (this_type == 3)) ? "positive) " : "negative) ")+
1202
- " this brings the comparison happiness <strong>" +
1203
- ((sortedMag[i] > 0) ? "up" : "down") +
1204
- "</strong> by " +
1205
- (Math.abs(sortedMag[i])).toFixed(3) +
1206
- ", or " +
1207
- (Math.abs(sortedMag[i] / (refH - compH)).toFixed(2)) +
1208
- "%. We can see this as the individual term in the shift equations' sum: " +
1209
- ' $$\\underbrace{' +
1210
- ' \\left[' +
1211
- ' h_{\\textrm{avg}} {(\\textrm{' + sortedWordsRaw[i] + '})} – h^{\\textrm{(ref)}}_{\\textrm{avg}}' +
1212
- ' \\right]' +
1213
- ' }_{' + sign + '}' +
1214
- ' \\underbrace{' +
1215
- ' \\left[' +
1216
- ' p_\\textrm{' + sortedWordsRaw[i] + '}^{\\textrm{(comp)}} – p_\\textrm{' + sortedWordsRaw[i] + '}^{\\textrm{(ref)}}' +
1217
- ' \\right]' +
1218
- ' }_{\\' + updown + 'arrow}.$$' +
1219
- "</li></ul>" +
1220
- (((this_type == 1) || (this_type == 3)) ? "Positive, " : "Negative, ") +
1221
- ((this_type > 1) ? " more frequent (" : " less frequent (") +
1222
- sign + frequency +
1223
- ") words " +
1224
- " will always be on the " +
1225
- leftright +
1226
- " contributing to a " +
1227
- risefall +
1228
- " in happiness.";
1229
- }
1230
-
1231
- var wordshift_tour = function() {
1232
- // function wordshift_tour() {
1233
- // Instance the tour
1234
- console.log("launching the tour");
1235
- var tour = new Tour({
1236
- steps: [{
1237
- element: "#shiftsvg",
1238
- title: "A quick wordshift whats-what",
1239
- placement: "auto left",
1240
- onShown: function() {
1241
- console.log("first element shown");
1242
- MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
1243
- },
1244
- // content: MathJax.HTML.Element("div",null,['We generate the wordshift from this equation: $$h^{\\textrm{(comp)}}_{\\textrm{avg}} – h^{\\textrm{(ref)}}_{\\textrm{avg}} = $$'])
1245
- // content: "We generate the wordshift from this equation: $$h^{\\textrm{(comp)}}_{\\textrm{avg}} – h^{\\textrm{(ref)}}_{\\textrm{avg}} = $$"
1246
-
1247
- content: "Let’s say we have two texts which we call ‘reference’, ${T}^\\textrm{(ref)}$, and ‘comparison’, ${T}^\\textrm{(comp)}$. We want to know why the happiness of the comparison text, $h^{\\textrm{(comp)}}_{\\textrm{avg}}$, is higher or lower than that of the reference text $h^{\\textrm{(ref)}}_{\\textrm{avg}}$." +
1248
- "<br>To do this, we analyze how each word $w$ which contributes to the difference in average happiness between the two texts:" +
1249
- ' $$h^{\\textrm{(comp)}}_{\\textrm{avg}} – h^{\\textrm{(ref)}}_{\\textrm{avg}} = ' +
1250
- ' \\sum_{w \\in L}' +
1251
- ' \\underbrace{' +
1252
- ' \\left[' +
1253
- ' h_{\\textrm{avg}} {(w)} – h^{\\textrm{(ref)}}_{\\textrm{avg}}' +
1254
- ' \\right]' +
1255
- ' }_{+/-}' +
1256
- ' \\underbrace{' +
1257
- ' \\left[' +
1258
- ' p_w^{\\textrm{(comp)}} – p_w^{\\textrm{(ref)}}' +
1259
- ' \\right]' +
1260
- ' }_{\\uparrow/\\downarrow}.$$' +
1261
- 'Next let\'s take a look at how the top three words contribute.'
1262
- },
1263
- {
1264
- element: "#shiftrect0",
1265
- // title: "Word with the greatest individual contribution",
1266
- content: word_list(0),
1267
- placement: "auto left",
1268
- onShown: function() {
1269
- console.log("first element shown");
1270
- MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
1271
- },
1272
- },
1273
- {
1274
- element: "#shiftrect1",
1275
- // title: "Second word",
1276
- content: word_list(1),
1277
- placement: "auto left",
1278
- onShown: function() {
1279
- console.log("first element shown");
1280
- MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
1281
- },
1282
- },
1283
- {
1284
- element: "#shiftrect2",
1285
- // title: "Third word",
1286
- content: word_list(2),
1287
- placement: "auto left",
1288
- onShown: function() {
1289
- console.log("first element shown");
1290
- MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
1291
- },
1292
- },
1293
- {
1294
- element: "#sumTextR0",
1295
- // title: "Third word",
1296
- content: "At the top, we see the relative contributions from each of the four words types, and the total (the grey bar). This particular bar, $\\sum +\\uparrow$, shows the relative contribution to the shift in happiness from positive words that increased in frequency. <br><br>Try clicking this bar to see only those word types. To reset the view, click the grey $\\sum$ bar.<br><br>And that's all for now, we hope this quick what's-what was helpful!",
1297
- placement: "auto left",
1298
- onShown: function() {
1299
- MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
1300
- },
1301
- }
1302
- ]
1303
- });
1304
-
1305
- // Initialize the tour
1306
- tour.init();
1307
-
1308
- // Start the tour
1309
- // force it, since it's an option
1310
- tour.restart();
1311
- tour.start(true);
1312
- }
1313
-
1314
- var add_help_button = function() {
1315
- // this requires bootstrap for stying
1316
- // it requires fontawesome for the icon
1317
- // requires bootstrap, bootstrap-tour for the tour
1318
- // and it requires mathjax for the equations
1319
- figure.append("a")
1320
- .attr({
1321
- "class": "btn btn-large btn-default"
1322
- })
1323
- .style({
1324
- "position": "absolute",
1325
- // this position starts from the padding on the left
1326
- // so inside a bootstrap col, this is 15px too far left
1327
- "left": function() {
1328
- return (fullwidth - 34) + "px";
1329
- },
1330
- })
1331
- .on("click", function() {
1332
- wordshift_tour();
1333
- })
1334
- .append("i")
1335
- .attr({
1336
- "class": "fa fa-question"
1337
- });
1338
-
1339
- // <a class="btn btn-large btn-default" style= onclick="wordshift_tour();"><i class="fa fa-question" aria-hidden="true"></i></a>
1340
- }
1341
-
1342
-
1343
- var plot = function() {
1344
- var that = this;
1345
- /* plot the shift
1346
-
1347
- -take a d3 selection, and draw the shift SVG on it
1348
- -requires sorted vectors of the shift magnitude, type and word
1349
- for each word
1350
-
1351
- */
1352
- // console.log("plotting shift");
1353
-
1354
- // first things first, plot the text on top
1355
- // if there wasn't any text passed, make it
1356
- if (comparisonText[0].length < 1) {
1357
- if (compH >= refH) {
1358
- var happysad = "happier";
1359
- } else {
1360
- var happysad = "less happy";
1361
- }
1362
-
1363
- // console.log("generating text for wordshift");
1364
- comparisonText = splitstring(["Reference happiness: " + refH.toFixed(2), "Comparison happiness: " + compH.toFixed(2), "Why comparison is " + happysad + " than reference:"], boxwidth - 10 - logowidth);
1365
-
1366
- // console.log(comparisonText);
1367
- } else {
1368
- if (split_top_strings) {
1369
- comparisonText = splitstring(comparisonText, boxwidth - 10 - logowidth);
1370
- }
1371
- // console.log(comparisonText);
1372
- }
1373
-
1374
- // this would put the text above the svg, in the figure div
1375
- // figure.selectAll("p")
1376
- // .remove();
1377
- // figure.selectAll("p")
1378
- // .data(comparisonText)
1379
- // .enter()
1380
- // .insert("p","svg")
1381
- // .attr("class","shifttitle")
1382
- // .html(function(d) { return d; });
1383
-
1384
- // made a new svg
1385
- figure.selectAll("svg").remove();
1386
- canvas = figure.append("svg")
1387
- .attr("id", my_shift_id)
1388
- .attr("width", function() {
1389
- return boxwidth;
1390
- })
1391
- .attr("height", function() {
1392
- return boxheight;
1393
- });
1394
-
1395
- // this one will be white, and behind EVERYTHING
1396
- bgbgrect = canvas.append("rect")
1397
- .attr("x", 0)
1398
- .attr("y", 0)
1399
- .attr("width", boxwidth)
1400
- .attr("height", boxheight)
1401
- .attr("class", "bgbg")
1402
- .attr("fill", bgcolor);
1403
-
1404
- toptextheight = comparisonText.length * 17 + 13;
1405
- // console.log(toptextheight);
1406
-
1407
- // reset this
1408
- figheight = boxheight - axeslabelmargin.top - axeslabelmargin.bottom - toptextheight;
1409
- // console.log(figheight);
1410
- // console.log(yHeight);
1411
-
1412
- // take the longest of the top five words
1413
- // console.log("appending to sorted words");
1414
- // console.log(sortedWords);
1415
-
1416
- maxWidth = d3.max(sortedWords.slice(0, 7).map(function(d) {
1417
- return d.width(wordfontsize + "px " + fontString);
1418
- }));
1419
-
1420
- // a little extra padding for the words
1421
- var xpadding = 10;
1422
- // linear scale function
1423
- x = d3.scale.linear()
1424
- .domain([-Math.abs(sortedMag[0]), Math.abs(sortedMag[0])])
1425
- .range([maxWidth + xpadding, figwidth - maxWidth - xpadding]);
1426
-
1427
- // linear scale function
1428
- y = d3.scale.linear()
1429
- .domain([numWords + 1, 1])
1430
- .range([figheight + 2, yHeight]);
1431
-
1432
- // zoom object for the axes
1433
- zoom = d3.behavior.zoom()
1434
- .y(y) // pass linear scale function
1435
- // .translate([10,10])
1436
- .scaleExtent([1, 1])
1437
- .on("zoom", zoomed);
1438
-
1439
- // drag = d3.behavior.drag()
1440
- // // .y(y) // pass linear scale function
1441
- // // .translate([10,10])
1442
- // // .scaleExtent([1,1])
1443
- // .on("drag",zoomed);
1444
-
1445
- // create the axes themselves
1446
- axes = canvas
1447
- // not using the "svg inside svg" approach again
1448
- // .append("svg")
1449
- // .attr("width", figwidth)
1450
- // .attr("height", figheight)
1451
- // .attr("class", "shiftcanvas")
1452
- .append("g")
1453
- .attr("transform", "translate(" + (axeslabelmargin.left) + "," + (axeslabelmargin.top + toptextheight) + ")")
1454
- .attr("width", figwidth)
1455
- .attr("height", figheight)
1456
- .attr("class", "main");
1457
-
1458
- axes.call(zoom);
1459
- // axes.call(drag);
1460
-
1461
- // don't need these
1462
- axes.on("wheel.zoom", null);
1463
- axes.on("mousewheel.zoom", null);
1464
- // can re-register them...
1465
- // axes.on("wheel",function(d) { console.log(d3.event); });
1466
- // axes.on("mousewheel",function(d) { console.log(d3.event); });
1467
- // now use them to translate (instead of zoom)
1468
- axes.on("wheel", function(d) {
1469
- d3.event.preventDefault();
1470
- zoom.translate([0, zoom.translate()[1] + d3.event.wheelDeltaY / 2]);
1471
- zoom.event(axes);
1472
- });
1473
- axes.on("mousewheel", function(d) {
1474
- d3.event.preventDefault();
1475
- zoom.translate([0, zoom.translate()[1] + d3.event.wheelDeltaY / 2]);
1476
- zoom.event(axes);
1477
- });
1478
-
1479
- // create the axes background
1480
- bgrect = axes.append("rect")
1481
- .attr({
1482
- "x": 0,
1483
- "y": 1,
1484
- "width": figwidth - 2,
1485
- "height": figheight - 2,
1486
- "class": "bg",
1487
- })
1488
- .style({
1489
- "stroke-width": "0.5",
1490
- "stroke": "rgb(0,0,0)",
1491
- "fill": bgcolor,
1492
- "opacity": ".96"
1493
- });
1494
-
1495
- if (show_x_axis_bool) {
1496
- // axes creation functions
1497
- var create_xAxis = function() {
1498
- return d3.svg.axis()
1499
- .ticks(4)
1500
- .scale(x)
1501
- .orient("bottom");
1502
- }
1503
-
1504
- xAxis = create_xAxis()
1505
- .innerTickSize(3)
1506
- .outerTickSize(0);
1507
-
1508
- canvas.append("g")
1509
- .attr("class", "x axis ")
1510
- .attr("font-size", xaxisfontsize)
1511
- .attr("transform", "translate(" + (axeslabelmargin.left) + "," + (yHeight + figheight) + ")")
1512
- // .attr("transform", "translate(0," + (figheight) + ")")
1513
- .call(xAxis);
1514
-
1515
- canvas.selectAll(".tick line").style({
1516
- "stroke": "black"
1517
- });
1518
- }
1519
-
1520
-
1521
- // figure.selectAll("p.sumtext.ref")
1522
- // .data([refH,])
1523
- // .html(function(d,i) {
1524
- // if (i===0) {
1525
- // return "Reference: happiness " + (d.toFixed(3));
1526
- // }
1527
- // });
1528
-
1529
- // figure.selectAll("p.sumtext.comp")
1530
- // .data([compH,])
1531
- // .html(function(d,i) {
1532
- // if (i===0) {
1533
- // return "Comparison: happiness " + (d.toFixed(3));
1534
- // }
1535
- // });
1536
-
1537
- // addthis_share.passthrough.twitter.text = "Why "+allData[shiftComp].name+" was "+happysad+" than "+allData[shiftRef].name+" in "+timeseldecoder().cached;
1538
-
1539
- // addthis_share.title = "Why "+allData[shiftComp].name+" was "+happysad+" than "+allData[shiftRef].name+" in "+timeseldecoder().cached;
1540
-
1541
- // addthis_share.url = document.URL;
1542
-
1543
- // d3.select("[id=fbtitle]").attr("content","Hedonometer Maps: Andy has been here");
1544
-
1545
- typeClass = ["negdown", "posdown", "negup", "posup"];
1546
-
1547
- var colorClass = ["#b3b3ff", "#ffffb3", "#4c4cff", "#ffff4c", "#272727"];
1548
-
1549
- shiftrects = axes.selectAll("rect.shiftrect")
1550
- .data(sortedMag)
1551
- .enter()
1552
- .append("rect")
1553
- .attr({
1554
- "class": function(d, i) {
1555
- return "shiftrect " + intStr0[sortedType[i]] + " " + typeClass[sortedType[i]];
1556
- },
1557
- // "x": function(d,i) {
1558
- // if (d>0) { return figcenter; }
1559
- // else { return x(d)}
1560
- // },
1561
- // "y": function(d,i) { return y(i+1); },
1562
- "id": function(d, i) {
1563
- return "shiftrect" + i;
1564
- },
1565
- "x": 0,
1566
- "y": 0,
1567
- "transform": function(d, i) {
1568
- if (d > 0) {
1569
- return "translate(" + figcenter + "," + y(i + 1) + ")";
1570
- } else {
1571
- return "translate(" + x(d) + "," + y(i + 1) + ")";
1572
- }
1573
- },
1574
- "height": function(d, i) {
1575
- return iBarH;
1576
- },
1577
- "width": function(d, i) {
1578
- if ((d) > 0) {
1579
- return x(d) - x(0);
1580
- } else {
1581
- return x(0) - x(d);
1582
- }
1583
- },
1584
- "opacity": "0.7",
1585
- "stroke-width": "1",
1586
- "stroke": "rgb(0,0,0)",
1587
- "fill": function(d, i) {
1588
- return colorClass[sortedType[i]];
1589
- },
1590
- });
1591
- // .on("mouseover", function(d){
1592
- // var rectSelection = d3.select(this).style({opacity:"1.0"});
1593
- // })
1594
- // .on("mouseout", function(d){
1595
- // var rectSelection = d3.select(this).style({opacity:"0.7"});
1596
- // });
1597
-
1598
-
1599
- shifttext = axes.selectAll("text.shifttext")
1600
- .data(sortedMag)
1601
- .enter()
1602
- .append("text")
1603
- .attr({
1604
- "class": function(d, i) {
1605
- return "shifttext " + intStr0[sortedType[i]];
1606
- },
1607
- "x": 0,
1608
- "y": 0,
1609
- "transform": function(d, i) {
1610
- if (d > 0) {
1611
- return "translate(" + (x(d) + 2) + "," + (y(i + 1) + iBarH) + ")";
1612
- } else {
1613
- return "translate(" + (x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1614
- }
1615
- },
1616
- })
1617
- // .attr("x",function(d,i) { if (d>0) {return x(d)+2;} else {return x(d)-2; } } )
1618
- // .attr("y",function(d,i) { return y(i+1)+iBarH; } )
1619
- .style({
1620
- "text-anchor": function(d, i) {
1621
- return ((d < 0) ? "end" : "start");
1622
- },
1623
- "font-size": wordfontsize
1624
- })
1625
- .text(function(d, i) {
1626
- return sortedWords[i];
1627
- });
1628
-
1629
- if (translate) {
1630
- // it is one longer than the words, the last entry being what
1631
- // everything will be set to on "translate all"
1632
- flipVector = Array(sortedWords.length + 1);
1633
- for (var i = 0; i < flipVector.length; i++) {
1634
- flipVector[i] = 0;
1635
- }
1636
- flipVector[flipVector.length - 1] = 1;
1637
- shifttext.on("click", function(d, i) {
1638
- // goal is to toggle translation
1639
- // need translation vector
1640
- //console.log(flipVector[i]);
1641
- if (flipVector[i]) {
1642
- d3.select(this).text(sortedWords[i]);
1643
- flipVector[i] = 0;
1644
- } else {
1645
- d3.select(this).text(sortedWordsEn[i]);
1646
- flipVector[i] = 1;
1647
- }
1648
- });
1649
- }
1650
-
1651
- // check if there is a word selection to apply
1652
- if (shiftseldecoder().current === "posup") {
1653
- shiftTypeSelect = true;
1654
- shiftType = 3;
1655
- resetButton(true);
1656
- // ((d>0) ? 500 : -500)
1657
- // ((d>0) ? figcenter : x(d))
1658
- axes.selectAll("rect.shiftrect.zero").attr("transform", function(d, i) {
1659
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1660
- });
1661
- axes.selectAll("text.shifttext.zero").attr("transform", function(d, i) {
1662
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1663
- });
1664
- axes.selectAll("rect.shiftrect.one").attr("transform", function(d, i) {
1665
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1666
- });
1667
- axes.selectAll("text.shifttext.one").attr("transform", function(d, i) {
1668
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1669
- });
1670
- axes.selectAll("rect.shiftrect.two").attr("transform", function(d, i) {
1671
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1672
- });
1673
- axes.selectAll("text.shifttext.two").attr("transform", function(d, i) {
1674
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1675
- });
1676
- // .attr("transform","translate(0,"+y(i+1)+")");
1677
- // .attr("transform",function(d,i) { return "translate("+((d>0) ? figcenter : x(d))+","+y(i+1)+")"; });
1678
- axes.selectAll("rect.shiftrect.three").attr("transform", function(d, i) {
1679
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
1680
- });
1681
- axes.selectAll("text.shifttext.three").attr("transform", function(d, i) {
1682
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1683
- });
1684
- } else if (shiftseldecoder().current === "negdown") {
1685
- shiftTypeSelect = true;
1686
- shiftType = 0;
1687
- resetButton(true);
1688
- axes.selectAll("rect.shiftrect.zero").attr("transform", function(d, i) {
1689
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
1690
- });
1691
- axes.selectAll("text.shifttext.zero").attr("transform", function(d, i) {
1692
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1693
- });
1694
- axes.selectAll("rect.shiftrect.one").attr("transform", function(d, i) {
1695
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1696
- });
1697
- axes.selectAll("text.shifttext.one").attr("transform", function(d, i) {
1698
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1699
- });
1700
- axes.selectAll("rect.shiftrect.two").attr("transform", function(d, i) {
1701
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1702
- });
1703
- axes.selectAll("text.shifttext.two").attr("transform", function(d, i) {
1704
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1705
- });
1706
- axes.selectAll("rect.shiftrect.three").attr("transform", function(d, i) {
1707
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1708
- });
1709
- axes.selectAll("text.shifttext.three").attr("transform", function(d, i) {
1710
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1711
- });
1712
- } else if (shiftseldecoder().current === "posdown") {
1713
- shiftTypeSelect = true;
1714
- shiftType = 1;
1715
- resetButton(true);
1716
- axes.selectAll("rect.shiftrect.zero").attr("transform", function(d, i) {
1717
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1718
- });
1719
- axes.selectAll("text.shifttext.zero").attr("transform", function(d, i) {
1720
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1721
- });
1722
- axes.selectAll("rect.shiftrect.three").attr("transform", function(d, i) {
1723
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1724
- });
1725
- axes.selectAll("text.shifttext.three").attr("transform", function(d, i) {
1726
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1727
- });
1728
- axes.selectAll("rect.shiftrect.two").attr("transform", function(d, i) {
1729
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1730
- });
1731
- axes.selectAll("text.shifttext.two").attr("transform", function(d, i) {
1732
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1733
- });
1734
- axes.selectAll("rect.shiftrect.one").attr("transform", function(d, i) {
1735
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
1736
- });
1737
- axes.selectAll("text.shifttext.one").attr("transform", function(d, i) {
1738
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1739
- });
1740
- } else if (shiftseldecoder().current === "negup") {
1741
- shiftTypeSelect = true;
1742
- shiftType = 2;
1743
- resetButton(true);
1744
- axes.selectAll("rect.shiftrect.zero").attr("transform", function(d, i) {
1745
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1746
- });
1747
- axes.selectAll("text.shifttext.zero").attr("transform", function(d, i) {
1748
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1749
- });
1750
- axes.selectAll("rect.shiftrect.one").attr("transform", function(d, i) {
1751
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1752
- });
1753
- axes.selectAll("text.shifttext.one").attr("transform", function(d, i) {
1754
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1755
- });
1756
- axes.selectAll("rect.shiftrect.two").attr("transform", function(d, i) {
1757
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
1758
- });
1759
- axes.selectAll("text.shifttext.two").attr("transform", function(d, i) {
1760
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1761
- });
1762
- axes.selectAll("rect.shiftrect.three").attr("transform", function(d, i) {
1763
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1764
- });
1765
- axes.selectAll("text.shifttext.three").attr("transform", function(d, i) {
1766
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1767
- });
1768
- }
1769
-
1770
- // draw a white rectangle to hide the shift bars behind the summary shifts
1771
- // move x,y to 3 and width to -6 to give the bg a little space
1772
- topbgrect = axes.append("rect").attr("x", 3).attr("y", 3).attr("class", "topbgrect").attr("width", figwidth - axeslabelmargin.left - 5).attr("height", 73 - 13).attr("fill", bgcolor).style({
1773
- "opacity": "1.0"
1774
- });
1775
-
1776
- topbgrect2 = canvas.append("rect").attr("x", 0).attr("y", 0).attr("class", "topbgrect").attr("width", boxwidth).attr("height", toptextheight).attr("fill", bgcolor).style({
1777
- "opacity": "1.0"
1778
- });
1779
-
1780
- // draw the text on top of this rect
1781
- toptext = canvas.selectAll("text.titletext")
1782
- .data(comparisonText)
1783
- .enter()
1784
- .append("text")
1785
- .attr("y", function(d, i) {
1786
- return (i + 1) * 17;
1787
- })
1788
- .attr("x", 3)
1789
- .attr("class", function(d, i) {
1790
- return "titletext " + intStr[i];
1791
- })
1792
- .style({ // "font-family": "Helvetica Neue",
1793
- "font-size": function(d, i) {
1794
- return topFontSizeArray[i];
1795
- },
1796
- "line-height": "1.42857143",
1797
- "color": function(d, i) {
1798
- return colorArray[i];
1799
- },
1800
- // if there are 4 items...make the first two bold
1801
- "font-weight": function(d, i) {
1802
- // using this variable numBoldLines
1803
- if (i < numBoldLines) {
1804
- return "bold";
1805
- } else {
1806
- return "normal";
1807
- }
1808
- // if (comparisonText.length > 3) {
1809
- // if (i < (comparisonText.length - 2) ) {
1810
- // return "bold";
1811
- // }
1812
- // else {
1813
- // return "normal";
1814
- // }
1815
- // }
1816
- // else {
1817
- // return "normal";
1818
- // }
1819
- },
1820
- })
1821
- .text(function(d, i) {
1822
- return d;
1823
- });
1824
-
1825
- bottombgrect = axes.append("rect")
1826
- .attr("x", 3)
1827
- .attr("y", fullheight - axeslabelmargin.bottom - toptextheight)
1828
- .attr("width", figwidth - 2)
1829
- .attr("height", axeslabelmargin.bottom)
1830
- .attr("fill", bgcolor)
1831
- .style({
1832
- "opacity": "1.0"
1833
- });
1834
-
1835
- // draw the summary things
1836
- sepline = axes.append("line")
1837
- .attr({
1838
- "x1": 0,
1839
- "x2": figwidth - 2,
1840
- "y1": barHeight,
1841
- "y2": barHeight,
1842
- })
1843
- .style({
1844
- "stroke-width": "1",
1845
- "stroke": "black",
1846
- });
1847
-
1848
- maxShiftSum = Math.max(Math.abs(sumTypes[1]), Math.abs(sumTypes[2]), sumTypes[0], sumTypes[3], d3.sum(sumTypes));
1849
-
1850
- topScale = d3.scale.linear()
1851
- .domain([-maxShiftSum, maxShiftSum])
1852
- // .range([figwidth*.12,figwidth*.88]);
1853
- .range([sumTextWidth, figwidth - sumTextWidth]);
1854
-
1855
- // define the RHS summary bars so I can add if needed
1856
- // summaryArray = [sumTypes[3],sumTypes[0],sumTypes[3]+sumTypes[1],d3.sum(sumTypes)];
1857
- summaryArray = [sumTypes[3], sumTypes[0], d3.sum(sumTypes)];
1858
-
1859
- typeClass = ["posup", "negdown", "sumgrey"];
1860
- colorClass = ["#ffff4c", "#b3b3ff", "#272727"];
1861
-
1862
- axes.selectAll(".sumrectR")
1863
- .data(summaryArray)
1864
- .enter()
1865
- .append("rect")
1866
- .attr({
1867
- "class": function(d, i) {
1868
- return "sumrectR " + intStr0[i] + " " + typeClass[i];
1869
- },
1870
- "x": function(d, i) {
1871
- if (d > 0) {
1872
- return figcenter;
1873
- } else {
1874
- return topScale(d);
1875
- }
1876
- },
1877
- "y": function(d, i) {
1878
- if (i < 3) {
1879
- return i * 17 + 7;
1880
- } else {
1881
- return i * 17 + 7 - 2;
1882
- }
1883
- },
1884
- "height": function(d, i) {
1885
- return 14;
1886
- },
1887
- "width": function(d, i) {
1888
- if (d > 0) {
1889
- return topScale(d) - figcenter;
1890
- } else {
1891
- return figcenter - topScale(d);
1892
- }
1893
- },
1894
- "fill": function(d, i) {
1895
- return colorClass[i];
1896
- },
1897
- })
1898
- .style({
1899
- "opacity": function(d, i) {
1900
- var specificType = [3, 0, -1];
1901
- if ((shiftTypeSelect) && (shiftType !== specificType[i])) {
1902
- return "0.14";
1903
- } else {
1904
- return "0.7";
1905
- }
1906
- },
1907
- "stroke-width": "1",
1908
- "stroke": "rgb(0,0,0)",
1909
- })
1910
- .on("mouseover", function(d, i) {
1911
- var specificType = [3, 0, -1];
1912
- // if we're in a shift selection
1913
- if (shiftTypeSelect) {
1914
- if (shiftType === specificType[i]) {
1915
- // console.log("in a shift type, and that specific type");
1916
- var rectSelection = d3.select(this).style({
1917
- opacity: "0.7"
1918
- });
1919
- } else {
1920
- // console.log("in a shift type, but not that specific type");
1921
- var rectSelection = d3.select(this).style({
1922
- opacity: "0.3"
1923
- });
1924
- }
1925
- }
1926
- // not in a shift selection
1927
- else {
1928
- // console.log("not in a shift type");
1929
- var rectSelection = d3.select(this).style({
1930
- opacity: "1.0"
1931
- });
1932
- }
1933
- })
1934
- .on("mouseout", function(d, i) {
1935
- var specificType = [3, 0, -1];
1936
- if (shiftTypeSelect) {
1937
- if (shiftType === specificType[i]) {
1938
- // console.log("in a shift type, and that specific type");
1939
- var rectSelection = d3.select(this).style({
1940
- opacity: "0.7"
1941
- });
1942
- } else {
1943
- // console.log("in a shift type, but not that specific type");
1944
- // console.log(shiftType);
1945
- // console.log(specificType);
1946
- // console.log(i);
1947
- // console.log(specificType[i]);
1948
- var rectSelection = d3.select(this).style({
1949
- opacity: "0.14"
1950
- });
1951
- }
1952
- } else {
1953
- // console.log("not in a shift type");
1954
- var rectSelection = d3.select(this).style({
1955
- opacity: "0.7"
1956
- });
1957
- }
1958
- })
1959
- .on("click", function(d, i) {
1960
- var specificType = [3, 0, -1];
1961
- figure.selectAll(".sumrectR,.sumrectL").style({
1962
- opacity: "0.1"
1963
- });
1964
- var rectSelection = d3.select(this).style({
1965
- opacity: "0.7"
1966
- });
1967
- if (i == 0) {
1968
- shiftTypeSelect = true;
1969
- shiftType = specificType[i];
1970
- resetButton(true);
1971
- shiftselencoder.varval("posup");
1972
- // shoot them all away
1973
- //d3.selectAll("rect.shiftrect, text.shifttext").transition().duration(1000).attr("transform",function(d,i) { if (d<0) { return "translate(-500,0)"; } else {return "translate(500,0)"; }});
1974
- // keep the ones with class "three"
1975
- //d3.selectAll("rect.shiftrect.three, text.shifttext.three").transition().duration(1000)
1976
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
1977
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1978
- });
1979
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
1980
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1981
- });
1982
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
1983
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1984
- });
1985
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
1986
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1987
- });
1988
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
1989
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
1990
- });
1991
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
1992
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
1993
- });
1994
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
1995
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
1996
- });
1997
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
1998
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
1999
- });
2000
- } else if (i == 1) {
2001
- shiftTypeSelect = true;
2002
- shiftType = specificType[i];
2003
- resetButton(true);
2004
- shiftselencoder.varval("negdown");
2005
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
2006
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
2007
- });
2008
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
2009
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
2010
- });
2011
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
2012
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2013
- });
2014
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
2015
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2016
- });
2017
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
2018
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2019
- });
2020
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
2021
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2022
- });
2023
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
2024
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2025
- });
2026
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
2027
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2028
- });
2029
- } else if (i == 2) {
2030
- // shiftTypeSelect = true;
2031
- // d3.selectAll(".sumrectR,.sumrectL").style({opacity:"0.7"});
2032
- resetfun();
2033
- // shiftselencoder.varval("negdown");
2034
- }
2035
- });
2036
-
2037
- axes.selectAll(".sumtextR")
2038
- .data([sumTypes[3], sumTypes[0], d3.sum(sumTypes)])
2039
- .enter()
2040
- .append("text")
2041
- .style({
2042
- "text-anchor": function(d, i) {
2043
- return ((d > 0) ? "start" : "end");
2044
- },
2045
- "font-size": bigshifttextsize,
2046
- })
2047
- //.attr("y",function(d,i) { if (i<2) {return i*17+17;} else if ((sumTypes[3]+sumTypes[1])*(sumTypes[0]+sumTypes[2])<0) {return i*17+33; } else {return i*17+33; } })
2048
- // for only three days
2049
- .attr({
2050
- "class": "sumtextR",
2051
- "id": function(d, i) {
2052
- return "sumTextR" + i;
2053
- },
2054
- "y": function(d, i) {
2055
- return i * 17 + 17;
2056
- },
2057
- "x": function(d, i) {
2058
- return topScale(d) + 5 * d / Math.abs(d);
2059
- },
2060
- })
2061
- .text(function(d, i) {
2062
- if (i == 0) {
2063
- return "\u2211+\u2191";
2064
- }
2065
- if (i == 1) {
2066
- return "\u2211-\u2193";
2067
- } else {
2068
- return "\u2211";
2069
- }
2070
- });
2071
-
2072
- // summaryArray = [sumTypes[1],sumTypes[2],sumTypes[0]+sumTypes[2]];
2073
- summaryArray = [sumTypes[1], sumTypes[2]];
2074
-
2075
- typeClass = ["posdown", "negup"];
2076
- colorClass = ["#ffffb3", "#4c4cff"];
2077
-
2078
- axes.selectAll(".sumrectL")
2079
- .data(summaryArray)
2080
- .enter()
2081
- .append("rect")
2082
- .attr({
2083
- "class": function(d, i) {
2084
- return "sumrectL " + intStr0[i] + " " + typeClass[i];
2085
- },
2086
- "id": function(d, i) {
2087
- return "sumTextL" + i;
2088
- },
2089
- "x": function(d, i) {
2090
- if (i < 2) {
2091
- return topScale(d);
2092
- } else {
2093
- // place the sum of negatives bar
2094
- // if they are not opposing
2095
- if ((sumTypes[3] + sumTypes[1]) * (sumTypes[0] + sumTypes[2]) > 0) {
2096
- // if positive, place at end of other bar
2097
- if (d > 0) {
2098
- return topScale((sumTypes[3] + sumTypes[1]));
2099
- }
2100
- // if negative, place at left of other bar, minus length (+topScale(d))
2101
- else {
2102
- return topScale(d) - (figcenter - topScale((sumTypes[3] + sumTypes[1])));
2103
- }
2104
- } else {
2105
- if (d > 0) {
2106
- return figcenter
2107
- } else {
2108
- return topScale(d)
2109
- }
2110
- }
2111
- }
2112
- },
2113
- "y": function(d, i) {
2114
- return i * 17 + 7;
2115
- },
2116
- "height": function(d, i) {
2117
- return 14;
2118
- },
2119
- "width": function(d, i) {
2120
- if (d > 0) {
2121
- return topScale(d) - figcenter;
2122
- } else {
2123
- return figcenter - topScale(d);
2124
- }
2125
- },
2126
- "fill": function(d, i) {
2127
- return colorClass[i];
2128
- },
2129
- })
2130
- .style({
2131
- "opacity": function(d, i) {
2132
- var specificType = [1, 2];
2133
- if ((shiftTypeSelect) && (shiftType !== specificType[i])) {
2134
- return "0.14";
2135
- } else {
2136
- return "0.7";
2137
- }
2138
- },
2139
- "stroke-width": "1",
2140
- "stroke": "rgb(0,0,0)"
2141
- })
2142
- .on("mouseover", function(d, i) {
2143
- var specificType = [1, 2];
2144
- // if we're in a shift selection
2145
- if (shiftTypeSelect) {
2146
- if (shiftType === specificType[i]) {
2147
- // console.log("in a shift type, and that specific type");
2148
- var rectSelection = d3.select(this).style({
2149
- opacity: "0.7"
2150
- });
2151
- } else {
2152
- // console.log("in a shift type, but not that specific type");
2153
- var rectSelection = d3.select(this).style({
2154
- opacity: "0.3"
2155
- });
2156
- }
2157
- }
2158
- // not in a shift selection
2159
- else {
2160
- // console.log("not in a shift type");
2161
- var rectSelection = d3.select(this).style({
2162
- opacity: "1.0"
2163
- });
2164
- }
2165
- })
2166
- .on("mouseout", function(d, i) {
2167
- var specificType = [1, 2];
2168
- if (shiftTypeSelect) {
2169
- if (shiftType === specificType[i]) {
2170
- // console.log("in a shift type, and that specific type");
2171
- var rectSelection = d3.select(this).style({
2172
- opacity: "0.7"
2173
- });
2174
- } else {
2175
- // console.log("in a shift type, but not that specific type");
2176
- // console.log(shiftType);
2177
- // console.log(specificType);
2178
- // console.log(i);
2179
- // console.log(specificType[i]);
2180
- var rectSelection = d3.select(this).style({
2181
- opacity: "0.14"
2182
- });
2183
- }
2184
- } else {
2185
- // console.log("not in a shift type");
2186
- var rectSelection = d3.select(this).style({
2187
- opacity: "0.7"
2188
- });
2189
- }
2190
- })
2191
- .on("click", function(d, i) {
2192
- var specificType = [1, 2];
2193
- shiftTypeSelect = true;
2194
- shiftType = specificType[i];
2195
- figure.selectAll(".sumrectR,.sumrectL").style({
2196
- opacity: "0.1"
2197
- });
2198
- var rectSelection = d3.select(this).style({
2199
- opacity: "0.7"
2200
- });
2201
- resetButton(true);
2202
- if (i == 0) {
2203
- shiftselencoder.varval("posdown");
2204
- // together
2205
- // axes.selectAll("rect.shiftrect.zero, text.shifttext.zero, rect.shiftrect.three, text.shifttext.three, rect.shiftrect.two, text.shifttext.two").transition().duration(1000).attr("transform",function(d,i) { if (d<0) { return "translate(-500,0)"; } else {return "translate(500,0)"; }});
2206
- // separate
2207
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
2208
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2209
- });
2210
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
2211
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2212
- });
2213
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
2214
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2215
- });
2216
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
2217
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2218
- });
2219
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
2220
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2221
- });
2222
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
2223
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2224
- });
2225
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
2226
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
2227
- });
2228
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
2229
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
2230
- });
2231
- } else if (i == 1) {
2232
- shiftselencoder.varval("negup");
2233
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
2234
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2235
- });
2236
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
2237
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2238
- });
2239
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
2240
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2241
- });
2242
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
2243
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2244
- });
2245
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
2246
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
2247
- });
2248
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
2249
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
2250
- });
2251
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
2252
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
2253
- });
2254
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
2255
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
2256
- });
2257
- }
2258
- });
2259
-
2260
- axes.selectAll(".sumtextL")
2261
- .data(summaryArray)
2262
- .enter()
2263
- .append("text")
2264
- .style({
2265
- "text-anchor": "end",
2266
- "font-size": bigshifttextsize,
2267
- })
2268
- .attr("class", "sumtextL")
2269
- .attr("y", function(d, i) {
2270
- return i * 17 + 17;
2271
- })
2272
- .text(function(d, i) {
2273
- if (i == 0) {
2274
- return "\u2211+\u2193";
2275
- } else {
2276
- return "\u2211-\u2191";
2277
- }
2278
- })
2279
- .attr("x", function(d, i) {
2280
- return topScale(d) - 5;
2281
- });
2282
-
2283
- // x label of shift, outside of the SVG
2284
- xlabel = canvas.append("text")
2285
- .text(xlabel_text)
2286
- .attr("class", "axes-text")
2287
- .attr("x", axeslabelmargin.left + figcenter) // 350-20-10 for svg width,
2288
- .attr("y", boxheight - 7)
2289
- .style({
2290
- "font-size": xylabelfontsize,
2291
- "fill": "#000000",
2292
- "text-anchor": "middle"
2293
- });
2294
-
2295
- ylabel = canvas.append("text")
2296
- .text(ylabel_text)
2297
- .attr("class", "axes-text")
2298
- .attr("x", 18)
2299
- .attr("y", figheight / 2 + 60 + toptextheight)
2300
- .attr("font-size", xylabelfontsize)
2301
- .attr("fill", "#000000")
2302
- .attr("transform", "rotate(-90.0," + (18) + "," + (figheight / 2 + 60 + toptextheight) + ")");
2303
-
2304
- function zoomed() {
2305
- // console.log(d3.event);
2306
-
2307
- // this prevents scrolling in the wrong direction
2308
- if (d3.event.translate[1] > 0) {
2309
- zoom.translate([0, 0]).scale(1);
2310
- }
2311
-
2312
- // if we have zoomed in, we set the y values for each subselection
2313
- if (shiftTypeSelect) {
2314
- for (var j = 0; j < 4; j++) {
2315
- axes.selectAll("rect.shiftrect." + intStr0[j])
2316
- .attr("transform", function(d, i) {
2317
- return "translate(" + (shiftType === j ? ((d > 0) ? figcenter : x(d)) : ((d > 0) ? 500 : -500)) + "," + (y(i + 1)) + ")";
2318
- });
2319
- axes.selectAll("text.shifttext." + intStr0[j])
2320
- .attr("transform", function(d, i) {
2321
- return "translate(" + (shiftType === j ? ((d > 0) ? (x(d) + 2) : (x(d) - 2)) : ((d > 0) ? 500 : -500)) + "," + (y(i + 1) + iBarH) + ")";
2322
- });
2323
- }
2324
- } else {
2325
- axes.selectAll("rect.shiftrect")
2326
- .attr("transform", function(d, i) {
2327
- if (d > 0) {
2328
- return "translate(" + (figcenter) + "," + (y(i + 1)) + ")";
2329
- } else {
2330
- return "translate(" + (x(d)) + "," + (y(i + 1)) + ")";
2331
- }
2332
- });
2333
- axes.selectAll("text.shifttext").attr("transform", function(d, i) {
2334
- if (d > 0) {
2335
- return "translate(" + (x(d) + 2) + "," + (y(i + 1) + iBarH) + ")";
2336
- } else {
2337
- return "translate(" + (x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
2338
- }
2339
- });
2340
-
2341
- }
2342
- if (distflag) {
2343
- // console.log(d3.event.translate);
2344
- // move scaled to the height of the window (23 words)
2345
- var scaledMove = d3.event.translate[1] / (figheight - yHeight);
2346
- // console.log(scaledMove);
2347
- // move relative to the height of the box and those 23 words
2348
- var relMove = scaledMove * distgrouph * numWords / lens.length;
2349
- // console.log(relMove);
2350
- figure.select(".distwin").attr({
2351
- "y": d3.max([2, -relMove + 2]),
2352
- });
2353
- }
2354
- }; // zoomed
2355
-
2356
- // // console.log(figheight);
2357
- // // attach this guy. cleaner with the group
2358
- // help = axes.append("g")
2359
- // .attr({"class": "help",
2360
- // "fill": "#B8B8B8",
2361
- // "transform": "translate("+(5)+","+(figheight-16)+")",
2362
- // })
2363
- // .on("click", function() {
2364
- // window.open("http://hedonometer.org/instructions.html#wordshifts","_blank");
2365
- // })
2366
- // .selectAll("text.help")
2367
- // .data(["click here","for instructions"])
2368
- // .enter()
2369
- // .append("text")
2370
- // .attr({"class": "help",
2371
- // "fill": "#B8B8B8",
2372
- // "x": 0,
2373
- // "y": function(d,i) { return i*10; },
2374
- // "font-size": "8.0px", })
2375
- // .style({"text-anchor": "start", })
2376
- // .text(function(d) { return d; });
2377
-
2378
- if (distflag) {
2379
- computedistributions();
2380
-
2381
- // console.log(figheight);
2382
- // console.log(yHeight);
2383
- var distgrouph = 250;
2384
- var distgroupw = 70;
2385
- var dxspace = 1;
2386
- var dyspace = 2;
2387
-
2388
- distgroup = axes.append("g")
2389
- .attr({
2390
- "class": "dist",
2391
- "fill": "#B8B8B8",
2392
- "transform": "translate(" + (5) + "," + (figheight - 28 - distgrouph) + ")",
2393
- });
2394
-
2395
- distgroup.append("rect")
2396
- .attr({
2397
- "x": 0,
2398
- "y": 0,
2399
- "height": distgrouph,
2400
- "width": distgroupw,
2401
- "class": "distbg",
2402
- "stroke-width": "2",
2403
- "stroke": "rgb(150,150,150)",
2404
- "fill": "#FCFCFC",
2405
- "opacity": "0.96",
2406
- });
2407
-
2408
- var distx = d3.scale.linear()
2409
- .domain(d3.extent(dist.map(function(d) {
2410
- return d[4];
2411
- })))
2412
- .range([dxspace, distgroupw - 2 * dxspace]);
2413
-
2414
- var disty = d3.scale.linear()
2415
- .domain([0, nbins - 1])
2416
- .range([dyspace, distgrouph - dyspace]);
2417
- // .range([dyspace,distgrouph-2*dyspace]);
2418
-
2419
- var line = d3.svg.line()
2420
- .x(function(d, i) {
2421
- return distx(d);
2422
- })
2423
- .y(function(d, i) {
2424
- return disty(i);
2425
- })
2426
- .interpolate("cardinal");
2427
-
2428
- // console.log(dist.map(function(d) { return d[4]; }));
2429
-
2430
- var distline = distgroup.append("path")
2431
- .datum(dist.map(function(d) {
2432
- return d[4];
2433
- }))
2434
- .attr("class", "line")
2435
- .attr("d", line)
2436
- .attr("stroke", "red")
2437
- .attr("stroke-width", 1.25)
2438
- .attr("fill", "none");
2439
-
2440
- var cdistx = d3.scale.linear()
2441
- .domain(d3.extent(cdist.map(function(d) {
2442
- return d[4];
2443
- })))
2444
- .range([dxspace, distgroupw - 2 * dxspace]);
2445
-
2446
- var cline = d3.svg.line()
2447
- .x(function(d, i) {
2448
- return cdistx(d);
2449
- })
2450
- .y(function(d, i) {
2451
- return disty(i);
2452
- })
2453
- .interpolate("cardinal");
2454
-
2455
- var cdistline = distgroup.append("path")
2456
- .datum(cdist.map(function(d) {
2457
- return d[4];
2458
- }))
2459
- .attr("class", "line")
2460
- .attr("d", cline)
2461
- .attr("stroke", "blue")
2462
- .attr("stroke-width", 1.25)
2463
- .attr("fill", "none");
2464
-
2465
- // console.log(distgrouph*numWords/lens.length);
2466
- // console.log(distgrouph*numWords/2000);
2467
-
2468
- var distwindowrect = distgroup.append("rect")
2469
- .attr({
2470
- "x": 0,
2471
- "y": 2,
2472
- "height": distgrouph * numWords / nwords,
2473
- "width": distgroupw,
2474
- "class": "distwin",
2475
- "stroke-width": "0.75",
2476
- "stroke": "rgb(20,20,20)",
2477
- "fill": "#FCFCFC",
2478
- "opacity": "0.6",
2479
- });
2480
-
2481
- var nwordstext = distgroup.append("text")
2482
- .attr({
2483
- "x": distgroupw + 2,
2484
- "y": distgrouph + 2,
2485
- "class": "nwordslabel",
2486
- })
2487
- .style({
2488
- "fill": "#B8B8B8",
2489
- "font-size": distlabeltext,
2490
- "text-anchor": "start",
2491
- })
2492
- .text(nwords);
2493
-
2494
- distgroup.append("text")
2495
- .attr({
2496
- "x": distgroupw + 2,
2497
- "y": 2,
2498
- "class": "zerolabel",
2499
- })
2500
- .style({
2501
- "fill": "#B8B8B8",
2502
- "font-size": distlabeltext,
2503
- "text-anchor": "start",
2504
- })
2505
- .text("0");
2506
- }
2507
-
2508
- credit = axes.selectAll("text.credit")
2509
- // .data(["visualization by","@andyreagan","word shifts by","@hedonometer"])
2510
- .data(["visualization by", "@andyreagan", ])
2511
- .enter()
2512
- .append("text")
2513
- .attr({
2514
- "class": "credit",
2515
- "x": (figwidth - 5),
2516
- "y": function(d, i) {
2517
- return figheight - 15 + i * 10;
2518
- },
2519
- })
2520
- .style({
2521
- "text-anchor": "end",
2522
- "fill": "#B8B8B8",
2523
- "font-size": creditfontsize,
2524
- })
2525
- .text(function(d) {
2526
- return d;
2527
- });
2528
-
2529
- // get this inside of the plot...so that resizeshift won't get called
2530
- // too early (before a shift has been plotted)
2531
- if (!widthsetexplicitly) {
2532
- d3.select(window).on("resize.shiftplot", resizeshift);
2533
- }
2534
-
2535
- if (reset) {
2536
- // call it
2537
- resetButton(true);
2538
- }
2539
-
2540
- if (translate) {
2541
- console.log(translate);
2542
- translateButton();
2543
- }
2544
-
2545
- return that;
2546
-
2547
- }; // hedotools.shifter.plot
2548
-
2549
- function resetfun() {
2550
- // console.log("reset function");
2551
- figure.selectAll(".sumrectR,.sumrectL").style({
2552
- opacity: "0.7"
2553
- });
2554
- shiftTypeSelect = false;
2555
- shiftType = -1;
2556
- figure.selectAll("rect.shiftrect").transition().duration(1000)
2557
- .attr("transform", function(d, i) {
2558
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
2559
- });
2560
- figure.selectAll("text.shifttext").transition().duration(1000)
2561
- .attr("transform", function(d, i) {
2562
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
2563
- });
2564
- // d3.selectAll(".resetbutton").remove();
2565
- shiftselencoder.varval("none");
2566
- shiftselencoder.destroy();
2567
- } // resetfun
2568
-
2569
- function resetButton(showb) {
2570
- // console.log("resetbutton function");
2571
-
2572
- // console.log(showb);
2573
- // showb = showb || true;
2574
- // console.log("showing reset button?");
2575
- // console.log(showb);
2576
- figure.selectAll(".resetbutton").remove();
2577
-
2578
- if (showb) {
2579
-
2580
- var resetGroup = canvas.append("g")
2581
- .attr("transform", "translate(" + (4) + "," + (56 + toptextheight) + ") rotate(-90)")
2582
- .attr("class", "resetbutton");
2583
-
2584
- resetGroup.append("rect")
2585
- .attr("x", 0)
2586
- .attr("y", 0)
2587
- .attr("rx", 3)
2588
- .attr("ry", 3)
2589
- .attr("width", 48)
2590
- .attr("height", 17)
2591
- .attr("fill", "#F0F0F0") //http://www.w3schools.com/html/html_colors.asp
2592
- .style({
2593
- "stroke-width": "0.5",
2594
- "stroke": "rgb(0,0,0)"
2595
- });
2596
-
2597
- resetGroup.append("text")
2598
- .text("Reset")
2599
- .attr("x", 6)
2600
- .attr("y", 13)
2601
- .attr("font-size", resetfontsize);
2602
-
2603
- resetGroup.append("rect")
2604
- .attr("x", 0)
2605
- .attr("y", 0)
2606
- .attr("rx", 3)
2607
- .attr("ry", 3)
2608
- .attr("width", 48)
2609
- .attr("height", 18)
2610
- .attr("fill", "white") //http://www.w3schools.com/html/html_colors.asp
2611
- .style({
2612
- "opacity": "0.0"
2613
- })
2614
- .on("click", function() {
2615
- resetfun();
2616
- });
2617
-
2618
- }
2619
-
2620
- }; // resetButton
2621
-
2622
- function translateButton() {
2623
- console.log("adding the translate button");
2624
- var translateGroup = canvas.append("g")
2625
- .attr("class", "translatebutton")
2626
- .attr("transform", "translate(" + (4) + "," + (136 + toptextheight) + ") rotate(-90)");
2627
-
2628
- translateGroup.append("rect")
2629
- .attr("x", 0)
2630
- .attr("y", 0)
2631
- .attr("rx", 3)
2632
- .attr("ry", 3)
2633
- .attr("width", 75)
2634
- .attr("height", 17)
2635
- .attr("fill", "#F0F0F0") //http://www.w3schools.com/html/html_colors.asp
2636
- .style({
2637
- "stroke-width": "0.5",
2638
- "stroke": "rgb(0,0,0)"
2639
- });
2640
-
2641
- translateGroup.append("text")
2642
- .text("Translate All")
2643
- .attr("x", 6)
2644
- .attr("y", 13)
2645
- .attr("font-size", "11.0px")
2646
-
2647
- translateGroup.append("rect")
2648
- .attr("x", 0)
2649
- .attr("y", 0)
2650
- .attr("rx", 3)
2651
- .attr("ry", 3)
2652
- .attr("width", 75)
2653
- .attr("height", 18)
2654
- .attr("fill", "white") //http://www.w3schools.com/html/html_colors.asp
2655
- .style({
2656
- "opacity": "0.0"
2657
- })
2658
- .on("click", function() {
2659
- for (var i = 0; i < flipVector.length - 1; i++) {
2660
- flipVector[i] = flipVector[flipVector.length - 1];
2661
- }
2662
- flipVector[flipVector.length - 1] = (flipVector[flipVector.length - 1] + 1) % 2;
2663
- // console.log("clicked translate");
2664
-
2665
- axes.selectAll("text.shifttext").transition().duration(1000)
2666
- .text(function(d, i) {
2667
- // goal is to toggle translation
2668
- // need translation vector
2669
- //console.log(flipVector[i]);
2670
- if (flipVector[i]) {
2671
- return sortedWordsEn[i];
2672
- } else {
2673
- return sortedWords[i];
2674
- }
2675
- }); // .text()
2676
- }); // on("click")
2677
- }; // translateButton
2678
-
2679
- var cloud = function() {
2680
- var that = this;
2681
-
2682
- if (viz_type_decoder().cached === "table") {
2683
- // console.log("removing table stuff");
2684
- newrank.remove();
2685
- newfreq.remove();
2686
- newtype.remove();
2687
- newmag.remove();
2688
- header.remove();
2689
- }
2690
-
2691
- // push the state the browser URL
2692
- viz_type.varval("cloud");
2693
- // console.log("making a cloud");
2694
-
2695
- // move all the stuff out of the way (table or wordshift)
2696
- axes.selectAll("rect.shiftrect").transition().duration(1000).attr("x", 1000);
2697
- axes.selectAll(".sumrectR").transition().duration(2000).attr("x", 1000);
2698
- axes.selectAll(".sumtextR").transition().duration(2000).attr("x", 1000);
2699
- axes.selectAll(".sumrectL").transition().duration(2000).attr("x", -1000);
2700
- axes.selectAll(".sumtextL").transition().duration(2000).attr("x", -1000);
2701
- // bgrect.style("stroke-width",0.5);
2702
- bottombgrect.attr("y", 1000);
2703
- // // need to get rid of the clipping boundary too?
2704
- // bgrect.remove();
2705
- xlabel.transition().duration(2000).attr("y", 1000);
2706
- ylabel.transition().duration(2000).attr("x", -1000);
2707
- topbgrect.transition().duration(2000).attr("y", -200);
2708
- sepline.transition().duration(1000).attr({
2709
- "y1": -10,
2710
- "y2": -10,
2711
- });
2712
-
2713
- var sizeScale = d3.scale.linear()
2714
- .domain([Math.abs(sortedMag[49]), Math.abs(sortedMag[0])])
2715
- .range([6, 70]);
2716
-
2717
- // go create a canvas and get the context there
2718
- // var cloud_canvas = document.createElement("canvas");
2719
- // cloud_canvas.width = figwidth;
2720
- // cloud_canvas.height = figheight;
2721
- // // cloud_canvas.width = 2048;
2722
- // // cloud_canvas.height = 2048;
2723
- figure.selectAll("canvas").remove();
2724
- figure.append("canvas")
2725
- .attr({
2726
- "width": figwidth,
2727
- "height": figheight,
2728
- "id": "cloudcanvas"
2729
- })
2730
- .style({
2731
- "display": "none"
2732
- });
2733
- // var cloud_canvas_context = cloud_canvas.getContext("2d");
2734
- var cloud_canvas_context = document.getElementById("cloudcanvas").getContext("2d");
2735
-
2736
- figure.append("canvas")
2737
- .attr({
2738
- "width": figwidth,
2739
- "height": figheight,
2740
- "id": "cloudcanvas2"
2741
- })
2742
- .style({
2743
- "display": "none"
2744
- });
2745
-
2746
- // var cloud_canvas_context = cloud_canvas.getContext("2d");
2747
- var cloud_canvas_context_demo = document.getElementById("cloudcanvas2").getContext("2d");
2748
-
2749
- cloud_canvas_context.textAlign = "center";
2750
- // cloud_canvas_context.textBaseline = "bottom";
2751
- cloud_canvas_context.fillStyle = "red";
2752
- cloud_canvas_context.strokeStyle = "red";
2753
- cloud_canvas_context.textAlign = "center";
2754
- cloud_canvas_context.save();
2755
-
2756
- var nbins = 1;
2757
-
2758
- // keep track of everything in this data structure
2759
- var data = sortedWordsRaw.map(function(d, i) {
2760
- a = {};
2761
- // text
2762
- a.text = d;
2763
- // random rotation
2764
- a.rotate = Math.round((Math.random() * nbins) - nbins / 2) * 90;
2765
- // a.rotate = 0;
2766
- // scale the size (see scale above)
2767
- a.size = sizeScale(Math.abs(sortedMag[i]));
2768
- // set the font style using a single string
2769
- // https://developer.mozilla.org/en-US/docs/Web/CSS/font
2770
- a.fontString = a.size + "px " + fontString;
2771
- // don't let them touch
2772
- a.padding = 1;
2773
- // initially space them along the horizontal line
2774
- // width half of the width
2775
- a.x = figcenter + (Math.random() - .5) * figwidth / 2;
2776
- a.y = figheight / 2;
2777
- return a;
2778
- });
2779
-
2780
- var num_to_cloud = 199;
2781
-
2782
- var size = [figwidth, figheight];
2783
- var bounds = null;
2784
- var board = [];
2785
- var i = -1;
2786
- while (i++ < num_to_cloud) {
2787
- var d = data[i];
2788
- // go and generate the image data
2789
- // it saves on d
2790
-
2791
- cloudSpriteSimple(cloud_canvas_context_demo, d, size);
2792
-
2793
- var cloud_canvas_monochrome = monochrome(cloud_canvas_context.getImageData(0, 0, size[0], size[1]).data);
2794
- // this will place it (updating x and y)
2795
- var success = place(board, d, cloud_canvas_monochrome);
2796
- // reset the bounds
2797
- // if (bounds) cloudBounds(bounds, d);
2798
- // else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}];
2799
- // translate such that the rotation actually is centered
2800
- // put it back to having all of the words
2801
- cloud_canvas_context.setTransform(1, 0, 0, 1, 0, 0);
2802
- cloud_canvas_context.save();
2803
- cloud_canvas_context.font = d.fontString;
2804
- cloud_canvas_context.lineWidth = 2 * d.padding;
2805
- cloud_canvas_context.translate(d.x, d.y);
2806
- cloud_canvas_context.rotate(d.rotate * cloudRadians);
2807
- // put it in the center (with the translation)
2808
- cloud_canvas_context.fillText(d.text, 0, 0);
2809
- cloud_canvas_context.strokeText(d.text, 0, 0);
2810
- cloud_canvas_context.restore();
2811
- // console.log(d);
2812
- }
2813
-
2814
- // check that the board works
2815
- // console.log(board);
2816
- // axes.append("rect")
2817
- // .attr({"x": board[0].x0,
2818
- // "y": board[0].y0,
2819
- // "width": board[0].w,
2820
- // "height": board[0].h,})
2821
- // .style({"stroke-width": 2,
2822
- // "stroke": "black",
2823
- // "fill": "white",
2824
- // "fill-opacity": "0.0",
2825
- // });
2826
-
2827
- // num_to_cloud += 30;
2828
- var newwords = axes.selectAll("text.shifttext").data(data)
2829
- .filter(function(d, i) {
2830
- if (i < num_to_cloud + 1) {
2831
- return 1;
2832
- }
2833
- });
2834
-
2835
- newwords.text(function(d, i) {
2836
- return d.text;
2837
- })
2838
- .transition().duration(1000)
2839
- .delay(function(d, i) {
2840
- return i * 10;
2841
- })
2842
- // .style("font-size", function(d,i) { return sizeScale(Math.abs(sortedMag[i])); })
2843
- // .attr("x",function(d,i) { return Math.random()*100+figcenter; })
2844
- // .attr("y",function(d,i) { return Math.random()*100+figheight/2; });
2845
- .attr("placed", function(d, i) {
2846
- return d.placed;
2847
- })
2848
- // .attr("x", function(d,i) { return d.x; })
2849
- // .attr("y", function(d,i) { return d.y; })
2850
- .attr("x", function(d, i) {
2851
- return 0;
2852
- })
2853
- .attr("y", function(d, i) {
2854
- return 0;
2855
- })
2856
- .style("text-anchor", "middle")
2857
- // .style("font-size", function(d) { return d.size + "px"; })
2858
- // .style("font-family", "\"Impact\", serif")
2859
- // .style("font", function(d,i) { return d.size + "px " + d.font + ", " + d.style; })
2860
- .style("font", function(d, i) {
2861
- return d.fontString;
2862
- })
2863
- .attr("transform", function(d, i) {
2864
- return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
2865
- // return "rotate(" + d.rotate + ")";
2866
- });
2867
-
2868
- function place(board, tag, my_monochrome) {
2869
- // size of the whole figure
2870
- var perimeter = [{
2871
- x: 0,
2872
- y: 0
2873
- }, {
2874
- x: size[0],
2875
- y: size[1]
2876
- }];
2877
- // initial position
2878
- var startX = tag.x;
2879
- var startY = tag.y;
2880
- // diagonal length of the board
2881
- var maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]);
2882
- // spiral outward!
2883
- var e = size[0] / size[1];
2884
- var archimedeanSpiral = function(t) {
2885
- return [e * t * Math.cos(t), t * Math.sin(t)];
2886
- };
2887
- // randomly choose a direction to spin
2888
- var dt = Math.random() < .5 ? 1 : -1;
2889
- // start on the other side of 0, with a small timestep
2890
- var delta = 2;
2891
- dt = dt * delta;
2892
- var t = -dt;
2893
- var dxdy;
2894
- var dx;
2895
- var dy;
2896
-
2897
- // march ahead, setting dxdy as the position of our spiral
2898
- while (dxdy = archimedeanSpiral(t += dt)) {
2899
- dx = dxdy[0];
2900
- dy = dxdy[1];
2901
-
2902
- // make sure we are not outside the radius
2903
- // if so, kill it
2904
- if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break;
2905
-
2906
- // update the position
2907
- tag.x = startX + dx;
2908
- tag.y = startY + dy;
2909
-
2910
- // console.log(dxdy);
2911
- // axes.selectAll("circle").remove();
2912
- // axes.append("circle")
2913
- // .attr({"cx": tag.x, "cy": tag.y, "r": 1})
2914
- // .style({"fill": "red",});
2915
-
2916
-
2917
- // if the word extends past the edge, keep rotating
2918
- // (it should come back in!)
2919
- if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
2920
- tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
2921
-
2922
- // now let's take the image data from the canvas, and compare the placement
2923
- // of the data from the tag's sprite
2924
- // not using the board, (which could store the bounding boxes for a smarter search)
2925
-
2926
- // for the whole canvas
2927
- // var cloud_canvas_monochrome = monochrome(cloud_canvas_context.getImageData(0, 0, size[0], size[1]).data);
2928
- // for the just the bounding box of the sprite
2929
- // could fetch this from the above....
2930
- // console.log(cloud_canvas_context.getImageData(tag.x+tag.x0, tag.y-tag.y1, 2*tag.x1, tag.y1));
2931
- var place_rect = {
2932
- "x0": Math.floor(tag.x) + tag.x0,
2933
- "y0": Math.floor(tag.y) - tag.y1,
2934
- "w": 2 * tag.x1,
2935
- "h": tag.y1,
2936
- };
2937
- place_rect.x1 = place_rect.x0 + place_rect.w;
2938
- place_rect.y1 = place_rect.y0 + place_rect.h;
2939
- // var cloud_canvas_monochrome = monochrome(cloud_canvas_context.getImageData(
2940
- // place_rect.x0,place_rect.y0,place_rect.w,place_rect.h
2941
- // ).data);
2942
-
2943
- var cloud_canvas_monochrome = indexer2d(my_monochrome,
2944
- size[0],
2945
- place_rect.y0,
2946
- place_rect.y1,
2947
- place_rect.x0,
2948
- place_rect.x1);
2949
-
2950
- // // console.log(cloud_canvas_monochrome);
2951
- // console.log(cloud_canvas_monochrome.reduce(function(pv, cv) { return pv + cv; }, 0))
2952
- // // console.log(tag.sprite);
2953
- // console.log(tag.sprite.reduce(function(pv, cv) { return pv + cv; }, 0));
2954
- for (var i = 0; i < tag.sprite.length; i++) {
2955
- // check that they both have data there
2956
- if (tag.sprite[i] && cloud_canvas_monochrome[i]) {
2957
- break
2958
- }
2959
- }
2960
- // index on the canvas data is tag.x
2961
- if (i === tag.sprite.length) {
2962
- board.push(place_rect)
2963
- // console.log(t);
2964
- return true;
2965
- }
2966
- } // while()
2967
- // console.log(t);
2968
- return false;
2969
- } // place()
2970
-
2971
- return that;
2972
- } // hedotools.shifter.cloud
2973
-
2974
- var newrank;
2975
- var newfreq;
2976
- var newtype;
2977
- var newmag;
2978
- var header;
2979
-
2980
- var table = function() {
2981
- var that = this;
2982
-
2983
- viz_type.varval("table");
2984
-
2985
- // console.log("making a table");
2986
-
2987
- var rankwidth = 20;
2988
- var wordwidth = 70;
2989
- var typewidth = 25;
2990
- var freqwidth = 25;
2991
- var magwidth = 35;
2992
- var totalwidth = rankwidth + wordwidth + typewidth + freqwidth + magwidth;
2993
- // console.log("width of all the text stuff "+totalwidth);
2994
- var barswidth = figwidth - totalwidth;
2995
- var aligns = ["start", "start", "middle", "middle", "end", "middle"];
2996
- // console.log("width left "+barswidth);
2997
- xpadding = 10;
2998
- var barcenter = totalwidth + barswidth / 2;
2999
- var width_offsets = [0, rankwidth, rankwidth + wordwidth, rankwidth + wordwidth + typewidth, rankwidth + wordwidth + typewidth + freqwidth + magwidth, barcenter];
3000
-
3001
- // linear scale function
3002
- x.domain([-Math.abs(sortedMag[0]), Math.abs(sortedMag[0])])
3003
- .range([xpadding, barswidth - xpadding]);
3004
-
3005
- yHeight = 15;
3006
-
3007
- // linear scale function
3008
- y.range([figheight + 2, yHeight]);
3009
-
3010
- // both of these need their y height reset
3011
- resetButton(false);
3012
-
3013
- // if (translate) {
3014
- // translateButton();
3015
- // }
3016
-
3017
- var newbars = axes.selectAll("rect.shiftrect").data(sortedMag);
3018
- var newwords = axes.selectAll("text.shifttext").data(sortedMag);
3019
-
3020
- newbars.transition().duration(1000)
3021
- .attr({
3022
- "fill": "grey",
3023
- "class": function(d, i) {
3024
- return "shiftrect " + intStr0[sortedType[i]];
3025
- },
3026
- "transform": function(d, i) {
3027
- if (d > 0) {
3028
- return "translate(" + barcenter + "," + (y(i + 1) + 2.5) + ")";
3029
- } else {
3030
- return "translate(" + (x(d) + totalwidth) + "," + (y(i + 1) + 2.5) + ")";
3031
- }
3032
- },
3033
- "height": function(d, i) {
3034
- return iBarH;
3035
- },
3036
- "width": function(d, i) {
3037
- if ((d) > 0) {
3038
- return x(d) - x(0);
3039
- } else {
3040
- return x(0) - x(d);
3041
- }
3042
- }
3043
- });
3044
-
3045
- newwords.transition().duration(1000)
3046
- .attr({
3047
- "class": function(d, i) {
3048
- return "shifttext " + intStr0[sortedType[i]];
3049
- },
3050
- "transform": function(d, i) {
3051
- return "translate(" + rankwidth + "," + (y(i + 1) + iBarH) + ")";
3052
- },
3053
- })
3054
- .style({
3055
- "text-anchor": "start",
3056
- "font-size": wordfontsize
3057
- })
3058
- .text(function(d, i) {
3059
- return sortedWordsRaw[i];
3060
- });
3061
-
3062
- // fix these both for the translate button
3063
- sortedWords = sortedWordsRaw;
3064
- if (translate) {
3065
- sortedWordsEn = sortedWordsEnRaw;
3066
- }
3067
-
3068
- newrank = axes.selectAll("text.shiftrank").data(sortedMag)
3069
- .enter()
3070
- .append("text")
3071
- .attr("y", function(d, i) {
3072
- return y(i + 1) + iBarH;
3073
- })
3074
- .attr("x", function(d, i) {
3075
- return 0;
3076
- })
3077
- .style({
3078
- "text-anchor": "start",
3079
- "font-size": wordfontsize
3080
- })
3081
- .text(function(d, i) {
3082
- return (i + 1) + ".";
3083
- });
3084
-
3085
- newtype = axes.selectAll("text.shifttype").data(sortedMag)
3086
- .enter()
3087
- .append("text")
3088
- .attr("y", function(d, i) {
3089
- return y(i + 1) + iBarH;
3090
- })
3091
- .attr("x", function(d, i) {
3092
- return rankwidth + wordwidth;
3093
- })
3094
- .style({
3095
- "text-anchor": "middle",
3096
- "font-size": wordfontsize
3097
- })
3098
- .text(function(d, i) {
3099
- if (sortedType[i] == 0) {
3100
- return "\u002D";
3101
- } else if (sortedType[i] == 2) {
3102
- return "\u002D";
3103
- } // -
3104
- else {
3105
- return "\u002B";
3106
- } // +
3107
- });
3108
-
3109
- newfreq = axes.selectAll("text.shiftfreq").data(sortedMag)
3110
- .enter()
3111
- .append("text")
3112
- .attr("y", function(d, i) {
3113
- return y(i + 1) + iBarH;
3114
- })
3115
- .attr("x", function(d, i) {
3116
- return rankwidth + wordwidth + typewidth;
3117
- })
3118
- .style({
3119
- "text-anchor": "middle",
3120
- "font-size": wordfontsize
3121
- })
3122
- .text(function(d, i) {
3123
- if (sortedType[i] == 0) {
3124
- return "\u2193";
3125
- } else if (sortedType[i] == 1) {
3126
- return "\u2193";
3127
- } else {
3128
- return "\u2191";
3129
- }
3130
- });
3131
-
3132
- newmag = axes.selectAll("text.shiftmag").data(sortedMag)
3133
- .enter()
3134
- .append("text")
3135
- .attr("y", function(d, i) {
3136
- return y(i + 1) + iBarH;
3137
- })
3138
- .attr("x", function(d, i) {
3139
- return rankwidth + wordwidth + typewidth + freqwidth + magwidth;
3140
- })
3141
- .style({
3142
- "text-anchor": "end",
3143
- "font-size": wordfontsize
3144
- })
3145
- .text(function(d, i) {
3146
- return (d / (Math.abs(compH - refH)) * 100).toFixed(2) + "%";
3147
- });
3148
-
3149
- header = axes.selectAll("text.header")
3150
- .data(["#", "Word", "\u002B/\u002D", "\u2191/\u2193", "% Cont.", "% Cont."])
3151
- .enter()
3152
- .append("text")
3153
- .attr({
3154
- "x": function(d, i) {
3155
- return width_offsets[i];
3156
- },
3157
- "y": function(d, i) {
3158
- return y(0) + iBarH;
3159
- },
3160
- })
3161
- .style({
3162
- "text-anchor": function(d, i) {
3163
- return aligns[i];
3164
- },
3165
- "font-size": function(d, i) {
3166
- return wordfontsize;
3167
- },
3168
- })
3169
- .text(function(d, i) {
3170
- return d;
3171
- })
3172
-
3173
- axes.selectAll(".sumrectR").transition().duration(2000).attr("x", 1000);
3174
- axes.selectAll(".sumtextR").transition().duration(2000).attr("x", 1000);
3175
- axes.selectAll(".sumrectL").transition().duration(2000).attr("x", -1000);
3176
- axes.selectAll(".sumtextL").transition().duration(2000).attr("x", -1000);
3177
- bgrect.style("stroke-width", 0);
3178
- bottombgrect.attr("y", 1000);
3179
- // // need to get rid of the clipping boundary too?
3180
- // bgrect.remove();
3181
- xlabel.transition().duration(2000).attr("y", 1000);
3182
- ylabel.transition().duration(2000).attr("x", -1000);
3183
- topbgrect.transition().duration(2000).attr("y", -200);
3184
- sepline.transition().duration(1000).attr({
3185
- "y1": "15",
3186
- "y2": 15,
3187
- });
3188
-
3189
- function zoomed() {
3190
- // console.log(d3.event);
3191
- if (d3.event.translate[1] > 0) {
3192
- zoom.translate([0, 0]).scale(1);
3193
- }
3194
- newbars.attr("transform", function(d, i) {
3195
- return "translate(" + ((d > 0) ? barcenter : x(d) + totalwidth) + "," + (y(i + 1) + 2.5) + ")";
3196
- });
3197
- newwords.attr("transform", function(d, i) {
3198
- return "translate(" + ((d > 0) ? rankwidth : rankwidth) + "," + (y(i + 1) + iBarH) + ")";
3199
- });
3200
-
3201
- // newbars.attr("y", function(d,i) { return y(i+1) });
3202
- // newwords.attr("y", function(d,i) { return y(i+1)+iBarH; } );
3203
- newrank.attr("y", function(d, i) {
3204
- return y(i + 1) + iBarH;
3205
- });
3206
- newtype.attr("y", function(d, i) {
3207
- return y(i + 1) + iBarH;
3208
- });
3209
- newfreq.attr("y", function(d, i) {
3210
- return y(i + 1) + iBarH;
3211
- });
3212
- newmag.attr("y", function(d, i) {
3213
- return y(i + 1) + iBarH;
3214
- });
3215
-
3216
- }; // zoomed
3217
-
3218
- zoom = d3.behavior.zoom()
3219
- .y(y) // pass linear scale function
3220
- // .translate([10,10])
3221
- .scaleExtent([1, 1])
3222
- .on("zoom", zoomed);
3223
-
3224
- return that;
3225
- } // hedotools.shifter.table()
3226
-
3227
- var replot = function() {
3228
- var that = this;
3229
-
3230
- // apply new data to the bars, transition everything
3231
- // tricky to get the transition right
3232
- var yHeight = (7 + 17 * 3 + 14 + 5 - 13); // 101
3233
-
3234
- // linear scale function
3235
- y.range([figheight + 2, yHeight]);
3236
- sepline.transition().duration(1000).attr({
3237
- "y1": barHeight,
3238
- "y2": barHeight,
3239
- });
3240
-
3241
- if (viz_type_decoder().cached === "table") {
3242
- // console.log("removing table stuff");
3243
- newrank.remove();
3244
- newfreq.remove();
3245
- newtype.remove();
3246
- newmag.remove();
3247
- header.remove();
3248
- }
3249
-
3250
- viz_type.varval("wordshift");
3251
- // console.log("making a wordshift");
3252
-
3253
- // make sure to update this
3254
- if (comparisonText[0].length < 1) {
3255
- if (compH >= refH) {
3256
- var happysad = "happier";
3257
- } else {
3258
- var happysad = "less happy";
3259
- }
3260
-
3261
- // console.log("generating text for wordshift");
3262
- comparisonText = splitstring(["Reference happiness: " + refH.toFixed(2), "Comparison happiness: " + compH.toFixed(2), "Why comparison is " + happysad + " than reference:"], boxwidth - 10 - logowidth, "14px " + fontString);
3263
- // console.log(comparisonText);
3264
- } else {
3265
- if (split_top_strings) {
3266
- comparisonText = splitstring(comparisonText, boxwidth - 10 - logowidth, "14px " + fontString);
3267
- }
3268
- // console.log(comparisonText);
3269
- }
3270
-
3271
- // could set a cap to make sure no 0"s
3272
- maxWidth = d3.max(sortedWords.slice(0, 5).map(function(d) {
3273
- return d.width(wordfontsize + "px " + fontString);
3274
- }));
3275
-
3276
- var xpadding = 10;
3277
- // linear scale function
3278
- x.domain([-Math.abs(sortedMag[0]), Math.abs(sortedMag[0])])
3279
- .range([maxWidth + xpadding, figwidth - maxWidth - xpadding]);
3280
-
3281
- if (show_x_axis_bool) {
3282
- canvas.select(".x.axis")
3283
- .call(xAxis);
3284
- }
3285
-
3286
- // get the height again
3287
- toptextheight = comparisonText.length * 17 + 13;
3288
- // console.log(toptextheight);
3289
-
3290
- resetButton(true);
3291
-
3292
- // reset this
3293
- figheight = boxheight - axeslabelmargin.top - axeslabelmargin.bottom - toptextheight;
3294
-
3295
- // linear scale function
3296
- y.range([figheight + 2, yHeight]);
3297
-
3298
- axes.attr("transform", "translate(" + (axeslabelmargin.left) + "," + (axeslabelmargin.top + toptextheight) + ")")
3299
- .attr("height", figheight);
3300
-
3301
- bgrect.attr("height", figheight - 2).style({
3302
- "stroke-width": 0.5,
3303
- "stroke": "rgb(20,20,20)"
3304
- });
3305
-
3306
- topbgrect2.attr("height", toptextheight);
3307
-
3308
- // // console.log(figheight);
3309
- // canvas.selectAll("g.help").remove();
3310
- // help.remove();
3311
- // help = axes.append("g")
3312
- // .attr({"class": "help",
3313
- // "fill": "#B8B8B8",
3314
- // "transform": "translate("+(5)+","+(figheight-16)+")",
3315
- // })
3316
- // .on("click", function() {
3317
- // window.open("http://hedonometer.org/instructions.html#wordshifts","_blank");
3318
- // })
3319
- // .selectAll("text.help")
3320
- // .data(["click here","for instructions"])
3321
- // .enter()
3322
- // .append("text")
3323
- // .attr({"class": "help",
3324
- // "fill": "#B8B8B8",
3325
- // "x": 0,
3326
- // "y": function(d,i) { return i*10; },
3327
- // "font-size": "8.0px", })
3328
- // .style({"text-anchor": "start", })
3329
- // .text(function(d) { return d; });
3330
-
3331
-
3332
- // since I really want this on there (in safari)
3333
- // go through the extra trouble of removing it first
3334
- canvas.selectAll("text.credit").remove();
3335
- credit.remove();
3336
- credit = axes.selectAll("text.credit")
3337
- .data(["visualization by", "@andyreagan"])
3338
- .enter()
3339
- .append("text")
3340
- .attr({
3341
- "class": "credit",
3342
- "fill": "#B8B8B8",
3343
- "x": (figwidth - 5),
3344
- "y": function(d, i) {
3345
- return figheight - 15 + i * 10;
3346
- },
3347
- "font-size": "8.0px",
3348
- })
3349
- .style({
3350
- "text-anchor": "end",
3351
- })
3352
- .text(function(d) {
3353
- return d;
3354
- });
3355
-
3356
- // console.log("the comparison text in replot is:");
3357
- // console.log(comparisonText);
3358
- // console.log(toptext);
3359
- canvas.selectAll("text.titletext").remove();
3360
- toptext.remove();
3361
- toptext = canvas.selectAll("text.titletext")
3362
- .data(comparisonText)
3363
- .enter()
3364
- .append("text")
3365
- .attr({
3366
- "y": function(d, i) {
3367
- return (i + 1) * 17;
3368
- },
3369
- "x": 3,
3370
- "class": function(d, i) {
3371
- return "titletext " + intStr[i];
3372
- },
3373
- })
3374
- .style({ // "font-family": "Helvetica Neue",
3375
- "font-size": function(d, i) {
3376
- return topFontSizeArray[i];
3377
- },
3378
- "line-height": "1.42857143",
3379
- "color": function(d, i) {
3380
- return colorArray[i];
3381
- },
3382
- // if there are 4 items...make the first two bold
3383
- "font-weight": function(d, i) {
3384
- // using this variable numBoldLines
3385
- if (i < numBoldLines) {
3386
- return "bold";
3387
- } else {
3388
- return "normal";
3389
- }
3390
- },
3391
- })
3392
- .text(function(d, i) {
3393
- return d;
3394
- });
3395
-
3396
- bottombgrect.attr("y", fullheight - axeslabelmargin.bottom - toptextheight);
3397
-
3398
- // both of these need their y height reset
3399
- // resetButton(true);
3400
-
3401
- // if (translate) {
3402
- // translateButton();
3403
- // }
3404
-
3405
- var newbars = axes.selectAll("rect.shiftrect").data(sortedMag);
3406
- var newwords = axes.selectAll("text.shifttext").data(sortedMag);
3407
- // console.log(sortedWords);
3408
- // console.log(sortedMag);
3409
- // console.log(compF);
3410
-
3411
- // if we haven't dont a subselection, apply with a transition
3412
- if (shiftseldecoder().current === "none" || shiftseldecoder().current.length === 0) {
3413
- newbars.transition().duration(1500)
3414
- .attr({
3415
- "fill": function(d, i) {
3416
- if (sortedType[i] == 2) {
3417
- return "#4C4CFF";
3418
- } else if (sortedType[i] == 3) {
3419
- return "#FFFF4C";
3420
- } else if (sortedType[i] == 0) {
3421
- return "#B3B3FF";
3422
- } else {
3423
- return "#FFFFB3";
3424
- }
3425
- },
3426
- "class": function(d, i) {
3427
- return "shiftrect " + intStr0[sortedType[i]];
3428
- },
3429
- // "x":function(d,i) {
3430
- // if (d>0) { return figcenter; }
3431
- // else { return x(d)} },
3432
- // "y": function(d,i) { return y(i+1); },
3433
- "x": 0,
3434
- "y": 0,
3435
- "transform": function(d, i) {
3436
- if (d > 0) {
3437
- return "translate(" + figcenter + "," + y(i + 1) + ")";
3438
- } else {
3439
- return "translate(" + x(d) + "," + y(i + 1) + ")";
3440
- }
3441
- },
3442
- "height": function(d, i) {
3443
- return iBarH;
3444
- },
3445
- "width": function(d, i) {
3446
- if ((d) > 0) {
3447
- return x(d) - x(0);
3448
- } else {
3449
- return x(0) - x(d);
3450
- }
3451
- }
3452
- });
3453
-
3454
- newwords.transition().duration(1500)
3455
- .attr({
3456
- "class": function(d, i) {
3457
- return "shifttext " + intStr0[sortedType[i]];
3458
- },
3459
- "x": 0,
3460
- "y": 0,
3461
- "transform": function(d, i) {
3462
- if (d > 0) {
3463
- return "translate(" + (x(d) + 2) + "," + (y(i + 1) + iBarH) + ")";
3464
- } else {
3465
- return "translate(" + (x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3466
- }
3467
- },
3468
- })
3469
- // .attr("class", function(d,i) { return "shifttext "+intStr0[sortedType[i]]; })
3470
- // .attr("transform", null)
3471
- // .attr("y",function(d,i) { return y(i+1)+iBarH; })
3472
- // .attr("x",function(d,i) { if (d>0) {return x(d)+2;} else {return x(d)-2; } } )
3473
- .style({
3474
- "text-anchor": function(d, i) {
3475
- if (sortedMag[i] < 0) {
3476
- return "end";
3477
- } else {
3478
- return "start";
3479
- }
3480
- },
3481
- "font-size": wordfontsize,
3482
- })
3483
- .text(function(d, i) {
3484
- return sortedWords[i];
3485
- });
3486
- }
3487
- // else apply without a transition
3488
- else {
3489
- newbars.attr({
3490
- "fill": function(d, i) {
3491
- if (sortedType[i] == 2) {
3492
- return "#4C4CFF";
3493
- } else if (sortedType[i] == 3) {
3494
- return "#FFFF4C";
3495
- } else if (sortedType[i] == 0) {
3496
- return "#B3B3FF";
3497
- } else {
3498
- return "#FFFFB3";
3499
- }
3500
- },
3501
- "class": function(d, i) {
3502
- return "shiftrect " + intStr0[sortedType[i]];
3503
- },
3504
- // "x":function(d,i) {
3505
- // if (d>0) { return figcenter; }
3506
- // else { return x(d)} },
3507
- // "y": function(d,i) { return y(i+1); },
3508
- "x": 0,
3509
- "y": 0,
3510
- "transform": function(d, i) {
3511
- if (d > 0) {
3512
- return "translate(" + figcenter + "," + y(i + 1) + ")";
3513
- } else {
3514
- return "translate(" + x(d) + "," + y(i + 1) + ")";
3515
- }
3516
- },
3517
- "height": function(d, i) {
3518
- return iBarH;
3519
- },
3520
- "width": function(d, i) {
3521
- if ((d) > 0) {
3522
- return x(d) - x(0);
3523
- } else {
3524
- return x(0) - x(d);
3525
- }
3526
- }
3527
- });
3528
-
3529
- newwords.attr({
3530
- "class": function(d, i) {
3531
- return "shifttext " + intStr0[sortedType[i]];
3532
- },
3533
- "x": 0,
3534
- "y": 0,
3535
- "transform": function(d, i) {
3536
- if (d > 0) {
3537
- return "translate(" + (x(d) + 2) + "," + (y(i + 1) + iBarH) + ")";
3538
- } else {
3539
- return "translate(" + (x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3540
- }
3541
- },
3542
- })
3543
- .style({
3544
- "text-anchor": function(d, i) {
3545
- if (sortedMag[i] < 0) {
3546
- return "end";
3547
- } else {
3548
- return "start";
3549
- }
3550
- },
3551
- "font-size": wordfontsize
3552
- })
3553
- .text(function(d, i) {
3554
- return sortedWords[i];
3555
- });
3556
-
3557
- if (shiftseldecoder().current === "posup") {
3558
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
3559
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3560
- });
3561
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
3562
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3563
- });
3564
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
3565
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3566
- });
3567
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
3568
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3569
- });
3570
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
3571
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3572
- });
3573
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
3574
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3575
- });
3576
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
3577
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
3578
- });
3579
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
3580
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3581
- });
3582
- } else if (shiftseldecoder().current === "negdown") {
3583
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
3584
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
3585
- });
3586
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
3587
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3588
- });
3589
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
3590
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3591
- });
3592
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
3593
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3594
- });
3595
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
3596
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3597
- });
3598
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
3599
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3600
- });
3601
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
3602
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3603
- });
3604
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
3605
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3606
- });
3607
- } else if (shiftseldecoder().current === "posdown") {
3608
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
3609
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3610
- });
3611
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
3612
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3613
- });
3614
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
3615
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3616
- });
3617
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
3618
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3619
- });
3620
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
3621
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3622
- });
3623
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
3624
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3625
- });
3626
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
3627
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
3628
- });
3629
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
3630
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3631
- });
3632
- } else if (shiftseldecoder().current === "negup") {
3633
- axes.selectAll("rect.shiftrect.zero").transition().duration(1000).attr("transform", function(d, i) {
3634
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3635
- });
3636
- axes.selectAll("text.shifttext.zero").transition().duration(1000).attr("transform", function(d, i) {
3637
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3638
- });
3639
- axes.selectAll("rect.shiftrect.one").transition().duration(1000).attr("transform", function(d, i) {
3640
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3641
- });
3642
- axes.selectAll("text.shifttext.one").transition().duration(1000).attr("transform", function(d, i) {
3643
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3644
- });
3645
- axes.selectAll("rect.shiftrect.two").transition().duration(1000).attr("transform", function(d, i) {
3646
- return "translate(" + ((d > 0) ? figcenter : x(d)) + "," + y(i + 1) + ")";
3647
- });
3648
- axes.selectAll("text.shifttext.two").transition().duration(1000).attr("transform", function(d, i) {
3649
- return "translate(" + ((d > 0) ? x(d) + 2 : x(d) - 2) + "," + (y(i + 1) + iBarH) + ")";
3650
- });
3651
- axes.selectAll("rect.shiftrect.three").transition().duration(1000).attr("transform", function(d, i) {
3652
- return "translate(" + ((d > 0) ? 500 : -500) + "," + y(i + 1) + ")";
3653
- });
3654
- axes.selectAll("text.shifttext.three").transition().duration(1000).attr("transform", function(d, i) {
3655
- return "translate(" + ((d > 0) ? 500 : -500) + "," + (y(i + 1) + iBarH) + ")";
3656
- });
3657
- }
3658
- }
3659
-
3660
- maxShiftSum = Math.max(Math.abs(sumTypes[1]), Math.abs(sumTypes[2]), sumTypes[0], sumTypes[3]);
3661
-
3662
- topScale.domain([-maxShiftSum, maxShiftSum]);
3663
-
3664
- // define the RHS summary bars so I can add if needed
3665
- // var summaryArray = [sumTypes[3],sumTypes[0],sumTypes[3]+sumTypes[1],d3.sum(sumTypes)];
3666
- summaryArray = [sumTypes[3], sumTypes[0], d3.sum(sumTypes)];
3667
-
3668
- var newRtopbars = axes.selectAll(".sumrectR")
3669
- .data(summaryArray);
3670
-
3671
- newRtopbars.transition().duration(1500)
3672
- .attr("x", function(d, i) {
3673
- if (d > 0) {
3674
- return figcenter;
3675
- } else {
3676
- return topScale(d)
3677
- }
3678
- })
3679
- .attr("width", function(d, i) {
3680
- if (d > 0) {
3681
- return topScale(d) - figcenter;
3682
- } else {
3683
- return figcenter - topScale(d);
3684
- }
3685
- });
3686
-
3687
- var newRtoptext = axes.selectAll(".sumtextR")
3688
- .data([sumTypes[3], sumTypes[0], d3.sum(sumTypes)]);
3689
-
3690
- newRtoptext.transition().duration(1500).attr("class", "sumtextR")
3691
- .style("text-anchor", function(d, i) {
3692
- if (d > 0) {
3693
- return "start";
3694
- } else {
3695
- return "end";
3696
- }
3697
- })
3698
- .attr("x", function(d, i) {
3699
- return topScale(d) + 5 * d / Math.abs(d);
3700
- });
3701
-
3702
- summaryArray = [sumTypes[1], sumTypes[2], sumTypes[0] + sumTypes[2]];
3703
-
3704
- var newLtopbars = axes.selectAll(".sumrectL")
3705
- .data(summaryArray);
3706
-
3707
- newLtopbars.transition().duration(1500).attr("fill", function(d, i) {
3708
- if (i == 0) {
3709
- return "#FFFFB3";
3710
- } else if (i == 1) {
3711
- return "#4C4CFF";
3712
- } else {
3713
- // choose color based on whether increasing/decreasing wins
3714
- if (d > 0) {
3715
- return "#B3B3FF";
3716
- } else {
3717
- return "#4C4CFF";
3718
- }
3719
- }
3720
- })
3721
- .attr("x", function(d, i) {
3722
- if (i < 2) {
3723
- return topScale(d);
3724
- } else {
3725
- // place the sum of negatives bar
3726
- // if they are not opposing
3727
- if ((sumTypes[3] + sumTypes[1]) * (sumTypes[0] + sumTypes[2]) > 0) {
3728
- // if positive, place at end of other bar
3729
- if (d > 0) {
3730
- return topScale((sumTypes[3] + sumTypes[1]));
3731
- }
3732
- // if negative, place at left of other bar, minus length (+topScale(d))
3733
- else {
3734
- return topScale(d) - (figcenter - topScale((sumTypes[3] + sumTypes[1])));
3735
- }
3736
- } else {
3737
- if (d > 0) {
3738
- return figcenter
3739
- } else {
3740
- return topScale(d)
3741
- }
3742
- }
3743
- }
3744
- })
3745
- .attr("width", function(d, i) {
3746
- if (d > 0) {
3747
- return topScale(d) - figcenter;
3748
- } else {
3749
- return figcenter - topScale(d);
3750
- }
3751
- });
3752
-
3753
- var newLtoptext = axes.selectAll(".sumtextL")
3754
- .data([sumTypes[1], sumTypes[2]]);
3755
-
3756
- newLtoptext.transition().duration(1500).attr("x", function(d, i) {
3757
- return topScale(d) - 5;
3758
- });
3759
-
3760
- return that;
3761
- }; // hedotools.shifter.replot
3762
-
3763
- function resizeshift() {
3764
- var that = this;
3765
-
3766
- // don't use this function...
3767
- // not sure why, but the updates don't always seem to work
3768
- // (need selections, can't pass variables that are local
3769
- // in scope)
3770
- return 1;
3771
-
3772
- fullwidth = parseInt(figure.style("width"));
3773
- boxwidth = fullwidth - margin.left - margin.right;
3774
- figwidth = boxwidth - axeslabelmargin.left - axeslabelmargin.right;
3775
- figcenter = figwidth / 2;
3776
- // console.log(figcenter);
3777
-
3778
- canvas.attr("width", boxwidth);
3779
- axes.attr("width", figwidth);
3780
-
3781
- x.range([maxWidth + 10, figwidth - maxWidth - 10]);
3782
-
3783
- topScale.range([figwidth * .12, figwidth * .88]);
3784
-
3785
- bgrect.attr("width", figwidth);
3786
- topbgrect.attr("width", figwidth - 5);
3787
- bottombgrect.attr("width", figwidth - 5);
3788
-
3789
- // fix the x axis
3790
- // canvas.select(".x.axis").call(xAxis);
3791
-
3792
- // get the x label
3793
- xlabel.transition().duration(2000).attr("x", (leftOffsetStatic + figwidth / 2))
3794
- .attr("y", boxheight - 7);
3795
- ylabel.transition().duration(2000).attr("y", figheight / 2 + 60 + toptextheight)
3796
- .attr("x", 18)
3797
- .attr("transform", "rotate(-90.0," + (18) + "," + (figheight / 2 + 60 + toptextheight) + ")");
3798
-
3799
- // the andy reagan credit
3800
- // credit.attr("x",width-7);
3801
-
3802
- // line separating summary
3803
- sepline.attr("x2", figwidth);
3804
-
3805
- axes.selectAll(".sumrectR")
3806
- .attr("x", function(d, i) {
3807
- if (d > 0) {
3808
- return figcenter;
3809
- } else {
3810
- return topScale(d)
3811
- }
3812
- })
3813
- .attr("width", function(d, i) {
3814
- if (d > 0) {
3815
- return topScale(d) - figcenter;
3816
- } else {
3817
- return figcenter - topScale(d);
3818
- }
3819
- });
3820
-
3821
- axes.selectAll(".sumtextR")
3822
- .attr("x", function(d, i) {
3823
- return topScale(d) + 5 * d / Math.abs(d);
3824
- });
3825
-
3826
- axes.selectAll(".sumrectL")
3827
- .attr("x", function(d, i) {
3828
- if (i < 2) {
3829
- return topScale(d);
3830
- } else {
3831
- // place the sum of negatives bar
3832
- // if they are not opposing
3833
- if ((sumTypes[3] + sumTypes[1]) * (sumTypes[0] + sumTypes[2]) > 0) {
3834
- // if positive, place at end of other bar
3835
- if (d > 0) {
3836
- return topScale((sumTypes[3] + sumTypes[1]));
3837
- }
3838
- // if negative, place at left of other bar, minus length (+topScale(d))
3839
- else {
3840
- return topScale(d) - (figcenter - topScale((sumTypes[3] + sumTypes[1])));
3841
- }
3842
- } else {
3843
- if (d > 0) {
3844
- return figcenter
3845
- } else {
3846
- return topScale(d)
3847
- }
3848
- }
3849
- }
3850
- })
3851
- .attr("width", function(d, i) {
3852
- if (d > 0) {
3853
- return topScale(d) - figcenter;
3854
- } else {
3855
- return figcenter - topScale(d);
3856
- }
3857
- });
3858
-
3859
- axes.selectAll(".sumtextL")
3860
- .attr("x", function(d, i) {
3861
- return topScale(d) - 5;
3862
- });
3863
-
3864
- shiftrects
3865
- .attr("x", function(d, i) {
3866
- if (d > 0) {
3867
- return figcenter;
3868
- } else {
3869
- return x(d);
3870
- }
3871
- })
3872
- .attr("width", function(d, i) {
3873
- if ((d) > 0) {
3874
- return x(d) - x(0);
3875
- } else {
3876
- return x(0) - x(d);
3877
- }
3878
- });
3879
-
3880
- // all of the lower shift text
3881
- shifttext.attr("x", function(d, i) {
3882
- if (d > 0) {
3883
- return x(d) + 2;
3884
- } else {
3885
- return x(d) - 2;
3886
- }
3887
- });
3888
-
3889
- }
3890
-
3891
- var opublic = {
3892
- shift: shift,
3893
- ignore: ignore,
3894
- setTextBold: setTextBold,
3895
- stop: stop,
3896
- istopper: istopper,
3897
- shifter: shifter,
3898
- selfShifter: selfShifter,
3899
- setfigure: setfigure,
3900
- getfigure: getfigure,
3901
- setdata: setdata,
3902
- plot: plot,
3903
- add_help_button: add_help_button,
3904
- show_x_axis: show_x_axis,
3905
- replot: replot,
3906
- table: table,
3907
- cloud: cloud,
3908
- setText: setText,
3909
- setWidth: setWidth,
3910
- setHeight: setHeight,
3911
- setBgcolor: setBgcolor,
3912
- splitstring: splitstring,
3913
- drawlogo: drawlogo,
3914
- resetbuttontoggle: resetbuttontoggle,
3915
- plotdist: plotdist,
3916
- _reset: _reset,
3917
- _stoprange: _stoprange,
3918
- _refF: _refF,
3919
- _compF: _compF,
3920
- _lens: _lens,
3921
- _complens: _complens,
3922
- _words: _words,
3923
- _words_en: _words_en,
3924
- // boatload more accessor functions
3925
- _refH: _refH,
3926
- _compH: _compH,
3927
- _xlabel_text: _xlabel_text,
3928
- _ylabel_text: _ylabel_text,
3929
- setTextColors: setTextColors,
3930
- setTopTextSizes: setTopTextSizes,
3931
- _split_top_strings: _split_top_strings,
3932
- _shiftMag: _shiftMag,
3933
- _shiftType: _shiftType,
3934
- dualShifter: dualShifter,
3935
- setFontSizes: setFontSizes,
3936
- _fontString: _fontString,
3937
- _viz_type_use_URL: _viz_type_use_URL,
3938
- _my_shift_id: _my_shift_id,
3939
- _sortedMag: _sortedMag,
3940
- _sortedType: _sortedType,
3941
- _sortedWords: _sortedWords,
3942
- _sortedWordsRaw: _sortedWordsRaw,
3943
- get_word_index: get_word_index,
3944
- }
3945
- return opublic;
3946
- };
3947
-
3948
- function cloudSpriteSimple(my_canvas_context, d, size) {
3949
- if (d.sprite) return;
3950
-
3951
- my_canvas_context.setTransform(1, 0, 0, 1, 0, 0);
3952
- my_canvas_context.clearRect(0, 0, size[0], size[1]);
3953
- my_canvas_context.save()
3954
-
3955
- // set the initial values
3956
- var x = 0;
3957
- var y = 0;
3958
- var maxh = 0;
3959
-
3960
- my_canvas_context.font = d.fontString;
3961
- my_canvas_context.textAlign = "center";
3962
- my_canvas_context.textBaseline = "bottom";
3963
- my_canvas_context.fillStyle = "red";
3964
- my_canvas_context.strokeStyle = "red";
3965
- my_canvas_context.textAlign = "center";
3966
- my_canvas_context.lineWidth = 2 * d.padding;
3967
-
3968
- var w = my_canvas_context.measureText(d.text + "m").width,
3969
- h = d.size;
3970
-
3971
- d.x0 = Math.floor(-w / 2);
3972
- d.x1 = Math.ceil(w / 2);
3973
- d.y0 = 0;
3974
- d.y1 = Math.ceil(h);
3975
-
3976
- // translate such that the rotation actually works
3977
- my_canvas_context.translate(size[0] / 2, size[1] / 2);
3978
-
3979
- my_canvas_context.rotate(d.rotate * cloudRadians);
3980
- // put it in the center (with the translation)
3981
- my_canvas_context.fillText(d.text, 0, 0);
3982
-
3983
- // test that we contain the text here
3984
- // my_canvas_context.strokeRect(d.x0, d.y0-d.y1, w, h);
3985
-
3986
- my_canvas_context.strokeText(d.text, 0, 0);
3987
- // var pixels = my_canvas_context.getImageData(0, 0, size[0], size[1]).data;
3988
- // my_canvas_context.setTransform(1, 0, 0, 1, 0, 0);
3989
- var pixels = my_canvas_context.getImageData(size[0] / 2 + d.x0, size[1] / 2 + d.y0 - d.y1, 2 * d.x1, d.y1).data;
3990
- // now let's convert this raw RGBA 0-255 data into a monochrome
3991
- d.sprite = monochrome(pixels);
3992
- my_canvas_context.restore();
3993
- }
3994
-
3995
- function monochrome(pixels) {
3996
- var a = Array(pixels.length / 4);
3997
- for (var i = 0; i < a.length; i++) {
3998
- // standard luminance scale
3999
- // var L = (0.2126 * pixels[i*4] + 0.7152 * pixels[i*4+1] + 0.0722 * pixels[i*4+2]);
4000
- // I set the canvas to only show red
4001
- var L = pixels[i * 4]
4002
- // don't multiply by the alpha, just make sure the luminance
4003
- // is more than .1 percent
4004
- if (L > (.1 * 256)) {
4005
- a[i] = 1;
4006
- } else {
4007
- a[i] = 0;
4008
- }
4009
- // a[i] = (L/256 > 0.1) ? 1 : 0;
4010
- }
4011
- return a;
4012
- }
4013
-
4014
- function collideRects(a, b) {
4015
- // a and b are both objects with x0,y0 and x1,y1 upper left and lower right points
4016
- // not right && not left && not above && not below
4017
- return b.x0 < a.x1 && b.x1 > a.x0 && b.y1 > a.y0 && b.y0 > a.y1;
4018
- // note that this may need to more complicated if the object is rotated:
4019
- // depends on the rotation
4020
- }
4021
-
4022
- var cloudRadians = Math.PI / 180;
4023
-
4024
- function indexer2d(a, w, i, ip, j, jp) {
4025
- // get a[i:ip,j:jp], where a has width w
4026
- // get the points ip and jp
4027
- // i goes down, j goes across
4028
-
4029
- // initialize result
4030
- var result = Array((ip - i + 1) * (jp - j + 1));
4031
-
4032
- // go down
4033
- for (var ii = i; ii <= ip; ii++) {
4034
- for (var jj = j; jj <= jp; jj++) {
4035
- // var flat_index = w*ii+jj;
4036
- // console.log(flat_index);
4037
- // console.log(ii*(ip-i+1)+(jj-j))
4038
- result[(ii - i) * (jp - j + 1) + (jj - j)] = a[w * ii + jj]
4039
- }
4040
- }
4041
- return result;
4042
- }
26
+ return instance;
27
+ })();