-
Notifications
You must be signed in to change notification settings - Fork 1
/
contain-element.js
197 lines (165 loc) · 6.26 KB
/
contain-element.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
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
function ContainElement(options) {
var scaleFactor = 1,
element = options.element || document.getElementById(options.id),
elementWidth = Number(options.width) || element.offsetWidth,
elementHeight = Number(options.height) || element.offsetHeight,
valign = options.valign || "center",
halign = options.halign || "center",
fit = options.fit || "cover",
scale = options.scale;
// Apply required attributes to the element
element.style.position = "absolute";
element.parentElement.style.overflow = "hidden";
// Apply required transform-origin if the scale option is set to true
if (scale) {
element.style.transformOrigin = "left top";
}
// Apply relative position to the parent if it doesn't already have relative, absolute or fixed positioning
if ([ "relative", "absolute", "fixed" ].indexOf(window.getComputedStyle(element.parentElement, null).getPropertyValue("position")) === -1) {
element.parentElement.style.position = "relative";
}
function parseVerticalAlignment() {
// Convert valign to decimal percent
switch (valign) {
case "top":
valign = 0;
break;
case "center":
valign = 0.5;
break;
case "bottom":
valign = 1;
break;
default:
valign = Number(valign) / 100;
}
}
function parseHorizontalAlignment() {
// Convert halign to decimal percent
switch (halign) {
case "left":
halign = 0;
break;
case "center":
halign = 0.5;
break;
case "right":
halign = 1;
break;
default:
halign = Number(halign) / 100;
}
}
function updateContain() {
var parentWidth = element.parentElement.offsetWidth,
parentHeight = element.parentElement.offsetHeight,
rightAlignment = 0 - (elementWidth * scaleFactor - parentWidth),
bottomAlignment = 0 - (elementHeight * scaleFactor - parentHeight);
// Run the scale/position functionality if able to determine the parent element's width and height
if (parentWidth && parentHeight) {
// Calculate the scale factor
if (fit === "cover") {
if (parentWidth > parentHeight / elementHeight * elementWidth) {
scaleFactor = parentWidth / elementWidth;
} else {
scaleFactor = parentHeight / elementHeight;
}
} else if (fit === "contain") {
if (parentHeight > parentWidth / elementWidth * elementHeight) {
scaleFactor = parentWidth / elementWidth;
} else {
scaleFactor = parentHeight / elementHeight;
}
} else {
scaleFactor = 1;
}
// Scale the element using the scale factor
if (scale) {
element.style.transform = "scale(" + scaleFactor + ")";
} else {
element.style.width = elementWidth * scaleFactor + "px";
element.style.height = elementHeight * scaleFactor + "px";
}
// Align the element horizontally
if (parentWidth !== elementWidth * scaleFactor) {
// Align horizontally by percent
element.style.left = rightAlignment * halign + "px";
} else {
// Align the element against the left if the width of the parent and element are the same
element.style.left = "0px";
}
// Align the element vertically
if (parentHeight !== elementHeight * scaleFactor) {
// Align vertically by percent
element.style.top = bottomAlignment * valign + "px";
} else {
// Align the element against the top if the height of the parent and element are the same
element.style.top = "0px";
}
} else {
// Try again in 30ms if the document didn't load enough to determine the parent element's width and height yet
setTimeout(updateContain, 30);
}
}
// Parse the valign and halign options
parseVerticalAlignment();
parseHorizontalAlignment();
// Run the function to scale and anchor the element
updateContain();
// External scale and anchor update function
this.update = updateContain;
// External function to set elementWidth
this.setWidth = function(newWidth) {
elementWidth = Number(newWidth);
};
// External function to set elementHeight
this.setHeight = function(newHeight) {
elementHeight = Number(newHeight);
};
// External function to set valign
this.setValign = function(newValign) {
valign = newValign;
parseVerticalAlignment();
};
// External function to set halign
this.setHalign = function(newHalign) {
halign = newHalign;
parseHorizontalAlignment();
};
// External function to set fit
this.setFit = function(newFit) {
fit = newFit;
};
// External function to return the elementWidth
this.getWidth = function() {
return Number(elementWidth);
};
// External function to return the elementHeight
this.getHeight = function() {
return Number(elementHeight);
};
// External function to return the current width
this.getCurrentWidth = function() {
return scaleFactor * elementWidth;
};
// External function to return the current height
this.getCurrentHeight = function() {
return scaleFactor * elementHeight;
};
// External function to return the current valign
this.getValign = function() {
return valign;
};
// External function to return the current halign
this.getHalign = function() {
return halign;
};
// External function to return the current fit
this.getFit = function() {
return fit;
};
// External function to return the current scale factor
this.getScale = function() {
return scaleFactor;
};
}