alongslide 0.9.10 → 0.9.11

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