UNPKG

vh-check

Version:
199 lines (187 loc) 7.48 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.vhCheck = factory()); }(this, (function () { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; // don't know a better way to get the size of a CSS 100vh… function createTestElement() { var testElement = document.createElement('div'); testElement.style.cssText = 'position: fixed; top: 0; height: 100vh; pointer-events: none;'; document.documentElement.insertBefore(testElement, document.documentElement.firstChild); return testElement; } function removeTestElement(element) { document.documentElement.removeChild(element); } // in some browsers this will be bigger than window.innerHeight function checkSizes() { var vhTest = createTestElement(); var windowHeight = window.innerHeight; var vh = vhTest.offsetHeight; var offset = vh - windowHeight; removeTestElement(vhTest); return { vh: vh, windowHeight: windowHeight, offset: offset, isNeeded: offset !== 0, value: 0, }; } // export function noop() { } function computeDifference() { var sizes = checkSizes(); sizes.value = sizes.offset; return sizes; } function redefineVhUnit() { var sizes = checkSizes(); sizes.value = sizes.windowHeight * 0.01; return sizes; } var methods = /*#__PURE__*/Object.freeze({ noop: noop, computeDifference: computeDifference, redefineVhUnit: redefineVhUnit }); function isString(text) { return typeof text === "string" && text.length > 0; } function isFunction(f) { return typeof f === "function"; } var defaultOptions = Object.freeze({ cssVarName: 'vh-offset', redefineVh: false, method: computeDifference, force: false, bind: true, updateOnTouch: false, onUpdate: noop, }); function getOptions(options) { // old options handling: only redefine the CSS var name if (isString(options)) { return __assign({}, defaultOptions, { cssVarName: options }); } // be sure to have a configuration object if (typeof options !== 'object') return defaultOptions; // make sure we have the right options to start with var finalOptions = { force: options.force === true, bind: options.bind !== false, updateOnTouch: options.updateOnTouch === true, onUpdate: isFunction(options.onUpdate) ? options.onUpdate : noop, }; // method change var redefineVh = options.redefineVh === true; finalOptions.method = methods[redefineVh ? 'redefineVhUnit' : 'computeDifference']; finalOptions.cssVarName = isString(options.cssVarName) ? options.cssVarName : redefineVh ? /* when redefining vh unit we follow this article name convention https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ */ 'vh' : defaultOptions.cssVarName; return finalOptions; } // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support var passiveSupported = false; var eventListeners = []; /* istanbul ignore next */ try { var options = Object.defineProperty({}, "passive", { get: function () { passiveSupported = true; }, }); window.addEventListener("test", options, options); window.removeEventListener("test", options, options); } catch (err) { passiveSupported = false; } function addListener(eventName, callback) { eventListeners.push({ eventName: eventName, callback: callback, }); window.addEventListener(eventName, callback, /* istanbul ignore next */ passiveSupported ? { passive: true } : false); } function removeAll() { eventListeners.forEach(function (config) { window.removeEventListener(config.eventName, config.callback); }); eventListeners = []; } function updateCssVar(cssVarName, result) { document.documentElement.style.setProperty("--" + cssVarName, result.value + "px"); } function formatResult(sizes, options) { return __assign({}, sizes, { unbind: removeAll, recompute: options.method }); } function vhCheck(options) { var config = Object.freeze(getOptions(options)); var result = formatResult(config.method(), config); // usefulness check if (!result.isNeeded && !config.force) { return result; } updateCssVar(config.cssVarName, result); config.onUpdate(result); // enabled by default if (!config.bind) return result; function onWindowChange() { window.requestAnimationFrame(function () { var sizes = config.method(); updateCssVar(config.cssVarName, sizes); config.onUpdate(formatResult(sizes, config)); }); } // be sure we don't duplicates events listeners result.unbind(); // listen for orientation change // - this can't be configured // - because it's convenient and not a real performance bottleneck addListener('orientationchange', onWindowChange); // listen to touch move for scrolling // – disabled by default // - listening to scrolling can be expansive… if (config.updateOnTouch) { addListener('touchmove', onWindowChange); } return result; } return vhCheck; })));