alongslide 0.9.10 → 0.9.11

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDM0ODFhYTU3OTQ2OGY1ODQwYzU4M2FlYzc3N2UxNDRlZmJiYjYxNQ==
5
- data.tar.gz: !binary |-
6
- YWU4YjgzNWM5MDYzMWZkNjhlZjc2YzJjNTBiNzdiNTRkZDU3ZGE2OQ==
2
+ SHA1:
3
+ metadata.gz: 542170c9eaf643945063831eba1c4197003157a2
4
+ data.tar.gz: 97ff3fa6ea20d7292d3cbf2ad7c03cc82b72b01d
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NDMxZTU3YzJlMjRmMTc2NmIxYThjNDhlZDAwYjNjZmNiZWNmMmNmMzFjOGZl
10
- ODM0MTcwMTUwZTgxY2QxMWE3NGEwN2UwYTkyMjI3ZDIyZGFiYTYyODRhMjgw
11
- MDdlYWZjOGYwZGViZDRhYTM0OTQ5NjQ0YTc5ODBjZWFjMGIyNGU=
12
- data.tar.gz: !binary |-
13
- Y2FjZjZhMzUyYmJmNzNjOGJiZjZhMTIwNTcwOWZmMjlmMWU3NjZlMGYyZDcz
14
- YzE0NTdkNDhiNDk2YmYzMzA1OTYwNWQwMTZjNDExZGJiNTkwOTc3MDEzY2Qy
15
- MDczY2Y5NzNiODkwNmQxMGNhZDcxMjVlMGY0YWUyYTEzMDQ4OGY=
6
+ metadata.gz: d5df3c8d11284c544419845fee71be332c244b27432ad9e5aefe59e08902e91494140c5cf67c968d5d05de8c0e888e336866441c61c227fd1fc8a97639b2bffd
7
+ data.tar.gz: da422b446b18f80f98a4b85127eb2e25ae925e32276fe02e929b957bb59ee1d8ff98666ce00d4ff1057904f98cbbd5d07fcaed6d65f6d9351fc2e63c290f9cce
data/Gemfile CHANGED
@@ -1,9 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- ruby '1.9.3'
3
+ ruby '2.2.2'
4
4
 
5
5
  gem 'redcarpet'
6
- gem 'treetop'
6
+ gem 'treetop', '~>1.4.14'
7
7
  gem 'polyglot'
8
8
  gem 'haml'
9
9
  gem 'sass'
data/Gemfile.lock CHANGED
@@ -102,4 +102,7 @@ DEPENDENCIES
102
102
  redcarpet
103
103
  rspec
104
104
  sass
105
- treetop
105
+ treetop (~> 1.4.14)
106
+
107
+ BUNDLED WITH
108
+ 1.10.6
data/alongslide.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'alongslide'
3
- gem.version = '0.9.10'
3
+ gem.version = '0.9.11'
4
4
 
5
5
  gem.summary = "Create dynamic web layouts with an extended Markdown syntax"
6
6
  gem.description = "Create dynamic web layouts with an extended Markdown syntax"
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.homepage = 'http://github.com/triplecanopy/alongslide'
11
11
 
12
12
  gem.add_dependency('redcarpet')
13
- gem.add_dependency('treetop')
13
+ gem.add_dependency('treetop','~>1.4.14')
14
14
  gem.add_dependency('polyglot')
15
15
  gem.add_development_dependency('rspec')
16
16
 
@@ -9,42 +9,47 @@ class Alongslide
9
9
  panels : {}
10
10
  sections : {}
11
11
 
12
- parser : null
13
- layout : null
14
- scrolling : null
15
- state : null
12
+ parser : null
13
+ layout : null
14
+ scrolling : null
15
+ state : null
16
16
 
17
17
  constructor: (options= {}) ->
18
18
  @source = $(options.source) ? $('#content .raw')
19
19
  @frames = $(options.to) ? $('#frames')
20
20
  @regionCls = options.regionCls ? 'column'
21
21
  @marginTop = options.marginTop ? 0
22
- @panelNames = {}
22
+ @panelIndices = []
23
+ @flowIndices = []
23
24
 
24
25
  RegionFlow::init()
25
26
 
26
27
  # parse
27
28
  @parser = new @Parser source: @source
28
- {@flowNames, @backgrounds, @panels, @footnotes, @sourceLength} = @parser.parse()
29
+ {@flowNames, @panelNames, @backgrounds, @panels, @footnotes, @sourceLength} = @parser.parse()
29
30
 
30
31
  # init layout
31
32
  @layout = new @Layout
32
- sourceLength: @sourceLength
33
- frames: @frames
34
- flowNames: @flowNames
35
- backgrounds: @backgrounds
36
- panels: @panels
37
- regionCls: @regionCls
38
- panelNames: @panelNames
33
+ sourceLength: @sourceLength
34
+ frames : @frames
35
+ flowNames : @flowNames
36
+ backgrounds : @backgrounds
37
+ panels : @panels
38
+ regionCls : @regionCls
39
+ panelNames : @panelNames
40
+ panelIndices: @panelIndices
41
+ flowIndices : @flowIndices
39
42
 
40
43
  # init scrolling
41
44
  @scrolling = new @Scrolling
42
- frames: @frames
45
+ frames: @frames
43
46
 
44
47
  # init broswer history
45
48
  @state = new @State
46
- panelNames: @panelNames
47
-
49
+ panelNames : @panelNames
50
+ flowNames : @flowNames
51
+ panelIndices: @panelIndices
52
+ flowIndices : @flowIndices
48
53
 
49
54
  # Render flowing layout and scroll behavior.
50
55
  #
@@ -55,6 +60,7 @@ class Alongslide
55
60
  # @param postRenderCallback - to be called when layout returns
56
61
  #
57
62
  render: (postRenderCallback) ->
63
+
58
64
  frameAspect = FixedAspect.prototype.fitFrame(@layout.FRAME_WIDTH, @marginTop)
59
65
  @layout.render (lastFramePosition) =>
60
66
 
@@ -65,9 +71,14 @@ class Alongslide
65
71
  @applyAnchorScrolling()
66
72
 
67
73
  # Emit notification that layout is complete.
74
+ #
68
75
  $(document).triggerHandler 'alongslide.ready', @frames
69
76
 
77
+ # Default array of indices for URL rewrites is set to section names
78
+ #
79
+ @state.setIndices(@flowIndices)
70
80
  @hashToPosition()
81
+
71
82
  FixedAspect.prototype.fitPanels(frameAspect)
72
83
  postRenderCallback()
73
84
 
@@ -80,11 +91,14 @@ class Alongslide
80
91
 
81
92
  hashToPosition: ->
82
93
  hash = window.location.hash
83
- if hash.length > 0
84
- @goToPanel(hash.substr(1))
85
- else
86
- @goToPanel('titlesplash')
94
+ if hash.length
87
95
 
96
+ # State will update hash on skroll
97
+ #
98
+ stateIndex = @goToPanel(hash.substr(1))
99
+
100
+ state = {index: stateIndex || 0}
101
+ @state.updateLocation state
88
102
 
89
103
  # Create footnotes
90
104
  #
@@ -93,34 +107,40 @@ class Alongslide
93
107
  # For each footnote in the article
94
108
  @frames.find('.als-fn-ref').each (i, el) =>
95
109
  # Reference the footnote
110
+ #
96
111
  $el = $(el)
97
- # Find the footnote text
98
- $footnote = @footnotes.find($el.data('anchor'))
99
112
 
100
- # Append the footnote text element to the column
113
+ # Find and clone the footnote element
114
+ #
115
+ $footnote = @footnotes.find($el.data('anchor')).clone()
116
+
117
+ # Append the cloned element to the column
118
+ #
101
119
  $column = $el.parents('.column')
102
120
  $column.append($footnote)
103
121
 
104
- # place footnote, prevent placing offscreen
105
- bottom = $column.height() + $column.offset().top
106
- if ($el.offset().top + $footnote.height()) > bottom
107
- $footnote.css('bottom', 0)
108
- else
109
- $footnote.css('top', $el.parent().position().top )
110
-
111
- $el.on "mouseenter click", (e) ->
122
+ $el.on 'click mouseenter', (e) ->
112
123
  e.preventDefault()
113
124
  e.stopImmediatePropagation()
125
+
126
+ # Place footnote, prevent placing offscreen
127
+ #
128
+ bottom = $column.height() + $column.offset().top
129
+ if ($el.offset().top + $footnote.height()) > bottom
130
+ $footnote.css('bottom', 0)
131
+ else
132
+ $footnote.css('top', $el.parent().position().top )
133
+
114
134
  $footnote.fadeIn(150)
115
- false
116
135
 
117
- $footnote.on "mouseleave click", (e) ->
118
- setTimeout ( ()-> $footnote.fadeOut(150) ), 100
119
- false
136
+ $footnote.on 'click mouseleave', (e) ->
137
+ setTimeout ->
138
+ $footnote.fadeOut(150)
139
+ , 100
120
140
 
121
141
  applyAnchorScrolling: ->
122
142
  self = @
123
- @frames.find('a[href*=#]:not([href=#])').on('click', (e) ->
143
+ @frames.find('a[href*=\\#]:not([href=\\#])').on('click', (e) ->
124
144
  self.goToPanel(@hash.substr(1))
125
145
  )
126
146
 
@@ -128,7 +148,7 @@ class Alongslide
128
148
  $target = $('#frames').find('[data-alongslide-id=' + alsId + ']')
129
149
  targetPos = $target.data('als-in-position')
130
150
  @scrolling.scrollToPosition(targetPos)
131
-
151
+ targetPos
132
152
 
133
153
  # Make global
134
154
  #
@@ -38,7 +38,7 @@ class Alongslide::Layout
38
38
  #
39
39
  #
40
40
  constructor: (options = {}) ->
41
- {@frames, @flowNames, @backgrounds, @panels, @regionCls, @sourceLength, @panelNames} = options
41
+ {@frames, @flowNames, @flowIndices, @panel, @panelIndices, @backgrounds, @panels, @regionCls, @sourceLength, @cols} = options
42
42
 
43
43
  # Main entrypoint for asynchronous chain of render calls.
44
44
  #
@@ -71,15 +71,23 @@ class Alongslide::Layout
71
71
  renderSection: ->
72
72
  flowName = @flowNames[@currentFlowIndex]
73
73
 
74
- @log "Laying out section \"#{flowName}\"", @SUPER_FRAME_LEVEL
75
- background = @findBackground(flowName)
76
- @setPositionOf background, to: @nextFramePosition() if background.length
77
- background.addClass('unstaged')
74
+ if flowName?
78
75
 
79
- # Reset section index before building another section
80
- @currentSectionFlowIndex = 0
76
+ # If there `flowName` exists, i.e., not `undefined`, lay out the section
77
+ # and increment `@currentFlowIndex`
78
+ #
79
+ @log "Laying out section \"#{flowName}\"", @SUPER_FRAME_LEVEL
80
+ @currentFlowIndex++
81
+ background = @findBackground(flowName)
82
+ @setPositionOf background, to: @nextFramePosition()
83
+ background.addClass('unstaged')
81
84
 
82
- @renderFrame(flowName)
85
+ # Reset section index before building another section
86
+ #
87
+ @currentSectionFlowIndex = 0
88
+ position = @nextFramePosition()
89
+ @pushFlows(flowName, position, @flowIndices)
90
+ @renderFrame(flowName)
83
91
 
84
92
  # Render one frame and its containing columns.
85
93
  #
@@ -97,7 +105,8 @@ class Alongslide::Layout
97
105
  column = @buildRegion frame, flowName
98
106
 
99
107
  # Give each section flow an index
100
- @currentSectionFlowIndex++
108
+ # @currentSectionFlowIndex++
109
+
101
110
  column.find('.section').attr('data-section-flow-idx', @currentSectionFlowIndex)
102
111
 
103
112
  # Move three-columns class from .section to .frame
@@ -115,17 +124,19 @@ class Alongslide::Layout
115
124
 
116
125
  # Section is complete. Current column is the last column of the
117
126
  # section (no longer the overflow column).
127
+ #
118
128
  if @flowComplete(flowName)
119
129
  @updateProgress column
120
130
  @checkForDirectives column, true
121
131
  @checkForEmpties column
122
132
 
123
133
  # render next section, or complete render.
124
- @currentFlowIndex++
134
+ # @currentSectionFlowIndex++
135
+
125
136
  unless @currentFlowIndex is @flowNames.length
126
137
  background = @findBackground(flowName)
127
138
  @setPositionOf background, until: @lastFramePosition() if background.length
128
- setTimeout((=> @renderSection()), 1)
139
+ setTimeout((=> @renderSection()), 0)
129
140
  else
130
141
  @log "Layout complete"
131
142
  @reorder()
@@ -138,9 +149,7 @@ class Alongslide::Layout
138
149
 
139
150
  # unstage earlier frames
140
151
  frame.prevAll().addClass('unstaged')
141
-
142
- # render next frame
143
- setTimeout((=> @renderFrame(flowName, frame, lastColumn)), 1)
152
+ @renderFrame(flowName, frame, lastColumn)
144
153
 
145
154
  # Check the last "fit" column for any special directives (CSS classes).
146
155
  #
@@ -213,6 +222,7 @@ class Alongslide::Layout
213
222
 
214
223
  # If we changed this frame's layout, re-flow this whole section's
215
224
  # regions.
225
+ #
216
226
  if directive.hasClass("now")
217
227
  sectionId = flowFrame.data('als-section-id')
218
228
  @frames.children('.flow').find(".frame[data-als-section-id=#{sectionId}]").removeClass('unstaged')
@@ -315,7 +325,14 @@ class Alongslide::Layout
315
325
  if panelPosition > frame.data(@IN_POINT_KEY)
316
326
  @log "Moving panel \"#{$(panel).data('alongslide-id')}\" at " +
317
327
  "#{panelPosition} to #{panelPosition-1}", @FRAME_LEVEL
328
+ @movePanelPos($(panel).data('alongslide-id'), panelPosition-1, panelPosition)
318
329
  $(panel).data(@IN_POINT_KEY, panelPosition-1)
330
+ oldOutKey = $(panel).data(@OUT_POINT_KEY)
331
+ newOutKey = if !isNaN(oldOutKey) and oldOutKey > -1
332
+ oldOutKey - 1
333
+ else
334
+ oldOutKey
335
+ $(panel).data(@OUT_POINT_KEY, newOutKey)
319
336
 
320
337
  # Create region to receive flowing text (column). Return jQuery object.
321
338
  #
@@ -327,20 +344,54 @@ class Alongslide::Layout
327
344
  document.namedFlows.get(flowName).addRegion(region.get(0))
328
345
  return region
329
346
 
347
+ # Create an index of flow names and panel names. Since `position` can
348
+ # increment by steps (0: a, 1: b, 3: c), we fill the gaps in the indices
349
+ # array with the array's previous index, if there is one (0: a, 1: b, 2: b,
350
+ # 3: c). This is used to sync skroll position with flow/panel name by
351
+ # `State`.
352
+ #
353
+ pushFlows: (id, position, arr) ->
354
+ # Frames named `sectionFlow[0-9]` are not part of the regular flow, and
355
+ # therefore shouldn't be included.
356
+ #
357
+ if position is arr.length and id.match(/^sectionFlow[0-9]/) is null
358
+ arr.push(id)
359
+ else if position > arr.length
360
+ while position > arr.length
361
+ arr.push(arr[arr.length - 1])
362
+ if id.match(/^sectionFlow[0-9]/) is null
363
+ arr.push(id)
364
+
365
+ # To build an array of panel objects indicating each panel's scroll position
366
+ # and id
367
+ #
368
+ pushPanels: (id, pos) ->
369
+ if pos then @panelIndices.push({pos:pos, id:id})
370
+
371
+ # When frames are destroyed, panels shift around, so we need to update the
372
+ # pointer to their scroll position in `@panelIndices` accordingly
373
+ #
374
+ movePanelPos:(panelName, newIndex, oldIndex)->
375
+ obj = _.findWhere(@panelIndices, {pos:oldIndex})
376
+ obj.pos = newIndex
377
+
330
378
  # Pull panel element out of @panels storage, apply its transition, and
331
379
  # append to DOM!
332
380
  #
333
381
  # @param id - Alongslide panel ID
334
382
  #
335
383
  buildPanel: (id, position) ->
336
- @panelNames[position] = id
337
- panel = @panels[id].clone().addClass('unstaged').show()
384
+ panel = @panels[id]
385
+ .clone()
386
+ .addClass('unstaged frame')
387
+ .attr('data-panel-index', position)
388
+ .show()
389
+ .appendTo @frames.children('.panels')
338
390
  alignment = _.filter @ALIGNMENTS, (alignment) -> panel.hasClass(alignment)
339
391
  @log "Building #{alignment} panel frame \"#{id}\" at position #{position}", @FRAME_LEVEL
340
- panel.addClass('frame')
341
- panel.attr('data-panel-index', position);
342
- panel.appendTo @frames.children('.panels')
343
392
  @setPositionOf panel, to: position
393
+ @pushPanels(id, position)
394
+
344
395
  return panel
345
396
 
346
397
  # Destroy all previously laid out content.
@@ -368,16 +419,19 @@ class Alongslide::Layout
368
419
  # until: out point (= end position)
369
420
  #
370
421
  setPositionOf: (frame, options={}) ->
371
- frameType = frame.parent().get(0).className
372
- if options.to?
373
- if (currentFramePosition = @getPositionOf frame)?
374
- @log "Moving #{frameType} frame at #{currentFramePosition} to " +
375
- "#{options.to}", @SUB_FRAME_LEVEL
376
- frame.data @IN_POINT_KEY, options.to
377
- if options.until?
378
- @log "Dismissing #{frameType} frame \"#{frame.data('alongslide-id')}\" " +
379
- "at #{options.until}", @SUB_FRAME_LEVEL
380
- frame.data @OUT_POINT_KEY, options.until
422
+ parent = frame.parent()
423
+ if parent.length
424
+ frameType = parent[0].className
425
+
426
+ if options.to?
427
+ if (currentFramePosition = @getPositionOf frame)?
428
+ @log "Moving #{frameType} frame at #{currentFramePosition} to " +
429
+ "#{options.to}", @SUB_FRAME_LEVEL
430
+ frame.data @IN_POINT_KEY, options.to
431
+ if options.until?
432
+ @log "Dismissing #{frameType} frame \"#{frame.data('alongslide-id')}\" " +
433
+ "at #{options.until}", @SUB_FRAME_LEVEL
434
+ frame.data @OUT_POINT_KEY, options.until
381
435
  return frame
382
436
 
383
437
  # Return start position.
@@ -1,56 +1,56 @@
1
- #
2
- # parser.coffee: parse raw HTML into Alongslide types: sections, panels, etc.
3
- #
1
+ #
2
+ # parser.coffee: parse raw HTML into Alongslide types: sections, panels, etc.
3
+ #
4
4
  # Copyright 2013 Canopy Canopy Canopy, Inc.
5
5
  # Author Adam Florin
6
6
 
7
7
  class Alongslide::Parser
8
8
 
9
9
  # Store names of flows here as we create them.
10
- #
10
+ #
11
11
  # sections: []
12
12
  backgrounds: []
13
- flowNames: []
13
+ flowNames : []
14
+ panelNames : []
14
15
 
15
16
  constructor: (options) ->
16
17
  {@source} = options
17
18
  @preprocessSource()
18
19
 
19
- #
20
- #
20
+ #
21
+ #
21
22
  preprocessSource: ->
22
23
  # Put dummy content inside empty directives as CSSRegions trims any empty
23
24
  # elements found near the boundaries of a region.
24
25
  (@source.find ".alongslide:empty").text("[ALS]")
25
26
 
26
27
  # Parser entrypoint.
27
- #
28
+ #
28
29
  # Build sections and store them directly as CSSRegions named flows.
29
- #
30
+ #
30
31
  # Retun panels and footnotes, which will be needed by other components.
31
- #
32
+ #
32
33
  # Note! Parse order matters! Sections should go last, once all non-section
33
34
  # material has been scraped out of @source.
34
- #
35
+ #
35
36
  parse: ->
36
37
  @sourceLength = 0
37
38
 
38
- panels = @collectPanels()
39
+ panels = @collectPanels()
39
40
  footnotes = @collectFootnotes()
40
41
  @collectSections()
41
42
 
42
- flowNames: @flowNames
43
- backgrounds: @backgrounds
44
- panels: panels
45
- footnotes: footnotes
43
+ flowNames : @flowNames
44
+ panelNames : @panelNames
45
+ backgrounds : @backgrounds
46
+ panels : panels
47
+ footnotes : footnotes
46
48
  sourceLength: @sourceLength
47
49
 
48
- #
49
- #
50
50
  collectPanels: ->
51
51
  rawPanels = @source.find('.alongslide.show.panel')
52
52
 
53
- _.object _.map rawPanels, (el) ->
53
+ _.object _.map rawPanels, (el) =>
54
54
  $el = $(el)
55
55
  panelId = $el.data('alongslide-id')
56
56
  panelEl = $el.clone().removeClass('show')
@@ -58,11 +58,12 @@ class Alongslide::Parser
58
58
  # Cleanup
59
59
  $el.empty().removeClass('panel')
60
60
 
61
+ @panelNames.push(panelId)
61
62
  return [ panelId, panelEl ]
62
63
 
63
64
  # Sift through passed-in sections, delineating them based on `enter` and `exit`
64
65
  # directives, then assigning each to a flow.
65
- #
66
+ #
66
67
  collectSections: ->
67
68
  @source.find('.alongslide.enter.section').each (index, directiveElement) =>
68
69
  directive = $(directiveElement)
@@ -84,15 +85,15 @@ class Alongslide::Parser
84
85
  @buildSection @source.children() unless @source.is(':empty')
85
86
 
86
87
  # Build section, given content.
87
- #
88
+ #
88
89
  # Create new NamedFlow for it, and log the name.
89
- #
90
+ #
90
91
  # Create section background.
91
- #
92
+ #
92
93
  # @param content - jQuery object of section contents
93
94
  # @param directive (optional) - directive which specified the section
94
95
  # @param id (optional) - Alongslide section ID
95
- #
96
+ #
96
97
  buildSection: (content, directive, id) ->
97
98
  flowName = id || "sectionFlow#{@flowNames.length}"
98
99
 
@@ -115,10 +116,10 @@ class Alongslide::Parser
115
116
  @backgrounds.push(background)
116
117
 
117
118
  # Search for footntes as formatted by Redcarpet's footnotes callback
118
- #
119
+ #
119
120
  # Each has an ID of the form `fn1`, which corresponds to the links in the
120
121
  # footnote references.
121
- #
122
+ #
122
123
  # Returns a DOM node whose child elements are footnote definitions and removes the generated footnotes from DOM
123
124
  collectFootnotes: ->
124
125
  @source.find('.als-footnotes:last')
@@ -9,27 +9,27 @@ class Alongslide::Scrolling
9
9
  # For applyTransition.
10
10
  #
11
11
  TRANSITIONS:
12
- in: [-1..0]
12
+ in : [-1..0]
13
13
  out: [0..1]
14
14
 
15
- FLIP_THRESHOLD: 0.04
16
- WAIT_BEFORE_RESET_MS: 250
17
- SLIDE_DURATION_MS: 250
18
- FORCE_SLIDE_DURATION_MS: 100
15
+ FLIP_THRESHOLD : 0.04
16
+ WAIT_BEFORE_RESET_MS : 250
17
+ SLIDE_DURATION_MS : 250
18
+ FORCE_SLIDE_DURATION_MS : 100
19
19
  NUM_WHEEL_HISTORY_EVENTS: 10
20
- MAGNITUDE_THRESHOLD: 2.2
20
+ MAGNITUDE_THRESHOLD : 2.2
21
21
 
22
- currentPosition: 0
23
- indexedTransitions: {}
22
+ currentPosition : 0
23
+ indexedTransitions : {}
24
24
 
25
25
  # For desktop scroll throttling.
26
26
  #
27
- wheelHistory: []
28
- lastAverageMagnitude: 0
29
- ignoreScroll: false
27
+ wheelHistory : []
28
+ lastAverageMagnitude : 0
29
+ ignoreScroll : false
30
30
  lastRequestedPosition: 0
31
31
 
32
- mouseDown: false
32
+ mouseDown : false
33
33
 
34
34
  # browser history
35
35
  stateData: {}
@@ -372,9 +372,9 @@ class Alongslide::Scrolling
372
372
  duration: duration
373
373
  easing: 'easeOutQuad'
374
374
  done: (skrollr) =>
375
- @stateData =
375
+ stateData =
376
376
  index: @currentPosition
377
- alongslide.state.update(@stateData)
377
+ alongslide.state.updateLocation(stateData)
378
378
 
379
379
  # For mobile, stage/unstage frames after transition
380
380
  if @skrollr.isMobile()
@@ -5,28 +5,53 @@
5
5
  #
6
6
  class Alongslide::State
7
7
 
8
- panelNames : {}
9
- documentTitle: ''
10
- hash : '#'
11
-
12
8
  constructor: (options = {}) ->
9
+
13
10
  History = window.History
14
- if !History.enabled then return false
11
+
15
12
  @documentTitle = document.getElementsByTagName('title')[0].innerHTML
16
13
  @panelNames = options.panelNames
14
+ @flowNames = options.flowNames
15
+ @panelIndices = options.panelIndices
16
+ @flowIndices = options.flowIndices
17
+ @hashIndices = []
18
+ @hash = '#'
17
19
 
18
- rewindStateIndex:(state) ->
20
+ setIndices:(arr) ->
21
+ @hashIndices = arr
22
+ # Manually pushing 'digital-project-context' to sections
23
+ #
24
+ @flowIndices.push('digital-project-context')
25
+
26
+ rewindIndex:(state) ->
19
27
  state.index -= 1
20
- @update(state);
21
-
22
- update:(state)->
23
- if @panelNames[state.index]
24
- History.replaceState null, @documentTitle, @hash + @panelNames[state.index]
25
- pageData =
26
- index : state.index
27
- hash : @panelNames[state.index]
28
- $(document).triggerHandler 'alongslide.pagechange', pageData
29
- else if !@panelNames[state.index] and state.index > -1
30
- @rewindStateIndex(state)
31
- else if state.index <= -1
28
+ @updateLocation(state);
29
+
30
+ updateLocation:(state = {})->
31
+
32
+ if !History.enabled then return
33
+
34
+ # Account for layouts that only have one section, as the `position`s
35
+ # won't be in the indices array.
36
+ #
37
+ if !@hashIndices[state.index] and state.index > -1
38
+ @rewindIndex(state)
39
+
40
+ # Exit if the indices array is empty
41
+ #
42
+ else if state.index < 0
32
43
  return
44
+
45
+ # Update the hash
46
+ #
47
+ else if @hashIndices[state.index]
48
+
49
+ History.replaceState null, @documentTitle, @hash + @hashIndices[state.index]
50
+
51
+ data =
52
+ index : state.index
53
+ sectionHash : @flowIndices[state.index]
54
+ panels : @panelIndices
55
+ sections : @flowIndices
56
+
57
+ $(document).triggerHandler 'alongslide.stateChange', data
@@ -66,9 +66,8 @@ $white-bg: #ffffff
66
66
  position: absolute
67
67
  text-rendering: optimizelegibility
68
68
  text-transform: auto
69
-
70
- em
71
- line-height: 1em
69
+ p:nth-of-type(1):not(.region-flow-post-text-break)
70
+ text-indent: 0
72
71
 
73
72
  // One frame is one screen's worth.
74
73
  //
@@ -99,12 +98,6 @@ $white-bg: #ffffff
99
98
  height: 45 * $vertical-grid-unit
100
99
  top: $outer-margin-height
101
100
  position: absolute
102
- // > div
103
- // height: $full-bleed - $frame-height-padding
104
- .section
105
- &[data-section-flow-idx]
106
- p:first-child
107
- text-indent: 0 !important
108
101
 
109
102
  // Left/right columns
110
103
  //
@@ -333,6 +326,7 @@ $white-bg: #ffffff
333
326
  text-indent: 0%
334
327
  padding: 2% 6% 0% 6%
335
328
  .als-fn-sup
329
+ line-height: 0
336
330
  position: relative
337
331
  top: -0.8em
338
332
  z-index: 1000000
@@ -1,121 +1,121 @@
1
- #
1
+ #
2
2
  # regionFlow.coffee: ultralightweight, if somewhat naïve, implementation of
3
3
  # CSS regions, according to the spec at:
4
- #
4
+ #
5
5
  # http://dev.w3.org/csswg/css-regions/
6
- #
6
+ #
7
7
  # Copyright 2013 Canopy Canopy Canopy, Inc.
8
- #
8
+ #
9
9
 
10
10
 
11
11
  # Initialize NamedFlowMap.
12
- #
12
+ #
13
13
  class RegionFlow
14
14
 
15
15
  # To be spec compliant, the NamedFlow .overset property should be proactively
16
16
  # calculated after any layout change.
17
- #
17
+ #
18
18
  # However, in reality, checking a DOM element's scrollHeight is very expensive,
19
19
  # so it's best not to call it any more than is stricly necessary.
20
- #
20
+ #
21
21
  # For that reason, lazy mode is enabled by default, and callers should call
22
22
  # .updateOverset() on namedFlows instead of checking the .overset property.
23
- #
23
+ #
24
24
  lazyMode: true
25
25
 
26
26
  init: ->
27
27
  document.namedFlows = new @NamedFlowMap
28
28
 
29
29
  # Document has one NamedFlowMap, so that flows may be looked up by index.
30
- #
30
+ #
31
31
  # [MapClass(DOMString, NamedFlow)]
32
- #
32
+ #
33
33
  class RegionFlow::NamedFlowMap
34
34
 
35
35
  namedFlows: {}
36
36
 
37
- #
38
- #
37
+ #
38
+ #
39
39
  build: (flowName) ->
40
40
  @namedFlows[flowName] = new RegionFlow::NamedFlow(flowName)
41
41
 
42
42
  # As specified:
43
- #
43
+ #
44
44
  # NamedFlow? get(DOMString flowName);
45
- #
45
+ #
46
46
  get: (flowName) ->
47
47
  @namedFlows[flowName] || @build(flowName)
48
48
 
49
49
  # As specified:
50
- #
50
+ #
51
51
  # boolean has(DOMString flowName);
52
- #
52
+ #
53
53
  has: (flowName) ->
54
54
  @namedFlows[flowName]?
55
55
 
56
56
  # As specified:
57
- #
57
+ #
58
58
  # NamedFlowMap set(DOMString flowName, NamedFlow flowValue);
59
- #
59
+ #
60
60
  set: (flowName, flowValue) ->
61
61
  @namedFlows[flowName] = flowValue
62
62
 
63
63
  # As specified:
64
- #
64
+ #
65
65
  # boolean delete(DOMString flowName);
66
- #
66
+ #
67
67
  delete: (flowName) ->
68
68
  delete @namedFlows[flowName]
69
69
 
70
70
  # A NamedFlow
71
- #
71
+ #
72
72
  # interface NamedFlow : EventTarget {
73
73
  # };
74
- #
74
+ #
75
75
  class RegionFlow::NamedFlow
76
76
  # readonly attribute DOMString name;
77
77
  # readonly attribute boolean overset;
78
78
  # readonly attribute integer firstEmptyRegionIndex;
79
79
 
80
- #
81
- #
80
+ #
81
+ #
82
82
  constructor: (@name) ->
83
83
  @contentNodes = []
84
84
  @overset = false
85
85
  @resetRegions()
86
86
 
87
87
  # Reset, assuming all previously-tracked regions have been destroyed.
88
- #
88
+ #
89
89
  # Leave content nodes right where they are.
90
- #
90
+ #
91
91
  resetRegions: ->
92
92
  @regions = []
93
93
  @firstEmptyRegionIndex = -1
94
94
  @updateOverset() unless RegionFlow::lazyMode
95
95
 
96
96
  # As specified:
97
- #
97
+ #
98
98
  # sequence<Region> getRegions();
99
- #
99
+ #
100
100
  getRegions: ->
101
101
  @regions
102
102
 
103
103
  # Push region to end of array and doFlow.
104
- #
104
+ #
105
105
  addRegion: (regionNode) ->
106
106
  @regions.push new RegionFlow::Region(regionNode)
107
107
  @firstEmptyRegionIndex = @regions.length - 1
108
108
  @doFlow()
109
109
 
110
110
  # As specified:
111
- #
111
+ #
112
112
  # sequence<Node> getContent();
113
- #
113
+ #
114
114
  getContent: ->
115
115
  @contentNodes
116
116
 
117
117
  # Push content to end of array and doFlow.
118
- #
118
+ #
119
119
  addContent: (contentNode) ->
120
120
  @contentNodes.push($(contentNode))
121
121
  @doFlow()
@@ -123,7 +123,7 @@ class RegionFlow::NamedFlow
123
123
  # If regions are all still there, but the dimensions of already laid-out
124
124
  # regions has changed, re-flow all regions from scratch (like resetRegions,
125
125
  # but softer).
126
- #
126
+ #
127
127
  reFlow: ->
128
128
  node.empty() for node in _.pluck @regions, 'node'
129
129
 
@@ -134,16 +134,16 @@ class RegionFlow::NamedFlow
134
134
  @firstEmptyRegionIndex++
135
135
 
136
136
  # Layout logic.
137
- #
137
+ #
138
138
  doFlow: ->
139
139
  if @firstEmptyRegionIndex is 0
140
140
 
141
141
  # TODO: prune marginal nodes? comments, scripts?
142
-
142
+
143
143
  @populateRegions()
144
144
 
145
145
  else if @firstEmptyRegionIndex > 0
146
-
146
+
147
147
  # move all nodes from oversetRegion to lastRegion
148
148
  # (which will later become the oversetRegion)
149
149
  nodes = $(@oversetRegion().node).contents().remove()
@@ -151,21 +151,36 @@ class RegionFlow::NamedFlow
151
151
 
152
152
  # enter recursive loop
153
153
  @breakUp nodes: nodes
154
-
154
+
155
155
  @updateOverset() unless RegionFlow::lazyMode
156
156
 
157
157
  # Place all content into regions. Performed only on first time.
158
- #
158
+ #
159
159
  populateRegions: ->
160
160
  @lastRegion().appendNode(node.clone()) for node in @contentNodes
161
161
 
162
+
163
+ # Verify that a node can be separated from it's predecessor. Used to prevent
164
+ # breaks on context-dependent elements, e.g., footnote references.
165
+ #
166
+ contextDependent:(node) ->
167
+ conditions = [
168
+ -> Boolean(@nodeName is 'SUP')
169
+ ]
170
+ result = false
171
+ i = conditions.length
172
+ while i--
173
+ result = conditions[i].call(node)
174
+ if result then break
175
+ result
176
+
162
177
  # Recursive layout call.
163
- #
178
+ #
164
179
  # @params options - hash
165
180
  # node - HTML element to be broken up. ignored if nodes option is specified.
166
181
  # nodes - array of HTML elements. overrides node option if specified.
167
182
  # into - targetNode to break up 'node' into. defaults to oversetRegion's root.
168
- #
183
+ #
169
184
  breakUp: (options = {}) ->
170
185
  nodes = options.nodes || $(options.node).contents()
171
186
 
@@ -182,11 +197,11 @@ class RegionFlow::NamedFlow
182
197
  formerParent = $(childNode).parent()
183
198
  $(childNode).remove().appendTo(targetNode)
184
199
 
185
- if @oversetRegion().updateOverset() is 'overset'
200
+ if @oversetRegion().updateOverset() is 'overset' and not @contextDependent(childNode)
186
201
 
187
202
  # move it back where it was
188
203
  $(childNode).remove().prependTo(formerParent)
189
-
204
+
190
205
  if childNode.nodeType is Node.TEXT_NODE
191
206
  @breakUpText node: childNode, into: targetNode
192
207
  else
@@ -198,17 +213,28 @@ class RegionFlow::NamedFlow
198
213
  else if $(childNode).hasClass('break-after-always')
199
214
  return false
200
215
 
216
+ # Helper function, recurses up the DOM looking for a block element
217
+ # @params elem - jQuery object
218
+ #
219
+ getBlockParent:(elem) ->
220
+ inlineEls = ['B', 'BIG', 'I', 'SMALL', 'TT', 'ABBR', 'ACRONYM', 'CITE', 'CODE', 'DFN', 'EM', 'KBD', 'STRONG', 'SAMP', 'VAR', 'A', 'BDO', 'BR', 'IMG', 'MAP', 'OBJECT', 'Q', 'SCRIPT', 'SPAN', 'SUB', 'SUP', 'BUTTON', 'INPUT', 'LABEL', 'SELECT', 'TEXTAREA']
221
+ blockElem = if $.inArray(elem.prop('tagName'), inlineEls) > -1
222
+ @getBlockParent(elem.parent(), inlineEls)
223
+ else
224
+ elem
225
+ return blockElem
226
+
201
227
  # Given a text node and a target node (in the overset region), find the number
202
228
  # of words which fit.
203
- #
229
+ #
204
230
  # @params options - hash
205
231
  # node - textNode to copy words from
206
232
  # into - targetNode to copy words to
207
- #
233
+ #
208
234
  breakUpText: (options = {}) ->
209
235
  textNode = options.node
210
236
  targetNode = document.createTextNode("")
211
- $(targetNode).appendTo(options.into)
237
+ inlineElements = $(targetNode).appendTo(options.into)
212
238
 
213
239
  words = textNode.nodeValue.split(/[ ]+/)
214
240
  highIndex = words.length - 1
@@ -224,38 +250,39 @@ class RegionFlow::NamedFlow
224
250
  lowIndex = tryIndex
225
251
 
226
252
  tryIndex = Math.floor(lowIndex + (highIndex - lowIndex) / 2)
227
-
253
+
228
254
  break if highIndex - lowIndex <= 1
229
-
255
+
230
256
  if tryIndex is 0
231
257
  $(targetNode).remove()
232
258
  else
233
259
  targetNode.textContent = words[0..tryIndex].join(" ")
234
260
  textNode.nodeValue = words[tryIndex+1..words.length-1].join(" ")
235
- $(textNode).parent().addClass("region-flow-post-text-break")
261
+ $parentElem = @getBlockParent $(textNode).parent() # prevents us from attaching classes to inline elements
262
+ $parentElem.addClass("region-flow-post-text-break")
236
263
 
237
264
  @oversetRegion().updateOverset() unless RegionFlow::lazyMode
238
265
 
239
266
  # Calculate whether named flow is overset.
240
- #
267
+ #
241
268
  # Normally treated as a private method, but called publicly in lazy mode.
242
269
  # See RegionFlow::lazyMode.
243
- #
270
+ #
244
271
  updateOverset: ->
245
272
  @overset = @regions[@firstEmptyRegionIndex]?.updateOverset() is 'overset'
246
273
 
247
274
  # Readability helpers.
248
- #
275
+ #
249
276
  oversetRegion: ->
250
277
  @regions[@firstEmptyRegionIndex - 1]
251
278
  lastRegion: ->
252
279
  @regions[@firstEmptyRegionIndex]
253
-
280
+
254
281
 
255
282
  # [NoInterfaceObject]
256
283
  # interface Region {
257
284
  # };
258
- #
285
+ #
259
286
  class RegionFlow::Region
260
287
 
261
288
  constructor: (node) ->
@@ -263,21 +290,21 @@ class RegionFlow::Region
263
290
  @updateOverset() unless RegionFlow::lazyMode
264
291
 
265
292
  # Append one or more nodes.
266
- #
293
+ #
267
294
  appendNode: (contentNode) ->
268
295
  $(@node).append(contentNode)
269
296
  @updateOverset() unless RegionFlow::lazyMode
270
297
 
271
298
  # As specified:
272
- #
299
+ #
273
300
  # readonly attribute DOMString regionOverset;
274
- #
301
+ #
275
302
  # Possible states
276
- #
303
+ #
277
304
  # 'overset': The region is the last one in the region chain and not able to fit the remaining content from the named flow.
278
305
  # 'fit': The region's flow fragment content fits into the region's content box.
279
306
  # 'empty': All content from the named flow was fitted in prior regions.
280
- #
307
+ #
281
308
  updateOverset: ->
282
309
  node = @node.get(0)
283
310
  isOverset = node.scrollHeight > node.clientHeight
@@ -301,5 +328,5 @@ class RegionFlow::Region
301
328
  else
302
329
  'fit'
303
330
 
304
- #
331
+ #
305
332
  window.RegionFlow = RegionFlow
@@ -722,7 +722,7 @@
722
722
  var deltaTime;
723
723
 
724
724
  _addEvent(documentElement, [EVENT_TOUCHSTART, EVENT_TOUCHMOVE, EVENT_TOUCHCANCEL, EVENT_TOUCHEND].join(' '), function(e) {
725
- e.preventDefault();
725
+ // e.preventDefault();
726
726
 
727
727
  var touch = e.changedTouches[0];
728
728
 
@@ -750,12 +750,18 @@
750
750
  deltaX = currentTouchX - lastTouchX;
751
751
  deltaTime = currentTouchTime - lastTouchTime;
752
752
 
753
- var position = _mobileOffset - (!_scrollHorizontal ? deltaY : deltaX);
754
- _instance.setScrollPosition(position, true);
753
+ // Allow horizontal scroll on overflowing elements
754
+ if (Math.abs(deltaX) < Math.abs(deltaY)) {
755
+ return;
756
+ } else {
757
+ var position = _mobileOffset - (!_scrollHorizontal ? deltaY : deltaX);
758
+ _instance.setScrollPosition(position, true);
759
+
760
+ lastTouchY = currentTouchY;
761
+ lastTouchX = currentTouchX;
762
+ lastTouchTime = currentTouchTime;
763
+ }
755
764
 
756
- lastTouchY = currentTouchY;
757
- lastTouchX = currentTouchX;
758
- lastTouchTime = currentTouchTime;
759
765
  break;
760
766
  default:
761
767
  case EVENT_TOUCHCANCEL:
@@ -1713,4 +1719,4 @@
1713
1719
  //Animation frame id returned by RequestAnimationFrame (or timeout when RAF is not supported).
1714
1720
  var _animFrame;
1715
1721
 
1716
- }(window, document));
1722
+ }(window, document));
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alongslide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.10
4
+ version: 0.9.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Florin
@@ -9,62 +9,62 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-09 00:00:00.000000000 Z
12
+ date: 2016-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redcarpet
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ! '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ! '>='
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: treetop
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ! '>='
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
34
+ version: 1.4.14
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ! '>='
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: 1.4.14
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: polyglot
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ! '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ! '>='
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ! '>='
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ! '>='
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  description: Create dynamic web layouts with an extended Markdown syntax
@@ -123,17 +123,17 @@ require_paths:
123
123
  - lib
124
124
  required_ruby_version: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - ! '>='
126
+ - - ">="
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  requirements:
131
- - - ! '>='
131
+ - - ">="
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
135
  rubyforge_project:
136
- rubygems_version: 2.2.2
136
+ rubygems_version: 2.4.8
137
137
  signing_key:
138
138
  specification_version: 4
139
139
  summary: Create dynamic web layouts with an extended Markdown syntax