ratchet_design 0.1.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/app/assets/images/ratchet/favicon.ico +0 -0
- data/app/assets/javascripts/ratchet/_svg.js +55 -0
- data/app/assets/javascripts/ratchet/base/form.js +220 -0
- data/app/assets/javascripts/ratchet/base/mobilemenu.js +62 -0
- data/app/assets/javascripts/ratchet/base/validation.js +230 -0
- data/app/assets/javascripts/ratchet/core.js +92 -0
- data/app/assets/javascripts/ratchet/enhancement/_collapse.js +96 -0
- data/app/assets/javascripts/ratchet/enhancement/_lightbox.js +93 -0
- data/app/assets/javascripts/ratchet/enhancement/_swap.js +120 -0
- data/app/assets/javascripts/ratchet/enhancement/_switcheroo.js +28 -0
- data/app/assets/javascripts/ratchet/enhancement/_textcounter.js +92 -0
- data/app/assets/javascripts/ratchet/enhancement/loader.js +77 -0
- data/app/assets/javascripts/ratchet/enhancement/notice.js +70 -0
- data/app/assets/javascripts/ratchet/enhancement/sticky.js +128 -0
- data/app/assets/javascripts/ratchet/enhancement/waypoints.js +328 -0
- data/app/assets/javascripts/ratchet/shim/classlist.js +234 -0
- data/app/assets/javascripts/ratchet/shim/object.assign.js +30 -0
- data/app/assets/javascripts/ratchet/utility/compile_data.js +32 -0
- data/app/assets/javascripts/ratchet/utility/from_top.js +14 -0
- data/app/assets/javascripts/ratchet/utility/full_stop.js +55 -0
- data/app/assets/javascripts/ratchet/utility/get_closest.js +20 -0
- data/app/assets/javascripts/ratchet/utility/get_next.js +17 -0
- data/app/assets/javascripts/ratchet/utility/load_font.js +72 -0
- data/app/assets/javascripts/ratchet/utility/load_script.js +34 -0
- data/app/assets/javascripts/ratchet/utility/matches.js +15 -0
- data/app/assets/javascripts/ratchet/utility/scroll_to.js +74 -0
- data/app/assets/javascripts/ratchet/utility/throttle.js +25 -0
- data/app/assets/javascripts/ratchet/utility/timeout.js +45 -0
- data/app/assets/javascripts/ratchet/utility/unhover.js +56 -0
- data/app/assets/javascripts/ratchet/utility/word_count.js +15 -0
- data/app/assets/stylesheets/ratchet/_core.scss +20 -0
- data/app/assets/stylesheets/ratchet/base/_button.scss +101 -0
- data/app/assets/stylesheets/ratchet/base/_document.scss +306 -0
- data/app/assets/stylesheets/ratchet/base/_form.scss +614 -0
- data/app/assets/stylesheets/ratchet/base/_list.scss +114 -0
- data/app/assets/stylesheets/ratchet/base/_media.scss +41 -0
- data/app/assets/stylesheets/ratchet/base/_table.scss +81 -0
- data/app/assets/stylesheets/ratchet/base/_text.scss +411 -0
- data/app/assets/stylesheets/ratchet/enhancement/_contrast-section.scss +22 -0
- data/app/assets/stylesheets/ratchet/enhancement/_feature.scss +49 -0
- data/app/assets/stylesheets/ratchet/enhancement/_hero.scss +44 -0
- data/app/assets/stylesheets/ratchet/enhancement/_loader.scss +109 -0
- data/app/assets/stylesheets/ratchet/enhancement/_notice.scss +74 -0
- data/app/assets/stylesheets/ratchet/enhancement/_signup.scss +206 -0
- data/app/assets/stylesheets/ratchet/enhancement/_sticky-sidebar.scss +36 -0
- data/app/assets/stylesheets/ratchet/fonts-woff.css +55 -0
- data/app/assets/stylesheets/ratchet/fonts-woff2.css +55 -0
- data/app/assets/stylesheets/ratchet/utility/_global.scss +255 -0
- data/app/assets/stylesheets/ratchet/utility/_grid.scss +102 -0
- data/app/assets/svgs/ratchet/facebook.svg +1 -0
- data/app/assets/svgs/ratchet/github.svg +1 -0
- data/app/assets/svgs/ratchet/google-plus.svg +1 -0
- data/app/assets/svgs/ratchet/ibm.svg +1 -0
- data/app/assets/svgs/ratchet/inbox.svg +1 -0
- data/app/assets/svgs/ratchet/linkedin.svg +1 -0
- data/app/assets/svgs/ratchet/ratchet.svg +1 -0
- data/app/assets/svgs/ratchet/search.svg +1 -0
- data/app/assets/svgs/ratchet/subscribe.svg +1 -0
- data/app/assets/svgs/ratchet/twitter.svg +1 -0
- data/app/assets/svgs/ratchet/y-combinator.svg +1 -0
- data/app/helpers/ratchet/application_helper.rb +51 -0
- data/app/views/layouts/ratchet/default.html.slim +61 -0
- data/app/views/shared/ratchet/_footer.html.slim +2 -0
- data/app/views/shared/ratchet/_header.html.slim +17 -0
- data/app/views/shared/ratchet/_icons.html.slim +89 -0
- data/lib/ratchet_design.rb +12 -0
- data/lib/ratchet_design/version.rb +3 -0
- data/public/assets/ratchet/core-0.1.0.js +103 -0
- data/public/assets/ratchet/core-0.1.0.js.gz +0 -0
- data/public/assets/ratchet/core-0.1.0.map.json +1 -0
- data/public/assets/ratchet/fonts-woff-0.1.0.css +55 -0
- data/public/assets/ratchet/fonts-woff-0.1.0.css.gz +0 -0
- data/public/assets/ratchet/fonts-woff2-0.1.0.css +55 -0
- data/public/assets/ratchet/fonts-woff2-0.1.0.css.gz +0 -0
- metadata +177 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClassList
|
|
3
|
+
* Cross-browser full element.classList implementation
|
|
4
|
+
* @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js
|
|
5
|
+
* @author Eli Grey - http://eligrey.com
|
|
6
|
+
* @license MIT
|
|
7
|
+
**/
|
|
8
|
+
|
|
9
|
+
if ( 'document' in self ) {
|
|
10
|
+
|
|
11
|
+
// Full polyfill for browsers with no classList support
|
|
12
|
+
if ( !( 'classList' in document.createElement( '_' ) ) ) {
|
|
13
|
+
|
|
14
|
+
( function( view ) {
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
if ( !( 'Element' in view ) ) return;
|
|
19
|
+
|
|
20
|
+
var
|
|
21
|
+
classListProp = 'classList',
|
|
22
|
+
protoProp = 'prototype',
|
|
23
|
+
elemCtrProto = view.Element[ protoProp ],
|
|
24
|
+
objCtr = Object,
|
|
25
|
+
|
|
26
|
+
strTrim = String[ protoProp ].trim || function() {
|
|
27
|
+
return this.replace( /^\s+|\s+$/g, '' );
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
arrIndexOf = Array[ protoProp ].indexOf || function( item ) {
|
|
31
|
+
for ( var i = 0; i < this.length; i++ ) {
|
|
32
|
+
if ( i in this && this[ i ] === item ) {
|
|
33
|
+
return i;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return -1;
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
DOMEx = function( type, message ) {
|
|
40
|
+
this.name = type;
|
|
41
|
+
this.code = DOMException[ type ];
|
|
42
|
+
this.message = message;
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
checkTokenAndGetIndex = function( classList, token ) {
|
|
46
|
+
if ( token === '' ) {
|
|
47
|
+
throw new DOMEx(
|
|
48
|
+
'SYNTAX_ERR',
|
|
49
|
+
'An invalid or illegal string was specified'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if ( /\s/.test( token ) ) {
|
|
53
|
+
throw new DOMEx(
|
|
54
|
+
'INVALID_CHARACTER_ERR',
|
|
55
|
+
'String contains an invalid character'
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return arrIndexOf.call( classList, token );
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
ClassList = function( elem ) {
|
|
62
|
+
var trimmedClasses = strTrim.call( elem.getAttribute( 'class' ) || '' ),
|
|
63
|
+
classes = trimmedClasses ? trimmedClasses.split( /\s+/ ) : [];
|
|
64
|
+
|
|
65
|
+
for ( var i = 0; i < classes.length; i++ ) {
|
|
66
|
+
this.push( classes[ i ] );
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this._updateClassName = function() {
|
|
70
|
+
elem.setAttribute( 'class', this.toString() );
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
classListProto = ClassList[ protoProp ] = [],
|
|
75
|
+
|
|
76
|
+
classListGetter = function() {
|
|
77
|
+
return new ClassList( this );
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
DOMEx[ protoProp ] = Error[ protoProp ];
|
|
81
|
+
|
|
82
|
+
classListProto.item = function( i ) {
|
|
83
|
+
return this[ i ] || null;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
classListProto.contains = function( token ) {
|
|
87
|
+
token += '';
|
|
88
|
+
return checkTokenAndGetIndex( this, token ) !== -1;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
classListProto.add = function() {
|
|
92
|
+
var
|
|
93
|
+
tokens = arguments,
|
|
94
|
+
iter = 0,
|
|
95
|
+
len = tokens.length,
|
|
96
|
+
updated = false,
|
|
97
|
+
token;
|
|
98
|
+
|
|
99
|
+
do {
|
|
100
|
+
token = tokens[ iter ] + '';
|
|
101
|
+
if ( checkTokenAndGetIndex( this, token ) === -1 ) {
|
|
102
|
+
this.push( token );
|
|
103
|
+
updated = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
while ( ++iter < len );
|
|
108
|
+
|
|
109
|
+
if ( updated ) {
|
|
110
|
+
this._updateClassName();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
classListProto.remove = function() {
|
|
115
|
+
var
|
|
116
|
+
tokens = arguments,
|
|
117
|
+
iter = 0,
|
|
118
|
+
len = tokens.length,
|
|
119
|
+
updated = false,
|
|
120
|
+
token,
|
|
121
|
+
index;
|
|
122
|
+
|
|
123
|
+
do {
|
|
124
|
+
token = tokens[ iter ] + '';
|
|
125
|
+
index = checkTokenAndGetIndex( this, token );
|
|
126
|
+
|
|
127
|
+
while ( index !== -1 ) {
|
|
128
|
+
this.splice( index, 1 );
|
|
129
|
+
updated = true;
|
|
130
|
+
index = checkTokenAndGetIndex( this, token );
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
while ( ++iter < len );
|
|
135
|
+
|
|
136
|
+
if ( updated ) {
|
|
137
|
+
this._updateClassName();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
classListProto.toggle = function( token, force ) {
|
|
142
|
+
token += '';
|
|
143
|
+
|
|
144
|
+
var
|
|
145
|
+
result = this.contains( token ),
|
|
146
|
+
method = result ? force !== true && 'remove' : force !== false && 'add';
|
|
147
|
+
|
|
148
|
+
if ( method ) {
|
|
149
|
+
this[ method ]( token );
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if ( force === true || force === false ) {
|
|
153
|
+
return force;
|
|
154
|
+
} else {
|
|
155
|
+
return !result;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
classListProto.toString = function() {
|
|
160
|
+
return this.join( ' ' );
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
if ( objCtr.defineProperty ) {
|
|
164
|
+
var classListPropDesc = {
|
|
165
|
+
get : classListGetter,
|
|
166
|
+
enumerable : true,
|
|
167
|
+
configurable : true
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
objCtr.defineProperty( elemCtrProto, classListProp, classListPropDesc );
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
catch ( ex ) {
|
|
175
|
+
if ( ex.number === -0x7FF5EC54 ) {
|
|
176
|
+
classListPropDesc.enumerable = false;
|
|
177
|
+
objCtr.defineProperty( elemCtrProto, classListProp, classListPropDesc );
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
} else if ( objCtr[ protoProp ].__defineGetter__ ) {
|
|
182
|
+
elemCtrProto.__defineGetter__( classListProp, classListGetter );
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}( self ));
|
|
186
|
+
|
|
187
|
+
} else {
|
|
188
|
+
|
|
189
|
+
( function() {
|
|
190
|
+
|
|
191
|
+
'use strict';
|
|
192
|
+
|
|
193
|
+
var testElement = document.createElement( '_' );
|
|
194
|
+
|
|
195
|
+
testElement.classList.add( 'c1', 'c2' );
|
|
196
|
+
|
|
197
|
+
if ( !testElement.classList.contains( 'c2' ) ) {
|
|
198
|
+
var createMethod = function( method ) {
|
|
199
|
+
var original = DOMTokenList.prototype[ method ];
|
|
200
|
+
|
|
201
|
+
DOMTokenList.prototype[ method ] = function( token ) {
|
|
202
|
+
var i, len = arguments.length;
|
|
203
|
+
|
|
204
|
+
for ( i = 0; i < len; i++ ) {
|
|
205
|
+
token = arguments[ i ];
|
|
206
|
+
original.call( this, token );
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
createMethod( 'add' );
|
|
211
|
+
createMethod( 'remove' );
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
testElement.classList.toggle( 'c3', false );
|
|
215
|
+
|
|
216
|
+
if ( testElement.classList.contains( 'c3' ) ) {
|
|
217
|
+
var _toggle = DOMTokenList.prototype.toggle;
|
|
218
|
+
|
|
219
|
+
DOMTokenList.prototype.toggle = function( token, force ) {
|
|
220
|
+
if ( 1 in arguments && !this.contains( token ) === !force ) {
|
|
221
|
+
return force;
|
|
222
|
+
} else {
|
|
223
|
+
return _toggle.call( this, token );
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
testElement = null;
|
|
230
|
+
|
|
231
|
+
}());
|
|
232
|
+
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object.assign polyfill
|
|
3
|
+
* Cross-browser full Object.assign implementation
|
|
4
|
+
* @source https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
if ( typeof Object.assign != 'function' ) {
|
|
9
|
+
( function() {
|
|
10
|
+
Object.assign = function( target ) {
|
|
11
|
+
'use strict';
|
|
12
|
+
if ( target === undefined || target === null ) {
|
|
13
|
+
throw new TypeError( 'Cannot convert undefined or null to object' );
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
var output = Object( target );
|
|
17
|
+
for ( var index = 1; index < arguments.length; index++ ) {
|
|
18
|
+
var source = arguments[ index ];
|
|
19
|
+
if ( source !== undefined && source !== null ) {
|
|
20
|
+
for ( var nextKey in source ) {
|
|
21
|
+
if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
|
|
22
|
+
output[ nextKey ] = source[ nextKey ];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return output;
|
|
28
|
+
};
|
|
29
|
+
})();
|
|
30
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompileData 0.0.1
|
|
3
|
+
* Compile input data from a given parent element
|
|
4
|
+
* @author Kyle Foster (@hkfoster)
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
// Public API function
|
|
9
|
+
var compileData = function( parent ) {
|
|
10
|
+
|
|
11
|
+
// Scoped variables
|
|
12
|
+
var formData = new FormData(),
|
|
13
|
+
allFields = parent.querySelectorAll( 'input:not([type=submit])' );
|
|
14
|
+
|
|
15
|
+
// Loop over fields
|
|
16
|
+
for ( var i = 0; i < allFields.length; i++ ) {
|
|
17
|
+
|
|
18
|
+
// Uncomment for testing
|
|
19
|
+
// console.log( 'Name: ' + allFields[ i ].name + '\n' + 'Value: ' + allFields[ i ].value );
|
|
20
|
+
|
|
21
|
+
// And append their name/value to new formData object
|
|
22
|
+
formData.append( allFields[ i ].name, allFields[ i ].value );
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Then return said formData object
|
|
27
|
+
return formData;
|
|
28
|
+
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Public API
|
|
32
|
+
module.exports = compileData;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FromTop 0.0.1
|
|
3
|
+
* Find element’s distance from top of document
|
|
4
|
+
* @author Kyle Foster (@hkfoster)
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
// Public API function
|
|
9
|
+
var fromTop = function( elem ) {
|
|
10
|
+
return Math.round( elem.getBoundingClientRect().top + window.pageYOffset );
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Public API
|
|
14
|
+
module.exports = fromTop;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FullStop 0.0.2
|
|
3
|
+
* Prevent CSS transitions from occurring during a window resize
|
|
4
|
+
* @author Kyle Foster (@hkfoster)
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
// Dependencies
|
|
9
|
+
var throttle = require( '../utility/throttle' ),
|
|
10
|
+
timeout = require( '../utility/timeout' );
|
|
11
|
+
|
|
12
|
+
// Public API function
|
|
13
|
+
var fullStop = function( settings ) {
|
|
14
|
+
|
|
15
|
+
// Overridable defaults
|
|
16
|
+
var defaults = {
|
|
17
|
+
resizeDelay : 250,
|
|
18
|
+
resizeClass : 'no-transitions'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Scoped variables
|
|
22
|
+
var options = Object.assign( {}, defaults, settings ),
|
|
23
|
+
docBody = document.body,
|
|
24
|
+
resizeTimer;
|
|
25
|
+
|
|
26
|
+
// Resize handler function
|
|
27
|
+
function resizeHandler() {
|
|
28
|
+
|
|
29
|
+
// Clear timer (if it exists)
|
|
30
|
+
if ( resizeTimer ) timeout.clear( resizeTimer );
|
|
31
|
+
|
|
32
|
+
// Add body class while resizing
|
|
33
|
+
docBody.classList.add( options.resizeClass );
|
|
34
|
+
|
|
35
|
+
// Check to see if resize is over
|
|
36
|
+
resizeTimer = timeout.set( function() {
|
|
37
|
+
|
|
38
|
+
// And remove body class upon completion
|
|
39
|
+
docBody.classList.remove( options.resizeClass );
|
|
40
|
+
|
|
41
|
+
// Delay firing function based on argument passed
|
|
42
|
+
}, options.resizeDelay );
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Resize throttle function init
|
|
47
|
+
throttle( 'resize', 'optimizedResize' );
|
|
48
|
+
|
|
49
|
+
// Resize function listener
|
|
50
|
+
window.addEventListener( 'optimizedResize', resizeHandler, false );
|
|
51
|
+
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Public API
|
|
55
|
+
module.exports = fullStop;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GetClosest 0.0.1
|
|
3
|
+
* Get closest DOM element up the tree that matches a given selector
|
|
4
|
+
* @author Kyle Foster (@hkfoster)
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
// Dependencies
|
|
9
|
+
var matches = require( './matches' );
|
|
10
|
+
|
|
11
|
+
// Public API function
|
|
12
|
+
var getClosest = function ( elem, selector ) {
|
|
13
|
+
for ( ; elem && elem !== document; elem = elem.parentNode ) {
|
|
14
|
+
if ( matches( elem, selector ) ) return elem;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Public API
|
|
20
|
+
module.exports = getClosest;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GetNext 0.0.1
|
|
3
|
+
* Get next DOM element that matches a given selector
|
|
4
|
+
* @author Kyle Foster (@hkfoster)
|
|
5
|
+
* @license MIT
|
|
6
|
+
**/
|
|
7
|
+
|
|
8
|
+
// Public API function
|
|
9
|
+
var getNext = function( elem, selector ) {
|
|
10
|
+
for ( ; elem && elem !== document; elem = elem.parentNode ) {
|
|
11
|
+
if ( elem.querySelector( selector ) ) return elem.querySelector( selector );
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Public API
|
|
17
|
+
module.exports = getNext;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoadFont 0.0.1
|
|
3
|
+
* A font loader that leverages LocalStorage
|
|
4
|
+
* @author Adam Beres-Deak (@bdadam) & Kyle Foster (@hkfoster)
|
|
5
|
+
* @source https://github.com/bdadam/OptimizedWebfontLoading
|
|
6
|
+
* @license MIT
|
|
7
|
+
**/
|
|
8
|
+
|
|
9
|
+
// Dependencies - https://github.com/filamentgroup/woff2-feature-test
|
|
10
|
+
var supportsWoff2 = ( function( win ) {
|
|
11
|
+
if ( !( "FontFace" in win ) ) return false;
|
|
12
|
+
var f = new FontFace( 't', 'url( "data:application/font-woff2;base64,d09GMgABAAAAAAIkAAoAAAAABVwAAAHcAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlYAgloKLEoBNgIkAxgLDgAEIAWDcgc1G7IEyB6SJAFID5YA3nAHC6h4+H7s27nP1kTyOoQkGuJWtNGIJKYznRI3VEL7IaHq985ZUuKryZKcAtJsi5eULwUybm9KzajBBhywZ5ZwoJNuwDX5C/xBjvz5DbsoNsvG1NGQiqp0NMLZ7JlnW+5MaM3HwcHheUQeiVokekHkn/FRdefvJaTp2PczN+I1Sc3k9VuX51Tb0Tqqf1deVXGdJsDOhz0/EffMOPOzHNH06pYkDDjs+P8fb/z/8n9Iq8ITzWywkP6PBMMN9L/O7vY2FNoTAkp5PpD6g1nV9WmyQnM5uPpAMHR2fe06jbfvzPriekVTQxC6lpKr43oDtRZfCATl5OVAUKykqwm9o8R/kg37cxa6eZikS7cjK4aIwoyh6jOFplhFrz2b833G3Jii9AjDUiAZ9AxZtxdEYV6imvRF0+0Nej3wu6nPZrTLh81AVcV3kmMVdQj6Qbe9qetzbuDZ7vXOlRrqooFSxCv6SfrDICA6rnHZXQPVcUHJYGcoqa3jVH7ATrjWBNYYkEqF3RFpVIl0q2JvMOJd7/TyjXHw2NyAuJpNaEbz8RTEVtCbSH7JrwQQOqwGl7sTUOtdBZIY2DKqKlvOmPvUxJaURAZZcviTT0SKHCXqzwc=" ) format( "woff2" )', {} );
|
|
13
|
+
f.load()[ 'catch' ]( function() {} );
|
|
14
|
+
return f.status == 'loading' || f.status == 'loaded';
|
|
15
|
+
})( window );
|
|
16
|
+
|
|
17
|
+
// Public API function -
|
|
18
|
+
var loadFont = function( fontName, woffUrl, woff2Url, onlyLoadFontOnSecondPageload ){
|
|
19
|
+
|
|
20
|
+
// Many unsupported browsers should stop here
|
|
21
|
+
var nua = navigator.userAgent,
|
|
22
|
+
nope = !window.addEventListener || ( nua.match( /(Android (2|3|4.0|4.1|4.2|4.3))|(Opera (Mini|Mobi))/ ) && !nua.match( /Chrome/ ) );
|
|
23
|
+
|
|
24
|
+
if ( nope ) return;
|
|
25
|
+
|
|
26
|
+
// Set up LocalStorage
|
|
27
|
+
var loSto = {};
|
|
28
|
+
|
|
29
|
+
// Set up a proxy variable to help with LocalStorage
|
|
30
|
+
try { loSto = localStorage || {}; }
|
|
31
|
+
catch( ex ) {}
|
|
32
|
+
|
|
33
|
+
var loStoPrefix = 'x-font-' + fontName,
|
|
34
|
+
loStoUrlKey = loStoPrefix + 'url',
|
|
35
|
+
loStoCssKey = loStoPrefix + 'css',
|
|
36
|
+
storedFontUrl = loSto[ loStoUrlKey ],
|
|
37
|
+
storedFontCss = loSto[ loStoCssKey ],
|
|
38
|
+
styleElement = document.createElement( 'style' );
|
|
39
|
+
|
|
40
|
+
// Make <style> element & apply base64 encoded font data
|
|
41
|
+
styleElement.rel = 'stylesheet';
|
|
42
|
+
document.head.appendChild( styleElement );
|
|
43
|
+
|
|
44
|
+
// CSS in LocalStorage & loaded from one of the current URLs
|
|
45
|
+
if ( storedFontCss && ( storedFontUrl === woffUrl || storedFontUrl === woff2Url ) ) {
|
|
46
|
+
|
|
47
|
+
styleElement.textContent = storedFontCss;
|
|
48
|
+
|
|
49
|
+
// Data not present or loaded from an obsolete URL
|
|
50
|
+
} else {
|
|
51
|
+
|
|
52
|
+
// Check for WOFF2 support
|
|
53
|
+
var cssUrl = ( woff2Url && supportsWoff2 ) ? woff2Url : woffUrl,
|
|
54
|
+
request = new XMLHttpRequest();
|
|
55
|
+
|
|
56
|
+
// Fetch font data from the server
|
|
57
|
+
request.open( 'GET', cssUrl );
|
|
58
|
+
request.onload = function() {
|
|
59
|
+
if ( request.status >= 200 && request.status < 400 ) {
|
|
60
|
+
|
|
61
|
+
// Update LocalStorage with fresh data & apply
|
|
62
|
+
loSto[ loStoUrlKey ] = cssUrl;
|
|
63
|
+
loSto[ loStoCssKey ] = request.responseText;
|
|
64
|
+
if ( !onlyLoadFontOnSecondPageload ) styleElement.textContent = request.responseText;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
request.send();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Public API
|
|
72
|
+
module.exports = loadFont;
|