alongslide 0.9.1 → 0.9.2
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.
- data/Gemfile +10 -0
- data/Gemfile.lock +103 -0
- data/alongslide.gemspec +18 -0
- data/app/assets/javascripts/alongslide/alongslide.coffee +107 -0
- data/app/assets/javascripts/alongslide/layout.coffee +504 -0
- data/app/assets/javascripts/alongslide/parser.coffee +125 -0
- data/app/assets/javascripts/alongslide/scrolling.coffee +423 -0
- data/app/assets/javascripts/alongslide.coffee +19 -0
- data/app/assets/stylesheets/alongslide.sass +444 -0
- data/app/views/panel/panel.haml +8 -0
- data/app/views/panel/unpin.haml +4 -0
- data/app/views/section/exit.haml +4 -0
- data/app/views/section/section.haml +4 -0
- data/grammar/alongslide.treetop +162 -0
- data/grammar/panel.treetop +67 -0
- data/vendor/assets/javascripts/jquery.fitvids.js +74 -0
- data/vendor/assets/javascripts/prefix.js +18 -0
- data/vendor/assets/javascripts/regionFlow.coffee +305 -0
- data/vendor/assets/javascripts/skrollr.js +1716 -0
- data/vendor/assets/javascripts/tether.js +1357 -0
- metadata +23 -3
@@ -0,0 +1,74 @@
|
|
1
|
+
/*global jQuery */
|
2
|
+
/*jshint multistr:true browser:true */
|
3
|
+
/*!
|
4
|
+
* FitVids 1.0.3
|
5
|
+
*
|
6
|
+
* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
|
7
|
+
* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
|
8
|
+
* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
|
9
|
+
*
|
10
|
+
* Date: Thu Sept 01 18:00:00 2011 -0500
|
11
|
+
*/
|
12
|
+
|
13
|
+
(function( $ ){
|
14
|
+
|
15
|
+
"use strict";
|
16
|
+
|
17
|
+
$.fn.fitVids = function( options ) {
|
18
|
+
var settings = {
|
19
|
+
customSelector: null
|
20
|
+
};
|
21
|
+
|
22
|
+
if(!document.getElementById('fit-vids-style')) {
|
23
|
+
|
24
|
+
var div = document.createElement('div'),
|
25
|
+
ref = document.getElementsByTagName('base')[0] || document.getElementsByTagName('script')[0],
|
26
|
+
cssStyles = '­<style>.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:12.5%;width:75%;height:75%;}</style>';
|
27
|
+
|
28
|
+
div.className = 'fit-vids-style';
|
29
|
+
div.id = 'fit-vids-style';
|
30
|
+
div.style.display = 'none';
|
31
|
+
div.innerHTML = cssStyles;
|
32
|
+
|
33
|
+
ref.parentNode.insertBefore(div,ref);
|
34
|
+
|
35
|
+
}
|
36
|
+
|
37
|
+
if ( options ) {
|
38
|
+
$.extend( settings, options );
|
39
|
+
}
|
40
|
+
|
41
|
+
return this.each(function(){
|
42
|
+
var selectors = [
|
43
|
+
"iframe[src*='player.vimeo.com']",
|
44
|
+
"iframe[src*='youtube.com']",
|
45
|
+
"iframe[src*='youtube-nocookie.com']",
|
46
|
+
"iframe[src*='kickstarter.com'][src*='video.html']",
|
47
|
+
"object",
|
48
|
+
"embed"
|
49
|
+
];
|
50
|
+
|
51
|
+
if (settings.customSelector) {
|
52
|
+
selectors.push(settings.customSelector);
|
53
|
+
}
|
54
|
+
|
55
|
+
var $allVideos = $(this).find(selectors.join(','));
|
56
|
+
$allVideos = $allVideos.not("object object"); // SwfObj conflict patch
|
57
|
+
|
58
|
+
$allVideos.each(function(){
|
59
|
+
var $this = $(this);
|
60
|
+
if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
|
61
|
+
var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
|
62
|
+
width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
|
63
|
+
aspectRatio = height / width;
|
64
|
+
if(!$this.attr('id')){
|
65
|
+
var videoID = 'fitvid' + Math.floor(Math.random()*999999);
|
66
|
+
$this.attr('id', videoID);
|
67
|
+
}
|
68
|
+
$this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%");
|
69
|
+
$this.removeAttr('height').removeAttr('width');
|
70
|
+
});
|
71
|
+
});
|
72
|
+
};
|
73
|
+
// Works with either jQuery or Zepto
|
74
|
+
})( window.jQuery || window.Zepto );
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// http://davidwalsh.name/vendor-prefix
|
2
|
+
//
|
3
|
+
|
4
|
+
var prefix = (function () {
|
5
|
+
var styles = window.getComputedStyle(document.documentElement, ''),
|
6
|
+
pre = (Array.prototype.slice
|
7
|
+
.call(styles)
|
8
|
+
.join('')
|
9
|
+
.match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
|
10
|
+
)[1],
|
11
|
+
dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
|
12
|
+
return {
|
13
|
+
dom: dom,
|
14
|
+
lowercase: pre,
|
15
|
+
css: '-' + pre + '-',
|
16
|
+
js: pre[0].toUpperCase() + pre.substr(1)
|
17
|
+
};
|
18
|
+
})();
|
@@ -0,0 +1,305 @@
|
|
1
|
+
#
|
2
|
+
# regionFlow.coffee: ultralightweight, if somewhat naïve, implementation of
|
3
|
+
# CSS regions, according to the spec at:
|
4
|
+
#
|
5
|
+
# http://dev.w3.org/csswg/css-regions/
|
6
|
+
#
|
7
|
+
# Copyright 2013 Canopy Canopy Canopy, Inc.
|
8
|
+
#
|
9
|
+
|
10
|
+
|
11
|
+
# Initialize NamedFlowMap.
|
12
|
+
#
|
13
|
+
class RegionFlow
|
14
|
+
|
15
|
+
# To be spec compliant, the NamedFlow .overset property should be proactively
|
16
|
+
# calculated after any layout change.
|
17
|
+
#
|
18
|
+
# However, in reality, checking a DOM element's scrollHeight is very expensive,
|
19
|
+
# so it's best not to call it any more than is stricly necessary.
|
20
|
+
#
|
21
|
+
# For that reason, lazy mode is enabled by default, and callers should call
|
22
|
+
# .updateOverset() on namedFlows instead of checking the .overset property.
|
23
|
+
#
|
24
|
+
lazyMode: true
|
25
|
+
|
26
|
+
init: ->
|
27
|
+
document.namedFlows = new @NamedFlowMap
|
28
|
+
|
29
|
+
# Document has one NamedFlowMap, so that flows may be looked up by index.
|
30
|
+
#
|
31
|
+
# [MapClass(DOMString, NamedFlow)]
|
32
|
+
#
|
33
|
+
class RegionFlow::NamedFlowMap
|
34
|
+
|
35
|
+
namedFlows: {}
|
36
|
+
|
37
|
+
#
|
38
|
+
#
|
39
|
+
build: (flowName) ->
|
40
|
+
@namedFlows[flowName] = new RegionFlow::NamedFlow(flowName)
|
41
|
+
|
42
|
+
# As specified:
|
43
|
+
#
|
44
|
+
# NamedFlow? get(DOMString flowName);
|
45
|
+
#
|
46
|
+
get: (flowName) ->
|
47
|
+
@namedFlows[flowName] || @build(flowName)
|
48
|
+
|
49
|
+
# As specified:
|
50
|
+
#
|
51
|
+
# boolean has(DOMString flowName);
|
52
|
+
#
|
53
|
+
has: (flowName) ->
|
54
|
+
@namedFlows[flowName]?
|
55
|
+
|
56
|
+
# As specified:
|
57
|
+
#
|
58
|
+
# NamedFlowMap set(DOMString flowName, NamedFlow flowValue);
|
59
|
+
#
|
60
|
+
set: (flowName, flowValue) ->
|
61
|
+
@namedFlows[flowName] = flowValue
|
62
|
+
|
63
|
+
# As specified:
|
64
|
+
#
|
65
|
+
# boolean delete(DOMString flowName);
|
66
|
+
#
|
67
|
+
delete: (flowName) ->
|
68
|
+
delete @namedFlows[flowName]
|
69
|
+
|
70
|
+
# A NamedFlow
|
71
|
+
#
|
72
|
+
# interface NamedFlow : EventTarget {
|
73
|
+
# };
|
74
|
+
#
|
75
|
+
class RegionFlow::NamedFlow
|
76
|
+
# readonly attribute DOMString name;
|
77
|
+
# readonly attribute boolean overset;
|
78
|
+
# readonly attribute integer firstEmptyRegionIndex;
|
79
|
+
|
80
|
+
#
|
81
|
+
#
|
82
|
+
constructor: (@name) ->
|
83
|
+
@contentNodes = []
|
84
|
+
@overset = false
|
85
|
+
@resetRegions()
|
86
|
+
|
87
|
+
# Reset, assuming all previously-tracked regions have been destroyed.
|
88
|
+
#
|
89
|
+
# Leave content nodes right where they are.
|
90
|
+
#
|
91
|
+
resetRegions: ->
|
92
|
+
@regions = []
|
93
|
+
@firstEmptyRegionIndex = -1
|
94
|
+
@updateOverset() unless RegionFlow::lazyMode
|
95
|
+
|
96
|
+
# As specified:
|
97
|
+
#
|
98
|
+
# sequence<Region> getRegions();
|
99
|
+
#
|
100
|
+
getRegions: ->
|
101
|
+
@regions
|
102
|
+
|
103
|
+
# Push region to end of array and doFlow.
|
104
|
+
#
|
105
|
+
addRegion: (regionNode) ->
|
106
|
+
@regions.push new RegionFlow::Region(regionNode)
|
107
|
+
@firstEmptyRegionIndex = @regions.length - 1
|
108
|
+
@doFlow()
|
109
|
+
|
110
|
+
# As specified:
|
111
|
+
#
|
112
|
+
# sequence<Node> getContent();
|
113
|
+
#
|
114
|
+
getContent: ->
|
115
|
+
@contentNodes
|
116
|
+
|
117
|
+
# Push content to end of array and doFlow.
|
118
|
+
#
|
119
|
+
addContent: (contentNode) ->
|
120
|
+
@contentNodes.push($(contentNode))
|
121
|
+
@doFlow()
|
122
|
+
|
123
|
+
# If regions are all still there, but the dimensions of already laid-out
|
124
|
+
# regions has changed, re-flow all regions from scratch (like resetRegions,
|
125
|
+
# but softer).
|
126
|
+
#
|
127
|
+
reFlow: ->
|
128
|
+
node.empty() for node in _.pluck @regions, 'node'
|
129
|
+
|
130
|
+
@firstEmptyRegionIndex = 0
|
131
|
+
loop
|
132
|
+
@doFlow()
|
133
|
+
break if @firstEmptyRegionIndex is @regions.length - 1
|
134
|
+
@firstEmptyRegionIndex++
|
135
|
+
|
136
|
+
# Layout logic.
|
137
|
+
#
|
138
|
+
doFlow: ->
|
139
|
+
if @firstEmptyRegionIndex is 0
|
140
|
+
|
141
|
+
# TODO: prune marginal nodes? comments, scripts?
|
142
|
+
|
143
|
+
@populateRegions()
|
144
|
+
|
145
|
+
else if @firstEmptyRegionIndex > 0
|
146
|
+
|
147
|
+
# move all nodes from oversetRegion to lastRegion
|
148
|
+
# (which will later become the oversetRegion)
|
149
|
+
nodes = $(@oversetRegion().node).contents().remove()
|
150
|
+
@lastRegion().appendNode(nodes)
|
151
|
+
|
152
|
+
# enter recursive loop
|
153
|
+
@breakUp nodes: nodes
|
154
|
+
|
155
|
+
@updateOverset() unless RegionFlow::lazyMode
|
156
|
+
|
157
|
+
# Place all content into regions. Performed only on first time.
|
158
|
+
#
|
159
|
+
populateRegions: ->
|
160
|
+
@lastRegion().appendNode(node.clone()) for node in @contentNodes
|
161
|
+
|
162
|
+
# Recursive layout call.
|
163
|
+
#
|
164
|
+
# @params options - hash
|
165
|
+
# node - HTML element to be broken up. ignored if nodes option is specified.
|
166
|
+
# nodes - array of HTML elements. overrides node option if specified.
|
167
|
+
# into - targetNode to break up 'node' into. defaults to oversetRegion's root.
|
168
|
+
#
|
169
|
+
breakUp: (options = {}) ->
|
170
|
+
nodes = options.nodes || $(options.node).contents()
|
171
|
+
|
172
|
+
targetNode = options.into || @oversetRegion().node
|
173
|
+
|
174
|
+
if options.node?
|
175
|
+
targetNode = $(options.node).clone().empty().appendTo(targetNode).get(0)
|
176
|
+
|
177
|
+
nodes.each (index, childNode) =>
|
178
|
+
|
179
|
+
if $(childNode).hasClass('break-before-always') and not $(targetNode).empty()
|
180
|
+
return false
|
181
|
+
|
182
|
+
formerParent = $(childNode).parent()
|
183
|
+
$(childNode).remove().appendTo(targetNode)
|
184
|
+
|
185
|
+
if @oversetRegion().updateOverset() is 'overset'
|
186
|
+
|
187
|
+
# move it back where it was
|
188
|
+
$(childNode).remove().prependTo(formerParent)
|
189
|
+
|
190
|
+
if childNode.nodeType is Node.TEXT_NODE
|
191
|
+
@breakUpText node: childNode, into: targetNode
|
192
|
+
else
|
193
|
+
@breakUp node: childNode, into: targetNode
|
194
|
+
|
195
|
+
# exit loop
|
196
|
+
return false
|
197
|
+
|
198
|
+
else if $(childNode).hasClass('break-after-always')
|
199
|
+
return false
|
200
|
+
|
201
|
+
# Given a text node and a target node (in the overset region), find the number
|
202
|
+
# of words which fit.
|
203
|
+
#
|
204
|
+
# @params options - hash
|
205
|
+
# node - textNode to copy words from
|
206
|
+
# into - targetNode to copy words to
|
207
|
+
#
|
208
|
+
breakUpText: (options = {}) ->
|
209
|
+
textNode = options.node
|
210
|
+
targetNode = document.createTextNode("")
|
211
|
+
$(targetNode).appendTo(options.into)
|
212
|
+
|
213
|
+
words = textNode.nodeValue.split(/[ ]+/)
|
214
|
+
highIndex = words.length - 1
|
215
|
+
lowIndex = 0
|
216
|
+
tryIndex = highIndex
|
217
|
+
|
218
|
+
loop
|
219
|
+
targetNode.textContent = words[0..tryIndex].join(" ")
|
220
|
+
|
221
|
+
if @oversetRegion().updateOverset() is 'overset'
|
222
|
+
highIndex = tryIndex
|
223
|
+
else
|
224
|
+
lowIndex = tryIndex
|
225
|
+
|
226
|
+
tryIndex = Math.floor(lowIndex + (highIndex - lowIndex) / 2)
|
227
|
+
|
228
|
+
break if highIndex - lowIndex <= 1
|
229
|
+
|
230
|
+
if tryIndex is 0
|
231
|
+
$(targetNode).remove()
|
232
|
+
else
|
233
|
+
targetNode.textContent = words[0..tryIndex].join(" ")
|
234
|
+
textNode.nodeValue = words[tryIndex+1..words.length-1].join(" ")
|
235
|
+
$(textNode).parent().addClass("region-flow-post-text-break")
|
236
|
+
|
237
|
+
@oversetRegion().updateOverset() unless RegionFlow::lazyMode
|
238
|
+
|
239
|
+
# Calculate whether named flow is overset.
|
240
|
+
#
|
241
|
+
# Normally treated as a private method, but called publicly in lazy mode.
|
242
|
+
# See RegionFlow::lazyMode.
|
243
|
+
#
|
244
|
+
updateOverset: ->
|
245
|
+
@overset = @regions[@firstEmptyRegionIndex]?.updateOverset() is 'overset'
|
246
|
+
|
247
|
+
# Readability helpers.
|
248
|
+
#
|
249
|
+
oversetRegion: ->
|
250
|
+
@regions[@firstEmptyRegionIndex - 1]
|
251
|
+
lastRegion: ->
|
252
|
+
@regions[@firstEmptyRegionIndex]
|
253
|
+
|
254
|
+
|
255
|
+
# [NoInterfaceObject]
|
256
|
+
# interface Region {
|
257
|
+
# };
|
258
|
+
#
|
259
|
+
class RegionFlow::Region
|
260
|
+
|
261
|
+
constructor: (node) ->
|
262
|
+
@node = $(node)
|
263
|
+
@updateOverset() unless RegionFlow::lazyMode
|
264
|
+
|
265
|
+
# Append one or more nodes.
|
266
|
+
#
|
267
|
+
appendNode: (contentNode) ->
|
268
|
+
$(@node).append(contentNode)
|
269
|
+
@updateOverset() unless RegionFlow::lazyMode
|
270
|
+
|
271
|
+
# As specified:
|
272
|
+
#
|
273
|
+
# readonly attribute DOMString regionOverset;
|
274
|
+
#
|
275
|
+
# Possible states
|
276
|
+
#
|
277
|
+
# 'overset': The region is the last one in the region chain and not able to fit the remaining content from the named flow.
|
278
|
+
# 'fit': The region's flow fragment content fits into the region's content box.
|
279
|
+
# 'empty': All content from the named flow was fitted in prior regions.
|
280
|
+
#
|
281
|
+
updateOverset: ->
|
282
|
+
node = @node.get(0)
|
283
|
+
isOverset = node.scrollHeight > node.clientHeight
|
284
|
+
|
285
|
+
# Check if region contains a node which needs breaking
|
286
|
+
containsUnrespectedBreak = false
|
287
|
+
@node.find('.break-before-always').each ->
|
288
|
+
unless $(@).prev().length == 0
|
289
|
+
containsUnrespectedBreak = true
|
290
|
+
return
|
291
|
+
@node.find('.break-after-always').each ->
|
292
|
+
unless $(@).next().length == 0
|
293
|
+
containsUnrespectedBreak = true
|
294
|
+
return
|
295
|
+
|
296
|
+
@regionOverset =
|
297
|
+
if @node.is(':empty')
|
298
|
+
'empty'
|
299
|
+
else if isOverset or containsUnrespectedBreak
|
300
|
+
'overset'
|
301
|
+
else
|
302
|
+
'fit'
|
303
|
+
|
304
|
+
#
|
305
|
+
window.RegionFlow = RegionFlow
|