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