Skip to content

Instantly share code, notes, and snippets.

@aurooba
Last active April 10, 2023 12:26
Show Gist options
  • Save aurooba/c9df8d2a1fc05b1d2790b63806207d64 to your computer and use it in GitHub Desktop.
Save aurooba/c9df8d2a1fc05b1d2790b63806207d64 to your computer and use it in GitHub Desktop.
/* plain JS slideToggle with display option, untested. for tested version, use the gist below */
HTMLElement.prototype.slideToggle = function (
duration,
display = "block",
callback,
) {
if (this.clientHeight === 0) {
_vanilla_slide_effect(this, duration, display, callback, true);
} else {
_vanilla_slide_effect(this, duration, display, callback);
}
};
HTMLElement.prototype.slideUp = function (
duration,
display = "block",
callback,
) {
_vanilla_slide_effect(this, duration, display, callback);
};
HTMLElement.prototype.slideDown = function (
duration,
display = "block",
callback,
) {
_vanilla_slide_effect(this, duration, display, callback, true);
};
function _vanilla_slide_effect(
element,
duration,
display = "block",
callback,
pullDown,
) {
if (typeof duration === "undefined") duration = 400;
if (typeof pullDown === "undefined") pullDown = false;
element.style.overflow = "hidden";
if (pullDown) element.style.display = display;
var elementStyles = window.getComputedStyle(element);
var elementHeight = parseFloat(elementStyles.getPropertyValue("height"));
var elementPaddingTop = parseFloat(
elementStyles.getPropertyValue("padding-top"),
);
var elementPaddingBottom = parseFloat(
elementStyles.getPropertyValue("padding-bottom"),
);
var elementMarginTop = parseFloat(
elementStyles.getPropertyValue("margin-top"),
);
var elementMarginBottom = parseFloat(
elementStyles.getPropertyValue("margin-bottom"),
);
var stepHeight = elementHeight / duration;
var stepPaddingTop = elementPaddingTop / duration;
var stepPaddingBottom = elementPaddingBottom / duration;
var stepMarginTop = elementMarginTop / duration;
var stepMarginBottom = elementMarginBottom / duration;
var start;
function step(timestamp) {
if (start === undefined) start = timestamp;
var elapsed = timestamp - start;
if (pullDown) {
element.style.height = stepHeight * elapsed + "px";
element.style.paddingTop = stepPaddingTop * elapsed + "px";
element.style.paddingBottom = stepPaddingBottom * elapsed + "px";
element.style.marginTop = stepMarginTop * elapsed + "px";
element.style.marginBottom = stepMarginBottom * elapsed + "px";
} else {
element.style.height = elementHeight - stepHeight * elapsed + "px";
element.style.paddingTop =
elementPaddingTop - stepPaddingTop * elapsed + "px";
element.style.paddingBottom =
elementPaddingBottom - stepPaddingBottom * elapsed + "px";
element.style.marginTop =
elementMarginTop - stepMarginTop * elapsed + "px";
element.style.marginBottom =
elementMarginBottom - stepMarginBottom * elapsed + "px";
}
if (elapsed >= duration) {
element.style.height = "";
element.style.paddingTop = "";
element.style.paddingBottom = "";
element.style.marginTop = "";
element.style.marginBottom = "";
element.style.overflow = "";
if (!pullDown) element.style.display = "none";
if (typeof callback === "function") callback();
} else {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}
/* plain JS slideToggle */
HTMLElement.prototype.slideToggle = function (duration, callback) {
if (this.clientHeight === 0) {
_s(this, duration, callback, true);
} else {
_s(this, duration, callback);
}
};
HTMLElement.prototype.slideUp = function (duration, callback) {
_s(this, duration, callback);
};
HTMLElement.prototype.slideDown = function (duration, callback) {
_s(this, duration, callback, true);
};
function _s(el, duration, callback, isDown) {
if (typeof duration === "undefined") duration = 400;
if (typeof isDown === "undefined") isDown = false;
el.style.overflow = "hidden";
if (isDown) el.style.display = "block";
var elStyles = window.getComputedStyle(el);
var elHeight = parseFloat(elStyles.getPropertyValue("height"));
var elPaddingTop = parseFloat(elStyles.getPropertyValue("padding-top"));
var elPaddingBottom = parseFloat(elStyles.getPropertyValue("padding-bottom"));
var elMarginTop = parseFloat(elStyles.getPropertyValue("margin-top"));
var elMarginBottom = parseFloat(elStyles.getPropertyValue("margin-bottom"));
var stepHeight = elHeight / duration;
var stepPaddingTop = elPaddingTop / duration;
var stepPaddingBottom = elPaddingBottom / duration;
var stepMarginTop = elMarginTop / duration;
var stepMarginBottom = elMarginBottom / duration;
var start;
function step(timestamp) {
if (start === undefined) start = timestamp;
var elapsed = timestamp - start;
if (isDown) {
el.style.height = stepHeight * elapsed + "px";
el.style.paddingTop = stepPaddingTop * elapsed + "px";
el.style.paddingBottom = stepPaddingBottom * elapsed + "px";
el.style.marginTop = stepMarginTop * elapsed + "px";
el.style.marginBottom = stepMarginBottom * elapsed + "px";
} else {
el.style.height = elHeight - stepHeight * elapsed + "px";
el.style.paddingTop = elPaddingTop - stepPaddingTop * elapsed + "px";
el.style.paddingBottom =
elPaddingBottom - stepPaddingBottom * elapsed + "px";
el.style.marginTop = elMarginTop - stepMarginTop * elapsed + "px";
el.style.marginBottom =
elMarginBottom - stepMarginBottom * elapsed + "px";
}
if (elapsed >= duration) {
el.style.height = "";
el.style.paddingTop = "";
el.style.paddingBottom = "";
el.style.marginTop = "";
el.style.marginBottom = "";
el.style.overflow = "";
if (!isDown) el.style.display = "none";
if (typeof callback === "function") callback();
} else {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment