waypoints-rails 0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b7c5e8a73912400678a776161f484976f19d3bd
4
+ data.tar.gz: b7a5cc6567f6f571d6bb1cf8b9dddfc2d1965bf8
5
+ SHA512:
6
+ metadata.gz: 72ef4d9d7ec4e6380222a93cbbb2d50f3e659ab6519792f01032d2bd0e150567c61cc26331d9930fe569600b57f8d90bf7563e59994d271a5625f2e4794374ef
7
+ data.tar.gz: 27030629d1dbee075019011d03cb1a7507df813329d217af4a1e0b0f682ec73c04a8206e4f6c61f1b8cc338f761d19310bacd68ac54c36b7c6e9275d04bf4817
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in waypoints-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Yoav Matchulsky
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Waypoints::Rails
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'waypoints-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install waypoints-rails
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require "waypoints-rails/version"
2
+
3
+ module Waypoints
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Waypoints
2
+ module Rails
3
+ VERSION = "0.1"
4
+ end
5
+ end
@@ -0,0 +1,104 @@
1
+ ###
2
+ Infinite Scroll Shortcut for jQuery Waypoints - v2.0.4
3
+ Copyright (c) 2011-2014 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt
6
+ ###
7
+ ((root, factory) ->
8
+ if typeof define is 'function' and define.amd
9
+ define ['jquery', 'waypoints'], factory
10
+ else
11
+ factory root.jQuery
12
+ ) this, ($) ->
13
+
14
+ # An extension of the waypoint defaults when calling the "infinite" method.
15
+
16
+ # - container: Selector that matches a container around the items that are
17
+ # infinitely loaded. Newly loaded items will be appended to this container.
18
+ # If this value is set to 'auto' as it is by default, the container will be
19
+ # the element .waypoint is called on.
20
+
21
+ # - items: Selector that matches the items to pull from each AJAX loaded
22
+ # page and append to the "container".
23
+
24
+ # - more: Selector that matches the next-page link. The href attribute of
25
+ # this anchor is AJAX loaded and harvested for new items and a new "more"
26
+ # link during each waypoint trigger.
27
+
28
+ # - offset: The same as the base waypoint offset. But in this case, we use
29
+ # bottom-in-view as the default instead of 0.
30
+
31
+ # - loadingClass: This class is added to the container while new items are
32
+ # being loaded, and removed once they are loaded and appended.
33
+
34
+ # - onBeforePageLoad: A callback function that is executed at the beginning
35
+ # of a page load trigger, before the AJAX request is sent.
36
+
37
+ # - onAfterPageLoad: A callback function that is executed at the end of a new
38
+ # page load, after new items have been appended.
39
+ defaults =
40
+ container: 'auto'
41
+ items: '.infinite-item'
42
+ more: '.infinite-more-link'
43
+ offset: 'bottom-in-view'
44
+ loadingClass: 'infinite-loading'
45
+ onBeforePageLoad: $.noop
46
+ onAfterPageLoad: $.noop
47
+
48
+ # .waypoint('infinite', [object])
49
+
50
+ # The infinite method is a shortcut method for a common UI pattern, infinite
51
+ # scrolling. This turns a traditional More/Next-Page style pagination into
52
+ # an infinite scrolling page. The recommended usage is to call this method
53
+ # on the container holding the items to be loaded. Ex:
54
+
55
+ # $('.infinite-container').waypoint('infinite');
56
+
57
+ # Using all of the default options, when the bottom of the infinite container
58
+ # comes into view, a new page of items will be loaded. The script will look
59
+ # for a link with the class of "infinite-more-link", grab its href attribute,
60
+ # and load that page with AJAX. It will then search for all items in this new
61
+ # page with a class of "infinite-item" and will append them to the
62
+ # "infinite-container". The "infinite-more-link" item is also replaced with
63
+ # the more link from the new page, allowing the next trigger to load the next
64
+ # page. This continues until no new more link is detected in the loaded page.
65
+
66
+ # An options object can optionally be passed in to override any of the
67
+ # defaults specified above, as well as the baseline waypoint defaults.
68
+
69
+ $.waypoints 'extendFn', 'infinite', (options) ->
70
+ options = $.extend {}, $.fn.waypoint.defaults, defaults, options
71
+ return @ if $(options.more).length is 0
72
+ $container = if options.container is 'auto' then @ else $ options.container
73
+
74
+ options.handler = (direction) ->
75
+ if direction in ['down', 'right']
76
+ $this = $ this
77
+ options.onBeforePageLoad()
78
+
79
+ # We disable the waypoint during item loading so that we can't trigger
80
+ # it again and cause duplicate loads.
81
+ $this.waypoint 'disable'
82
+
83
+ # During loading a class is added to the container, should the user
84
+ # wish to style it during this state.
85
+ $container.addClass options.loadingClass
86
+
87
+ # Load items from the next page.
88
+ $.get $(options.more).attr('href'), (data) ->
89
+ $data = $ $.parseHTML(data)
90
+ $more = $ options.more
91
+ $newMore = $data.find options.more
92
+ $container.append $data.find options.items
93
+ $container.removeClass options.loadingClass
94
+
95
+ if $newMore.length
96
+ $more.replaceWith $newMore
97
+ $this.waypoint 'enable'
98
+ else
99
+ $this.waypoint 'destroy'
100
+ options.onAfterPageLoad()
101
+
102
+ # Initialize the waypoint with our built-up options. Returns the original
103
+ # jQuery object per normal for chaining.
104
+ @waypoint options
@@ -0,0 +1,83 @@
1
+ ###
2
+ Sticky Elements Shortcut for jQuery Waypoints - v2.0.4
3
+ Copyright (c) 2011-2014 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt
6
+ ###
7
+ ((root, factory) ->
8
+ if typeof define is 'function' and define.amd
9
+ define ['jquery', 'waypoints'], factory
10
+ else
11
+ factory root.jQuery
12
+ ) this, ($) ->
13
+
14
+ # An extension of the waypoint defaults when calling the "sticky" method.
15
+
16
+ # - wrapper: Each sticky element gets wrapped in another element. This
17
+ # element acts as the actual waypoint and stays in the document flow,
18
+ # leaving the sticky element to gain/lost fixed positioning freely without
19
+ # effecting layout. "wrapper" is the HTML for this element.
20
+
21
+ # - stuckClass: The class that is added to the sticky element when the
22
+ # waypoint is reached. Users should style this class to add fixed
23
+ # positioning and whatever other styles are necessary for their
24
+ # particular design.
25
+ defaults =
26
+ wrapper: '<div class="sticky-wrapper" />'
27
+ stuckClass: 'stuck'
28
+
29
+ # Internal: Wraps the sticky elements in the sticky wrapper and returns the
30
+ # wrapper elements.
31
+ wrap = ($elements, options) ->
32
+ $elements.wrap options.wrapper
33
+ $elements.parent()
34
+
35
+ # .waypoint('sticky', [object])
36
+
37
+ # The sticky method is a shortcut method for a common UI pattern, sticky
38
+ # elements. In its most common form, this pattern consists of an item that
39
+ # is part of the normal document flow until it reaches the top of the
40
+ # viewport, where it gains a fixed position state.
41
+
42
+ # This shortcut does very little to actually create the sticky state. It only
43
+ # adds a class to the element when it reaches the appropriate part of the
44
+ # viewport. It is the job of the user to define the styles for this "stuck"
45
+ # state in CSS. There are many different ways one could style their sticky
46
+ # elements, and trying to implement all of them in JS is futile. Everyone's
47
+ # design is different.
48
+
49
+ # This shortcut does take care of the most common pitfall in previous
50
+ # versions of Waypoints: Using the sticky element as the waypoint. Fixed
51
+ # position elements do not work well as waypoints since their position in
52
+ # the document is constantly changing as the user scrolls (and their
53
+ # position relative to the viewport never does, which is the whole point of
54
+ # Waypoints). This shortcut will create a wrapper element around the sticky
55
+ # element that acts as the actual waypoint, as well as a placeholder for the
56
+ # waypoint in the document flow, as fixed positioning takes an element out
57
+ # of flow and would otherwise effect the page layout. Users are recommended
58
+ # to define any margins on their sticky elements as margins on this
59
+ # wrapper instead.
60
+
61
+ $.waypoints 'extendFn', 'sticky', (opt) ->
62
+ options = $.extend {}, $.fn.waypoint.defaults, defaults, opt
63
+ $wrap = wrap this, options
64
+ originalHandler = options.handler
65
+ options.handler = (direction) ->
66
+ $sticky = $(this).children ':first'
67
+ shouldBeStuck = direction in ['down', 'right']
68
+ $sticky.toggleClass options.stuckClass, shouldBeStuck
69
+ $wrap.height if shouldBeStuck then $sticky.outerHeight() else ''
70
+ originalHandler.call this, direction if originalHandler?
71
+ $wrap.waypoint options
72
+ this.data 'stuckClass', options.stuckClass
73
+
74
+ # .waypoint('unsticky')
75
+
76
+ # Undoes everything done within the sticky shortcut by removing the parent
77
+ # sticky wrapper, destroying the waypoint, and removing any stuck class
78
+ # that may be applied.
79
+
80
+ $.waypoints 'extendFn', 'unsticky', () ->
81
+ this.parent().waypoint 'destroy'
82
+ this.unwrap()
83
+ this.removeClass this.data 'stuckClass'
@@ -0,0 +1,692 @@
1
+ ###
2
+ jQuery Waypoints - v2.0.4
3
+ Copyright (c) 2011-2014 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt
6
+ ###
7
+ ((root, factory) ->
8
+ if typeof define is 'function' and define.amd
9
+ define 'waypoints', ['jquery'], ($) ->
10
+ factory $, root
11
+ else
12
+ factory root.jQuery, root
13
+ ) this, ($, window) ->
14
+ $w = $ window
15
+
16
+ # Touch support feature test
17
+ isTouch = 'ontouchstart' in window
18
+
19
+ # Internal plugin-wide variables:
20
+
21
+ # - allWaypoints: A hash containing two hashes, one for vertical waypoints
22
+ # and one for horizontal waypoints. In each hash they value is a Waypoint
23
+ # instance and the key is that waypoint's unique ID.
24
+
25
+ # - contextCounter: A counter that is incremented with each instantiation
26
+ # of the Context class, used in its unique ID.
27
+
28
+ # - contexts: A hash of all contexts. The value of each entry is a Context
29
+ # instance and the key is that context's unique ID.
30
+
31
+ # - contextKey: The DOM element for each context keeps a reference to the
32
+ # context's unique ID in the jQuery .data() object. This is the key for
33
+ # that data entry.
34
+
35
+ # - resizeEvent: The namespaced resize event used by contexts.
36
+
37
+ # - scrollEvent: The namespaced scroll event used by contexts.
38
+
39
+ # - waypointCounter: A counter that is incremented with each instantiation
40
+ # of the Waypoint class, used in its unique ID.
41
+
42
+ # - waypointKey: The DOM element for each waypoint keeps a reference to an
43
+ # array of the unique IDs of all waypoints attached to that element. This
44
+ # array is kept in the jQuery .data() object, and this is the key for
45
+ # that entry.
46
+
47
+ # - wp: A variable shortcut for the waypoint method name on the $.fn object.
48
+ # Using this variable just helps with minification.
49
+
50
+ # - wps: A variable shortcut for the waypoints method name on the $ object.
51
+ # Using this variable just helps with minification.
52
+
53
+ allWaypoints =
54
+ horizontal: {}
55
+ vertical: {}
56
+ contextCounter = 1
57
+ contexts = {}
58
+ contextKey = 'waypoints-context-id'
59
+ resizeEvent = 'resize.waypoints'
60
+ scrollEvent = 'scroll.waypoints'
61
+ waypointCounter = 1
62
+ waypointKey = 'waypoints-waypoint-ids'
63
+ wp = 'waypoint'
64
+ wps = 'waypoints'
65
+
66
+ # Context: Represents a single scrolling element in which waypoints live.
67
+ # For most users there will only be one Context, the window, but users can
68
+ # use other scrollable elements as a context using the "context" option
69
+ # when creating waypoints.
70
+
71
+ # Properties:
72
+
73
+ # - $element: jQuery object containing the context element.
74
+
75
+ # - element: The raw HTMLNode of the context element.
76
+
77
+ # - didResize: A flag used in throttling the resize event.
78
+
79
+ # - didScroll: A flag used in throttling the scroll event.
80
+
81
+ # - id: A unique identifier for the context.
82
+
83
+ # - oldScroll: A hash containing...
84
+ # - x: The context's last known horizontal scroll value.
85
+ # - y: The context's last known vertical scroll value.
86
+
87
+ # - waypoints: A hash containing two hashes with all waypoints in the context.
88
+ # Entries are in the same style as the allWaypoints hashes:
89
+ # (key = waypoint.id, value = waypoint)
90
+ # - horizontal: A hash of all horizontal waypoints.
91
+ # - vertical: A hash of all vertical waypoints.
92
+
93
+ class Context
94
+ constructor: ($element) ->
95
+ @$element = $element
96
+ @element = $element[0]
97
+ @didResize = no
98
+ @didScroll = no
99
+ @id = 'context' + contextCounter++
100
+ @oldScroll =
101
+ x: $element.scrollLeft()
102
+ y: $element.scrollTop()
103
+ @waypoints =
104
+ horizontal: {}
105
+ vertical: {}
106
+
107
+ # We need to keep a reference to this Context instance on the DOM node
108
+ # so we can look it up later based on the node.
109
+ @element[contextKey] = @id
110
+
111
+ # To do that look up, we need to have this instance in the global hash.
112
+ contexts[@id] = this
113
+
114
+ # Run scroll checks on scroll, but throttle it for performance reasons.
115
+ $element.bind scrollEvent, =>
116
+ unless @didScroll or isTouch
117
+ @didScroll = yes
118
+ scrollHandler = =>
119
+ @doScroll()
120
+ @didScroll = no
121
+ window.setTimeout scrollHandler, $[wps].settings.scrollThrottle
122
+
123
+ # Run a refresh on resize, but throttle it for performance reasons.
124
+ $element.bind resizeEvent, =>
125
+ unless @didResize
126
+ @didResize = yes
127
+ resizeHandler = =>
128
+ $[wps] 'refresh'
129
+ @didResize = no
130
+ window.setTimeout resizeHandler, $[wps].settings.resizeThrottle
131
+
132
+ # doScroll()
133
+
134
+ # Looks at the new scroll values for the context, compares them to the old
135
+ # scroll values, and checks to see if any waypoints should be triggered
136
+ # by that change.
137
+ doScroll: ->
138
+
139
+ # We use some hashes with common values for each axis so that we can
140
+ # just iterate over it rather than write the whole thing twice for
141
+ # each axis.
142
+ axes =
143
+ horizontal:
144
+ newScroll: @$element.scrollLeft()
145
+ oldScroll: @oldScroll.x
146
+ forward: 'right'
147
+ backward: 'left'
148
+ vertical:
149
+ newScroll: @$element.scrollTop()
150
+ oldScroll: @oldScroll.y
151
+ forward: 'down'
152
+ backward: 'up'
153
+
154
+ # This is a small "hack" for iOS, needed because scrolls in mobile
155
+ # Safari that start or end with the URL bar showing will cause window
156
+ # height changes without firing a resize event.
157
+ if isTouch and (!axes.vertical.oldScroll or !axes.vertical.newScroll)
158
+ $[wps] 'refresh'
159
+
160
+ # For each axis, check to see if any waypoints have been crossed.
161
+ # Also determine the direction it's being crossed and sort/reverse all
162
+ # crossed waypoints accordingly. And, of course, trigger the waypoints.
163
+ $.each axes, (aKey, axis) =>
164
+ triggered = []
165
+ isForward = axis.newScroll > axis.oldScroll
166
+ direction = if isForward then axis.forward else axis.backward
167
+ $.each @waypoints[aKey], (wKey, waypoint) ->
168
+ if axis.oldScroll < waypoint.offset <= axis.newScroll
169
+ triggered.push waypoint
170
+ else if axis.newScroll < waypoint.offset <= axis.oldScroll
171
+ triggered.push waypoint
172
+ triggered.sort (a, b) -> a.offset - b.offset
173
+ triggered.reverse() unless isForward
174
+ $.each triggered, (i, waypoint) ->
175
+ if waypoint.options.continuous or i is triggered.length - 1
176
+ waypoint.trigger [direction]
177
+
178
+ # Now that we're done with the check, the new scroll values become
179
+ # the old scroll values for the next check.
180
+ @oldScroll =
181
+ x: axes.horizontal.newScroll
182
+ y: axes.vertical.newScroll
183
+
184
+ # refresh()
185
+ # Runs through all of the waypoints in the context and recalculates
186
+ # their offsets (the scroll value at which the waypoint is triggered.)
187
+ # If a change in offset also happens to cross the context's current
188
+ # scroll value, the waypoint will be triggered in the appropriate direction
189
+ # unless prevented by the "onlyOnScroll" waypoint option.
190
+ refresh: () ->
191
+ isWin = $.isWindow @element
192
+ cOffset = @$element.offset()
193
+
194
+ # Make sure we have the most up-to-date scroll values for our context.
195
+ @doScroll()
196
+
197
+ # Each axis recalculation needs to know some things:
198
+
199
+ # - contextOffset: The distance between the edge of the document and
200
+ # the context element.
201
+
202
+ # - contextScroll: The scroll value of the context. However, if the
203
+ # context is the window this needs to be 0 because this value only
204
+ # comes into play when used in adjustment calculations for non-window
205
+ # context waypoints.
206
+
207
+ # - contextDimension: Width or height of the context.
208
+
209
+ # - oldScroll: The scroll value of the context. Unlike "contextScroll",
210
+ # this is the same no matter the type of context, and is used when
211
+ # determining whether a newly added waypoint should immediately fire
212
+ # on its first offset calculation.
213
+
214
+ # - forward: Direction string passed to forward waypoint triggers.
215
+
216
+ # - backward: Direction string passed to backward waypoint triggers.
217
+
218
+ # - offsetProp: Key of the .offset() object for this axis.
219
+ axes =
220
+ horizontal:
221
+ contextOffset: if isWin then 0 else cOffset.left
222
+ contextScroll: if isWin then 0 else @oldScroll.x
223
+ contextDimension: @$element.width()
224
+ oldScroll: @oldScroll.x
225
+ forward: 'right'
226
+ backward: 'left'
227
+ offsetProp: 'left'
228
+ vertical:
229
+ contextOffset: if isWin then 0 else cOffset.top
230
+ contextScroll: if isWin then 0 else @oldScroll.y
231
+ contextDimension: if isWin then $[wps]('viewportHeight') else \
232
+ @$element.height()
233
+ oldScroll: @oldScroll.y
234
+ forward: 'down'
235
+ backward: 'up'
236
+ offsetProp: 'top'
237
+
238
+ # For each axis, run through the waypoints. Store the old offset.
239
+ # Recalculate the new offset. Check the difference against the context's
240
+ # current scroll value and trigger any crossed waypoints accordingly.
241
+ $.each axes, (aKey, axis) =>
242
+ $.each @waypoints[aKey], (i, waypoint) ->
243
+ adjustment = waypoint.options.offset
244
+ oldOffset = waypoint.offset
245
+ elementOffset = if $.isWindow waypoint.element then 0 else \
246
+ waypoint.$element.offset()[axis.offsetProp]
247
+
248
+ # The "offset" waypoint option (which we call "adjustment" here) can
249
+ # be a number, percentage string, keyword string (bottom-in-view),
250
+ # or a function. So we deal with all of these types here.
251
+ if $.isFunction adjustment
252
+ adjustment = adjustment.apply waypoint.element
253
+ else if typeof adjustment is 'string'
254
+ adjustment = parseFloat adjustment
255
+ if waypoint.options.offset.indexOf('%') > -1
256
+ adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
257
+
258
+ # We've finally calculated all the crazy little adjustments that
259
+ # can come from using non-window contexts and the "offset" option.
260
+ # Store the damn thing.
261
+ waypoint.offset = elementOffset \
262
+ - axis.contextOffset \
263
+ + axis.contextScroll \
264
+ - adjustment
265
+
266
+ # "onlyOnScroll" tells us to not even consider triggering waypoints
267
+ # during refresh, so we can eject early.
268
+ return if (waypoint.options.onlyOnScroll and oldOffset?) or \
269
+ !waypoint.enabled
270
+
271
+ # Case where the refresh causes a backward trigger.
272
+ if oldOffset isnt null and \
273
+ oldOffset < axis.oldScroll <= waypoint.offset
274
+ waypoint.trigger [axis.backward]
275
+
276
+ # Now the forward case.
277
+ else if oldOffset isnt null and \
278
+ oldOffset > axis.oldScroll >= waypoint.offset
279
+ waypoint.trigger [axis.forward]
280
+
281
+ # "oldOffset" values of null mean this is the first calculation of
282
+ # the waypoint's offset. It's a special time in a waypoint's life.
283
+ else if oldOffset is null and axis.oldScroll >= waypoint.offset
284
+ waypoint.trigger [axis.forward]
285
+
286
+ # checkEmpty()
287
+
288
+ # Looks at the waypoints hashes. If they are empty, the context removes
289
+ # itself from the global contexts hash.
290
+ checkEmpty: ->
291
+ if $.isEmptyObject(@waypoints.horizontal) and \
292
+ $.isEmptyObject(@waypoints.vertical)
293
+ @$element.unbind [resizeEvent, scrollEvent].join(' ')
294
+ delete contexts[@id]
295
+
296
+ # Waypoint: Represents a single callback function tied to an element. An
297
+ # element can have multiple waypoints with multiple offsets.
298
+
299
+ # Properties:
300
+
301
+ # - $element: jQuery object containing the waypoint element.
302
+
303
+ # - element: The raw HTMLNode of the waypoint element.
304
+
305
+ # - axis: 'horizontal' || 'vertical' - The axis on which this waypoint lives.
306
+
307
+ # - callback: The function that is fired when the waypoint is triggered.
308
+
309
+ # - context: A reference to the context this waypoint belongs to.
310
+
311
+ # - enabled: Boolean indicating whether this waypoint is enabled or not.
312
+ # Disabled waypoints are still returned in functions that aggregate
313
+ # waypoints, but do not fire their callbacks.
314
+
315
+ # - id: A unique identifier for the waypoint.
316
+
317
+ # - offset: The scroll offset at which the waypoint should trigger.
318
+
319
+ # - options: A hash containing the various waypoint options.
320
+ # See $.fn.waypoint.defaults for more information on those options.
321
+ class Waypoint
322
+ constructor: ($element, context, options) ->
323
+ options = $.extend {}, $.fn[wp].defaults, options
324
+ if options.offset is 'bottom-in-view'
325
+ options.offset = ->
326
+ contextHeight = $[wps] 'viewportHeight'
327
+ unless $.isWindow context.element
328
+ contextHeight = context.$element.height()
329
+ contextHeight - $(this).outerHeight()
330
+
331
+ @$element = $element
332
+ @element = $element[0]
333
+ @axis = if options.horizontal then 'horizontal' else 'vertical'
334
+ @callback = options.handler
335
+ @context = context
336
+ @enabled = options.enabled
337
+ @id = 'waypoints' + waypointCounter++
338
+ @offset = null
339
+ @options = options
340
+
341
+ # Add our new waypoint to its context.
342
+ context.waypoints[@axis][@id] = this
343
+
344
+ # Add it to the global hash.
345
+ allWaypoints[@axis][@id] = this
346
+
347
+ # Add the waypoint's id to the element's waypoint id list.
348
+ idList = @element[waypointKey] ? []
349
+ idList.push @id
350
+ @element[waypointKey] = idList
351
+
352
+ # trigger(array)
353
+
354
+ # Calls the waypoint's callback function, passing to it the arguments
355
+ # supplied in the "args" array.
356
+ trigger: (args) ->
357
+ return unless @enabled
358
+ if @callback?
359
+ @callback.apply @element, args
360
+ if @options.triggerOnce
361
+ @destroy()
362
+
363
+ # disable()
364
+
365
+ # Temporarily disables a waypoint from firing its callback.
366
+ disable: ->
367
+ @enabled = false
368
+
369
+ # enable()
370
+
371
+ # Breathe life back into the waypoint.
372
+ enable: ->
373
+ @context.refresh()
374
+ @enabled = true
375
+
376
+ # destroy()
377
+
378
+ # Kills the waypoint for good.
379
+ destroy: ->
380
+ delete allWaypoints[@axis][@id]
381
+ delete @context.waypoints[@axis][@id]
382
+ @context.checkEmpty()
383
+
384
+ # Waypoint.getWaypointsByElement(HTMLNode)
385
+
386
+ # Returns an array of all Waypoint instances attached to the "element"
387
+ # HTMLNode. Returns an empty array if there are no attached waypoints.
388
+ @getWaypointsByElement: (element) ->
389
+ ids = element[waypointKey]
390
+ return [] unless ids
391
+ all = $.extend {}, allWaypoints.horizontal, allWaypoints.vertical
392
+ $.map ids, (id) ->
393
+ all[id]
394
+
395
+ # These methods are available on the $.fn object by using the method
396
+ # name as the first argument to .waypoint. Ex: $('div').waypoint('destroy')
397
+ methods =
398
+
399
+ # init(function, object)
400
+
401
+ # Creates a new waypoint (and if needed, a new context) using the supplied
402
+ # callback function and options.
403
+
404
+ # The "f" function and the "options" object are both optional, but at least
405
+ # one must be supplied. So acceptable signatures are:
406
+
407
+ # - .waypoint(f)
408
+ # - .waypoint(options)
409
+ # - .waypoint(f, options)
410
+
411
+ # This "init" method should never need to be called explicity by the user.
412
+ # It is the default method that is delegated to when .waypoint is called
413
+ # with one of the above signatures.
414
+
415
+ # Ex: $('div').waypoint(function(direction) {
416
+ # // Do things
417
+ # }, { offset: '100%' });
418
+ init: (f, options) ->
419
+ options ?= {}
420
+ options.handler ?= f
421
+
422
+ @each ->
423
+ $this = $ this
424
+ contextElement = options.context ? $.fn[wp].defaults.context
425
+ unless $.isWindow contextElement
426
+ contextElement = $this.closest contextElement
427
+ contextElement = $ contextElement
428
+ context = contexts[contextElement[0][contextKey]]
429
+ context = new Context contextElement unless context
430
+ new Waypoint $this, context, options
431
+ $[wps] 'refresh'
432
+ this
433
+
434
+ # Disable, enable, and destroy all just delegate to the instance methods
435
+ # of the waypoints attached to the subject elements.
436
+ disable: -> methods._invoke.call this, 'disable'
437
+ enable: -> methods._invoke.call this, 'enable'
438
+ destroy: -> methods._invoke.call this, 'destroy'
439
+
440
+ # .waypoint('prev', string, string|HTMLNode|jQuery)
441
+
442
+ # Returns a jQuery object containing previous waypoint elements. This
443
+ # creates a new entry in the jQuery object stack just like jQuery's prev
444
+ # function. "axis" indicates the axis on which to traverse
445
+ # ('horizontal' | 'vertical') and "selector" indicates which context
446
+ # element to use. The defaults are 'vertical' and window respectively.
447
+ prev: (axis, selector) ->
448
+ methods._traverse.call this, axis, selector, (stack, index, waypoints) ->
449
+ stack.push waypoints[index-1] if index > 0
450
+
451
+ # .waypoint('next', string, string|HTMLNode|jQuery)
452
+
453
+ # Returns a jQuery object containing next waypoint elements. This
454
+ # creates a new entry in the jQuery object stack just like jQuery's next
455
+ # function. "axis" indicates the axis on which to traverse
456
+ # ('horizontal' | 'vertical') and "selector" indicates which context
457
+ # element to use. The defaults are 'vertical' and window respectively.
458
+ next: (axis, selector) ->
459
+ methods._traverse.call this, axis, selector, (stack, index, waypoints) ->
460
+ stack.push waypoints[index+1] if index < waypoints.length-1
461
+
462
+ # Internal: Aggregates waypoints on a given axis of a context, and applies
463
+ # a "push" callback for each element in the subject jQuery object. This
464
+ # callback builds the element array to push to the jQuery stack.
465
+ _traverse: (axis = 'vertical', selector = window, push) ->
466
+ waypoints = jQMethods.aggregate selector
467
+ stack = []
468
+ @each ->
469
+ index = $.inArray this, waypoints[axis]
470
+ push stack, index, waypoints[axis]
471
+ @pushStack stack
472
+
473
+ # Internal: Finds all waypoints on a given set of "$elements" and invokes
474
+ # "method" on each instance.
475
+ _invoke: (method) ->
476
+ this.each ->
477
+ waypoints = Waypoint.getWaypointsByElement this
478
+ $.each waypoints, (i, waypoint) ->
479
+ waypoint[method]()
480
+ true
481
+ this
482
+
483
+ # $.fn.waypoint. Let's just hook this guy up to our methods hash and
484
+ # add some trivial error reporting for bogus calls.
485
+ $.fn[wp] = (method, args...) ->
486
+ if methods[method]
487
+ methods[method].apply this, args
488
+ else if $.isFunction(method)
489
+ methods.init.apply this, arguments
490
+ else if $.isPlainObject(method)
491
+ methods.init.apply this, [null, method]
492
+ else if !method
493
+ $.error "jQuery Waypoints needs a callback function or handler option."
494
+ else
495
+ $.error "The #{method} method does not exist in jQuery Waypoints."
496
+
497
+ # The default options object for a waypoint.
498
+
499
+ # - context: string|HTMLNode|jQuery - The scrollable element that the
500
+ # waypoint acts within. The waypoint will look for the closest ancestor
501
+ # element that matches this selector or node.
502
+
503
+ # - continuous: Multiple waypoints may be triggered by a single scroll check.
504
+ # If you would like a waypoint to only trigger if it is the last waypoint
505
+ # in a scroll check, set this to false.
506
+
507
+ # - enabled: Should this waypoint start enabled (true) or disabled (false)?
508
+
509
+ # - handler: This option is not defined by default, but can be used as an
510
+ # alternate way to pass the waypoint callback function, rather than as
511
+ # the first argument to .waypoint.
512
+
513
+ # Ex: $('div').waypoint({
514
+ # handler: function(direction) { ... }
515
+ # });
516
+
517
+ # - horizontal: Set this to true if the waypoint is, well, horizontal.
518
+
519
+ # - offset: number|string|function - Determines how far from the top (or left
520
+ # if the waypoint is horizontal) of the context's viewport to trigger the
521
+ # waypoint. The default of 0 means that the waypoint is triggered when the
522
+ # top of the waypoint element hits the top of the window/context-element.
523
+ # An offset of 50 would mean the waypoint triggers when the top of the
524
+ # element is 50 pixels from the top of the window.
525
+
526
+ # A % string is translated into a percentage of the width/height of
527
+ # the context.
528
+
529
+ # If a function is passed, that function should return a number. The "this"
530
+ # keyword within this function will be set to the raw HTMLNode of the
531
+ # waypoint element.
532
+
533
+ # - triggerOnce: If true, the waypoint will destroy itself after
534
+ # first trigger.
535
+ $.fn[wp].defaults =
536
+ context: window
537
+ continuous: true
538
+ enabled: true
539
+ horizontal: false
540
+ offset: 0
541
+ triggerOnce: false
542
+
543
+ # These methods are available on the $ object by using the method name as
544
+ # the first argument to .waypoint. Ex: $.waypoints('refresh')
545
+ jQMethods =
546
+
547
+ # $.waypoints('refresh')
548
+
549
+ # Forces a refresh on all contexts, recalculating all waypoint offsets.
550
+ # This is done automatically on waypoint addition and during resize events,
551
+ # but if a user does something to change the DOM, CSS, or in some way
552
+ # change the layout of a page and its elements, they might need to call
553
+ # this method manually.
554
+ refresh: ->
555
+ $.each contexts, (i, context) -> context.refresh()
556
+
557
+ # $.waypoints('viewportHeight')
558
+
559
+ # A utility method that returns the window height, but takes into account
560
+ # inconsistencies that come with just using jQuery's .height() on iOS.
561
+ viewportHeight: ->
562
+ window.innerHeight ? $w.height()
563
+
564
+ # $.waypoints(['aggregate'], [contextSelector])
565
+
566
+ # Returns an object containing two HTMLNode arrays, one for each axis:
567
+
568
+ # {
569
+ # horizontal: [ HTMLNode... ]
570
+ # vertical: [ HTMLNode... ]
571
+ # }
572
+
573
+ # This is the default method used when calling $.waypoints(). If
574
+ # "contextSelector" is not supplied, it returns all waypoints. If
575
+ # "contextSelector" is supplied it only returns waypoints for that context.
576
+
577
+ # The array of waypoint elements is returned sorted by calculated offset,
578
+ # the order in which they would be triggered on the page.
579
+ aggregate: (contextSelector) ->
580
+ collection = allWaypoints
581
+ if contextSelector
582
+ collection = contexts[$(contextSelector)[0][contextKey]]?.waypoints
583
+ return [] unless collection
584
+ waypoints =
585
+ horizontal: []
586
+ vertical: []
587
+ $.each waypoints, (axis, arr) ->
588
+ $.each collection[axis], (key, waypoint) ->
589
+ arr.push waypoint
590
+ arr.sort (a, b) -> a.offset - b.offset
591
+ waypoints[axis] = $.map arr, (waypoint) -> waypoint.element
592
+ waypoints[axis] = $.unique waypoints[axis]
593
+ waypoints
594
+
595
+ # $.waypoints('above', [string|HTMLNode|jQuery])
596
+
597
+ # Returns all vertical waypoints that lie above the current scroll position
598
+ # of the context specified by "contextSelector". If no "contextSelector"
599
+ # is supplied, it defaults to the window.
600
+ above: (contextSelector = window) ->
601
+ jQMethods._filter contextSelector, 'vertical', (context, waypoint) ->
602
+ waypoint.offset <= context.oldScroll.y
603
+
604
+ # $.waypoints('below', [string|HTMLNode|jQuery])
605
+
606
+ # Returns all vertical waypoints that lie below the current scroll position
607
+ # of the context specified by "contextSelector". If no "contextSelector"
608
+ # is supplied, it defaults to the window.
609
+ below: (contextSelector = window) ->
610
+ jQMethods._filter contextSelector, 'vertical', (context, waypoint) ->
611
+ waypoint.offset > context.oldScroll.y
612
+
613
+ # $.waypoints('left', [string|HTMLNode|jQuery])
614
+
615
+ # Returns all horizontal waypoints left of the current scroll position
616
+ # of the context specified by "contextSelector". If no "contextSelector"
617
+ # is supplied, it defaults to the window.
618
+ left: (contextSelector = window) ->
619
+ jQMethods._filter contextSelector, 'horizontal', (context, waypoint) ->
620
+ waypoint.offset <= context.oldScroll.x
621
+
622
+ # $.waypoints('right', [string|HTMLNode|jQuery])
623
+
624
+ # Returns all horizontal waypoints right of the current scroll position
625
+ # of the context specified by "contextSelector". If no "contextSelector"
626
+ # is supplied, it defaults to the window.
627
+ right: (contextSelector = window) ->
628
+ jQMethods._filter contextSelector, 'horizontal', (context, waypoint) ->
629
+ waypoint.offset > context.oldScroll.x
630
+
631
+ # $.waypoints('enable/disable/destroy')
632
+
633
+ # These methods delegate to the enable/disable/destroy instance methods
634
+ # for all waypoints.
635
+ enable: -> jQMethods._invoke 'enable'
636
+ disable: -> jQMethods._invoke 'disable'
637
+ destroy: -> jQMethods._invoke 'destroy'
638
+
639
+ # $.waypoints('extendFn', string, function)
640
+
641
+ # Extends the $.fn.waypoint method object with a new method, "f". This
642
+ # just lets other modules piggyback on the .waypoint namespace.
643
+ extendFn: (methodName, f) ->
644
+ methods[methodName] = f
645
+
646
+ # Internal: Invokes "method" on all waypoints.
647
+ _invoke: (method) ->
648
+ waypoints = $.extend {}, allWaypoints.vertical, allWaypoints.horizontal
649
+ $.each waypoints, (key, waypoint) ->
650
+ waypoint[method]()
651
+ true
652
+
653
+ # Internal: Returns an array of all HTMLNodes for each waypoint that passes
654
+ # the "test" function. Only waypoints within the "selector" context on the
655
+ # "axis" axis are tested. As with .aggregate, the array is sorted by
656
+ # calculated offset (trigger order).
657
+ _filter: (selector, axis, test) ->
658
+ context = contexts[$(selector)[0][contextKey]]
659
+ return [] unless context
660
+ waypoints = []
661
+ $.each context.waypoints[axis], (i, waypoint) ->
662
+ waypoints.push waypoint if test context, waypoint
663
+ waypoints.sort (a, b) -> a.offset - b.offset
664
+ $.map waypoints, (waypoint) -> waypoint.element
665
+
666
+ # Hook up jQMethods to the $.waypoints namespace.
667
+ $[wps] = (method, args...) ->
668
+ if jQMethods[method]
669
+ jQMethods[method].apply null, args
670
+ else
671
+ jQMethods.aggregate.call null, method
672
+
673
+ # Plugin-wide settings:
674
+
675
+ # - resizeThrottle: For performance reasons, the refresh performed during
676
+ # resizes is throttled. This value is the rate-limit in milliseconds
677
+ # between resize refreshes. For more information on throttling, check out
678
+ # Ben Alman’s throttle / debounce plugin.
679
+ # http://benalman.com/projects/jquery-throttle-debounce-plugin/
680
+
681
+ # - scrollThrottle: For performance reasons, checking for any crossed
682
+ # waypoints during a scroll event is throttled. This value is the
683
+ # rate-limit in milliseconds between scroll checks. For more information
684
+ # on throttling, check out Ben Alman’s throttle / debounce plugin.
685
+ # http://benalman.com/projects/jquery-throttle-debounce-plugin/
686
+
687
+ $[wps].settings =
688
+ resizeThrottle: 100
689
+ scrollThrottle: 30
690
+
691
+ # Ensure a refresh on page load. Newly loaded images often shift layout.
692
+ $w.load -> $[wps] 'refresh'
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'waypoints-rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "waypoints-rails"
8
+ spec.version = Waypoints::Rails::VERSION
9
+ spec.authors = ["Yoav Matchulsky"]
10
+ spec.email = ["yoavmatchulsky@gmail.com"]
11
+ spec.description = "jquery-waypoints support for Rails"
12
+ spec.summary = "Waypoints is a jQuery plugin that makes it easy to execute a function whenever you scroll to an element. More info is at http://imakewebthings.com/jquery-waypoints/"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "railties", ">= 3.1.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: waypoints-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Yoav Matchulsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: jquery-waypoints support for Rails
56
+ email:
57
+ - yoavmatchulsky@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/waypoints-rails.rb
68
+ - lib/waypoints-rails/version.rb
69
+ - vendor/assets/javascripts/waypoints-infinite.js.coffee
70
+ - vendor/assets/javascripts/waypoints-sticky.js.coffee
71
+ - vendor/assets/javascripts/waypoints.js.coffee
72
+ - waypoints-rails.gemspec
73
+ homepage: ''
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.2.0
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Waypoints is a jQuery plugin that makes it easy to execute a function whenever
97
+ you scroll to an element. More info is at http://imakewebthings.com/jquery-waypoints/
98
+ test_files: []
99
+ has_rdoc: