This repository has been archived by the owner on Jul 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresponsive-utility.html
177 lines (160 loc) · 6.14 KB
/
responsive-utility.html
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">
<!--
`responsive-utility`
Until there are container queries, this utility will provide some level of responsivity to containers.
@demo demo/index.html
@microcopy - the mental model for this element
<responsive-grid-utility
sm="600" //custom breakpoint for small screens
md="900" //custom breakpoint for medium screens
sm="1200" //custom breakpoint for large screens
md="1800" //custom breakpoint for extra-large screens
responsive-to-parent$=[[responsiveToParent]]> //allows content to be relative to parent container
</responsive-grid-utility>
Add an event listener to get
-->
<dom-module id="responsive-utility">
<template>
<style>
:host {
display: inline;
}
</style>
<slot></slot>
</template>
<script>
(function() {
'use strict';
Polymer.ResponsiveUtility = Polymer({
is: 'responsive-utility',
behaviors: [
Polymer.IronResizableBehavior
],
listeners: {
'iron-resize': '_onIronResize'
},
properties: {
/**
* Stores
*/
targets: {
type: Array,
value: [],
},
},
/**
* An array of objects. Each object is contains data about an element
* that will be updated with responsive values.
*
* To add an element to this array, fire a 'responsive-element' event
* with the following data:
*
* {
* "element": (the element itself),
* "attribute": (the attribute that will be set with the size),
* "relativeToParent": (true for @element query instead of @media query),
* "sm": (optional custom sm breakpoint, default is 600),
* "md": (optional custom md breakpoint, default is 900),
* "lg": (optional custom lg breakpoint, default is 1200),
* "xl": (optional custom xl breakpoint, default is 1500),
* }
*
*/
attached: function() {
this.async(this.notifyResize, 1);
this._onIronResize();
},
/**
* Makes sure there is a utility ready and listening for elements.
*/
created: function() {
let root = this;
if (!Polymer.ResponsiveUtility.instance) {
Polymer.ResponsiveUtility.instance = root;
}
/* handle element registration */
document.body.addEventListener('responsive-element', function(e){
let relative = e.detail.relativeToParent !== undefined && e.detail.relativeToParent !== null ? e.detail.relativeToParent : true;
if ('ResizeObserver' in window && relative.relativeToParent === true) {
let parent = e.detail.element.parentNode, resize = new ResizeObserver(function(){
Polymer.ResponsiveUtility.setSize(e.detail);
});
if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
parent = parent.host;
}
resize.observe(parent);
}
root.push('targets',e.detail);
Polymer.ResponsiveUtility.setSize(e.detail);
});
/* handle element deregistration */
document.body.addEventListener('delete-responsive-element', function(e){
for(let i=0; i < this.targets.length; i++){
if(e.detail === target[i]) root.splice('targets',i,1);
}
});
},
/**
* On resize, sets sizes of any target element that has changed.
*/
_onIronResize: function(){
for(let i=0; i < this.targets.length; i++){
Polymer.ResponsiveUtility.setSize(this.targets[i]);
}
},
});
Polymer.ResponsiveUtility.instance = null;
/**
* Checks to see if there is an instance available, and if not appends one
*/
Polymer.ResponsiveUtility.requestAvailability = function() {
if (!Polymer.ResponsiveUtility.instance) {
Polymer.ResponsiveUtility.instance = document.createElement('responsive-utility');
}
document.body.appendChild(Polymer.ResponsiveUtility.instance);
};
/**
* Sets responsive size of target.
*/
Polymer.ResponsiveUtility.setSize = function(target) {
let element = target.element;
let attribute = target.attribute !== undefined && target.attribute !== null ? target.attribute : 'responsive-size';
let size = Polymer.ResponsiveUtility.getSize(target);
if (element.getAttribute(attribute) === undefined || size !== element.getAttribute(attribute)) {
element.setAttribute(attribute,size);
}
};
/**
* Returns responsive size of target.
*/
Polymer.ResponsiveUtility.getSize = function(target) {
let relative = target.relativeToParent !== undefined && target.relativeToParent !== null ? target.relativeToParent : true;
let getWidth = function() {
if(target.element.parentNode !== null && relative === true){
if (target.element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
return target.element.parentNode.host.offsetWidth;
}
return target.element.parentNode.offsetWidth;
}
return window.outerWidth;
}, testBreakpoint = function(width,breakpoint,def){
let val = breakpoint !== undefined && breakpoint !== null ? breakpoint : def;
return width < val;
}, size, width = getWidth();
if(testBreakpoint(width,target.sm,600)) {
size = 'xs';
} else if(testBreakpoint(width,target.md,900)) {
size = 'sm';
} else if(testBreakpoint(width,target.lg,1200)) {
size = 'md';
} else if(testBreakpoint(width,target.xl,1200)) {
size = 'lg';
} else {
size = 'xl';
}
return size;
};
})();
</script>
</dom-module>