How to create different background for my Table row nth-child? - javascript

I have created a table by using the external grid js library. I am facing some issues in styling the table. I want to change the background color of all the rows by leaving one row. I am using the code tr.gridjs-tr:nth-child(even) {background: #47bb60;} but It's not working. Can you suggest to me, What is missing in the CSS?
new gridjs.Grid({
columns: ["Name", "Email", "Phone Number"],
data: [
["John", "john#example.com", "(353) 01 222 3333"],
["Mark", "mark#gmail.com", "(01) 22 888 4444"],
["Eoin", "eoin#gmail.com", "0097 22 654 00033"],
["Sarah", "sarahcdd#gmail.com", "+322 876 1233"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"]
],
sort: true,
Default: true,
style: {
table: {
border: '3px solid #ccc'
},
th: {
'background-color': 'rgba(0, 0, 0, 0.1)',
'color': '#fff',
'border-bottom': '3px solid #ccc',
'text-align': 'center'
},
td: {
'text-align': 'center'
},
}
}).render(document.getElementById("wrapper"));
th {
box-sizing: border-box;
background: #1f61cf;
color: #fff;
}
tr.gridjs-tr:nth-child(even) {
background: #47bb60;
}
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet">
<link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
</head>
<body>
<div id="wrapper"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="https://unpkg.com/gridjs/dist/gridjs.umd.js"></script>
<script type="text/javascript" src="js.js"></script>
</body>
</html>

If you want to change the row color alternatively, select the tr using nth-child(even/odd) and then apply the background color to td
new gridjs.Grid({
columns: ["Name", "Email", "Phone Number"],
data: [
["John", "john#example.com", "(353) 01 222 3333"],
["Mark", "mark#gmail.com", "(01) 22 888 4444"],
["Eoin", "eoin#gmail.com", "0097 22 654 00033"],
["Sarah", "sarahcdd#gmail.com", "+322 876 1233"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"],
["Afshin", "afshin#mail.com", "(353) 22 87 8356"]
],
sort: true,
Default: true,
style: {
table: {
border: '3px solid #ccc'
},
th: {
'background-color': 'rgba(0, 0, 0, 0.1)',
'color': '#fff',
'border-bottom': '3px solid #ccc',
'text-align': 'center'
},
td: {
'text-align': 'center'
},
}
}).render(document.getElementById("wrapper"));
th {
box-sizing: border-box;
background: #1f61cf;
color: #fff;
}
.gridjs-tr:nth-child(even) td {
background: #47bb60;
}
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="style.css" rel="stylesheet">
<link href="https://unpkg.com/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
</head>
<body>
<div id="wrapper"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="https://unpkg.com/gridjs/dist/gridjs.umd.js"></script>
<script type="text/javascript" src="js.js"></script>
</body>
</html>

Related

How to get the DOM content as seen in inspect element window after rendering?

I am trying to get the SVG generated using MathJax using JS and animate it like here
In my code, I have
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
SVG: {
useGlobalCache: true,
useFontCache: false
}
})
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS_SVG"></script>
<div id="sup">$$a$$</div>
When I check the rendered DOM using inspect element, i get the contents of div with id sup as
<span class="MathJax_Preview" style="color: inherit; display: none;"></span>
<div class="MathJax_SVG_Display" style="text-align: center;">
<span style="font-size: 100%; display: inline-block; position: relative;" class="MathJax_SVG" id="MathJax-Element-1-Frame" tabindex="0" data-mathml="<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>a</mi></math>" role="presentation">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="1.23ex" height="1.454ex" style="vertical-align: -0.227ex;" viewBox="0 -528.2 529.5 625.9" role="img" focusable="false" aria-hidden="true">
<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)">
<path stroke-width="1" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z"></path>
</g>
</svg>
<span class="MJX_Assistive_MathML MJX_Assistive_MathML_Block" role="presentation">
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>a</mi></math>
</span>
</span>
</div>
<script type="math/tex; mode=display" id="MathJax-Element-1">a</script>
But when I try to get the innerHTML of the div with id sup using
window.addEventListener('load', function(){
console.log(document.getElementById("sup").innerHTML);
})
I get $$a$$ as output.
How can I get the output same as that shown in inspect element?
Your problem is that MathJax is never loaded when you console.log on window.load.
First, you need to wait until MathJax is loaded and rendered in order to get the desired output result.
I've found This question which might help you
The way to synchronize with MathJax's startup actions it to register a StartupHook that will fire when the startup is complete. For example, you can use
MathJax.Hub.Register.StartupHook("End",function () {
console.log(document.getElementById("sup").innerHTML);
});

Why is HTML5 text measuring with offsetWidth giving two different results for Arabic text at two different points in time

I just logged these values for measuring Arabic text with el.offsetWidth:
t1 t2
-----
35 87 "بِسْمِ بِسْمِ"
77 114 "بِسْمِ ٱللَّهِ ٱللَّهِ"
150 224 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحْمَنِ"
215 279 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ٱلرَّحِيمِ"
221 227 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ‎"
281 341 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ ٱلْحَمْدُ"
312 344 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ لِلَّهِ"
351 390 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ رَبِّ رَبِّ"
429 508 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ رَبِّ ٱلْعَلَمِينَ ٱلْعَلَمِينَ"
436 442 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ رَبِّ ٱلْعَلَمِينَ ‎ ‎"
509 582 "بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ رَبِّ ٱلْعَلَمِينَ ‎ ٱلرَّحْمَنِ ٱلرَّحْمَنِ"
573 122 "ٱلرَّحِيمِ ٱلرَّحِيمِ"
64 70 "ٱلرَّحِيمِ ‎ ‎"
112 161 "ٱلرَّحِيمِ ‎ مَلِكِ مَلِكِ"
149 185 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ يَوْمِ"
204 260 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ٱلدِّينِ"
211 217 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ ‎"
258 305 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ إِيَّاكَ"
304 350 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ نَعْبُدُ"
362 420 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ وَإِيَّاكَ وَإِيَّاكَ"
443 524 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ وَإِيَّاكَ نَسْتَعِينُ نَسْتَعِينُ"
449 456 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ وَإِيَّاكَ نَسْتَعِينُ ‎ ‎"
501 553 "ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ وَإِيَّاكَ نَسْتَعِينُ ‎ ٱهْدِنَا ٱهْدِنَا"
571 132 "ٱلصِّرَطَ ٱلصِّرَطَ"
159 254 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ٱلْمُسْتَقِيمَ"
165 171 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ ‎"
221 278 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ صِرَطَ"
277 332 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ ٱلَّذِينَ"
348 419 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ أَنْعَمْتَ أَنْعَمْتَ"
408 468 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ أَنْعَمْتَ عَلَيْهِمْ عَلَيْهِمْ"
445 481 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ أَنْعَمْتَ عَلَيْهِمْ غَيْرِ غَيْرِ"
547 650 "ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ أَنْعَمْتَ عَلَيْهِمْ غَيْرِ ٱلْمَغْضُوبِ ٱلْمَغْضُوبِ"
607 114 "عَلَيْهِمْ عَلَيْهِمْ"
85 116 "عَلَيْهِمْ وَلَا وَلَا"
165 246 "عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ ٱلضَّآلِّينَ"
172 178 "عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ ‎ ‎"
203 235 "عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ ‎ الٓمٓ الٓمٓ"
210 216 "عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ ‎ الٓمٓ ‎ ‎"
256 302 "عَلَيْهِمْ وَلَا ٱلضَّآلِّينَ ‎ الٓمٓ ‎
The code is essentially this:
var measurer = document.createElement('span')
document.body.appendChild(measurer)
var strings = [
'arabic string 1...',
'arabic string 2...',
...
]
next()
function next() {
var string = strings.shift()
var s1 = measure(string)
setTimeout(function(){
var s2 = measure(string)
console.log(s1, s2, string)
next()
}, 300)
}
function measure(string) {
measurer.innerHTML = string
return measurer.offsetWidth
}
Why is it doing this? Why is the final value "after I've waited for a little while" usually greater than the initially calculated offsetWidth value? How do I accurately calculate these?
I wasn't able to reproduce your findings (using a simplified version of your code with a sample of the strings you provided).
const measurer = document.createElement('span');
document.body.appendChild(measurer);
const strings = [
"بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحْمَنِ",
"بِسْمِ ٱللَّهِ ٱلرَّحْمَنِ ٱلرَّحِيمِ ‎ ٱلْحَمْدُ لِلَّهِ رَبِّ ٱلْعَلَمِينَ ‎ ٱلرَّحْمَنِ ٱلرَّحْمَنِ",
"ٱلرَّحِيمِ ‎ مَلِكِ يَوْمِ ٱلدِّينِ ‎ إِيَّاكَ نَعْبُدُ نَعْبُدُ",
"ٱلصِّرَطَ ٱلْمُسْتَقِيمَ ‎ صِرَطَ ٱلَّذِينَ ٱلَّذِينَ"
];
console.log("t1 t2 string\n--------------------------");
strings.forEach(next);
function next(str) {
const s1 = measure(str);
setTimeout( () => console.log(s1, measure(str), str), 300);
}
function measure(string) {
measurer.innerHTML = string;
return measurer.offsetWidth;
}

Multiples transformations matrix on SVG, get cursor point

This question is probably more related to math than svg itself.
Inside a main svg, got multiples transformed svg, (from different events), by a viewBox attribute.
Inside those svg, others elements are grouped in a g, modified using matrix transformations.
How to obtain the points on the elements transformed from the mouse pointer.
The goal could be to draw a point or obtain the related point, as a graph chart.
let point = document.getElementById("main").createSVGPoint();
// The mouse cursor points
point.x = 180
point.y = 63
mouse = point.matrixTransform(sub.getCTM())
// console.log(mouse)
// Output
// "x": 611.75439453125,
// "y": 68.71578979492188
// Testing:
circle.setAttribute("cx", 611.75439453125)
circle.setAttribute("cy", 68.71578979492188)
// Not working
<!-- Parent svg -->
<!-- Not preserving aspect ratios -->
<svg id="main" viewBox="0 0 300 400">
<!-- Includes others svg, transformed with a viewBox -->
<!-- Not preserving aspect ratios -->
<svg id="group1" viewBox="7 54 10 570">
<!-- Group element modified with a matrix -->
<!-- Using css to define the matrix behave identicaly -->
<!-- All elements in this group are transformed by this matrix -->
<g id="sub" transform="matrix(4.5,0,0,0.84,-140,99)">
<!-- Exemple element in group -->
<polyline points="4 65.94338623003772 5 78 6 50.10565885410098 7 40.95007190251531 8 53.698867220021675 9 49.43265131064406 10 44.36112722960851 11 56.329540580770356 12 49.785452985846554 13 44.10803037565898 14 40.537830814642945 15 41.84933269419995 16 38.33857254585345 17 43.590332265307744 18 49.16421525342487 19 49.49017332290519 20 42.51658803643061 21 46.943865580139814 22 36.27544970608283 23 38.070136488634255 24 43.46186643792423 25 42.20788657062835 26 48.37424628503659 27 25.58210762671243 28 23.927391073996347 29 22.349370537628886 30 30.592274894669004 31 21.97356005752208 32 24.960869894290738 33 23.221787723591348 34 17.41781668642936 35 2 36 19.335217095138404 37 39.60405681560149 38 38.49579937936788 39 32.47132729520408 40 25.016474506143126 41 27.037414536922626 42 27.541690844412955 43 20.37253071624997 44 9.872846078159213 45 17.79362716653617 46 13.107500567651172 47 24.955117693064494 48 24.247596942250766 49 19.728284178923616 50 11.341574791230315 51 8.248807931982782 52 10.697328253903962 " ></polyline>
<!-- This circle should be at the cursor -->
<circle id="circle" cx="50" cy="50" r="50"fill="blue">
</g>
</svg>
<!-- Rectangles symbolizing the mouse cursor -->
<rect width="1000" height="1" x="0" y="63" ></rect>
<rect width="1" height="500" x="180" y="0"></rect>
</svg>
Svg has numerous bindings related to transformations, we can retrieve the transformation matrix of each elements with getCTM() and getBBox(), and use matrixTransform.
This works for one level of transformation?
How to chain multiples matrix transformations?
If you want the point relative to the transformed area, then it should get reflected as the offsetX and offsetY properties of their corresponding MouseEvents.
However, there seems to be a bug in Webkit / Blink browsers with this regard, so this actually only works in Firefox (and maybe IE?)...
const poly = document.querySelector('polyline');
poly.addEventListener('mousemove', evt => {
circle.setAttribute("cx", evt.offsetX + 2.5);
circle.setAttribute("cy", evt.offsetY + 2.5);
});
<!-- Parent svg -->
<!-- Not preserving aspect ratios -->
<svg id="main" viewBox="0 0 300 400">
<!-- Includes others svg, transformed with a viewBox -->
<!-- Not preserving aspect ratios -->
<svg id="group1" viewBox="7 54 10 570">
<!-- Group element modified with a matrix -->
<!-- Using css to define the matrix behave identicaly -->
<!-- All elements in this group are transformed by this matrix -->
<g id="sub" transform="matrix(4.5,0,0,0.84,-140,99)">
<!-- Exemple element in group -->
<polyline points="4 65.94338623003772 5 78 6 50.10565885410098 7 40.95007190251531 8 53.698867220021675 9 49.43265131064406 10 44.36112722960851 11 56.329540580770356 12 49.785452985846554 13 44.10803037565898 14 40.537830814642945 15 41.84933269419995 16 38.33857254585345 17 43.590332265307744 18 49.16421525342487 19 49.49017332290519 20 42.51658803643061 21 46.943865580139814 22 36.27544970608283 23 38.070136488634255 24 43.46186643792423 25 42.20788657062835 26 48.37424628503659 27 25.58210762671243 28 23.927391073996347 29 22.349370537628886 30 30.592274894669004 31 21.97356005752208 32 24.960869894290738 33 23.221787723591348 34 17.41781668642936 35 2 36 19.335217095138404 37 39.60405681560149 38 38.49579937936788 39 32.47132729520408 40 25.016474506143126 41 27.037414536922626 42 27.541690844412955 43 20.37253071624997 44 9.872846078159213 45 17.79362716653617 46 13.107500567651172 47 24.955117693064494 48 24.247596942250766 49 19.728284178923616 50 11.341574791230315 51 8.248807931982782 52 10.697328253903962 " ></polyline>
<!-- This circle should be at the cursor -->
<circle id="circle" cx="5" cy="5" r="5" fill="blue" pointer-events="none">
</g>
</svg>
<!-- Rectangles symbolizing the mouse cursor -->
<rect width="1000" height="1" x="0" y="63" ></rect>
<rect width="1" height="500" x="180" y="0"></rect>
</svg>
If you wish to transform arbitrary values, then you use the technique described in this Answer which consists in dispatching such a MouseEvent on your element:
const point = {x:180, y:63};
const poly = document.querySelector('polyline');
poly.addEventListener('mousemove', evt => {
point.x = evt.offsetX;
point.y = evt.offsetY;
}, {once: true});
const evt = new MouseEvent('mousemove', {
clientX: point.x,
clientY: point.y
});
poly.dispatchEvent(evt);
console.log(point);
circle.setAttribute("cx", point.x);
circle.setAttribute("cy", point.y);
<!-- Parent svg -->
<!-- Not preserving aspect ratios -->
<svg id="main" viewBox="0 0 300 400">
<!-- Includes others svg, transformed with a viewBox -->
<!-- Not preserving aspect ratios -->
<svg id="group1" viewBox="7 54 10 570">
<!-- Group element modified with a matrix -->
<!-- Using css to define the matrix behave identicaly -->
<!-- All elements in this group are transformed by this matrix -->
<g id="sub" transform="matrix(4.5,0,0,0.84,-140,99)">
<!-- Exemple element in group -->
<polyline points="4 65.94338623003772 5 78 6 50.10565885410098 7 40.95007190251531 8 53.698867220021675 9 49.43265131064406 10 44.36112722960851 11 56.329540580770356 12 49.785452985846554 13 44.10803037565898 14 40.537830814642945 15 41.84933269419995 16 38.33857254585345 17 43.590332265307744 18 49.16421525342487 19 49.49017332290519 20 42.51658803643061 21 46.943865580139814 22 36.27544970608283 23 38.070136488634255 24 43.46186643792423 25 42.20788657062835 26 48.37424628503659 27 25.58210762671243 28 23.927391073996347 29 22.349370537628886 30 30.592274894669004 31 21.97356005752208 32 24.960869894290738 33 23.221787723591348 34 17.41781668642936 35 2 36 19.335217095138404 37 39.60405681560149 38 38.49579937936788 39 32.47132729520408 40 25.016474506143126 41 27.037414536922626 42 27.541690844412955 43 20.37253071624997 44 9.872846078159213 45 17.79362716653617 46 13.107500567651172 47 24.955117693064494 48 24.247596942250766 49 19.728284178923616 50 11.341574791230315 51 8.248807931982782 52 10.697328253903962 " ></polyline>
<!-- This circle should be at the cursor -->
<circle id="circle" cx="5" cy="5" r="5" fill="blue" pointer-events="none">
</g>
</svg>
<!-- Rectangles symbolizing the mouse cursor -->
<rect width="1000" height="1" x="0" y="63" ></rect>
<rect width="1" height="500" x="180" y="0"></rect>
</svg>
Note that WebKit / Blink do set it correctly on HTML elements as demonstrated in this Q/A...
The problem is that getCTM() only returns the transformation up to the nearest enclosing <svg> element. Instead you can use getScreenCTM() to calculate the transformation relative to the window. Except we actually need to take the inverse of this transformation so it will be subtracted it from the mouse point. Then we make sure everything is relative to the top-level svg container.
This will be accurate no matter how many layers of transformations the target element is nested under.
<svg id="main" viewBox="0 0 300 400">
<svg id="group1" viewBox="7 54 10 570">
<g id="sub" transform="matrix(4.5,0,0,0.84,-140,99)">
<polyline points="4 65.94338623003772 5 78 6 50.10565885410098 7 40.95007190251531 8 53.698867220021675 9 49.43265131064406 10 44.36112722960851 11 56.329540580770356 12 49.785452985846554 13 44.10803037565898 14 40.537830814642945 15 41.84933269419995 16 38.33857254585345 17 43.590332265307744 18 49.16421525342487 19 49.49017332290519 20 42.51658803643061 21 46.943865580139814 22 36.27544970608283 23 38.070136488634255 24 43.46186643792423 25 42.20788657062835 26 48.37424628503659 27 25.58210762671243 28 23.927391073996347 29 22.349370537628886 30 30.592274894669004 31 21.97356005752208 32 24.960869894290738 33 23.221787723591348 34 17.41781668642936 35 2 36 19.335217095138404 37 39.60405681560149 38 38.49579937936788 39 32.47132729520408 40 25.016474506143126 41 27.037414536922626 42 27.541690844412955 43 20.37253071624997 44 9.872846078159213 45 17.79362716653617 46 13.107500567651172 47 24.955117693064494 48 24.247596942250766 49 19.728284178923616 50 11.341574791230315 51 8.248807931982782 52 10.697328253903962 " />
<circle id="circle" cx="50" cy="50" r="50" fill="blue" />
</g>
</svg>
<rect width="1000" height="1" x="0" y="63" />
<rect width="1" height="500" x="180" y="0" />
<script>
let sub = document.getElementById('sub');
let circle = document.getElementById('circle');
let main = document.getElementById("main");
let mouse = main.createSVGPoint();
mouse.x = 180; mouse.y = 63;
function getMatrix(el) {
let matrix = el.getScreenCTM().inverse();
matrix = matrix.multiply(main.getScreenCTM());
return matrix;
}
let result = mouse.matrixTransform(getMatrix(sub));
circle.setAttribute("cx", result.x);
circle.setAttribute("cy", result.y);
</script>
</svg>

HTML, SVG, and Javascript with XML - DOMParser not reading every other element

I'm working on a program that saves and loads SVG data to and from an xml file and it does work, but for some reason whenever the DOMParser runs, every other element is not being read.
The XML file I am trying to read is formatted like this:
<?xml version="1.0" encoding="utf-8"?>
<marks>
<path xmlns="http://www.w3.org/2000/svg" class="mark" d="M736 264 L736 264 L736 264 L736 265 L736 268 L736 269 L736 272 L736 277 L736 280 L736 288 L736 304 L736 312 L737 318 L740 356 L740 364 L740 376 L741 398 L742 430 L742 474 L744 488" fill="none" stroke="#000000" stroke-width="2" id="A"></path>
<path xmlns="http://www.w3.org/2000/svg" class="mark" d="M1230 426 L1230 428 L1230 428 L1229 428 L1228 429 L1228 430 L1228 430 L1226 432 L1224 432 L1218 434 L1216 436 L1209 436 L1194 440 L1186 440 L1180 440 L1158 444 L1092 445 L1018 446 L928 446 L902 446" fill="none" stroke="#000000" stroke-width="2" id="AA"></path>
</marks>
In this example, the first element is not read but the second one is. Here's the javascript code:
var e = '<?xml version="1.0" encoding="utf-8"?><marks><path xmlns="http://www.w3.org/2000/svg" class="mark" d="M736 264 L736 264 L736 264 L736 265 L736 268 L736 269 L736 272 L736 277 L736 280 L736 288 L736 304 L736 312 L737 318 L740 356 L740 364 L740 376 L741 398 L742 430 L742 474 L744 488" fill="none" stroke="#000000" stroke-width="2" id="A"></path><path xmlns="http://www.w3.org/2000/svg" class="mark" d="M1230 426 L1230 428 L1230 428 L1229 428 L1228 429 L1228 430 L1228 430 L1226 432 L1224 432 L1218 434 L1216 436 L1209 436 L1194 440 L1186 440 L1180 440 L1158 444 L1092 445 L1018 446 L928 446 L902 446" fill="none" stroke="#000000" stroke-width="2" id="AA"></path></marks>';
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(e, "text/xml");
console.log(xmlDoc);
Even at this point the XML is not being parsed correctly. Please let me know if you have a solution.
Try to use "application/xml" instead of "text/xml".

How do I use javascript to clone an SVG element?

I am trying to follow the example here under the cloneNode section (fourth occurrence of 'cloneNode' in the document). The document says it's a DRAFT so i'm wondering if these features don't exist with SVG yet??
Here is my HTML:
<html>
<head>
<script>
var Root=document.documentElement
function clone(){
var G=document.getElementById("groupid")
alert('hi')
var NewG=G.cloneNode(true)
alert('bye')
var move="translate("+0+","+30+")"
NewG.setAttributeNS(null,"transform",move)
Root.appendChild(NewG)
}
clone()
</script>
</head>
<body>
<div style="" width="100px" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="bigsvg"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)" id="groupid">
<path class="onepointsix" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
</svg>
</div>
</body>
</html>
As you can see, the alert 'bye' doesn't work. Thanks in advance for the help.
When you call getElementById, the element doesn't yet exist. Put the script at the end of the body :
<head>
</head>
<body>
<div style="" width="100px" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="bigsvg"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)" id="groupid">
<path class="onepointsix" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
</svg>
</div>
<script>
var Root=document.documentElement
function clone(){
var G=document.getElementById("groupid")
alert('hi')
var NewG=G.cloneNode(true)
alert('bye')
var move="translate("+0+","+30+")"
NewG.setAttributeNS(null,"transform",move)
Root.appendChild(NewG)
}
clone()
</script>
</body>
</html>
This seems to be more complicated than need be. Start with just your pawn path in your root svg. Then clone, and append to root. One of the important things to address that once you clone, you should change the id of the cloned element. Otherwise you will get a conflict when addressing the original cloned element.
Try This:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Title</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='font-family:arial'>
<center>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400" xmlns="http://www.w3.org/2000/svg" >
<path id="pawn" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</svg>
</div>
<br />SVG Source:<br />
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<script id=myScript>
var Root=mySVG
function clone(){
var newPawn=pawn.cloneNode(true)
newPawn.id="newPawn1"
var move="translate("+0+","+30+")"
newPawn.setAttribute("transform",move)
Root.appendChild(newPawn)
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
clone()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>
To make it clear what was causing errors:
var Root=document.documentElement was wrong because we need to make sure the new clone gets added to its parent SVG, not at the end of the page. Instead we must add an id="mySVG" to the parent and then use var Root=mySVG.
var G=document.getElementById("groupid") didn't grab the 'groupid' element because the code ran before the element existed. The solution is to trigger the code to run AFTER the page loads (use onload event, or move the script to the bottom of the body).
var move="translate("+0+","+30+")" was replacing the transform property in the SVG group, overwriting the old translate AND the scale(0.022). Therefore, while the clone existed after fixing the above two errors, it was so far down that it was out of the viewBox. Instead I should use var move="translate(0,1) scale(0.022)"

Categories

Resources