/*
* This file is part of AUX.
*
* AUX is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* AUX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
/**
* This module contains functions useful for manipulating SVGs.
*
* @module utils/svg
*/
import { getStyle, hasClass, getTag } from './dom.js';
const data_store = new WeakMap();
function data(e) {
let r;
r = data_store.get(e);
if (!r) {
r = {};
data_store.set(e, r);
}
return r;
}
function store(e, key, val) {
/**
* Store a piece of data in an object.
* @param {object} object - The object to store the data
* @param {string} key - The key to identify the memory
* @param {*} data - The data to store
* @function store
*/
data(e)[key] = val;
}
function retrieve(e, key) {
/**
* Retrieve a piece of data from an object.
* @param {object} object - The object to retrieve the data from
* @param {string} key - The key to identify the memory
* @function retrieve
* @returns {*}
*/
return data(e)[key];
}
/**
* Move SVG for some sub-pixel if their position in viewport is not int.
* @param {SVGElement} svg - The SVG to manipulate
* @function seatSVG
*/
export function seatSVG(e) {
if (retrieve(e, 'margin-left') === null) {
store(e, 'margin-left', parseFloat(getStyle(e, 'margin-left')));
} else {
e.style.marginLeft = retrieve(e, 'margin-left') || 0;
}
let l = parseFloat(retrieve(e, 'margin-left')) || 0;
let b = e.getBoundingClientRect();
const x = b.left % 1;
if (x) {
if (x < 0.5) l -= x;
else l += 1 - x;
}
if (e.parentElement && getStyle(e.parentElement, 'text-align') === 'center')
l += 0.5;
e.style.marginLeft = l + 'px';
//console.log(l);
if (retrieve(e, 'margin-top') === null) {
store(e, 'margin-top', parseFloat(getStyle(e, 'margin-top')));
} else {
e.style.marginTop = retrieve(e, 'margin-top') || 0;
}
let t = parseFloat(retrieve(e, 'margin-top') || 0);
b = e.getBoundingClientRect();
const y = b.top % 1;
if (y) {
if (x < 0.5) t -= y;
else t += 1 - y;
}
//console.log(t);
e.style.marginTop = t + 'px';
}
/**
* Searches for all SVG that don't have the class "svg-fixed" and re-positions them
* in order to avoid blurry lines.
* @param {HTMLElement} parent - If set only children of parent are searched
* @function seatAllSVG
*/
export function seatAllSVG(parent) {
const a = getTag('svg', parent);
for (let i = 0; i < a.length; i++) {
if (!hasClass(a[i], 'svg-fixed')) seatSVG(a[i]);
}
}
/**
* Creates and returns an SVG child element.
* @param {string} tag - The element to create as string, e.g. "line" or "g"
* @param {object} arguments - The attributes to set onto the element
* @returns {SVGElement}
*/
export function makeSVG(tag, args) {
const el = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg:' + tag
);
for (const k in args) {
if (Object.prototype.hasOwnProperty.call(args, k))
el.setAttribute(k, args[k]);
}
return el;
}