waypoints-rails 0.1

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.
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: