timeline_setter 0.1.0 → 0.1.1

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.
@@ -237,6 +237,27 @@ A new instance of CLI.
237
237
 
238
238
 
239
239
 
240
+ <span class="summary_desc"><div class='inline'></div></span>
241
+
242
+ </li>
243
+
244
+
245
+ <li class="public ">
246
+ <span class="summary_signature">
247
+
248
+ <a href="#timeline_page_path-instance_method" title="#timeline_page_path (instance method)">- (Object) <strong>timeline_page_path</strong> </a>
249
+
250
+
251
+
252
+ </span>
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
240
261
  <span class="summary_desc"><div class='inline'></div></span>
241
262
 
242
263
  </li>
@@ -308,10 +329,6 @@ A new instance of CLI
308
329
  <pre class="lines">
309
330
 
310
331
 
311
- 68
312
- 69
313
- 70
314
- 71
315
332
  72
316
333
  73
317
334
  74
@@ -323,17 +340,21 @@ A new instance of CLI
323
340
  80
324
341
  81
325
342
  82
326
- 83</pre>
343
+ 83
344
+ 84
345
+ 85
346
+ 86
347
+ 87</pre>
327
348
  </td>
328
349
  <td>
329
- <pre class="code"><span class="info file"># File 'lib/timeline_setter/cli.rb', line 68</span>
350
+ <pre class="code"><span class="info file"># File 'lib/timeline_setter/cli.rb', line 72</span>
330
351
 
331
352
  <span class='def def kw'>def</span> <span class='compile! fid id'>compile!</span>
332
353
  <span class='if if kw'>if</span> <span class='@options ivar id'>@options</span><span class='lbrack token'>[</span><span class='symbol val'>:assets</span><span class='rbrack token'>]</span>
333
354
  <span class='FileUtils constant id'>FileUtils</span><span class='dot token'>.</span><span class='cp_r identifier id'>cp_r</span><span class='lparen token'>(</span><span class='Dir constant id'>Dir</span><span class='dot token'>.</span><span class='glob identifier id'>glob</span><span class='lparen token'>(</span><span class='dstring node'>&quot;#{TimelineSetter::ROOT}/public/*&quot;</span><span class='rparen token'>)</span><span class='comma token'>,</span> <span class='outdir identifier id'>outdir</span><span class='rparen token'>)</span>
334
355
  <span class='end end kw'>end</span>
335
356
 
336
- <span class='File constant id'>File</span><span class='dot token'>.</span><span class='open identifier id'>open</span><span class='lparen token'>(</span><span class='outdir identifier id'>outdir</span> <span class='plus op'>+</span> <span class='string val'>'timeline.html'</span><span class='comma token'>,</span> <span class='string val'>'w+'</span><span class='rparen token'>)</span> <span class='do do kw'>do</span> <span class='bitor op'>|</span><span class='doc identifier id'>doc</span><span class='bitor op'>|</span>
357
+ <span class='File constant id'>File</span><span class='dot token'>.</span><span class='open identifier id'>open</span><span class='lparen token'>(</span><span class='timeline_page_path identifier id'>timeline_page_path</span><span class='comma token'>,</span> <span class='string val'>'w+'</span><span class='rparen token'>)</span> <span class='do do kw'>do</span> <span class='bitor op'>|</span><span class='doc identifier id'>doc</span><span class='bitor op'>|</span>
337
358
  <span class='doc identifier id'>doc</span><span class='dot token'>.</span><span class='write identifier id'>write</span> <span class='html identifier id'>html</span>
338
359
  <span class='end end kw'>end</span>
339
360
 
@@ -341,7 +362,7 @@ A new instance of CLI
341
362
 
342
363
  <span class='if if kw'>if</span> <span class='@options ivar id'>@options</span><span class='lbrack token'>[</span><span class='symbol val'>:open</span><span class='rbrack token'>]</span>
343
364
  <span class='puts identifier id'>puts</span> <span class='string val'>&quot;== Opening ...&quot;</span>
344
- <span class='dxstring node'>%x{ open #{outdir}timeline.html }</span>
365
+ <span class='dxstring node'>%x[ open #{timeline_page_path} ]</span>
345
366
  <span class='end end kw'>end</span>
346
367
  <span class='end end kw'>end</span>
347
368
  </pre>
@@ -559,6 +580,35 @@ A new instance of CLI
559
580
  </td>
560
581
  </tr>
561
582
  </table>
583
+ </div>
584
+
585
+ <div class="method_details ">
586
+ <p class="signature " id="timeline_page_path-instance_method">
587
+
588
+ - (<tt>Object</tt>) <strong>timeline_page_path</strong>
589
+
590
+
591
+
592
+ </p><table class="source_code">
593
+ <tr>
594
+ <td>
595
+ <pre class="lines">
596
+
597
+
598
+ 68
599
+ 69
600
+ 70</pre>
601
+ </td>
602
+ <td>
603
+ <pre class="code"><span class="info file"># File 'lib/timeline_setter/cli.rb', line 68</span>
604
+
605
+ <span class='def def kw'>def</span> <span class='timeline_page_path identifier id'>timeline_page_path</span>
606
+ <span class='File constant id'>File</span><span class='dot token'>.</span><span class='join identifier id'>join</span><span class='lparen token'>(</span><span class='outdir identifier id'>outdir</span><span class='comma token'>,</span> <span class='string val'>'timeline.html'</span><span class='rparen token'>)</span>
607
+ <span class='end end kw'>end</span>
608
+ </pre>
609
+ </td>
610
+ </tr>
611
+ </table>
562
612
  </div>
563
613
 
564
614
  </div>
@@ -566,7 +616,7 @@ A new instance of CLI
566
616
  </div>
567
617
 
568
618
  <div id="footer">
569
- Generated on Mon Apr 4 11:05:25 2011 by
619
+ Generated on Wed Apr 6 10:07:07 2011 by
570
620
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
571
621
  0.6.5 (ruby-1.8.7).
572
622
  </div>
@@ -276,7 +276,7 @@ Returns the value of attribute events
276
276
  </div>
277
277
 
278
278
  <div id="footer">
279
- Generated on Mon Apr 4 11:05:24 2011 by
279
+ Generated on Wed Apr 6 10:07:08 2011 by
280
280
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
281
281
  0.6.5 (ruby-1.8.7).
282
282
  </div>
@@ -504,7 +504,7 @@ the events hash to JSON to stick into our HTML.
504
504
  </div>
505
505
 
506
506
  <div id="footer">
507
- Generated on Mon Apr 4 11:05:24 2011 by
507
+ Generated on Wed Apr 6 10:07:08 2011 by
508
508
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
509
509
  0.6.5 (ruby-1.8.7).
510
510
  </div>
@@ -103,7 +103,7 @@
103
103
  </div>
104
104
 
105
105
  <div id="footer">
106
- Generated on Mon Apr 4 11:05:25 2011 by
106
+ Generated on Wed Apr 6 10:07:08 2011 by
107
107
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
108
  0.6.5 (ruby-1.8.7).
109
109
  </div>
@@ -123,7 +123,7 @@
123
123
  </div>
124
124
 
125
125
  <div id="footer">
126
- Generated on Mon Apr 4 11:05:22 2011 by
126
+ Generated on Wed Apr 6 10:07:06 2011 by
127
127
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
128
128
  0.6.5 (ruby-1.8.7).
129
129
  </div>
@@ -61,7 +61,7 @@
61
61
  </div></div>
62
62
 
63
63
  <div id="footer">
64
- Generated on Mon Apr 4 11:05:22 2011 by
64
+ Generated on Wed Apr 6 10:07:06 2011 by
65
65
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
66
66
  0.6.5 (ruby-1.8.7).
67
67
  </div>
@@ -61,7 +61,7 @@
61
61
  </div></div>
62
62
 
63
63
  <div id="footer">
64
- Generated on Mon Apr 4 11:05:22 2011 by
64
+ Generated on Wed Apr 6 10:07:06 2011 by
65
65
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
66
66
  0.6.5 (ruby-1.8.7).
67
67
  </div>
@@ -61,17 +61,17 @@
61
61
 
62
62
 
63
63
  <li class="r1 ">
64
- <span class='object_link'><a href="TimelineSetter/Timeline.html#initialize-instance_method" title="TimelineSetter::Timeline#initialize (method)">#initialize</a></span>
64
+ <span class='object_link'><a href="TimelineSetter/CLI.html#initialize-instance_method" title="TimelineSetter::CLI#initialize (method)">#initialize</a></span>
65
65
 
66
- <small>TimelineSetter::Timeline</small>
66
+ <small>TimelineSetter::CLI</small>
67
67
 
68
68
  </li>
69
69
 
70
70
 
71
71
  <li class="r2 ">
72
- <span class='object_link'><a href="TimelineSetter/CLI.html#initialize-instance_method" title="TimelineSetter::CLI#initialize (method)">#initialize</a></span>
72
+ <span class='object_link'><a href="TimelineSetter/Timeline.html#initialize-instance_method" title="TimelineSetter::Timeline#initialize (method)">#initialize</a></span>
73
73
 
74
- <small>TimelineSetter::CLI</small>
74
+ <small>TimelineSetter::Timeline</small>
75
75
 
76
76
  </li>
77
77
 
@@ -133,6 +133,14 @@
133
133
 
134
134
 
135
135
  <li class="r2 ">
136
+ <span class='object_link'><a href="TimelineSetter/CLI.html#timeline_page_path-instance_method" title="TimelineSetter::CLI#timeline_page_path (method)">#timeline_page_path</a></span>
137
+
138
+ <small>TimelineSetter::CLI</small>
139
+
140
+ </li>
141
+
142
+
143
+ <li class="r1 ">
136
144
  <span class='object_link'><a href="TimelineSetter/Timeline.html#tmpl-instance_method" title="TimelineSetter::Timeline#tmpl (method)">#tmpl</a></span>
137
145
 
138
146
  <small>TimelineSetter::Timeline</small>
@@ -140,7 +148,7 @@
140
148
  </li>
141
149
 
142
150
 
143
- <li class="r1 ">
151
+ <li class="r2 ">
144
152
  <span class='object_link'><a href="TimelineSetter/Timeline.html#to_json-instance_method" title="TimelineSetter::Timeline#to_json (method)">#to_json</a></span>
145
153
 
146
154
  <small>TimelineSetter::Timeline</small>
@@ -79,7 +79,7 @@
79
79
  </div>
80
80
 
81
81
  <div id="footer">
82
- Generated on Mon Apr 4 11:05:25 2011 by
82
+ Generated on Wed Apr 6 10:07:08 2011 by
83
83
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
84
84
  0.6.5 (ruby-1.8.7).
85
85
  </div>
data/index.html CHANGED
@@ -180,7 +180,7 @@ supporting assets if applicable) within the current directory.</p>
180
180
 
181
181
  <p>TimelineSetter looks for certain column names in your CSV file in order to
182
182
  generate a timeline. All columns are required, though as you&rsquo;ll see, some of
183
- them can be left blank. Here&rsquo;s a summary of each column and its significance:</p>
183
+ them can be left blank (see a <a href="https://github.com/propublica/timeline-setter/blob/master/spec/test_data.csv">sample CSV</a>). Here&rsquo;s a summary of each column and its significance:</p>
184
184
 
185
185
  <p><a id="date-csv"></a></p>
186
186
 
@@ -230,7 +230,7 @@ best not to assign a name.</p>
230
230
  <p>Any arbitrary HTML that will be inserted above <code>description</code>. This
231
231
  field may contain image tags, YouTube tags, etc. &mdash; nearly everything except
232
232
  <code>&lt;script&gt;</code> tags. If you choose to use JavaScript, you must do it inside an
233
- iframe and call that iframe inside this field.</p>
233
+ iframe and call that iframe inside this field. <strong>Note</strong>: If you put an image or iframe in this field, make sure to set <code>height</code> and <code>width</code> attributes, or the card may not extend around the image.</p>
234
234
 
235
235
  <p><a id="deployment"></a></p>
236
236
 
@@ -343,6 +343,7 @@ Feb. 21, 1952 and Jan. 26, 1957, as shown
343
343
 
344
344
  <ul>
345
345
  <li>In the Wild: <a href="http://www.propublica.org/special/tbi-psycho-platoon-timeline">ProPublica: How One Blast Affected Five Soldiers</a></li>
346
+ <li>In the Wild: <a href="http://www.talkingpointsmemo.com/interactive/2011/04/the-wisconsin-union-struggle-timeline.php">TPM: The Wisconsin Union Struggle Timeline</a></li>
346
347
  </ul>
347
348
 
348
349
 
@@ -63,13 +63,17 @@ module TimelineSetter
63
63
  def outdir
64
64
  @options[:output] ? @options[:output] : "#{`pwd`.strip}/"
65
65
  end
66
+
67
+ def timeline_page_path
68
+ File.join(outdir, 'timeline.html')
69
+ end
66
70
 
67
71
  def compile!
68
72
  if @options[:assets]
69
73
  FileUtils.cp_r(Dir.glob("#{TimelineSetter::ROOT}/public/*"), outdir)
70
74
  end
71
75
 
72
- File.open(outdir + 'timeline.html', 'w+') do |doc|
76
+ File.open(timeline_page_path, 'w+') do |doc|
73
77
  doc.write html
74
78
  end
75
79
 
@@ -77,7 +81,7 @@ module TimelineSetter
77
81
 
78
82
  if @options[:open]
79
83
  puts "== Opening ..."
80
- %x{ open #{outdir}timeline.html }
84
+ %x[ open #{timeline_page_path} ]
81
85
  end
82
86
  end
83
87
 
@@ -10,7 +10,7 @@ module TimelineSetter
10
10
  # Convert human dates to timestamps, sort the hash by timestamp, and
11
11
  # convert the events hash to JSON to stick into our HTML.
12
12
  def to_json
13
- @events.collect {|r| r[:timestamp] = Time.parse(r[:date]).to_i * 1000 }.sort{|a,b| b[:timestamp] <=> a[:timestamp]}
13
+ @events.each {|r| r[:timestamp] = Time.parse(r[:date]).to_i * 1000 }
14
14
  @events.to_json
15
15
  end
16
16
 
@@ -1,3 +1,3 @@
1
1
  module TimelineSetter
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -21,7 +21,7 @@
21
21
 
22
22
  // Invoke all callbacks registered to the object with `bind`.
23
23
  obj.trigger = function(){
24
- if(!this._callbacks) return;
24
+ if (!this._callbacks) return;
25
25
  for(var i = 0; callback = this._callbacks[i]; i++)
26
26
  callback.apply(this, arguments);
27
27
  };
@@ -37,9 +37,9 @@
37
37
  // message passing. So each registered callback first checks to see if the
38
38
  // event fired matches the event it is listening for.
39
39
  obj.move = function(e){
40
- if(!e.type === "move" || !e.deltaX) return;
40
+ if (!e.type === "move" || !e.deltaX) return;
41
41
 
42
- if(_.isUndefined(this.currOffset)) this.currOffset = 0;
42
+ if (_.isUndefined(this.currOffset)) this.currOffset = 0;
43
43
  this.currOffset += e.deltaX;
44
44
  this.el.css({"left" : this.currOffset});
45
45
  };
@@ -48,7 +48,7 @@
48
48
  // in order to zoom the Timeline all that's needed is to increase or decrease
49
49
  // the percentage width.
50
50
  obj.zoom = function(e){
51
- if(!e.type === "zoom") return;
51
+ if (!e.type === "zoom") return;
52
52
  this.el.css({ "width": e.width });
53
53
  };
54
54
  };
@@ -60,7 +60,7 @@
60
60
 
61
61
  // Check to see if we're on a mobile device.
62
62
  var touchInit = 'ontouchstart' in document;
63
- if(touchInit) jQuery.event.props.push("touches");
63
+ if (touchInit) jQuery.event.props.push("touches");
64
64
 
65
65
  // The `draggable` plugin tracks changes in X offsets due to mouse movement
66
66
  // or finger gestures and proxies associated events on a particular element.
@@ -78,7 +78,7 @@
78
78
 
79
79
  // The user is interacting; capture the offset and trigger a `dragging` event.
80
80
  function mousemove(e){
81
- if(!drag) return;
81
+ if (!drag) return;
82
82
  e.preventDefault();
83
83
  e.type = "dragging";
84
84
  e = _.extend(e, {
@@ -90,13 +90,13 @@
90
90
 
91
91
  // We're done tracking the movement set drag back to `null` for the next event.
92
92
  function mouseup(e){
93
- if(!drag) return;
93
+ if (!drag) return;
94
94
  drag = null;
95
95
  e.type = "dragend";
96
96
  obj.el.trigger(e);
97
97
  };
98
98
 
99
- if(!touchInit) {
99
+ if (!touchInit) {
100
100
  // Bind on mouse events if we have a mouse...
101
101
  obj.el.bind("mousedown", mousedown);
102
102
 
@@ -130,7 +130,7 @@
130
130
  function mousewheel(e){
131
131
  e.preventDefault();
132
132
  var delta = (e.wheelDelta || -e.detail);
133
- if(safari){
133
+ if (safari){
134
134
  var negative = delta < 0 ? -1 : 1;
135
135
  delta = Math.log(Math.abs(delta)) * negative * 2;
136
136
  };
@@ -288,7 +288,7 @@
288
288
  var events = Array.prototype.slice.call(arguments, 2);
289
289
  _.each(events, function(ev){
290
290
  origin.bind(function(e){
291
- if(e.type === ev && listener[ev])
291
+ if (e.type === ev && listener[ev])
292
292
  listener[ev](e);
293
293
  });
294
294
  });
@@ -302,7 +302,7 @@
302
302
  // Simple function to strip suffixes like `"px"` and return a clean integer for
303
303
  // use.
304
304
  var cleanNumber = function(str){
305
- return parseInt(str.replace(/^[^+\-\d]?([+\-]\d+)?.*$/, "$1"), 10);
305
+ return parseInt(str.replace(/^[^+\-\d]?([+\-]?\d+)?.*$/, "$1"), 10);
306
306
  };
307
307
 
308
308
  // Zero pad a number less than 10 and return a 2 digit value.
@@ -362,7 +362,7 @@
362
362
  // takes a json array of card representations and then builds series, calculates
363
363
  // intervals `sync`s the `Bar` and `CardContainer` objects and triggers the
364
364
  // `render` event.
365
- var Timeline = TimelineSetter.Timeline = function(data) {
365
+ var Timeline = TimelineSetter.Timeline = function(data) {
366
366
  data = data.sort(function(a, b){ return a.timestamp - b.timestamp; });
367
367
  this.bySid = {};
368
368
  this.series = [];
@@ -394,12 +394,13 @@
394
394
  // in the `bySid` object add it. Then add a card to the `Series` and extend
395
395
  // the global `bounds`.
396
396
  add : function(card){
397
- if(!(card.series in this.bySid)){
397
+ if (!(card.series in this.bySid)){
398
398
  this.bySid[card.series] = new Series(card, this);
399
399
  this.series.push(this.bySid[card.series]);
400
400
  }
401
401
  var series = this.bySid[card.series];
402
402
  series.add(card);
403
+
403
404
  this.bounds.extend(series.max());
404
405
  this.bounds.extend(series.min());
405
406
  }
@@ -441,11 +442,11 @@
441
442
  var pOffset = parent.offset().left;
442
443
  var offset = this.el.offset().left;
443
444
  var width = this.el.width();
444
- if(_.isUndefined(e.deltaX)) e.deltaX = 0;
445
+ if (_.isUndefined(e.deltaX)) e.deltaX = 0;
445
446
 
446
- if(offset + width + e.deltaX < pOffset + parent.width())
447
+ if (offset + width + e.deltaX < pOffset + parent.width())
447
448
  e.deltaX = (pOffset + parent.width()) - (offset + width);
448
- if(offset + e.deltaX > pOffset)
449
+ if (offset + e.deltaX > pOffset)
449
450
  e.deltaX = pOffset - offset;
450
451
 
451
452
  e.type = "move";
@@ -543,8 +544,8 @@
543
544
  // Create and append the label to `.TS-series_nav_container` and bind up
544
545
  // `hideNotches` and `showNotches`.
545
546
  render : function(e){
546
- if(!e.type === "render") return;
547
- if(this.name.length === 0) return;
547
+ if (!e.type === "render") return;
548
+ if (this.name.length === 0) return;
548
549
  this.el = $(this.template(this));
549
550
  $(".TS-series_nav_container").append(this.el);
550
551
  this.el.toggle(this.hideNotches, this.showNotches);
@@ -567,12 +568,13 @@
567
568
  this.timestamp = card.timestamp;
568
569
  this.attributes = card;
569
570
  this.attributes.topcolor = series.color;
571
+
570
572
  this.template = template("#TS-card_tmpl");
571
573
  this.ntemplate = template("#TS-notch_tmpl");
572
- _.bindAll(this, "render", "activate", "position", "setPermalink", "toggleNotch");
574
+ _.bindAll(this, "render", "activate", "flip", "setPermalink", "toggleNotch");
573
575
  this.series.bind(this.toggleNotch);
574
576
  this.series.timeline.bind(this.render);
575
- this.series.timeline.bar.bind(this.position);
577
+ this.series.timeline.bar.bind(this.flip);
576
578
  this.id = [
577
579
  this.get('timestamp'),
578
580
  this.get('description').split(/ /)[0].replace(/[^a-zA-Z\-]/g,"")
@@ -594,7 +596,7 @@
594
596
  // `Bar` and binds a click handler so it can be activated. if the `Card`'s id
595
597
  // is currently selected via `window.location.hash` it's activated.
596
598
  render : function(e){
597
- if(!e.type === "render") return;
599
+ if (!e.type === "render") return;
598
600
  this.offset = this.series.timeline.bounds.project(this.timestamp, 100);
599
601
  var html = this.ntemplate(this.attributes);
600
602
  this.notch = $(html).css({"left": this.offset + "%"});
@@ -603,55 +605,36 @@
603
605
  if (history.get() === this.id) this.activate();
604
606
  },
605
607
 
606
- // As the `Bar` moves each card checks to see if it's outside the viewport,
608
+ // As the `Bar` moves the current card checks to see if it's outside the viewport,
607
609
  // if it is the card is flipped so as to be visible for the longest period
608
- // of time.
609
- position : function(e) {
610
- if (e.type !== "move" || !this.el) return;
611
- var onBarEdge = this.cardOffset().onBarEdge;
612
-
613
- switch(onBarEdge) {
614
- case 'right':
615
- this.el.css({"margin-left": -(this.cardOffset().item.width() + 7)});
616
- this.$(".TS-css_arrow").css("left", this.cardOffset().item.width());
617
- break;
618
- case 'default':
619
- this.el.css({"margin-left": this.originalMargin});
620
- this.$(".TS-css_arrow").css("left", 0);
610
+ // of time. The magic number here (7) is half the width of the css arrow.
611
+ flip : function(e) {
612
+ if (e.type !== "move" || !this.el || !this.el.is(":visible")) return;
613
+ var rightEdge = this.$(".TS-item").offset().left + this.$(".TS-item").width();
614
+ var tRightEdge = $("#timeline_setter").offset().left + $("#timeline_setter").width();
615
+ var margin = this.el.css("margin-left") === this.originalMargin;
616
+ var flippable = this.$(".TS-item").width() < $("#timeline_setter").width() / 2;
617
+ var offTimeline = this.el.position().left - this.$(".TS-item").width() < 0;
618
+
619
+ // If the card's right edge is more than the timeline's right edge and
620
+ // it's never been flipped before and it won't go off the timeline when
621
+ // flipped. We'll flip it.
622
+ if (tRightEdge - rightEdge < 0 && margin && !offTimeline) {
623
+ this.el.css({"margin-left": -(this.$(".TS-item").width() + 7)});
624
+ this.$(".TS-css_arrow").css({"left" : this.$(".TS-item").width()});
625
+ // Otherwise, if the card is off the left side of the timeline and we have
626
+ // flipped it before and the card's width is less than half of the width
627
+ // of the whole timeline, we'll flip it to the default position.
628
+ } else if (this.el.offset().left - $("#timeline_setter").offset().left < 0 && !margin && flippable) {
629
+ this.el.css({"margin-left": this.originalMargin});
630
+ this.$(".TS-css_arrow").css({"left": 0});
621
631
  }
622
632
  },
623
633
 
624
- // A utility function to suss out whether the card is fully viewable.
625
- cardOffset : function() {
626
- if (!this.el) return { onBarEdge : false };
627
-
628
- var that = this;
629
- var item = this.el.children(".TS-item");
630
- var currentMargin = this.el.css("margin-left");
631
- var timeline = $("#timeline_setter");
632
- var right = (this.el.offset().left + item.width()) - (timeline.offset().left + timeline.width());
633
- var left = (this.el.offset().left) - timeline.offset().left;
634
-
635
- return {
636
- item : item,
637
- onBarEdge : (right > 0 && currentMargin === that.originalMargin) ?
638
- 'right' :
639
- (left < 0 && that.el.css("margin-left") !== that.originalMargin) ?
640
- 'default' :
641
- (left < 0 && that.el.css("margin-left") === that.originalMargin) ?
642
- 'left' :
643
- false
644
- };
645
- },
646
-
647
634
  // The first time a card is activated it renders its `template` and appends
648
- // its element to the `Bar`. After doing so it moves the `Bar` if its
649
- // element isn't currently visible. For ie each card sets the width of
650
- // `.TS-item_label` to the maximum width of the card's children, or
651
- // if that is less than the `.TS-item_year` element's width, `.TS-item_label`
652
- // gets `.TS-item_year`s width. Which is a funny way of saying, if you'd
653
- // like to set the width of the card as a whole, fiddle with `.TS-item_year`s
654
- // width.
635
+ // its element to the `Bar`. After doing so it sets the width if `.TS-item_label`
636
+ // and moves the `Bar` if its element outside the visible portion of the
637
+ // timeline.
655
638
  activate : function(e){
656
639
  this.hideActiveCard();
657
640
  if (!this.el) {
@@ -660,36 +643,47 @@
660
643
  $("#TS-card_scroller_inner").append(this.el);
661
644
  this.originalMargin = this.el.css("margin-left");
662
645
  this.el.delegate(".TS-permalink", "click", this.setPermalink);
646
+ // Reactivate if there are images in the html so we can recalculate
647
+ // widths and position accordingly.
648
+ this.$("img").load(this.activate);
663
649
  }
664
-
665
650
  this.el.show().addClass(("TS-card_active"));
666
-
651
+ this.notch.addClass("TS-notch_active");
652
+ this.setWidth();
653
+
654
+ // In the case that the card is outside the bounds the wrong way when
655
+ // it's flipped, we'll take care of it here before we move the actual
656
+ // card.
657
+ this.flip($.Event("move"));
658
+ this.move();
659
+ },
660
+
661
+ // For Internet Explorer each card sets the width of` .TS-item_label` to
662
+ // the maximum width of the card's children, or if that is less than the
663
+ // `.TS-item_year` element's width, `.TS-item_label` gets `.TS-item_year`s
664
+ // width. Which is a funny way of saying, if you'd like to set the width of
665
+ // the card as a whole, fiddle with `.TS-item_year`s width.
666
+ setWidth : function(){
667
667
  var max = _.max(_.toArray(this.$(".TS-item_user_html").children()), function(el){ return $(el).width(); });
668
- if($(max).width() > this.$(".TS-item_year").width()){
668
+ if ($(max).width() > this.$(".TS-item_year").width()) {
669
669
  this.$(".TS-item_label").css("width", $(max).width());
670
670
  } else {
671
671
  this.$(".TS-item_label").css("width", this.$(".TS-item_year").width());
672
672
  }
673
-
674
- this.moveBarWithCard();
675
- this.notch.addClass("TS-notch_active");
676
673
  },
677
674
 
678
- // Move the `Bar` if the `Card`'s element isn't visible.
679
- moveBarWithCard : function() {
675
+ // Move the `Bar` if the card is outside the visible region on activation.
676
+ move : function() {
680
677
  var e = $.Event('moving');
681
- var onBarEdge = this.cardOffset().onBarEdge;
682
-
683
- switch(onBarEdge) {
684
- case 'right':
685
- e.deltaX = -(this.cardOffset().item.width());
686
- this.series.timeline.bar.moving(e);
687
- break;
688
- case 'left':
689
- e.deltaX = (this.cardOffset().item.width());
690
- this.series.timeline.bar.moving(e);
678
+ var offset = this.$(".TS-item").offset();
679
+ var toffset = $("#timeline_setter").offset();
680
+ if (offset.left < toffset.left) {
681
+ e.deltaX = toffset.left - offset.left + cleanNumber(this.$(".TS-item").css("padding-left"));
682
+ this.series.timeline.bar.moving(e);
683
+ } else if (offset.left + this.$(".TS-item").outerWidth() > toffset.left + $("#timeline_setter").width()) {
684
+ e.deltaX = toffset.left + $("#timeline_setter").width() - (offset.left + this.$(".TS-item").outerWidth());
685
+ this.series.timeline.bar.moving(e);
691
686
  }
692
- this.position($.Event('move'));
693
687
  },
694
688
 
695
689
  // The click handler to set the current hash to the `Card`'s id.
@@ -705,10 +699,10 @@
705
699
 
706
700
  // An event listener to toggle this notche on and off via `Series`.
707
701
  toggleNotch : function(e){
708
- switch(e.type) {
702
+ switch (e.type) {
709
703
  case "hideNotch":
710
704
  this.notch.hide().removeClass("TS-notch_active").addClass("TS-series_inactive");
711
- if(this.el) this.el.hide();
705
+ if (this.el) this.el.hide();
712
706
  return;
713
707
  case "showNotch":
714
708
  this.notch.removeClass("TS-series_inactive").show();
@@ -782,7 +776,7 @@
782
776
  } else {
783
777
  el = (curCardIdx > 0 ? notches.eq(curCardIdx - 1) : false);
784
778
  }
785
- if(!el) return;
779
+ if (!el) return;
786
780
  el.trigger("click");
787
781
  }
788
782
  });
@@ -799,7 +793,9 @@
799
793
  // and binding to `"keydown"`.
800
794
  Timeline.boot = function(data) {
801
795
  $(function(){
796
+
802
797
  TimelineSetter.timeline = new Timeline(data);
798
+
803
799
  new Zoom("in");
804
800
  new Zoom("out");
805
801
  var chooseNext = new Chooser("next");