Repository: sparanoid/lightense-images Branch: master Commit: d51a1db9baab Files: 18 Total size: 51.6 KB Directory structure: gitextract_vkyqeos0/ ├── .babelrc ├── .eslintrc.json ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── test.yml ├── .gitignore ├── .huskyrc ├── .jshintrc ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── demo.html ├── dist/ │ └── lightense.js ├── package.json ├── renovate.json ├── src/ │ └── index.js └── webpack.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": [ [ "@babel/preset-env", { "useBuiltIns": "entry", "corejs": "3" } ] ] } ================================================ FILE: .eslintrc.json ================================================ { "env": { "browser": true, "commonjs": true, "es2021": true }, "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": 12 }, "rules": { "accessor-pairs": "error", "array-bracket-newline": "error", "array-bracket-spacing": [ "error", "never" ], "array-callback-return": "error", "array-element-newline": "off", "arrow-body-style": "error", "arrow-parens": "error", "arrow-spacing": [ "error", { "after": true, "before": true } ], "block-scoped-var": "error", "block-spacing": "error", "brace-style": [ "error", "1tbs" ], "callback-return": "error", "camelcase": "off", "capitalized-comments": "off", "class-methods-use-this": "error", "comma-dangle": "error", "comma-spacing": [ "error", { "after": true, "before": false } ], "comma-style": [ "error", "last" ], "complexity": "error", "computed-property-spacing": [ "error", "never" ], "consistent-return": "off", "consistent-this": "error", "curly": "error", "default-case": "off", "dot-location": "error", "dot-notation": "error", "eol-last": "error", "eqeqeq": "error", "func-call-spacing": "error", "func-name-matching": "error", "func-names": "off", "func-style": [ "error", "declaration", { "allowArrowFunctions": true } ], "function-paren-newline": "error", "generator-star-spacing": "error", "global-require": "error", "guard-for-in": "error", "handle-callback-err": "error", "id-blacklist": "error", "id-length": "off", "id-match": "error", "implicit-arrow-linebreak": [ "error", "beside" ], "indent": "off", "indent-legacy": "off", "init-declarations": "off", "jsx-quotes": "error", "key-spacing": "error", "keyword-spacing": "off", "line-comment-position": "error", "linebreak-style": [ "error", "unix" ], "lines-around-comment": "error", "lines-around-directive": "error", "lines-between-class-members": "error", "max-classes-per-file": "error", "max-depth": "error", "max-len": "off", "max-lines": "off", "max-lines-per-function": "off", "max-nested-callbacks": "error", "max-params": "error", "max-statements": "off", "max-statements-per-line": "error", "multiline-comment-style": [ "error", "separate-lines" ], "new-parens": "error", "newline-after-var": "off", "newline-before-return": "off", "newline-per-chained-call": "error", "no-alert": "error", "no-array-constructor": "error", "no-async-promise-executor": "error", "no-await-in-loop": "error", "no-bitwise": "off", "no-buffer-constructor": "error", "no-caller": "error", "no-catch-shadow": "error", "no-confusing-arrow": "error", "no-continue": "error", "no-div-regex": "error", "no-duplicate-imports": "error", "no-else-return": "error", "no-empty-function": "error", "no-eq-null": "error", "no-eval": "error", "no-extend-native": "error", "no-extra-bind": "error", "no-extra-label": "error", "no-extra-parens": "off", "no-floating-decimal": "error", "no-implicit-coercion": "error", "no-implicit-globals": "error", "no-implied-eval": "error", "no-inline-comments": "error", "no-inner-declarations": [ "error", "functions" ], "no-invalid-this": "off", "no-iterator": "error", "no-label-var": "error", "no-labels": "error", "no-lone-blocks": "error", "no-lonely-if": "error", "no-loop-func": "error", "no-magic-numbers": "off", "no-misleading-character-class": "error", "no-mixed-operators": "off", "no-mixed-requires": "error", "no-multi-assign": "error", "no-multi-spaces": "off", "no-multi-str": "error", "no-multiple-empty-lines": "error", "no-native-reassign": "error", "no-negated-condition": "error", "no-negated-in-lhs": "error", "no-nested-ternary": "error", "no-new": "error", "no-new-func": "error", "no-new-object": "error", "no-new-require": "error", "no-new-wrappers": "error", "no-octal-escape": "error", "no-param-reassign": "error", "no-path-concat": "error", "no-plusplus": [ "error", { "allowForLoopAfterthoughts": true } ], "no-process-env": "error", "no-process-exit": "error", "no-proto": "error", "no-prototype-builtins": "error", "no-restricted-globals": "error", "no-restricted-imports": "error", "no-restricted-modules": "error", "no-restricted-properties": "error", "no-restricted-syntax": "error", "no-return-assign": "error", "no-return-await": "error", "no-script-url": "error", "no-self-compare": "error", "no-sequences": "error", "no-shadow": "off", "no-shadow-restricted-names": "error", "no-spaced-func": "error", "no-sync": "error", "no-tabs": "error", "no-template-curly-in-string": "error", "no-ternary": "off", "no-throw-literal": "off", "no-trailing-spaces": "error", "no-undef-init": "error", "no-undefined": "error", "no-underscore-dangle": "error", "no-unmodified-loop-condition": "error", "no-unneeded-ternary": "error", "no-unused-expressions": "error", "no-use-before-define": "off", "no-useless-call": "error", "no-useless-computed-key": "error", "no-useless-concat": "error", "no-useless-constructor": "error", "no-useless-rename": "error", "no-useless-return": "error", "no-var": "off", "no-void": "error", "no-warning-comments": "off", "no-whitespace-before-property": "error", "no-with": "error", "nonblock-statement-body-position": "error", "object-curly-newline": "error", "object-curly-spacing": [ "error", "never" ], "object-shorthand": "error", "one-var": "off", "one-var-declaration-per-line": "error", "operator-assignment": "error", "operator-linebreak": "error", "padded-blocks": "off", "padding-line-between-statements": "error", "prefer-arrow-callback": "off", "prefer-const": "error", "prefer-destructuring": "off", "prefer-numeric-literals": "error", "prefer-object-spread": "error", "prefer-promise-reject-errors": "error", "prefer-reflect": "error", "prefer-rest-params": "error", "prefer-spread": "error", "prefer-template": "off", "quote-props": "off", "quotes": [ "error", "single" ], "radix": "error", "require-atomic-updates": "error", "require-await": "error", "require-jsdoc": "off", "require-unicode-regexp": "off", "rest-spread-spacing": [ "error", "never" ], "semi": "error", "semi-spacing": [ "error", { "after": true, "before": false } ], "semi-style": [ "error", "last" ], "sort-imports": "error", "sort-keys": "off", "sort-vars": "error", "space-before-blocks": "off", "space-before-function-paren": "off", "space-in-parens": [ "error", "never" ], "space-infix-ops": "error", "space-unary-ops": "error", "spaced-comment": [ "error", "always" ], "strict": [ "error", "function" ], "switch-colon-spacing": "error", "symbol-description": "error", "template-curly-spacing": [ "error", "never" ], "template-tag-spacing": "error", "unicode-bom": [ "error", "never" ], "valid-jsdoc": "error", "vars-on-top": "off", "wrap-iife": "error", "wrap-regex": "off", "yield-star-spacing": "error", "yoda": [ "error", "never" ] } } ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: [sparanoid] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel custom: https://sparanoid.com/donate/ ================================================ FILE: .github/workflows/test.yml ================================================ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages name: Test on: push: branches: - '**' tags: - '**' pull_request: branches: - '**' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - run: yarn --frozen-lockfile - run: yarn test ================================================ FILE: .gitignore ================================================ # Numerous always-ignore extensions *.diff *.err *.orig *.log *.rej *.swo *.swp *.zip *.vi *~ # OS or Editor folders .DS_Store ._* Thumbs.db .cache .project .settings .tmproj *.esproj nbproject *.sublime-project *.sublime-workspace .idea # Folders to ignore node_modules ================================================ FILE: .huskyrc ================================================ { "hooks": { "pre-commit": "yarn test && git add .", "pre-push": "yarn build" } } ================================================ FILE: .jshintrc ================================================ { "esnext": true } ================================================ FILE: .npmrc ================================================ message="chore(release): %s :tada:" ================================================ FILE: .travis.yml ================================================ sudo: false language: node_js node_js: - "10" notifications: email: false slack: secure: P/ngpvqinM/t9tdXZO2qHQvq2XCkcerKM+KwNJlQoVHnkl/Z/EtzB1yxiZZ6LGdHp+r3nShBhfW+gJVojU80EObt0iWHbFTkUUMFf6WI6c056937CksQI4atmDBiCJxMAnkd6DCLWfBexVtKDhkc5vX0bYhgoiXEzCYUhFd8pZ4= ================================================ FILE: CHANGELOG.md ================================================ Deprecated. See GitHub releases for latest updates. ## [1.0.10](https://github.com/sparanoid/lightense-images/compare/v1.0.9...v1.0.10) (2020-07-16) ### Features * **js:** native dark theme support via root-variables ([bfdd5c6](https://github.com/sparanoid/lightense-images/commit/bfdd5c605a8468e71cfc94818041e6938cdafdbd)) ## [1.0.9](https://github.com/sparanoid/lightense-images/compare/v1.0.8...v1.0.9) (2019-09-01) ### Bug Fixes * **css:** blur effect not supported corrently for chrome ([640acc9](https://github.com/sparanoid/lightense-images/commit/640acc968371092e990cae2662f7533df1615156)) * **js:** z-index too high, ref https://github.com/sparanoid/lightense-images/issues/41 ([a60342a](https://github.com/sparanoid/lightense-images/commit/a60342a4ea49b9c20fc0375ca939f9450630d617)) ### Features * update demo page ([5af3700](https://github.com/sparanoid/lightense-images/commit/5af3700caa047974a478d0eacae8563604ea7e88)) ## [1.0.8](https://github.com/sparanoid/lightense-images/compare/v1.0.7...v1.0.8) (2019-02-20) ### Features * **js:** use native css variables ([ea3fcc5](https://github.com/sparanoid/lightense-images/commit/ea3fcc51a1d2516c9910cc5be37dbdfb467927b8)) ## [1.0.7](https://github.com/sparanoid/lightense-images/compare/v1.0.6...v1.0.7) (2019-02-19) ## [1.0.6](https://github.com/sparanoid/lightense-images/compare/v1.0.5...v1.0.6) (2018-12-09) ### Bug Fixes * **js:** blurry images with transform, should fixes https://github.com/sparanoid/lightense-images/issues/31 ([1e318d9](https://github.com/sparanoid/lightense-images/commit/1e318d93f42270f89fcd429720292366f774a7a4)) ### Features * basic linting ([d7e0595](https://github.com/sparanoid/lightense-images/commit/d7e05954cfe17ca85834b52748e71c2b28bdce09)) * **js:** check if elements already inited, fixes https://github.com/sparanoid/lightense-images/issues/34 ([f2f0d84](https://github.com/sparanoid/lightense-images/commit/f2f0d841ccf59d4d47777e36d74099af17f30a2b)) ## [1.0.5](https://github.com/sparanoid/lightense-images/compare/v1.0.4...v1.0.5) (2018-03-28) ### Bug Fixes * missing fallback for deprecated attribute ([0285b80](https://github.com/sparanoid/lightense-images/commit/0285b80c00174ae7dc751df7b918e8f72da870c7)) ### Features * better config inheritance, should fix https://github.com/sparanoid/lightense-images/issues/32 ([0d57306](https://github.com/sparanoid/lightense-images/commit/0d57306e0cc62a79a54147039a0301791f3c973a)) * generate Safari specific background color, automatically ([ae48d3b](https://github.com/sparanoid/lightense-images/commit/ae48d3bb888e7ff3227f3aad302e8f6d9c3ae610)) ## [1.0.4](https://github.com/sparanoid/lightense-images/compare/v1.0.3...v1.0.4) (2017-03-13) ### Features * smaller output ([143773d](https://github.com/sparanoid/lightense-images/commit/143773d69a377669530bd2d3e0e2ffa26c269ff0)) ## [1.0.3](https://github.com/sparanoid/lightense-images/compare/v1.0.2...v1.0.3) (2017-01-17) ### Features * allow passing string as target ([6608acc](https://github.com/sparanoid/lightense-images/commit/6608acc82397ff19201ed1763ec24ab90b9847dd)) * **demo:** add lazy load example ([1a16d81](https://github.com/sparanoid/lightense-images/commit/1a16d81b2da0bf0f653810ccd6a43fc0f7b891fc)) * **js:** allow select images, user should have the rights to select them ([7d24343](https://github.com/sparanoid/lightense-images/commit/7d243436fce23171a1393875b473dad322e4294a)) ## [1.0.2](https://github.com/sparanoid/lightense-images/compare/v1.0.1...v1.0.2) (2016-12-21) ### Bug Fixes * **js:** selectable `.lightense-wrap` causes zoom out not working in some area ([860d632](https://github.com/sparanoid/lightense-images/commit/860d632b73497ed37d33adf7894dea600557d17f)) ### Features * **js:** ability to override image padding ([bac3c4f](https://github.com/sparanoid/lightense-images/commit/bac3c4f664fb3daad30d3671e8f4e7c765a79654)) * **js:** avoid select images ([adf3a7e](https://github.com/sparanoid/lightense-images/commit/adf3a7ecdb8c572eed1a8f39b6e185653e4c152d)) ## [1.0.1](https://github.com/sparanoid/lightense-images/compare/v1.0.0...v1.0.1) (2016-10-28) ### Bug Fixes * missing timeout for Firefox to work ([b7ffebc](https://github.com/sparanoid/lightense-images/commit/b7ffebca240b2bc52291a5098357d3e3cef69ead)) * **docs:** wrong demo link ([91d663b](https://github.com/sparanoid/lightense-images/commit/91d663bacd0d6a28e21342d11d436c3a5823b148)) * **docs:** wrong dep check link [ci skip] ([c256f30](https://github.com/sparanoid/lightense-images/commit/c256f30c02c17ee6dda37fa8588d0f2c2587411c)) * **travis:** remove `0.12` support ([dcd3124](https://github.com/sparanoid/lightense-images/commit/dcd3124124ea2235c936213e5dff5da1ce859922)) ### Features * ability to toggle keyboard feature ([c1b9800](https://github.com/sparanoid/lightense-images/commit/c1b98002d5c0f401a67cba58f680e4909c9d1082)) * add `config.offset` support ([515fba7](https://github.com/sparanoid/lightense-images/commit/515fba73fdd0eb4d7b6682705bf0d99d075e412d)) * add demo page ([3924ac5](https://github.com/sparanoid/lightense-images/commit/3924ac51cb2d07a104d93a937b28bf8a70a0f1e9)) * add modifier keys support ([8a82ade](https://github.com/sparanoid/lightense-images/commit/8a82ade305f6af7e1daddbd8573b3f7cd418066a)) * add more options ([e0f994e](https://github.com/sparanoid/lightense-images/commit/e0f994e15c02b48171b643661efe3e1a1d70eb69)) * brand new effect as seen on Medium.com ([2323092](https://github.com/sparanoid/lightense-images/commit/23230929e50cba666c2e034064448890677a76e4)) * enable Travis CI ([644495f](https://github.com/sparanoid/lightense-images/commit/644495fe6f1413cff597f1b5480b647b4c113de3)) * handle user options ([9f5956d](https://github.com/sparanoid/lightense-images/commit/9f5956d88f0798b83e50465e402fabc41b5fe3c9)) * **docs:** add badges ([3e41f1b](https://github.com/sparanoid/lightense-images/commit/3e41f1b31059b891ffc8cdcb5e8b3dfc6c314d08)) * **docs:** add license ([6e960f6](https://github.com/sparanoid/lightense-images/commit/6e960f63b67f439d8d86c201f89158715cf6f379)) # [1.0.0](https://github.com/sparanoid/lightense-images/compare/1ade8c2f4c0afc745d37ec388234fab6397223b0...v1.0.0) (2016-03-11) ### Features * init release ([1ade8c2](https://github.com/sparanoid/lightense-images/commit/1ade8c2f4c0afc745d37ec388234fab6397223b0)) ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2021 Tunghsiao Liu Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Lightense Images [![Build Status](https://travis-ci.org/sparanoid/lightense-images.svg?branch=master)](https://travis-ci.org/sparanoid/lightense-images) [![devDependency Status](https://david-dm.org/sparanoid/lightense-images/dev-status.svg?theme=shields.io)](https://david-dm.org/sparanoid/lightense-images?type=dev) A dependency-free pure JavaScript image zooming library less than 2 KB (gzipped). Inspired by [tholman/intense-images](https://github.com/tholman/intense-images). You can play with the code [live on CodePen](http://codepen.io/sparanoid/pen/yOJyjV). This library is mainly used by [Almace Scaffolding](https://github.com/sparanoid/almace-scaffolding). ----- ## [Getting Started](http://sparanoid.com/work/lightense-images/) ## Donate Wanna buy me a cup of coffee? [Great](http://sparanoid.com/donate/). ## Author **Tunghsiao Liu** - Twitter: @[tunghsiao](http://twitter.com/tunghsiao) - GitHub: @[sparanoid](http://github.com/sparanoid) ## License MIT ================================================ FILE: demo.html ================================================

Lightense Images by Tunghsiao Liu

General Usage

Custom Background

Disable Lightense Images with Specific Class

Custom Padding

Custom Background

Custom Thumbnail Preview

Flexbox Gallery

Event Hooks

================================================ FILE: dist/lightense.js ================================================ /*! lightense-images v1.0.17 | © Tunghsiao Liu | MIT */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["Lightense"] = factory(); else root["Lightense"] = factory(); })(this, function() { return /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ 352: /***/ ((module) => { function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } var Lightense = function Lightense() { 'use strict'; // default options var defaults = { time: 300, padding: 40, offset: 40, keyboard: true, cubicBezier: 'cubic-bezier(.2, 0, .1, 1)', background: 'var(--bg-color-80, rgba(255, 255, 255, .98))', backgroundFilter: 'blur(30px)', zIndex: 1000000, /* eslint-disable no-undefined */ beforeShow: undefined, afterShow: undefined, beforeHide: undefined, afterHide: undefined /* eslint-enable no-undefined */ }; // Init user options var config = {}; function invokeCustomHook(methodName) { var method = config[methodName]; if (!method) { return; } if (typeof method !== 'function') { throw "config.".concat(methodName, " must be a function!"); } Reflect.apply(method, config, [config]); } // Init target elements var elements; function getElements(elements) { switch (_typeof(elements)) { case 'undefined': throw 'You need to pass an element!'; case 'string': return document.querySelectorAll(elements); case 'object': return elements; } } function startTracking(passedElements) { // If passed an array of elements, assign tracking to all var len = passedElements.length; if (len) { // Loop and assign for (var i = 0; i < len; i++) { track(passedElements[i]); } } else { track(passedElements); } } function track(element) { if (element.src && !element.classList.contains('lightense-target')) { element.classList.add('lightense-target'); element.addEventListener('click', function (event) { if (config.keyboard) { // If Command (macOS) or Ctrl (Windows) key pressed, stop processing // and open the image in a new tab if (event.metaKey || event.ctrlKey) { return window.open(element.src, '_blank'); } } // Init instance init(this); }, false); } } function insertCss(styleId, styleContent) { var head = document.head || document.getElementsByTagName('head')[0]; // Remove existing instance if (document.getElementById(styleId)) { document.getElementById(styleId).remove(); } // Create new instance var styleEl = document.createElement('style'); styleEl.id = styleId; // Check if content exists if (styleEl.styleSheet) { styleEl.styleSheet.cssText = styleContent; } else { styleEl.appendChild(document.createTextNode(styleContent)); } head.appendChild(styleEl); } function createDefaultCss() { var css = "\n:root {\n --lightense-z-index: ".concat(config.zIndex - 1, ";\n --lightense-backdrop: ").concat(config.background, ";\n --lightense-backdrop-filter: ").concat(config.backgroundFilter, ";\n --lightense-duration: ").concat(config.time, "ms;\n --lightense-timing-func: ").concat(config.cubicBezier, ";\n}\n\n.lightense-backdrop {\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n position: fixed;\n top: 0;\n left: 0;\n overflow: hidden;\n z-index: calc(var(--lightense-z-index) - 1);\n padding: 0;\n margin: 0;\n transition: opacity var(--lightense-duration) ease;\n cursor: zoom-out;\n opacity: 0;\n background-color: var(--lightense-backdrop);\n visibility: hidden;\n}\n\n@supports (-webkit-backdrop-filter: blur(30px)) {\n .lightense-backdrop {\n background-color: var(--lightense-backdrop);\n -webkit-backdrop-filter: var(--lightense-backdrop-filter);\n }\n}\n\n@supports (backdrop-filter: blur(30px)) {\n .lightense-backdrop {\n background-color: var(--lightense-backdrop);\n backdrop-filter: var(--lightense-backdrop-filter);\n }\n}\n\n.lightense-wrap {\n position: relative;\n transition: transform var(--lightense-duration) var(--lightense-timing-func);\n z-index: var(--lightense-z-index);\n pointer-events: none;\n}\n\n.lightense-target {\n cursor: zoom-in;\n transition: transform var(--lightense-duration) var(--lightense-timing-func);\n pointer-events: auto;\n}\n\n.lightense-open {\n cursor: zoom-out;\n}\n\n.lightense-transitioning {\n pointer-events: none;\n}"); insertCss('lightense-images-css', css); } function createBackdrop() { if (document.querySelector('.lightense-backdrop') === null) { config.container = document.createElement('div'); config.container.className = 'lightense-backdrop'; document.body.appendChild(config.container); } else { config.container = document.querySelector('.lightense-backdrop'); } } function createTransform(img) { // Get original image size var naturalWidth = img.width; var naturalHeight = img.height; // Calc zoom ratio var scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0; var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0; var targetImage = config.target.getBoundingClientRect(); var maxScaleFactor = naturalWidth / targetImage.width; var viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0; var viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0; var viewportPadding = config.target.getAttribute('data-lightense-padding') || config.target.getAttribute('data-padding') || config.padding; var viewportWidthOffset = viewportWidth > viewportPadding ? viewportWidth - viewportPadding : viewportWidth - defaults.padding; var viewportHeightOffset = viewportHeight > viewportPadding ? viewportHeight - viewportPadding : viewportHeight - defaults.padding; var imageRatio = naturalWidth / naturalHeight; var viewportRatio = viewportWidthOffset / viewportHeightOffset; if (naturalWidth < viewportWidthOffset && naturalHeight < viewportHeightOffset) { config.scaleFactor = maxScaleFactor; } else if (imageRatio < viewportRatio) { config.scaleFactor = viewportHeightOffset / naturalHeight * maxScaleFactor; } else { config.scaleFactor = viewportWidthOffset / naturalWidth * maxScaleFactor; } // Calc animation var viewportX = viewportWidth / 2; var viewportY = scrollTop + viewportHeight / 2; var imageCenterX = targetImage.left + scrollLeft + targetImage.width / 2; var imageCenterY = targetImage.top + scrollTop + targetImage.height / 2; config.translateX = Math.round(viewportX - imageCenterX); config.translateY = Math.round(viewportY - imageCenterY); } function createViewer() { config.target.classList.add('lightense-open'); // Create wrapper element config.wrap = document.createElement('div'); config.wrap.className = 'lightense-wrap'; // Apply zoom ratio to target image setTimeout(function () { config.target.style.transform = 'scale(' + config.scaleFactor + ')'; }, 20); // Apply animation to outer wrapper config.target.parentNode.insertBefore(config.wrap, config.target); config.wrap.appendChild(config.target); setTimeout(function () { config.wrap.style.transform = 'translate3d(' + config.translateX + 'px, ' + config.translateY + 'px, 0)'; }, 20); // Show backdrop var item_options = { cubicBezier: config.target.getAttribute('data-lightense-cubic-bezier') || config.cubicBezier, background: config.target.getAttribute('data-lightense-background') || config.target.getAttribute('data-background') || config.background, zIndex: config.target.getAttribute('data-lightense-z-index') || config.zIndex }; // Create new config for item-specified styles var config_computed = _objectSpread(_objectSpread({}, config), item_options); var css = "\n :root {\n --lightense-z-index: ".concat(config_computed.zIndex - 1, ";\n --lightense-backdrop: ").concat(config_computed.background, ";\n --lightense-duration: ").concat(config_computed.time, "ms;\n --lightense-timing-func: ").concat(config_computed.cubicBezier, ";\n }"); insertCss('lightense-images-css-computed', css); config.container.style.visibility = 'visible'; setTimeout(function () { config.container.style.opacity = '1'; }, 20); } function removeViewer() { invokeCustomHook('beforeHide'); unbindEvents(); config.target.classList.remove('lightense-open'); // Remove transform styles config.wrap.style.transform = ''; config.target.style.transform = ''; config.target.classList.add('lightense-transitioning'); // Fadeout backdrop config.container.style.opacity = ''; // Hide backdrop and remove target element wrapper setTimeout(function () { invokeCustomHook('afterHide'); config.container.style.visibility = ''; config.container.style.backgroundColor = ''; config.wrap.parentNode.replaceChild(config.target, config.wrap); config.target.classList.remove('lightense-transitioning'); }, config.time); } function checkViewer() { var scrollOffset = Math.abs(config.scrollY - window.scrollY); if (scrollOffset >= config.offset) { removeViewer(); } } function once(target, event, handler) { target.addEventListener(event, function fn(args) { Reflect.apply(handler, this, args); target.removeEventListener(event, fn); }); } function init(element) { config.target = element; // TODO: need refine // If element already openned, close it if (config.target.classList.contains('lightense-open')) { return removeViewer(); } invokeCustomHook('beforeShow'); // Save current window scroll position for later use config.scrollY = window.scrollY; once(config.target, 'transitionend', function () { invokeCustomHook('afterShow'); }); var img = new Image(); img.onload = function () { createTransform(this); createViewer(); bindEvents(); }; img.src = config.target.src; } function bindEvents() { window.addEventListener('keyup', onKeyUp, false); window.addEventListener('scroll', checkViewer, false); config.container.addEventListener('click', removeViewer, false); } function unbindEvents() { window.removeEventListener('keyup', onKeyUp, false); window.removeEventListener('scroll', checkViewer, false); config.container.removeEventListener('click', removeViewer, false); } // Exit on excape (esc) key pressed function onKeyUp(event) { event.preventDefault(); if (event.keyCode === 27) { removeViewer(); } } function main(target) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // Parse elements elements = getElements(target); // Parse user options config = _objectSpread(_objectSpread({}, defaults), options); // Prepare stylesheets createDefaultCss(); // Prepare backdrop element createBackdrop(); // Pass and prepare elements startTracking(elements); } return main; }; var singleton = Lightense(); module.exports = singleton; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined /******/ var __webpack_exports__ = __webpack_require__(352); /******/ /******/ return __webpack_exports__; /******/ })() ; }); ================================================ FILE: package.json ================================================ { "name": "lightense-images", "version": "1.0.17", "description": "A dependency-free pure JavaScript image zooming library less than 2 KB (gzipped)", "main": "dist/lightense.js", "scripts": { "build": "webpack --progress --mode=production", "test": "yarn eslint src/index.js", "watch": "webpack --progress --watch --mode=development", "release": "release-it" }, "repository": { "type": "git", "url": "git+https://github.com/sparanoid/lightense-images.git" }, "publishConfig": { "registry": "https://registry.npmjs.org/" }, "keywords": [ "css", "image", "javascript", "webpack" ], "author": "Tunghsiao Liu", "license": "MIT", "bugs": { "url": "https://github.com/sparanoid/lightense-images/issues" }, "homepage": "http://sparanoid.com/work/lightense-images/", "devDependencies": { "@babel/core": "^7.10.5", "@babel/preset-env": "^7.10.4", "babel-loader": "^8.1.0", "core-js": "^3.15.2", "eslint": "^8.0.0", "eslint-webpack-plugin": "^3.0.0", "husky": "^8.0.0", "release-it": "^15.0.0", "terser-webpack-plugin": "^5.1.4", "webpack": "^5.41.1", "webpack-cli": "^4.7.2" }, "release-it": { "hooks": { "before:bump": [ "yarn test" ], "after:bump": [ "yarn build" ] }, "github": { "release": true } } } ================================================ FILE: renovate.json ================================================ { "extends": [ "config:base", ":preserveSemverRanges" ] } ================================================ FILE: src/index.js ================================================ const Lightense = () => { 'use strict'; // default options const defaults = { time: 300, padding: 40, offset: 40, keyboard: true, cubicBezier: 'cubic-bezier(.2, 0, .1, 1)', background: 'var(--bg-color-80, rgba(255, 255, 255, .98))', backgroundFilter: 'blur(30px)', zIndex: 1000000, /* eslint-disable no-undefined */ beforeShow: undefined, afterShow: undefined, beforeHide: undefined, afterHide: undefined /* eslint-enable no-undefined */ }; // Init user options var config = {}; function invokeCustomHook(methodName) { const method = config[methodName]; if (!method) { return; } if (typeof method !== 'function') { throw `config.${methodName} must be a function!`; } Reflect.apply(method, config, [config]); } // Init target elements var elements; function getElements(elements) { switch (typeof elements) { case 'undefined': throw 'You need to pass an element!'; case 'string': return document.querySelectorAll(elements); case 'object': return elements; } } function startTracking(passedElements) { // If passed an array of elements, assign tracking to all var len = passedElements.length; if (len) { // Loop and assign for (var i = 0; i < len; i++) { track(passedElements[i]); } } else { track(passedElements); } } function track(element) { if (element.src && !element.classList.contains('lightense-target')) { element.classList.add('lightense-target'); element.addEventListener( 'click', function(event) { if (config.keyboard) { // If Command (macOS) or Ctrl (Windows) key pressed, stop processing // and open the image in a new tab if (event.metaKey || event.ctrlKey) { return window.open(element.src, '_blank'); } } // Init instance init(this); }, false ); } } function insertCss(styleId, styleContent) { var head = document.head || document.getElementsByTagName('head')[0]; // Remove existing instance if (document.getElementById(styleId)) { document.getElementById(styleId).remove(); } // Create new instance var styleEl = document.createElement('style'); styleEl.id = styleId; // Check if content exists if (styleEl.styleSheet) { styleEl.styleSheet.cssText = styleContent; } else { styleEl.appendChild(document.createTextNode(styleContent)); } head.appendChild(styleEl); } function createDefaultCss() { var css = ` :root { --lightense-z-index: ${config.zIndex - 1}; --lightense-backdrop: ${config.background}; --lightense-backdrop-filter: ${config.backgroundFilter}; --lightense-duration: ${config.time}ms; --lightense-timing-func: ${config.cubicBezier}; } .lightense-backdrop { box-sizing: border-box; width: 100%; height: 100%; position: fixed; top: 0; left: 0; overflow: hidden; z-index: calc(var(--lightense-z-index) - 1); padding: 0; margin: 0; transition: opacity var(--lightense-duration) ease; cursor: zoom-out; opacity: 0; background-color: var(--lightense-backdrop); visibility: hidden; } @supports (-webkit-backdrop-filter: blur(30px)) { .lightense-backdrop { background-color: var(--lightense-backdrop); -webkit-backdrop-filter: var(--lightense-backdrop-filter); } } @supports (backdrop-filter: blur(30px)) { .lightense-backdrop { background-color: var(--lightense-backdrop); backdrop-filter: var(--lightense-backdrop-filter); } } .lightense-wrap { position: relative; transition: transform var(--lightense-duration) var(--lightense-timing-func); z-index: var(--lightense-z-index); pointer-events: none; } .lightense-target { cursor: zoom-in; transition: transform var(--lightense-duration) var(--lightense-timing-func); pointer-events: auto; } .lightense-open { cursor: zoom-out; } .lightense-transitioning { pointer-events: none; }`; insertCss('lightense-images-css', css); } function createBackdrop() { if (document.querySelector('.lightense-backdrop') === null) { config.container = document.createElement('div'); config.container.className = 'lightense-backdrop'; document.body.appendChild(config.container); } else { config.container = document.querySelector('.lightense-backdrop'); } } function createTransform(img) { // Get original image size var naturalWidth = img.width; var naturalHeight = img.height; // Calc zoom ratio var scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0; var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0; var targetImage = config.target.getBoundingClientRect(); var maxScaleFactor = naturalWidth / targetImage.width; var viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0; var viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0; var viewportPadding = config.target.getAttribute('data-lightense-padding') || config.target.getAttribute('data-padding') || config.padding; var viewportWidthOffset = viewportWidth > viewportPadding ? viewportWidth - viewportPadding : viewportWidth - defaults.padding; var viewportHeightOffset = viewportHeight > viewportPadding ? viewportHeight - viewportPadding : viewportHeight - defaults.padding; var imageRatio = naturalWidth / naturalHeight; var viewportRatio = viewportWidthOffset / viewportHeightOffset; if ( naturalWidth < viewportWidthOffset && naturalHeight < viewportHeightOffset ) { config.scaleFactor = maxScaleFactor; } else if (imageRatio < viewportRatio) { config.scaleFactor = (viewportHeightOffset / naturalHeight) * maxScaleFactor; } else { config.scaleFactor = (viewportWidthOffset / naturalWidth) * maxScaleFactor; } // Calc animation var viewportX = viewportWidth / 2; var viewportY = scrollTop + viewportHeight / 2; var imageCenterX = targetImage.left + scrollLeft + targetImage.width / 2; var imageCenterY = targetImage.top + scrollTop + targetImage.height / 2; config.translateX = Math.round(viewportX - imageCenterX); config.translateY = Math.round(viewportY - imageCenterY); } function createViewer() { config.target.classList.add('lightense-open'); // Create wrapper element config.wrap = document.createElement('div'); config.wrap.className = 'lightense-wrap'; // Apply zoom ratio to target image setTimeout(function() { config.target.style.transform = 'scale(' + config.scaleFactor + ')'; }, 20); // Apply animation to outer wrapper config.target.parentNode.insertBefore(config.wrap, config.target); config.wrap.appendChild(config.target); setTimeout(function() { config.wrap.style.transform = 'translate3d(' + config.translateX + 'px, ' + config.translateY + 'px, 0)'; }, 20); // Show backdrop var item_options = { cubicBezier: config.target.getAttribute('data-lightense-cubic-bezier') || config.cubicBezier, background: config.target.getAttribute('data-lightense-background') || config.target.getAttribute('data-background') || config.background, zIndex: config.target.getAttribute('data-lightense-z-index') || config.zIndex }; // Create new config for item-specified styles var config_computed = {...config, ...item_options}; var css = ` :root { --lightense-z-index: ${config_computed.zIndex - 1}; --lightense-backdrop: ${config_computed.background}; --lightense-duration: ${config_computed.time}ms; --lightense-timing-func: ${config_computed.cubicBezier}; }`; insertCss('lightense-images-css-computed', css); config.container.style.visibility = 'visible'; setTimeout(function() { config.container.style.opacity = '1'; }, 20); } function removeViewer() { invokeCustomHook('beforeHide'); unbindEvents(); config.target.classList.remove('lightense-open'); // Remove transform styles config.wrap.style.transform = ''; config.target.style.transform = ''; config.target.classList.add('lightense-transitioning'); // Fadeout backdrop config.container.style.opacity = ''; // Hide backdrop and remove target element wrapper setTimeout(function() { invokeCustomHook('afterHide'); config.container.style.visibility = ''; config.container.style.backgroundColor = ''; config.wrap.parentNode.replaceChild(config.target, config.wrap); config.target.classList.remove('lightense-transitioning'); }, config.time); } function checkViewer() { var scrollOffset = Math.abs(config.scrollY - window.scrollY); if (scrollOffset >= config.offset) { removeViewer(); } } function once(target, event, handler) { target.addEventListener(event, function fn(args) { Reflect.apply(handler, this, args); target.removeEventListener(event, fn); }); } function init(element) { config.target = element; // TODO: need refine // If element already openned, close it if (config.target.classList.contains('lightense-open')) { return removeViewer(); } invokeCustomHook('beforeShow'); // Save current window scroll position for later use config.scrollY = window.scrollY; once(config.target, 'transitionend', function() { invokeCustomHook('afterShow'); }); var img = new Image(); img.onload = function() { createTransform(this); createViewer(); bindEvents(); }; img.src = config.target.src; } function bindEvents() { window.addEventListener('keyup', onKeyUp, false); window.addEventListener('scroll', checkViewer, false); config.container.addEventListener('click', removeViewer, false); } function unbindEvents() { window.removeEventListener('keyup', onKeyUp, false); window.removeEventListener('scroll', checkViewer, false); config.container.removeEventListener('click', removeViewer, false); } // Exit on excape (esc) key pressed function onKeyUp(event) { event.preventDefault(); if (event.keyCode === 27) { removeViewer(); } } function main(target, options = {}) { // Parse elements elements = getElements(target); // Parse user options config = {...defaults, ...options}; // Prepare stylesheets createDefaultCss(); // Prepare backdrop element createBackdrop(); // Pass and prepare elements startTracking(elements); } return main; }; const singleton = Lightense(); module.exports = singleton; ================================================ FILE: webpack.config.js ================================================ const webpack = require('webpack'); const path = require('path'); const pkg = require('./package.json'); const banner = `/*! ${ pkg.name } v${ pkg.version } | © ${ pkg.author } | ${ pkg.license } */`; const ESLintPlugin = require('eslint-webpack-plugin'); const TerserPlugin = require("terser-webpack-plugin"); module.exports = { entry: { './dist/lightense': './src/index.js', './dist/lightense.min': './src/index.js', }, output: { path: path.resolve(__dirname, './'), filename: '[name].js', libraryTarget: 'umd', library: 'Lightense', globalObject: 'this', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, enforce: 'pre', use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] }, }, } ] }, optimization: { minimize: true, minimizer: [ new TerserPlugin({ include: /\.min\.js$/, parallel: true, extractComments: false, }) ] }, plugins: [ new webpack.BannerPlugin({ banner: banner, raw: true, entryOnly: true }), new ESLintPlugin({ extensions: 'js' }) ] };