contain-element/contain-element-module.js

197 lines
6.3 KiB
JavaScript

module.exports = function(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;
};
};