ratchet_design 0.1.5 → 0.1.6

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/ratchet/favicon.ico +0 -0
  3. data/app/assets/javascripts/ratchet/base/form.js +117 -8
  4. data/app/assets/javascripts/ratchet/base/mobilemenu.js +50 -12
  5. data/app/assets/javascripts/ratchet/base/validation.js +263 -0
  6. data/app/assets/javascripts/ratchet/core.js +78 -57
  7. data/app/assets/javascripts/ratchet/enhancement/_collapse.js +6 -3
  8. data/app/assets/javascripts/ratchet/enhancement/_lightbox.js +93 -0
  9. data/app/assets/javascripts/ratchet/enhancement/_swap.js +7 -3
  10. data/app/assets/javascripts/ratchet/{utility → enhancement}/loader.js +8 -15
  11. data/app/assets/javascripts/ratchet/enhancement/notice.js +3 -8
  12. data/app/assets/javascripts/ratchet/enhancement/sticky.js +35 -18
  13. data/app/assets/javascripts/ratchet/enhancement/waypoints.js +162 -125
  14. data/app/assets/javascripts/ratchet/shim/classlist.js +234 -0
  15. data/app/assets/javascripts/ratchet/shim/object.assign.js +30 -0
  16. data/app/assets/javascripts/ratchet/utility/ajax.js +122 -0
  17. data/app/assets/javascripts/ratchet/utility/compile_data.js +40 -0
  18. data/app/assets/javascripts/ratchet/utility/from_top.js +14 -0
  19. data/app/assets/javascripts/ratchet/utility/full_stop.js +55 -0
  20. data/app/assets/javascripts/ratchet/utility/get_closest.js +20 -0
  21. data/app/assets/javascripts/ratchet/utility/get_next.js +17 -0
  22. data/app/assets/javascripts/ratchet/utility/matches.js +15 -0
  23. data/app/assets/javascripts/ratchet/utility/scroll_to.js +74 -0
  24. data/app/assets/javascripts/ratchet/utility/throttle.js +25 -0
  25. data/app/assets/javascripts/ratchet/utility/timeout.js +45 -0
  26. data/app/assets/javascripts/ratchet/utility/unhover.js +56 -0
  27. data/app/assets/javascripts/ratchet/utility/word_count.js +15 -0
  28. data/app/assets/stylesheets/ratchet/_core.scss +2 -4
  29. data/app/assets/stylesheets/ratchet/base/_button.scss +1 -1
  30. data/app/assets/stylesheets/ratchet/base/_form.scss +50 -61
  31. data/app/assets/stylesheets/ratchet/base/_text.scss +8 -8
  32. data/app/assets/stylesheets/ratchet/{utility → enhancement}/_loader.scss +1 -1
  33. data/app/assets/stylesheets/ratchet/enhancement/_tooltip.scss +1 -6
  34. data/app/assets/stylesheets/ratchet/utility/_global.scss +12 -2
  35. data/app/helpers/ratchet/application_helper.rb +2 -28
  36. data/app/views/layouts/ratchet/default.html.slim +4 -5
  37. data/app/views/shared/ratchet/_footer.html.slim +2 -3
  38. data/app/views/shared/ratchet/_header.html.slim +1 -1
  39. data/lib/ratchet_design/version.rb +1 -1
  40. data/lib/ratchet_design.rb +0 -1
  41. data/public/assets/ratchet/core-0.1.6.js +105 -0
  42. data/public/assets/ratchet/core-0.1.6.js.gz +0 -0
  43. data/public/assets/ratchet/core-0.1.6.map.json +1 -0
  44. data/public/assets/ratchet/{fonts-woff-0.1.5.css → fonts-woff-0.1.6.css} +0 -0
  45. data/public/assets/ratchet/{fonts-woff-0.1.5.css.gz → fonts-woff-0.1.6.css.gz} +0 -0
  46. data/public/assets/ratchet/{fonts-woff2-0.1.5.css → fonts-woff2-0.1.6.css} +0 -0
  47. data/public/assets/ratchet/{fonts-woff2-0.1.5.css.gz → fonts-woff2-0.1.6.css.gz} +0 -0
  48. metadata +28 -47
  49. data/app/assets/images/ratchet/safari-pinned-tab.svg +0 -1
  50. data/app/assets/javascripts/ratchet/base/sync-input-value.js +0 -30
  51. data/app/assets/javascripts/ratchet/enhancement/lightbox.js +0 -165
  52. data/app/assets/javascripts/ratchet/shim/scope.js +0 -94
  53. data/app/assets/stylesheets/ratchet/base/_multistep-form.scss +0 -64
  54. data/app/assets/stylesheets/ratchet/enhancement/_lightbox.scss +0 -98
  55. data/app/helpers/ratchet/form_helper.rb +0 -140
  56. data/public/assets/ratchet/core-0.1.5.js +0 -133
  57. data/public/assets/ratchet/core-0.1.5.js.gz +0 -0
  58. data/public/assets/ratchet/core-0.1.5.map.json +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9854474d864b29d5388bc282aecad7fc7a3f8760
4
- data.tar.gz: 3b1eb0f65c9eefa2d94cca6781911eead681e4fd
3
+ metadata.gz: 800a6bcc6a8a10f42a0684bb4dda1d88dfb52cd7
4
+ data.tar.gz: 78ba7b72667ec3c73de93bc91b6eab8d269fac17
5
5
  SHA512:
6
- metadata.gz: 4948c22ed7802902649afd43073d4f68f343218ef55d9a8aeab7164a7ee8ccbee6b4aec7a00996c338b7547cc2d9179a625676eb4d1fc9e9d37ac4f361f149f3
7
- data.tar.gz: 518a7a7bc903d003065d93d83488924c3631a449752771afe684bc464b5938e59260f14987b921a14917c254549217fbf72cc39a06abd9c3f9e73476f43dea5c
6
+ metadata.gz: a573756a5d39a85e1e890ae4b3c72669146fbc77d820a7a3594fb132af7774b7f7926d56bfa8caaa8f35fd13428d56c898d3f8da831f4e92abd1a99516aa26d7
7
+ data.tar.gz: 5239ca2ac035a0dd1144b11247f4b9bc38582cc387ddb795a4c8a6a9903df512fe912305c73af4c0c6d97990f8f005f4ec69c14af576da5ee6470f4b84db247a
Binary file
@@ -5,13 +5,14 @@
5
5
  * @license MIT
6
6
  **/
7
7
 
8
- var toolbox = require( 'compose-toolbox' )
8
+ // Dependencies
9
+ var evt = require( 'compose-event' );
9
10
 
10
11
  // Public API function
11
12
  var form = function( element, settings ) {
12
13
 
13
14
  // Overridable defaults
14
- var defaults = {}
15
+ var defaults = {};
15
16
 
16
17
  // Parameter variables
17
18
  var selector = document.querySelector( element ) || document.querySelector( 'form' );
@@ -20,22 +21,22 @@ var form = function( element, settings ) {
20
21
  if ( !selector ) return false;
21
22
 
22
23
  // Scoped variables
23
- var options = toolbox.merge( defaults, settings ),
24
+ var options = Object.assign( {}, defaults, settings ),
24
25
  rangeEls = document.querySelectorAll( 'input[type=range]' ),
25
26
  tickEls = document.querySelectorAll( 'input[type=checkbox], input[type=radio]' ),
26
27
  docBody = document.body;
27
28
 
28
29
  // Prevent non-numeric characters in number fields
29
- toolbox.event.on( docBody, 'keypress', 'input[type=number]', restrictInput )
30
+ docBody.addEventListener( 'keypress', keyHandler, false );
30
31
 
31
32
  // Run delegated `on input` listener
32
- toolbox.event.on( docBody, 'input', '[type=range]', rangeHandler )
33
+ docBody.addEventListener( 'input', rangeHandler, true );
33
34
 
34
35
  // Loop over any range inputs that are present
35
36
  for ( var rangeIndex = 0; rangeIndex < rangeEls.length; rangeIndex++ ) {
36
37
 
37
38
  // And run their handler function explicitly at runtime
38
- rangeHandler( rangeEls[ rangeIndex ] )
39
+ rangeHandler( rangeEls[ rangeIndex ] );
39
40
 
40
41
  }
41
42
 
@@ -74,9 +75,14 @@ var form = function( element, settings ) {
74
75
  }
75
76
 
76
77
  // Keydown handler function
77
- function restrictInput( event ) {
78
+ function keyHandler( event ) {
78
79
 
79
- // If user typing in an input[type=number] and enters non-numeric characters
80
+ // Only run on number inputs
81
+ if ( event.target.type !== 'number' ) {
82
+ return false;
83
+ }
84
+
85
+ // If user enters non-numeric characters
80
86
  if ( event.which < 48 || event.which > 57 ) {
81
87
 
82
88
  // Supress them
@@ -105,6 +111,109 @@ var form = function( element, settings ) {
105
111
 
106
112
  }
107
113
 
114
+ // Rangetouch 0.0.9 - https://github.com/selz/rangetouch
115
+ function rangeTouch( size ) {
116
+
117
+ // Bail if not a touch device
118
+ if ( !( 'ontouchstart' in document.documentElement ) ) {
119
+ return;
120
+ }
121
+
122
+ // Scoped variables
123
+ var rangeInputs = document.querySelectorAll( '[type=range]' ),
124
+ thumbSize = size || 20;
125
+
126
+ // Set touchAction to prevent delays
127
+ for ( var i = rangeInputs.length - 1; i >= 0; i-- ) {
128
+ rangeInputs[ i ].style.touchAction = 'manipulation';
129
+ rangeInputs[ i ].style.webkitUserSelect = 'none';
130
+ }
131
+
132
+ // Listen for events
133
+ docBody.addEventListener( 'touchstart', setValue, false );
134
+ docBody.addEventListener( 'touchmove', setValue, false );
135
+ docBody.addEventListener( 'touchend', setValue, false );
136
+
137
+ // Get the number of decimal places
138
+ function getDecimalPlaces( value ) {
139
+ var match = ( '' + value ).match( /( ?:\.( \d+ ) )?( ?:[eE]( [+-]?\d+ ) )?$/ );
140
+ if ( !match ) {
141
+ return 0;
142
+ }
143
+ return Math.max( 0, ( match[ 1 ] ? match[ 1 ].length : 0 ) - ( match[ 2 ] ? +match[ 2 ] : 0 ) );
144
+ }
145
+
146
+ // Round to the nearest step
147
+ function roundToStep( number, step ) {
148
+ if ( step < 1 ) {
149
+ var places = getDecimalPlaces( parseInt( step ) );
150
+ return parseFloat( number.toFixed( places ) );
151
+ }
152
+ return ( Math.round( number / step ) * step );
153
+ }
154
+
155
+ // Get the value based on touch position
156
+ function getValue( event ) {
157
+
158
+ // Scoped variables
159
+ var input = event.target,
160
+ touch = event.changedTouches[ 0 ],
161
+ min = parseFloat( input.getAttribute( 'min' ) ) || 0,
162
+ max = parseFloat( input.getAttribute( 'max' ) ) || 100,
163
+ step = parseFloat( input.getAttribute( 'step' ) ) || 1,
164
+ delta = max - min;
165
+
166
+ // Calculate percentage
167
+ var percent,
168
+ clientRect = input.getBoundingClientRect(),
169
+ thumbWidth = ( ( ( 100 / clientRect.width ) * ( thumbSize / 2 ) ) / 100 );
170
+
171
+ // Determine left percentage
172
+ percent = ( ( 100 / clientRect.width ) * ( touch.clientX - clientRect.left ) );
173
+
174
+ // Don't allow outside bounds
175
+ if ( percent < 0 ) {
176
+ percent = 0;
177
+ } else if ( percent > 100 ) {
178
+ percent = 100;
179
+ }
180
+
181
+ // Factor in the thumb offset
182
+ if ( percent < 50 ) {
183
+ percent -= ( ( 100 - ( percent * 2 ) ) * thumbWidth );
184
+ } else if ( percent > 50 ) {
185
+ percent += ( ( ( percent - 50 ) * 2 ) * thumbWidth );
186
+ }
187
+
188
+ // Find the closest step to the mouse position
189
+ return min + roundToStep( delta * ( percent / 100 ), step );
190
+
191
+ }
192
+
193
+ // Update range value based on position
194
+ function setValue( event ) {
195
+
196
+ // Bail if not a range slider
197
+ if ( event.target.type !== 'range' ) {
198
+ return;
199
+ }
200
+
201
+ // Prevent text highlight on iOS
202
+ event.preventDefault();
203
+
204
+ // Set value
205
+ event.target.value = getValue( event );
206
+
207
+ // Trigger input event
208
+ evt.fire( event.target, ( event.type === 'touchend' ? 'change' : 'input' ) );
209
+
210
+ }
211
+
212
+ }
213
+
214
+ // Initialize RangeTouch
215
+ rangeTouch();
216
+
108
217
  };
109
218
 
110
219
  // Public API
@@ -6,31 +6,69 @@
6
6
  **/
7
7
 
8
8
  // Dependencies
9
- var toolbox = require( 'compose-toolbox' )
9
+ var matches = require( '../utility/matches' );
10
10
 
11
11
  // Public API function
12
- var mobileMenu = function( settings ) {
12
+ var mobileMenu = function( element, settings ) {
13
13
 
14
14
  // Overridable defaults
15
15
  var defaults = {
16
16
  initWidth : '700px',
17
17
  openClass : 'menu-open',
18
- nav : '.main-nav',
19
- button : '.mobile-menu-button'
18
+ menuButton : '.mobile-menu-button'
20
19
  },
21
20
 
22
21
  // Scoped variables
23
- options = toolbox.merge( defaults, settings ),
24
- selector = options.button + ', ' + options.openClass + ' ' + options.nav + ' a',
22
+ options = Object.assign( {}, defaults, settings ),
23
+ selector = document.querySelector( element ),
24
+ widthQuery = window.matchMedia( '(max-width: ' + options.initWidth + ')' ),
25
25
  docBody = document.body;
26
26
 
27
27
  // Attach listeners
28
- toolbox.event.on( document, 'click', selector, function() {
29
- // Toggle body class
30
- docBody.classList.toggle( options.openClass )
31
- })
28
+ if ( selector ) {
32
29
 
33
- }
30
+ // Call listener function explicitly at run time
31
+ queryHandler( widthQuery );
32
+
33
+ // Attach listener function to listen in on state changes
34
+ widthQuery.addListener( queryHandler );
35
+
36
+ }
37
+
38
+ // Click handler function
39
+ function clickHandler( event ) {
40
+
41
+ // Combine element selector with anchor links
42
+ var toggleSelector = options.menuButton + ', .' + options.openClass + ' ' + element + ' a[href^="#"]';
43
+
44
+ // Only run on menu button
45
+ if ( matches( event.target, toggleSelector ) ) {
46
+
47
+ // Toggle body class
48
+ docBody.classList.toggle( options.openClass );
49
+
50
+ }
51
+
52
+ }
53
+
54
+ // Media query handler function
55
+ function queryHandler( condition ) {
56
+
57
+ // If media query matches
58
+ if ( condition.matches ) {
59
+
60
+ // Click function listener
61
+ selector.addEventListener( 'click', clickHandler, false );
62
+
63
+ } else {
64
+
65
+ // Remove click listener
66
+ selector.removeEventListener( 'click', clickHandler, false );
67
+
68
+ }
69
+ }
70
+
71
+ };
34
72
 
35
73
  // Public API
36
- module.exports = mobileMenu
74
+ module.exports = mobileMenu;
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Validation 0.0.6
3
+ * Compose form validation module
4
+ * @author Kyle Foster (@hkfoster)
5
+ * @license MIT
6
+ **/
7
+
8
+ // Dependencies
9
+ var matches = require( '../utility/matches' ),
10
+ getClosest = require( '../utility/get_closest' ),
11
+ wordCount = require( '../utility/word_count' );
12
+
13
+ // Public API function
14
+ var validation = function( element, settings ) {
15
+
16
+ // Overridable defaults
17
+ var defaults = {};
18
+
19
+ // Parameter variables
20
+ var selector = document.querySelector( element ) || document.querySelector( '[required]' );
21
+
22
+ // Only run if selector exists & validation is supported
23
+ if ( !selector || typeof document.createElement( 'input' ).checkValidity !== 'function' ) return false;
24
+
25
+ // Scoped variables
26
+ var options = Object.assign( {}, defaults, settings ),
27
+ docBody = document.body;
28
+
29
+ // Suppress default message bubbles
30
+ docBody.addEventListener( 'invalid', function( event ) {
31
+ event.preventDefault();
32
+ }, true );
33
+
34
+ // Run delegated `on blur` validation checks
35
+ docBody.addEventListener( 'blur', blurHandler, true );
36
+
37
+ // Run delegated `on submit` validation checks
38
+ docBody.addEventListener( 'click', submissionHandler, false );
39
+
40
+ // Blur validation handler
41
+ function blurHandler( event ) {
42
+
43
+ // Only run on non-submit inputs
44
+ if ( !matches( event.target, 'input:not([type=submit]), textarea' ) ) return false;
45
+
46
+ // Scoped variables
47
+ var element = event.target,
48
+ minWords = element.dataset.minWords,
49
+ maxWords = element.dataset.maxWords,
50
+ indicator = getClosest( element, 'label' ) || element,
51
+ validity;
52
+
53
+ // If element only contains whitespace, strip value
54
+ if ( element.value && !element.value.replace( /\s/g, '' ).length ) {
55
+ element.value = '';
56
+ }
57
+
58
+ // Remove pre-existing validation message
59
+ messageHandler( 'hide', element );
60
+
61
+ // If element has `data-min-words` attribute
62
+ if ( minWords ) {
63
+
64
+ // Run respective validation function
65
+ validateWords( 'min', element, minWords );
66
+
67
+ }
68
+
69
+ // If element has `data-min-words` attribute
70
+ if ( maxWords ) {
71
+
72
+ // Run respective validation function
73
+ validateWords( 'max', element, maxWords );
74
+
75
+ }
76
+
77
+ // Check validity
78
+ validity = element.checkValidity();
79
+
80
+ // If the element has a value but is invalid
81
+ if ( element.value && !validity ) {
82
+
83
+ // Set invalid state
84
+ indicator.classList.remove( 'valid' );
85
+ indicator.classList.add( 'invalid' );
86
+
87
+ // If the element has a value and is valid
88
+ } else if ( element.value && validity ) {
89
+
90
+ // Set valid state
91
+ indicator.classList.remove( 'invalid' );
92
+ indicator.classList.add( 'valid' );
93
+
94
+ // If the element has no value
95
+ } else if ( !element.value ) {
96
+
97
+ // Set neutral state
98
+ indicator.classList.remove( 'valid' );
99
+ indicator.classList.remove( 'invalid' );
100
+
101
+ }
102
+
103
+ }
104
+
105
+ // Submission validation handler function
106
+ function submissionHandler( event ) {
107
+
108
+ // Only run on submission
109
+ if ( !matches( event.target, 'input[type=submit], button[type=submit]' ) ) return;
110
+
111
+ // Scoped variables
112
+ var invalidForm = getClosest( event.target, 'form' ),
113
+ invalidElem = invalidForm.querySelector( 'input:invalid, textarea:invalid' ),
114
+ indicator;
115
+
116
+ // If invalid element found
117
+ if ( invalidElem ) {
118
+
119
+ // Set indicator to parent label if it exists
120
+ indicator = getClosest( invalidElem, 'label' ) || invalidElem;
121
+
122
+ // If credit card field is invalid
123
+ if ( matches( invalidElem, '[data-stripe=number]' ) ) {
124
+
125
+ // Strip it of non-number characters
126
+ invalidElem.value = invalidElem.value.replace( /[^0-9 -]/g, '' );
127
+
128
+ // Evaluate form validity again
129
+ invalidElem = invalidForm.querySelector( 'input:invalid, textarea:invalid' );
130
+
131
+ // And return if valid
132
+ if ( !invalidElem ) return;
133
+
134
+ }
135
+
136
+ // Prevent default behavior
137
+ event.preventDefault();
138
+
139
+ // If invalid is not hidden
140
+ if ( invalidElem.style.display !== 'none' ) {
141
+
142
+ // Focus it
143
+ invalidElem.focus();
144
+
145
+ // Otherwise
146
+ } else {
147
+
148
+ // Focus its immediate sibling (mostly used for upload buttons)
149
+ invalidElem.nextSibling.focus();
150
+
151
+ }
152
+
153
+ // Toggle classes
154
+ indicator.classList.remove( 'valid' );
155
+ indicator.classList.add( 'invalid' );
156
+
157
+ // Show validation message
158
+ messageHandler( 'show', invalidElem );
159
+
160
+ // Prevent Safari submission
161
+ return false;
162
+
163
+ }
164
+
165
+ }
166
+
167
+ // Validation message handler function
168
+ function messageHandler( action, element ) {
169
+
170
+ // Scoped variables
171
+ var parentForm = getClosest( element, 'form' ),
172
+ oldMessage = parentForm.querySelector( '.validation-message' ),
173
+ newMessage = element.validationMessage,
174
+
175
+ // Hide old message
176
+ hideMessage = function() {
177
+ oldMessage.parentNode.removeChild( oldMessage );
178
+ },
179
+
180
+ // Show new message
181
+ showMessage = function() {
182
+
183
+ // Find the element's parent label
184
+ var labelParent = getClosest( element, 'label' );
185
+
186
+ // If it doesn't exist, abort
187
+ if ( !labelParent ) return false;
188
+
189
+ // Otherwise, create and append the validation message
190
+ labelParent.insertAdjacentHTML( 'beforeend', '<aside class="validation-message"><p>' + newMessage + '</p></aside>' );
191
+
192
+ };
193
+
194
+ // If a `data-message` attribute exists, use it in message
195
+ if ( element.dataset.message ) newMessage = element.dataset.message;
196
+
197
+ // If hide action is passed hide old message
198
+ if ( oldMessage && action === 'hide' ) hideMessage();
199
+
200
+ // If show action is passed and no old message exists
201
+ if ( action === 'show' && !oldMessage ) {
202
+
203
+ // Show new message
204
+ showMessage();
205
+
206
+ // If show action is passed and old message exists
207
+ } else if ( action === 'show' && oldMessage ) {
208
+
209
+ // Make sure old message is not on currently invalid element
210
+ if ( oldMessage.parentNode !== element.parentNode ) {
211
+
212
+ // Hide old message
213
+ hideMessage();
214
+
215
+ // And show new message
216
+ showMessage();
217
+
218
+ // Otherwise
219
+ } else {
220
+
221
+ // Update message text on currently invalid element
222
+ oldMessage.childNodes[ 0 ].textContent = newMessage;
223
+
224
+ }
225
+
226
+ }
227
+
228
+ }
229
+
230
+ // Min- or max-words validation function
231
+ function validateWords( type, element, goal ) {
232
+
233
+ // Defaults settings to min-words
234
+ var value = element.value,
235
+ condition = wordCount( value ) < goal,
236
+ verbiage = 'at least ';
237
+
238
+ // Overwrite defaults in case of max-words
239
+ if ( type === 'max' ) {
240
+ condition = wordCount( value ) > goal;
241
+ verbiage = 'no more than ';
242
+ }
243
+
244
+ // If value exists and it meets invalid condition
245
+ if ( value && condition ) {
246
+
247
+ // Set a custom error message
248
+ element.setCustomValidity( 'Please write ' + verbiage + goal + ' words.' );
249
+
250
+ // Otherwise
251
+ } else {
252
+
253
+ // Default to normal error messaging
254
+ element.setCustomValidity( '' );
255
+
256
+ }
257
+
258
+ }
259
+
260
+ };
261
+
262
+ // Public API
263
+ module.exports = validation;