/* # ----------------------------------------------------------------------------- # ~/assets/themes/j1/modules/spinner/js/spin.js # Provides Javascript functions for an animated loading spinner # # Product/Info: # https://jekyll.one # https://github.com/fgnass/spin.js # # Copyright (C) 2023 Juergen Adams # Copyright (c) 2011-2018 Felix Gnass # # J1 Template is licensed under the MIT License. # See: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE.md # Spin is licensed under the MIT License. # See: https://github.com/fgnass/spin.js/blob/master/LICENSE.md # ----------------------------------------------------------------------------- */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Spin = {})); }(this, (function (exports) { 'use strict'; var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(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); }; var defaults = { lines: 12, length: 7, width: 5, radius: 10, scale: 1.0, corners: 1, color: '#000', fadeColor: 'transparent', animation: 'spinner-line-fade-default', rotate: 0, direction: 1, speed: 1, zIndex: 2e9, className: 'spinner', top: '50%', left: '50%', shadow: '0 0 1px transparent', position: 'absolute', }; var Spinner = /** @class */ (function () { function Spinner(opts) { if (opts === void 0) { opts = {}; } this.opts = __assign(__assign({}, defaults), opts); } /** * Adds the spinner to the given target element. If this instance is already * spinning, it is automatically removed from its previous target by calling * stop() internally. */ Spinner.prototype.spin = function (target) { this.stop(); this.el = document.createElement('div'); this.el.className = this.opts.className; this.el.setAttribute('role', 'progressbar'); css(this.el, { position: this.opts.position, width: 0, zIndex: this.opts.zIndex, left: this.opts.left, top: this.opts.top, transform: "scale(" + this.opts.scale + ")", }); if (target) { target.insertBefore(this.el, target.firstChild || null); } drawLines(this.el, this.opts); return this; }; /** * Stops and removes the Spinner. * Stopped spinners may be reused by calling spin() again. */ Spinner.prototype.stop = function () { if (this.el) { if (typeof requestAnimationFrame !== 'undefined') { cancelAnimationFrame(this.animateId); } else { clearTimeout(this.animateId); } if (this.el.parentNode) { this.el.parentNode.removeChild(this.el); } this.el = undefined; } return this; }; return Spinner; }()); /** * Sets multiple style properties at once. */ function css(el, props) { for (var prop in props) { el.style[prop] = props[prop]; } return el; } /** * Returns the line color from the given string or array. */ function getColor(color, idx) { return typeof color == 'string' ? color : color[idx % color.length]; } /** * Internal method that draws the individual lines. */ function drawLines(el, opts) { var borderRadius = (Math.round(opts.corners * opts.width * 500) / 1000) + 'px'; var shadow = 'none'; if (opts.shadow === true) { shadow = '0 2px 4px #000'; // default shadow } else if (typeof opts.shadow === 'string') { shadow = opts.shadow; } var shadows = parseBoxShadow(shadow); for (var i = 0; i < opts.lines; i++) { var degrees = ~~(360 / opts.lines * i + opts.rotate); var backgroundLine = css(document.createElement('div'), { position: 'absolute', top: -opts.width / 2 + "px", width: (opts.length + opts.width) + 'px', height: opts.width + 'px', background: getColor(opts.fadeColor, i), borderRadius: borderRadius, transformOrigin: 'left', transform: "rotate(" + degrees + "deg) translateX(" + opts.radius + "px)", }); var delay = i * opts.direction / opts.lines / opts.speed; delay -= 1 / opts.speed; // so initial animation state will include trail var line = css(document.createElement('div'), { width: '100%', height: '100%', background: getColor(opts.color, i), borderRadius: borderRadius, boxShadow: normalizeShadow(shadows, degrees), animation: 1 / opts.speed + "s linear " + delay + "s infinite " + opts.animation, }); backgroundLine.appendChild(line); el.appendChild(backgroundLine); } } function parseBoxShadow(boxShadow) { var regex = /^\s*([a-zA-Z]+\s+)?(-?\d+(\.\d+)?)([a-zA-Z]*)\s+(-?\d+(\.\d+)?)([a-zA-Z]*)(.*)$/; var shadows = []; for (var _i = 0, _a = boxShadow.split(','); _i < _a.length; _i++) { var shadow = _a[_i]; var matches = shadow.match(regex); if (matches === null) { continue; // invalid syntax } var x = +matches[2]; var y = +matches[5]; var xUnits = matches[4]; var yUnits = matches[7]; if (x === 0 && !xUnits) { xUnits = yUnits; } if (y === 0 && !yUnits) { yUnits = xUnits; } if (xUnits !== yUnits) { continue; // units must match to use as coordinates } shadows.push({ prefix: matches[1] || '', x: x, y: y, xUnits: xUnits, yUnits: yUnits, end: matches[8], }); } return shadows; } /** * Modify box-shadow x/y offsets to counteract rotation */ function normalizeShadow(shadows, degrees) { var normalized = []; for (var _i = 0, shadows_1 = shadows; _i < shadows_1.length; _i++) { var shadow = shadows_1[_i]; var xy = convertOffset(shadow.x, shadow.y, degrees); normalized.push(shadow.prefix + xy[0] + shadow.xUnits + ' ' + xy[1] + shadow.yUnits + shadow.end); } return normalized.join(', '); } function convertOffset(x, y, degrees) { var radians = degrees * Math.PI / 180; var sin = Math.sin(radians); var cos = Math.cos(radians); return [ Math.round((x * cos + y * sin) * 1000) / 1000, Math.round((-x * sin + y * cos) * 1000) / 1000, ]; } exports.Spinner = Spinner; window.Spinner = Spinner; Object.defineProperty(exports, '__esModule', { value: true }); })));