-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathbreakdancer.js
123 lines (104 loc) · 3.47 KB
/
breakdancer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Breakdancer is a simple breakpoint utility.
*
* @constructor
* @param {Object} specification Different breakpoints we need to know.
* @public
*/
export default class Breakdancer {
constructor(specification) {
//
// Setup our default values after the window has been set so we don't have
// any undefined references.
//
this.specification = this.normalize(specification);
}
/**
* Normalize the specification.
*
* @param {Array|Object} specification Different breakpoints we need to know.
* @returns {Array} List of media query specifications
* @private
*/
normalize(specification) {
if (Array.isArray(specification)) return specification;
return Object.keys(specification).reduce(function reduce(memo, key) {
var breakpoint = specification[key];
//
// If there is no name specified, use the key as name.
//
breakpoint.name = breakpoint.name || key;
memo.push(breakpoint);
return memo;
}, []);
}
/**
* Check if the setup has changed since we've last checked the real estate.
*
* @param {Object} viewport The view port specification.
* @returns {Boolean} True if the breakpoint for the viewport has changed.
* @public
*/
changed(viewport) {
var breakpoint = this.breakpoint;
this.breakpoint = this.currently(viewport);
return this.breakpoint !== breakpoint;
}
/**
* Check if a given specification matches our current set resolution.
*
* @param {Object} viewport The view port specification.
* @param {Object} specification The supplied specification.
* @returns {Boolean} True if viewport fits into the specification.
* @private
*/
matches(viewport, specification) {
viewport = viewport || this.viewport();
let matched = false;
if ('height' in specification) {
matched = viewport.height < specification.height;
if (!matched) return matched;
}
if ('width' in specification) {
matched = viewport.width < specification.width;
}
return matched;
}
/**
* Find out which breakpoint we're currently triggering.
*
* @param {Object} viewport The view port specification.
* @returns {String} The current breakpoint that we got triggered.
* @public
*/
currently(viewport) {
viewport = viewport || this.viewport();
for (var i = 0, l = this.specification.length; i < l; i++) {
var spec = this.specification[i];
if (this.matches(viewport, spec)) return spec.name;
}
return 'unknown';
}
/**
* Returns the difference between the current width and the given breakpoint. This
* can be used to check if the window is "greater" than a breakpoint. If either the
* given breakpoint or the given attribute do not exist, a `TypeError` will be thrown.
*
*
* @param {String} breakpoint to be compared
* @param {String} property height or width
* @throws {TypeError} If not given breakpoint and property do not exist within the given spec
* @returns {Number} different between current and specified properties
* @public
*/
compare(breakpoint, property) {
const desiredSpec = this.specification.filter(spec => spec.name === breakpoint)[0];
if (!desiredSpec) {
return new TypeError(`${breakpoint} is not part of the given specifications`);
}
if (!desiredSpec[property]) {
return new TypeError(`${breakpoint}.${property} is not part of the given specifications`);
}
return this[property]() - desiredSpec[property];
}
}