alongslide 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Alongslide
2
2
 
3
- Alongslide is a layout engine extending Markdown syntax.
3
+ Alongslide is a layout engine extending Markdown syntax for use in Rails-based
4
+ web applications
4
5
 
5
6
  It was developed by [Triple Canopy](http://canopycanopycanopy.com/) as a
6
7
  text-editable yet sophisticated platform for producing long-form reading
@@ -8,6 +9,8 @@ content on the web.
8
9
 
9
10
  Try the demo at [alongslide.com](http://alongslide.com) or [read some theory](http://canopycanopycanopy.com/contents/announcing_alongslide) underlying the project.
10
11
 
12
+ *Copyright 2013-2014 Canopy Canopy Canopy, Inc.*
13
+
11
14
  ## Dependencies
12
15
 
13
16
  The Ruby backend uses Redcarpet to extract layout directives from the
@@ -15,10 +18,79 @@ Markdown, Treetop to parse their grammar, and HAML to render them into
15
18
  templates.
16
19
 
17
20
  The CoffeeScript/SASS frontend then scan the resulting HTML for layout
18
- cues, using Adobe's CSS Regions polyfill to flow the body text, and
19
- skrollr to build transition animations and respond to user scrolling.
21
+ cues, using a custom CSS Regions polyfill to flow the body text,
22
+ skrollr to build transition animations and respond to user scrolling,
23
+ plus jQuery and underscore.js as utilities.
24
+
25
+ ## Installing
26
+
27
+ ```bash
28
+ gem install alongslide
29
+ ```
30
+
31
+ The gem includes both the Ruby and frontend components.
32
+
33
+ ## Usage
34
+
35
+ To use Alongslide, begin by setting up your view:
36
+
37
+ ```erb
38
+ <article id="frames">
39
+ <div class="backgrounds"></div>
40
+ <div class="flow"></div>
41
+ <div class="panels"></div>
42
+ </article>
43
+ <div id="content" style="display: none">
44
+ <%= Alongslide::render(your_markdown_string) %>
45
+ </div>
46
+ ```
47
+
48
+ Where `your_markdown_string` is a string of Alongslide-flavored Markdown.
49
+
50
+ Note that the Alongslide HTML is rendered into a hidden DOM element. The empty
51
+ elements above are there for Alongslide's JS to write into.
52
+
53
+ Then, once the page is loaded and ready, you can kick off the Alongslide render:
54
+
55
+ ```javascript
56
+ MIN_WINDOW_WIDTH = 980
57
+ window.alongslide = new Alongslide({
58
+ source: '#content',
59
+ to: '#frames'
60
+ })
61
+ frameAspect = FixedAspect.prototype.fitFrame(MIN_WINDOW_WIDTH)
62
+ window.alongslide.render(frameAspect, function({
63
+ FixedAspect.prototype.fitPanels(frameAspect)
64
+ }))
65
+ ```
66
+
67
+ For RegionFlow (our CSS Regions polyfill) to work properly, it is critical that
68
+ _all_ styles and webfonts be loaded in browser memory before the Alongslide
69
+ render begins. For that reason, it is recommend that you use the included
70
+ `Styles.prototype.doLoad()` utility to force CSS to load (by loading it via
71
+ Ajax and writing it to the DOM) and/or a tool such as
72
+ [webfontloader](https://github.com/typekit/webfontloader).
73
+
74
+ After the inital render, you can use `window.alongslide.refresh(frameAspect)`
75
+ to update just the scroll positioning (after a window resize for example) without
76
+ incurring the full cost of doing the layout over again.
77
+
78
+ ### Creating custom templates
79
+
80
+ You may specify a directory in your application where you can specify your own
81
+ custom Alongslide templates. To do so, create an `alongslide.rb` in
82
+ `config/initializers` with the contents:
83
+
84
+ ```ruby
85
+ Alongslide.configure do |config|
86
+ config.user_template_dir = Rails.root.join("app/views/alongslide")
87
+ end
88
+ ```
89
+
90
+ Then you may create views in that directory using the YAML frontmatter format
91
+ described below.
20
92
 
21
- *Copyright 2013 Canopy Canopy Canopy, Inc.*
93
+ If these template have JS/CSS components, those may go wherever you like.
22
94
 
23
95
  ## Syntax
24
96
 
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.2'
3
+ gem.version = '0.9.3'
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"
@@ -8,6 +8,10 @@
8
8
  #= require prefix
9
9
  #= require jquery.fitvids
10
10
  #
11
+ # Utility
12
+ #= require ./styles
13
+ #= require ./fixedAspect
14
+ #
11
15
  # Core
12
16
  #= require alongslide/alongslide
13
17
  #= require alongslide/parser
@@ -0,0 +1,145 @@
1
+ #
2
+ # fixedAspect.coffee: Maintain fixed aspect ratio for given element.
3
+ #
4
+ # Copyright 2013 Canopy Canopy Canopy, Inc.
5
+ #
6
+
7
+ class window.FixedAspect
8
+
9
+ # Fit the content elements so that they maintain a consistent aspect ratio
10
+ # no matter the aspect ratio of the browser window.
11
+ #
12
+ # @param minWidthPx - minimum width in pixels to allow. Don't shrink smaller!
13
+ # @param marginTopPx - margin top in pixels to leave open.
14
+ #
15
+ # @return frame - bounding rect of content area, expressed as percentages
16
+ # relative to the browser window (0.0-1.0).
17
+ #
18
+ fitFrame: (minWidthPx, marginTopPx = 0) ->
19
+ FRAME_ASPECT = 1.6
20
+ FRAME_SELECTOR = '#frames > .flow > .frame'
21
+
22
+ frameAspect =
23
+ width: 1.0
24
+ height: 1.0
25
+ left: 0
26
+ top: 0
27
+
28
+ # aspect ratio calculations
29
+ window_aspect = $(window).width() / $(window).height()
30
+ if window_aspect > FRAME_ASPECT
31
+ frameAspect.width = FRAME_ASPECT / window_aspect
32
+ frameAspect.left = (1.0 - frameAspect.width) / 2
33
+ else
34
+ frameAspect.height = window_aspect / FRAME_ASPECT
35
+ frameAspect.top = (1.0 - frameAspect.height) / 2
36
+
37
+ # enforce margins, squeezing content down if necessary
38
+ marginTop = marginTopPx / $(window).height()
39
+ if frameAspect.top < marginTop
40
+ frameAspect.top = marginTop
41
+ scaleDown = (1.0 - frameAspect.top) / frameAspect.height
42
+ frameAspect.height *= scaleDown
43
+ frameAspect.width *= scaleDown
44
+ frameAspect.left = (1.0 - frameAspect.width) / 2
45
+
46
+ # enforce minWidthPx
47
+ frameWidthPx = frameAspect.width * $(window).width()
48
+ scaleUp = minWidthPx / frameWidthPx
49
+ if scaleUp > 1.0
50
+ frameAspect.height *= scaleUp
51
+ frameAspect.width *= scaleUp
52
+
53
+ # write to DOM, except for offset value for ALS
54
+ Styles::write 'debug-grid-aspect', Styles::formatPercentages('#als-debug-grid', frameAspect)
55
+ Styles::write 'frame-aspect', Styles::formatPercentages(FRAME_SELECTOR, _(frameAspect).omit('left'))
56
+
57
+ # write font-size / line-height
58
+ scalar = Math.max(1.0, (1.0 / scaleUp))
59
+ textStyles =
60
+ 'font-size': parseInt($('#content-display').css('font-size')) * scalar
61
+ 'line-height': parseInt($('#content-display').css('line-height')) * scalar
62
+ Styles::write 'frame-text', Styles::formatPixels('#frames', textStyles)
63
+
64
+ return frameAspect
65
+
66
+ # Go through all panels and manually turn absolute pixel-based values into
67
+ # percentage-based values.
68
+ #
69
+ # Do this after render, as once the operation is done, it can't be undone.
70
+ #
71
+ # Because of the complex interrelation between the CSS values (specified in a
72
+ # long, structural SASS doc) and the frame aspect value (computed on the fly),
73
+ # there's just no other way to do this but to get dirty and effectively write
74
+ # part of a CSS engine.
75
+ #
76
+ # Every `.panel` contains a `.contents`. The latter class has top/left/width/height
77
+ # specified--relative to the `.panel`. We re-derive the percentages from these
78
+ # relative values, because JS can't easily access CSS percentage values. And this
79
+ # method of dynamic re-percentifying seemed more sensible than putting large amounts
80
+ # of style data into JSON.
81
+ #
82
+ fitPanels: (frameAspect) ->
83
+ $('#frames > .panels > .panel').each (index, panel) =>
84
+ $panel = $(panel)
85
+ $contents = $panel.find('> .contents')
86
+
87
+ alignment = Alongslide::Layout::panelAlignment($panel)
88
+
89
+ innerFrame = $contents.data('innerFrame')
90
+
91
+ # If innerFrame isn't already stored, compute it now and store it.
92
+ unless innerFrame?
93
+ innerFrame = @innerFrame($panel)
94
+ $contents.data('innerFrame', innerFrame)
95
+
96
+ # .panel
97
+ #
98
+ panelFrame =
99
+ width: 1.0
100
+ height: 1.0
101
+
102
+ switch alignment
103
+ when "left"
104
+ panelFrame.width = frameAspect.left + (innerFrame.left + innerFrame.width) * frameAspect.width
105
+ when "right"
106
+ panelFrame.width = frameAspect.left + (1.0 - innerFrame.left) * frameAspect.width
107
+ when "top"
108
+ panelFrame.height = frameAspect.top + (innerFrame.top + innerFrame.height) * frameAspect.height
109
+ when "bottom"
110
+ # can't assume that frameAspect is vertically centered,
111
+ # due to `marginTop` (above). re-compute bottom.
112
+ frameAspectBottom = 1.0 - frameAspect.top - frameAspect.height
113
+ panelFrame.height = frameAspectBottom + (1.0 - innerFrame.top) * frameAspect.height
114
+
115
+ # .panel .contents
116
+ #
117
+ contentsFrame =
118
+ left: (frameAspect.left + innerFrame.left * frameAspect.width) / panelFrame.width
119
+ top: (frameAspect.top + innerFrame.top * frameAspect.height) / panelFrame.height
120
+ width: (innerFrame.width * frameAspect.width) / panelFrame.width
121
+ height: (innerFrame.height * frameAspect.height) / panelFrame.height
122
+
123
+ switch alignment
124
+ when "right"
125
+ # must use margin-left as skrollr uses left (so right-aligning won't work)
126
+ panelFrame['margin-left'] = (frameAspect.left + innerFrame.left * frameAspect.width)
127
+ contentsFrame.left = 0
128
+ when "bottom"
129
+ panelFrame.bottom = 0
130
+ contentsFrame.top = 0
131
+
132
+ # burn styles into CSS
133
+ #
134
+ $panel.css Styles::formatPercentageValues panelFrame
135
+ $contents.css Styles::formatPercentageValues contentsFrame
136
+
137
+ # Given a panel, determine its innerFrame.
138
+ #
139
+ innerFrame: ($panel) ->
140
+ $contents = $panel.find('> .contents')
141
+
142
+ left: parseInt($contents.css('left')) / $panel.width()
143
+ top: parseInt($contents.css('top')) / $panel.height()
144
+ width: $contents.width() / $panel.width()
145
+ height: $contents.height() / $panel.height()
@@ -0,0 +1,57 @@
1
+ #
2
+ # styles.coffee: Load CSS styles manually to be sure when they're loaded.
3
+ #
4
+ # Copyright 2013 Canopy Canopy Canopy, Inc.
5
+ #
6
+
7
+ class window.Styles
8
+ urls: []
9
+
10
+ # Break open HTML snippet and store href attributes of contained <link>s.
11
+ #
12
+ loadLater: (snippet) ->
13
+ $(snippet).filter('link').each (index, link) =>
14
+ @urls.push $(link).attr('href')
15
+
16
+ # Load all CSS files, then execute callback.
17
+ #
18
+ # For now, load synchronously, to make sure CSS is loaded in the correct
19
+ # order. Async loading is a possible optimization, but would have to do
20
+ # more legwork to keep track of all requests.
21
+ #
22
+ doLoad: (callback) ->
23
+ styles = $('<style type="text/css"/>').appendTo('body')
24
+ $.each @urls, (index, url) =>
25
+ $.ajax url,
26
+ async: false
27
+ success: (data, textStatus, jqXHR) =>
28
+ styles.append data
29
+ callback()
30
+
31
+ # Util: CSS formatter
32
+ #
33
+ formatPercentages: (selector, values) ->
34
+ declarations = (_.map values, (value, key) => "#{key}: #{@formatPercentageValue(value)}").join(';')
35
+ return "#{selector} { #{declarations} }"
36
+
37
+ #
38
+ #
39
+ formatPercentageValues: (values) ->
40
+ _.object _(values).map (percent, key) => [key, @formatPercentageValue percent]
41
+
42
+ # Util.
43
+ #
44
+ formatPercentageValue: (value) ->
45
+ "#{value * 100}%"
46
+
47
+ # Util: CSS formatter
48
+ #
49
+ formatPixels: (selector, values) ->
50
+ declarations = (_.map values, (value, key) -> "#{key}: #{value}px").join(';')
51
+ return "#{selector} { #{declarations} }"
52
+
53
+ # Util: set CSS by writing <style> to the DOM.
54
+ #
55
+ write: (id, styles) ->
56
+ $("style##{id}").remove()
57
+ $('<style type="text/css" id="'+id+'"/>').append(styles).appendTo('body')
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.2
4
+ version: 0.9.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -92,6 +92,8 @@ files:
92
92
  - app/assets/javascripts/alongslide/layout.coffee
93
93
  - app/assets/javascripts/alongslide/parser.coffee
94
94
  - app/assets/javascripts/alongslide/scrolling.coffee
95
+ - app/assets/javascripts/fixedAspect.coffee
96
+ - app/assets/javascripts/styles.coffee
95
97
  - app/assets/stylesheets/alongslide.sass
96
98
  - app/views/panel/panel.haml
97
99
  - app/views/panel/unpin.haml