ratchet_design 0.1.5 → 0.1.6

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