Browse Source

Add a citation to your clip.

parisminton 7 years ago
parent
commit
b4809f442f
8 changed files with 117 additions and 2 deletions
  1. 1 0
      audiogram/draw-frames.js
  2. 1 0
      audiogram/index.js
  3. 9 0
      client/index.js
  4. 7 0
      client/preview.js
  5. 6 0
      editor/index.html
  6. 5 0
      renderer/index.js
  7. 73 0
      renderer/text-wrapper.js
  8. 15 2
      settings/themes.json

+ 1 - 0
audiogram/draw-frames.js View File

25
 
25
 
26
     renderer.drawFrame(context, {
26
     renderer.drawFrame(context, {
27
       caption: options.caption,
27
       caption: options.caption,
28
+      citation: options.citation,
28
       label: options.label,
29
       label: options.label,
29
       waveform: options.waveform[frameNumber],
30
       waveform: options.waveform[frameNumber],
30
       frame: frameNumber
31
       frame: frameNumber

+ 1 - 0
audiogram/index.js View File

115
       numFrames: self.numFrames,
115
       numFrames: self.numFrames,
116
       frameDir: self.frameDir,
116
       frameDir: self.frameDir,
117
       caption: self.settings.caption,
117
       caption: self.settings.caption,
118
+      citation: self.settings.citation,
118
       label: self.settings.label,
119
       label: self.settings.label,
119
       waveform: self.waveform,
120
       waveform: self.waveform,
120
       tick: function() {
121
       tick: function() {

+ 9 - 0
client/index.js View File

58
 
58
 
59
   var theme = preview.theme(),
59
   var theme = preview.theme(),
60
       caption = preview.caption(),
60
       caption = preview.caption(),
61
+      citation = preview.citation(),
61
       label = preview.label(),
62
       label = preview.label(),
62
       selection = preview.selection(),
63
       selection = preview.selection(),
63
       file = preview.file();
64
       file = preview.file();
91
   }
92
   }
92
   formData.append("theme", JSON.stringify($.extend({}, theme, { backgroundImageFile: null })));
93
   formData.append("theme", JSON.stringify($.extend({}, theme, { backgroundImageFile: null })));
93
   formData.append("caption", caption);
94
   formData.append("caption", caption);
95
+  formData.append("citation", citation);
94
   formData.append("label", label);
96
   formData.append("label", label);
95
 
97
 
96
   setClass("loading");
98
   setClass("loading");
176
   // Get initial caption (e.g. back button)
178
   // Get initial caption (e.g. back button)
177
   d3.select("#input-caption").on("change keyup", updateCaption).each(updateCaption);
179
   d3.select("#input-caption").on("change keyup", updateCaption).each(updateCaption);
178
 
180
 
181
+  // Get initial citation (e.g. back button)
182
+  d3.select("#input-citation").on("change keyup", updateCitation).each(updateCitation);
183
+
179
   // Space bar listener for audio play/pause
184
   // Space bar listener for audio play/pause
180
   d3.select(document).on("keypress", function(){
185
   d3.select(document).on("keypress", function(){
181
     if (!d3.select("body").classed("rendered") && d3.event.key === " " && !d3.matcher("input, textarea, button, select").call(d3.event.target)) {
186
     if (!d3.select("body").classed("rendered") && d3.event.key === " " && !d3.matcher("input, textarea, button, select").call(d3.event.target)) {
245
   preview.caption(this.value);
250
   preview.caption(this.value);
246
 }
251
 }
247
 
252
 
253
+function updateCitation() {
254
+  preview.citation(this.value);
255
+}
256
+
248
 function updateLabel() {
257
 function updateLabel() {
249
   preview.label(this.value);
258
   preview.label(this.value);
250
 }
259
 }

+ 7 - 0
client/preview.js View File

10
 
10
 
11
 var theme,
11
 var theme,
12
     caption,
12
     caption,
13
+    citation,
13
     label,
14
     label,
14
     file,
15
     file,
15
     selection;
16
     selection;
26
   return arguments.length ? (caption = _, redraw()) : caption;
27
   return arguments.length ? (caption = _, redraw()) : caption;
27
 }
28
 }
28
 
29
 
30
+function _citation(_) {
31
+  return arguments.length ? (citation = _, redraw()) : citation;
32
+}
33
+
29
 function _label(_) {
34
 function _label(_) {
30
   return arguments.length ? (label = _, redraw()) : label;
35
   return arguments.length ? (label = _, redraw()) : label;
31
 }
36
 }
85
 
90
 
86
   renderer.drawFrame(context, {
91
   renderer.drawFrame(context, {
87
     caption: caption,
92
     caption: caption,
93
+    citation: citation,
88
     label: label,
94
     label: label,
89
     waveform: sampleWave,
95
     waveform: sampleWave,
90
     frame: 0
96
     frame: 0
114
 
120
 
115
 module.exports = {
121
 module.exports = {
116
   caption: _caption,
122
   caption: _caption,
123
+  citation: _citation,
117
   label: _label,
124
   label: _label,
118
   theme: _theme,
125
   theme: _theme,
119
   file: _file,
126
   file: _file,

+ 6 - 0
editor/index.html View File

40
           </label>
40
           </label>
41
           <input id="input-caption" name="caption" type="text" autocomplete="off" placeholder="Add a caption" />
41
           <input id="input-caption" name="caption" type="text" autocomplete="off" placeholder="Add a caption" />
42
         </div>
42
         </div>
43
+        <div class="row form-row" id="row-citation">
44
+          <label for="input-citation">
45
+            Citation
46
+          </label>
47
+          <input id="input-citation" name="citation" type="text" autocomplete="off" placeholder="Who's being quoted? In what context?" />
48
+        </div>
43
         <div id="preview">
49
         <div id="preview">
44
           <div style="background-color: black;">
50
           <div style="background-color: black;">
45
             <div id="canvas">
51
             <div id="canvas">

+ 5 - 0
renderer/index.js View File

58
       wrapText(context, options.caption, 'caption');
58
       wrapText(context, options.caption, 'caption');
59
     }
59
     }
60
 
60
 
61
+    // Write the citation
62
+    if (options.citation) {
63
+      wrapText(context, options.citation, 'citation');
64
+    }
65
+
61
     // Write the label
66
     // Write the label
62
     if (options.label) {
67
     if (options.label) {
63
       wrapText(context, options.label, 'label');
68
       wrapText(context, options.label, 'label');

+ 73 - 0
renderer/text-wrapper.js View File

7
       right = ifNumeric(theme.captionRight, theme.width),
7
       right = ifNumeric(theme.captionRight, theme.width),
8
       bottom = ifNumeric(theme.captionBottom, null),
8
       bottom = ifNumeric(theme.captionBottom, null),
9
       top = ifNumeric(theme.captionTop, null),
9
       top = ifNumeric(theme.captionTop, null),
10
+      citationLeft = ifNumeric(theme.citationLeft, 0),
11
+      citationRight = ifNumeric(theme.citationRight, theme.width),
12
+      citationBottom = ifNumeric(theme.citationBottom, null),
13
+      citationTop = ifNumeric(theme.citationTop, null),
10
       labelLeft = ifNumeric(theme.labelLeft, 0),
14
       labelLeft = ifNumeric(theme.labelLeft, 0),
11
       labelRight = ifNumeric(theme.labelRight, theme.width),
15
       labelRight = ifNumeric(theme.labelRight, theme.width),
12
       labelBottom = ifNumeric(theme.labelBottom, null),
16
       labelBottom = ifNumeric(theme.labelBottom, null),
23
   }
27
   }
24
 
28
 
25
   var captionWidth = right - left,
29
   var captionWidth = right - left,
30
+      citationWidth = citationRight - citationLeft;
26
       labelWidth = labelRight - labelLeft;
31
       labelWidth = labelRight - labelLeft;
27
 
32
 
28
   return function(context, caption, type) {
33
   return function(context, caption, type) {
98
     } // end if caption
103
     } // end if caption
99
 
104
 
100
 
105
 
106
+    if (type === 'citation') {
107
+      var lines = [[]],
108
+          maxWidth = 0,
109
+          words = smartquotes(caption + "").trim().replace(/\s\s+/g, " \n").split(/ /g);
110
+
111
+      context.font = theme.citationFont;
112
+      context.textBaseline = "top";
113
+      context.textAlign = theme.citationAlign || "center";
114
+
115
+      // Check whether each word exceeds the width limit
116
+      // Wrap onto next line as needed
117
+      words.forEach(function(word,i){
118
+
119
+        var width = context.measureText(lines[lines.length - 1].concat([word]).join(" ")).width;
120
+
121
+        if (word[0] === "\n" || (lines[lines.length - 1].length && width > citationWidth)) {
122
+
123
+          word = word.trim();
124
+          lines.push([word]);
125
+          width = context.measureText(word).width;
126
+
127
+        } else {
128
+
129
+          word = (i === 0) ? '— ' + word : word;
130
+          lines[lines.length - 1].push(word);
131
+
132
+        }
133
+
134
+        maxWidth = Math.max(maxWidth,width);
135
+
136
+      });
137
+
138
+      var totalHeight = lines.length * theme.citationLineHeight + (lines.length - 1) * theme.citationLineSpacing;
139
+
140
+      // horizontal alignment
141
+      var x = theme.citationAlign === "left" ? left : theme.citationAlign === "right" ? right : (left + right) / 2;
142
+
143
+      // Vertical alignment
144
+      var y;
145
+
146
+      if (citationTop !== null && citationBottom !== null) {
147
+        // Vertical center
148
+        y = (citationBottom + citationTop - totalHeight) / 2;
149
+      } else if (citationBottom !== null) {
150
+        // Vertical align bottom
151
+        y = citationBottom - totalHeight;
152
+      } else {
153
+        // Vertical align top
154
+        y = citationTop;
155
+      }
156
+
157
+      // draw citation
158
+      context.fillStyle = theme.citationColor;
159
+      lines.forEach(function(line, i){
160
+
161
+        // negative indentation for opening em dash
162
+        var indented_x = (x + 50);
163
+
164
+        if (i === 0 && /^—/.test(line[0])) {
165
+          context.fillText(line.join(" "), x, y + i * (theme.citationLineHeight + theme.citationLineSpacing));
166
+        }
167
+        else {
168
+          context.fillText(line.join(" "), indented_x, y + i * (theme.citationLineHeight + theme.citationLineSpacing));
169
+        }
170
+      });
171
+    } // end if citation
172
+
173
+
101
     if (type === 'label' && caption != 'None') {
174
     if (type === 'label' && caption != 'None') {
102
       var lines = [[]],
175
       var lines = [[]],
103
           maxWidth = 0,
176
           maxWidth = 0,

+ 15 - 2
settings/themes.json View File

12
     "captionTop": 70,
12
     "captionTop": 70,
13
     "captionLeft": 50,
13
     "captionLeft": 50,
14
     "captionRight": 860,
14
     "captionRight": 860,
15
-    "captionFont": "300 71px 'NYT Franklin Light'",
16
-    "captionLineHeight": 80,
15
+    "captionFont": "300 68px 'NYT Franklin Light'",
16
+    "captionLineHeight": 76,
17
     "captionLineSpacing": 7,
17
     "captionLineSpacing": 7,
18
+    "citationAlign": "left",
19
+    "citationFont": "300 38px 'NYT Franklin Light'",
20
+    "citationTopMargin": 40,
21
+    "citationTop": 342,
22
+    "citationLeft": 50,
23
+    "citationRight": 890,
24
+    "citationMaxBottom": 390,
25
+    "citationLineHeight": 38,
26
+    "citationLineSpacing": 7,
18
     "labelFont": "44px 'NYT Karnak'",
27
     "labelFont": "44px 'NYT Karnak'",
19
     "labelAlign": "left",
28
     "labelAlign": "left",
20
     "labelTop": 470,
29
     "labelTop": 470,
25
   "NYT Light": {
34
   "NYT Light": {
26
     "waveColor": "#d9d9d9",
35
     "waveColor": "#d9d9d9",
27
     "foregroundColor": "#000",
36
     "foregroundColor": "#000",
37
+    "citationColor": "#000",
28
     "backgroundImage": "t_logo_light.png",
38
     "backgroundImage": "t_logo_light.png",
29
     "labelColor": "#000"
39
     "labelColor": "#000"
30
   },
40
   },
32
     "backgroundColor": "#000",
42
     "backgroundColor": "#000",
33
     "waveColor": "#4d4d4d",
43
     "waveColor": "#4d4d4d",
34
     "foregroundColor": "#fff",
44
     "foregroundColor": "#fff",
45
+    "citationColor": "#fff",
35
     "backgroundImage": "t_logo_dark.png",
46
     "backgroundImage": "t_logo_dark.png",
36
     "labelColor": "#fff"
47
     "labelColor": "#fff"
37
   },
48
   },
38
   "Still Processing": {
49
   "Still Processing": {
39
     "waveColor": "rgba(102, 80, 62, 0.25)",
50
     "waveColor": "rgba(102, 80, 62, 0.25)",
40
     "foregroundColor": "#66503e",
51
     "foregroundColor": "#66503e",
52
+    "citationColor": "#66503e",
41
     "backgroundColor": "#f4d7b9",
53
     "backgroundColor": "#f4d7b9",
42
     "backgroundImage": "t_logo_white_alpha.png",
54
     "backgroundImage": "t_logo_white_alpha.png",
43
     "labelColor": "#fff",
55
     "labelColor": "#fff",
46
   "The Daily": {
58
   "The Daily": {
47
     "waveColor": "rgba(102, 102, 102, 0.25)",
59
     "waveColor": "rgba(102, 102, 102, 0.25)",
48
     "foregroundColor": "#fff",
60
     "foregroundColor": "#fff",
61
+    "citationColor": "#fff",
49
     "backgroundColor": "#f4d7b9",
62
     "backgroundColor": "#f4d7b9",
50
     "backgroundImage": "the_daily_audiogram_background.png",
63
     "backgroundImage": "the_daily_audiogram_background.png",
51
     "labelColor": "#fff",
64
     "labelColor": "#fff",