timeline_setter 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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");