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