how to create a Popover dynamically for each rendered item - javascript

I'm trying to create a popover dynamically for all my to be rendered elements.
However the method from this post only outputs the following error message:
"TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'."
In the end the svg should behave like a bootstrap popover. All the necessary libs are in the project.
Here is my code:
function renderLinkIcon(node) {
const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const iconPath = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
iconSvg.setAttribute('height', "16px");
iconSvg.setAttribute('width', "16px");
iconSvg.setAttribute('fill', 'currentColor');
iconSvg.setAttribute('viewBox', '0 0 16 16');
iconSvg.setAttribute('stroke', 'black');
iconSvg.setAttribute('class', 'bi bi-three-dots-vertical threeDotsMenu');
iconPath.setAttribute(
'd',
'M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z'
);
iconSvg.appendChild(iconPath);
let editAndDeleteDiv = document.createElement("div");
editAndDeleteDiv.setAttribute("type", "Button")
editAndDeleteDiv.setAttribute("data-toggle", "popover")
editAndDeleteDiv.setAttribute("title", "My first popover")
editAndDeleteDiv.setAttribute("data-content", "this is the content")
editAndDeleteDiv = $(editAndDeleteDiv)
editAndDeleteDiv.popover()
editAndDeleteDiv.append(iconSvg);
return node.appendChild(editAndDeleteDiv)
}```

Related

How to click a specific DOM element (not button) with pure js that act like selenuim.click()

I need to write script to existing site(i can't change its code)
orders = document.getElementsByClassName('table-row');
for (order of orders){
let text = order.innerText;
let btn = order.getElementsByClassName('icon-btn')[0];
btn.click()
}
The problem is that btn is not button. It's an SVG that has to be clicked on (processed in internal js of website)
<svg width="1.2em" height="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32" class="icon-btn align-middle"><path d="M30 10.68l-2-6A1 1 0 0 0 27 4H5a1 1 0 0 0-1 .68l-2 6A1.19 1.19 0 0 0 2 11v6a1 1 0 0 0 1 1h1v10h2V18h6v10h16V18h1a1 1 0 0 0 1-1v-6a1.19 1.19 0 0 0 0-.32zM26 26H14v-8h12zm2-10h-4v-4h-2v4h-5v-4h-2v4h-5v-4H8v4H4v-4.84L5.72 6h20.56L28 11.16z" fill="currentColor"></path></svg>
so by default it has not click() property
VM844:9 Uncaught TypeError: Cannot read properties of undefined (reading 'click')
at <anonymous>:9:13
So the task is just click on that element, and after that internal site js would process this click and give me popup.
Awaited event is like selenium.click() that just immitate click on object
I tried to add btn.addEventListener('click', ...)
for (order of orders){
console.log(order)
let text = order.innerText;
let btn = order.getElementsByClassName('icon-btn')[0];
btn.addEventListener("click", function(){ alert("Hello World!"); })
}
and i got error
VM1553:9 Uncaught TypeError: Cannot read properties of undefined (reading 'addEventListener')
at <anonymous>:9:13
(anonymous) # VM1553:9
document.getElementsByClassName('icon-btn')[0]._vei.onClick.value()

Vue unicons - set viewBox in custom icon

I have just installed the Vue Unicons module in my vue project.
Vue version: 2.6.10
Vue unicons version: 3.3.1
I am trying to create my own custom icons as explained here:
custom-icons.js:
export const myTestIcon = {
name: 'myTestIcon',
style: 'line',
viewBox: '0 0 680 680',
path: '<path d="M 635 497 l 1 -466 l -620 0 L 20 640 L 516 643 L 231 221z"></path>';
}
app.js:
import Unicon from 'vue-unicons/dist/vue-unicons-vue2.umd';
import { myTestIcon } from './custom-icons';
Unicon.add([myTestIcon]);
App.vue:
<unicon name="my-test-icon"></unicon>
Although I set viewBox is the icon definition, the icon is rendered with default value of viewBox (0 0 24 24).
If I add viewBox="0 0 650 650" or even v-bind="{viewBox:'0 0 650 650'}" to the <unicon> element, it works fine. But I cannot do it since I use icons dynamically.
I read in this place that it might happen due to compilation, but the answer did not help me.
Any idea how can I achieve it?
The custom icon definition schema does not include a viewBox property, so setting it in your definition has no effect. Specifically, Vue Unicons only reads name, style, and path from the custom icon definition.
The viewBox can only be set as a prop on the <unicon> component:
<unicon name="my-custom-icon"
viewBox="0 0 32 32" 👈
width="64"
height="64" />
demo

How to fix issue with svg element not rendering into image (dom2img)

I'm using amcharts4 to build heat map and then via dom2img I'm transforming that into image. Everything is fine and map itself is rendered but legend is not captured with dom2img. Legend itself is an svg element.
I thought maybe it has something to do with gradient because that's the only element with it.
svg element:
<g fill-opacity="1" fill="url("http://localhost:4200/campaigns/pptx/2#gradient-id-257")" style="pointer-events: none;"><path d="M0,0 L455,0 a0,0 0 0 1 0,0 L455,20 a0,0 0 0 1 -0,0 L0,20 a0,0 0 0 1 -0,-0 L0,0 a0,0 0 0 1 0,-0 Z"></path></g>
Dom2img should render legend element.
Use amCharts built-in export feature instead: https://www.amcharts.com/docs/v4/concepts/exporting/
// First enable export
chart.exporting.menu = new am4core.ExportMenu();
chart.exporting.extraSprites.push({
"sprite": legendContainer,
"position": "bottom",
"marginTop": 20
});
// Then you can get the Base64 image
var imgData = chart.exporting.getImage("png");
You can also include the legend using extraSprites as shown above. Read more about including external legend in export.

Fontawesome Icon SVG Not shown in Firefox for Heremap Marker

I have a Here Map, within a Vue application, that shows a marker at a specific lat/lng. The marker uses an SVG from FontAwesome (with appropriately displayed attribution)
In Chrome, IE and Safari the marker displays perfectly. However, in Firefox (65.0.1 (64-bit) on MacOS) it doesn't show at all.
There are no errors thrown, it just silently refuses to display.
The code looks like this:
let img = document.createElement('img');
img.src = require('../assets/img/home-solid.svg');
const icon = new H.map.Icon(img, {
size: {
w: 55,
h: 55
}
});
const actMarker = new H.map.Marker(
{ lat: newVal.latitude, lng: newVal.longitude },
{ icon: icon }
);
this.markerGroup.addObject(actMarker);
this.map.setViewBounds(this.markerGroup.getBounds());
The SVG looks like this:
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="home" class="svg-inline--fa fa-home fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
<path fill="currentColor" d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z">
</path>
</svg>
As I mentioned, the same code loaded in Chrome works fine.
I've looked at some answers on SO regarding Firefox and SVG but none of what I've read seem to help - e.g. ensuring the CSS class is loaded (that's coming in from the FA CDN)
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr"
crossorigin="anonymous">
Does anyone know what's going on here?
As an aside - using a PNG works fine in all browsers so this definitely seems to be SVG related.
Firefox requires that SVG documents used as images and then converted to canvas have a defined width and height.
Adding width="576px" height="512px" to your SVG document's root element will fix it.

How to set a External SVG color in HTML using CSS? [duplicate]

This question already has answers here:
Manipulating external svg file style properties with CSS
(4 answers)
Closed 8 months ago.
I am trying to use SVG on my web page.
But it's color is black.
So, I want it to be changed.
So, I have done-
.red_color_svg
{
color: red;
border: 5px solid currentColor;
fill: currentColor;
}
<object type="image/svg+xml" data="https://rawcdn.githack.com/encharm/Font-Awesome-SVG-PNG/master/black/svg/heart.svg" class="weather_icon red_color_svg circle"></object>
To import heart_border.svg file and make its color red. But it does not work as you see i the output.
Can anyone help me please to solve this?
Thank you very much in advance for helping.
CSS does not apply cross document and you've two documents here heart_border.svg and the container html document.
You need to include the CSS in heart_border.svg e.g. by adding a <link> element or an <xml-stylesheet> processing instruction or by adding it inline in that file via a <style> element.
Alternatively if you add the SVG inline in the html document itself so that you only have one document the CSS will then apply.
This thread is old but I wanted to share my solution, based on SVG filters. You just need to define a feColorMatrix filter as you want and apply it to the external image. See example below for more details.
Compatible with any browsers that can handle SVG.
<svg width="100%" height="100%" class="draggable">
<defs>
<filter id="customColor1">
<!-- Match hex color for #50A -->
<feColorMatrix
in="SourceGraphic"
type="matrix"
values="0 0 0 0 0.3333333333333333 0 0 0 0 0 0 0 0 0 0.6666666666666666 0 0 0 1 0"
></feColorMatrix>
</filter>
<filter id="customColor2">
<!-- Match hex color for #0F0 -->
<feColorMatrix
in="SourceGraphic"
type="matrix"
values="0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0"
></feColorMatrix>
</filter>
</defs>
<image href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/icon-bike-black.svg" width="50" height="50"></image>
<image href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/icon-bike-black.svg" filter="url(#customColor1)" width="50" height="50" x="100"></image>
<image href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/icon-bike-black.svg" filter="url(#customColor2)" width="50" height="50" x="200"></image>
</svg>
[BONUS]
// A little helper to generate matrix color from source and destination colors
// To easily dive in : https://codepen.io/jacobberglund/pen/ORNQAr
// To understand what's going on here read this article by A List Apart
// https://alistapart.com/article/finessing-fecolormatrix/
interface RgbColor {
/** Values are in percent (ex: 255,127,0,255 => 1,0.5,0,1) */
r: number;
g: number;
b: number;
a: number;
}
export class ColorMatrixHelper {
public static getMatrix(hexColor: string) {
const rgbColor: RgbColor = ColorMatrixHelper.hexToRgb(hexColor);
return ColorMatrixHelper.computeMatrixColor(rgbColor);
}
// Inspired by this answer : https://stackoverflow.com/a/5624139/11480016
private static hexToRgb(hex3or6): RgbColor {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
const hex6 = hex3or6.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex6);
const base = 1 / 255;
return result
? {
r: parseInt(result[1], 16) * base,
g: parseInt(result[2], 16) * base,
b: parseInt(result[3], 16) * base,
a: result[4] ? parseInt(result[4], 16) * base : 1,
}
: null;
}
private static computeMatrixColor(rgbColor: RgbColor): string {
let matrix;
if (rgbColor) {
// Ignore original colors and apply the new one
matrix =
`0 0 0 0 ${rgbColor.r} ` + // Red
`0 0 0 0 ${rgbColor.g} ` + // Green
`0 0 0 0 ${rgbColor.b} ` + // Blue
`0 0 0 ${rgbColor.a} 0`; // Alpha
} else {
// Identity (keep orignal colors)
matrix =
`1 0 0 0 0 ` + // Red
`0 1 0 0 0 ` + // Green
`0 0 1 0 0 ` + // Blue
`0 0 0 1 0`; // Alpha
}
return matrix;
}
}
With your current code you set the fill on the object element.
Instead, you need to set it on the svg element.
Something like this:
.red_color_svg svg {
fill: currentColor;
}
The problem is that you don't target the actual SVG element, you target the "SVG container". To be able to change the color of one of the elements inside the SVG you have to target that specific element.
E.g change the fill color of all paths in a SVG:
.weather_icon path {
fill: yellow;
}
If you want to make it easier to handle add class names to the different elements inside the svg.
<path class="my-class" ......... />
This will make it possible to target a specific element by its class:
.weather_icon .my-class {
fill:blue;
stroke:green;
}
Do you really need SVG to be external file? you might want to put svg locally once in document.
<div style="display: none">
<svg><g id="svg1"><path d="some exampe path"/></g></svg>
</div>
And link to it in several places
<svg viewBox="0 0 64 64"><use xlink:href="#svg1"></use></svg>
Than you can style every link separately

Categories

Resources