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

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);
});

Related

Make animate execute again after svg path changes

I want to animate an svg path such that the animation only runs once, however if the d values change then animation should run again once. I'm having trouble having the animation run every time the path values change, if I set the repeatCount value to 1 it won't run again after the svg values change and the svg "rerenders". I included some code below that replicates what I'm trying to do, any help is appreciated. Here is a code demo with just the animation, no react: https://codepen.io/shak8/pen/RwLLjNm
const SVGAnimate = () =>{
const [width, setWidth] = useState(213)
const [prevWidth, setPrevWidth] = useState(213)
return (
<div>
<svg width="400" height="500">
<path style="stroke-width:3;stroke:rgb(0,0,0)"
fill="black"
d=`M 0 212 S 226 212, ${width} 20 V 212 H 0`>
<animate
attributeName="d"
dur="5s"
from=`M 0 212 S 226 212,${prevWidth} 20 V 212 H 0`
to=`M 0 212 S 226 212, ${width} 20 V 212 H 0`
repeatCount="1"
fill="black"
/>
</path>
<button onClick={() => {
// These should trigger svg path to change, desired
// effect is for path to change with animation.
setPrevWidth(width == width)
setWidth(width == 213 ? 320 : 213)
}
}> Change</button>
</div>
)
}
I've also tried using transition on the path, which works perfectly on chrome but doesn't work on safari.
You can use onClick="animation.beginElement()"
As an observation: you have a fill="black" attribute for the animation. I suppose you meant it to be fill="freeze". This would freeze the animation similar to animation-fill-mode: forwards.
<div>
<svg width="400" height="200">
<path style="stroke-width:3;stroke:rgb(0,0,0)"
fill="black"
d="M 0 212 S 226 212, 100 20 V 212 H 0">
<animate id="animation"
attributeName="d"
dur="5s"
from="M 0 212 S 226 212,100 20 V 212 H 0"
to="M 0 212 S 226 212, 300 20 V 212 H 0"
repeatCount="1"
fill="freeze"
/>
</path>
</svg>
<button onClick="animation.beginElement()"> Change</button>
</div>

How to align a group (instead of text) along a path in svg?

Lets assume I have programmatically created a circle and some text,
that I want to align along the circle.
I am able to do so using the textPath element.
In addition I have a rectangular image (or any svg group <g>),
that I also would like to align to the circle
(the red rectangle in the image below is just an example; actually I would like to be able to align arbitrary svg groups <g> as image labels on the nodes of a chord diagram.).
However, textPath only seems to work for text elements.
=> Is there something similar that works for group elements?
Or do I need to manually calculate the transformation for my group
(following from some tangent of the circle)?
(A workaround could be to create some hidden text with a single letter and
the same size as my group ... align it and grab its transformation. However, that feels ugly.)
In addition I have a rectangular image (or any svg group ), that I
also would like to align to the circle (see red rectangle in the
example image below).
However, textPath only seems to work for text elements.
You can use the rectangle unicode character ▮
In this case you will be able to include it in one textPath command along with other words
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-20" dy="-10" fill="red" font-size="72px"> ▮</tspan>
</textPath>
</text>
</svg>
You can use any unicode character that suits you
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px"> ⮔</tspan>
</textPath>
</text>
</svg>
If necessary, you can make the animation of the letters
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px"> ⮔</tspan>
<animate dur="10s" repeatCount="5" attributeName="startOffset" values="5%;50%;50%;5%;5%"/>
</textPath>
</text>
</svg>
As #Paul LeBeau commented:
No there is no automatic way to do that. You have to position it
yourself
Consider adding svg images to text using absolute positioning
Since any text in SVG is a vector object, it has absolute coordinates x, y, as the first character of the word and the last.
Using this you can position an icon or any other vector image to the beginning or end of the text.
I put the icon in the <symbol> tag and position it at the end of the word using the <use> tag
<use xlink:href="#speaker" x="245" y="35" />
<svg width="400" height="400" viewBox="0 0 400 400">
<symbol>
<g id="speaker" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);" >
<path fill="#089421" d="M28,7.1v2c7.3,1,13,7.3,13,14.9s-5.7,13.9-13,14.9v2c8.4-1,15-8.2,15-16.9S36.4,8.1,28,7.1z"/>
<path fill="#546E7A" d="M14,32H7c-1.1,0-2-0.9-2-2V18c0-1.1,0.9-2,2-2h7V32z"/>
<polygon fill="#78909C" points="26,42 14,32 14,16 26,6"/>
<path fill="#089421" d="M28,17.3v2.1c1.8,0.8,3,2.5,3,4.6s-1.2,3.8-3,4.6v2.1c2.9-0.9,5-3.5,5-6.7S30.9,18.2,28,17.3z"/>
<path fill="#089421" d="M28,12.2v2c4.6,0.9,8,5,8,9.8s-3.4,8.9-8,9.8v2c5.7-1,10-5.9,10-11.8S33.7,13.1,28,12.2z"/>
</g>
</symbol>
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello Wordl </tspan>
</textPath>
</text>
<use xlink:href="#speaker" x="245" y="35" />
</svg>
An example with a growing line on which text and an icon are located
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
<symbol id="grow">
<g>
<circle fill="#FF9800" cx="28" cy="9" r="5"/>
</g>
<path fill="#00796B" d="M29,27.3l-9.2-4.1c-1-0.5-1.5,1-2,2c-0.5,1-4.1,7.2-3.8,8.3c0.3,0.9,1.1,1.4,1.9,1.4c0.2,0,0.4,0,0.6-0.1 L28.8,31c0.8-0.2,1.4-1,1.4-1.8C30.2,28.4,29.7,27.6,29,27.3z"/>
<path fill="#009688" d="M26.8,15.2l-2.2-1c-1.3-0.6-2.9,0-3.5,1.3L9.2,41.1c-0.5,1,0,2.2,1,2.7c0.3,0.1,0.6,0.2,0.9,0.2 c0.8,0,1.5-0.4,1.8-1.1c0,0,9.6-13.3,10.4-14.9s4.9-9.3,4.9-9.3C28.7,17.4,28.2,15.8,26.8,15.2z"/>
<path fill="#FF9800" d="M40.5,15.7c-0.7-0.8-2-1-2.8-0.3l-5,4.2l-6.4-3.5c-1.1-0.6-2.6-0.4-3.3,0.9c-0.8,1.3-0.4,2.9,0.8,3.4 l8.3,3.4c0.3,0.1,0.6,0.2,0.9,0.2c0.5,0,0.9-0.2,1.3-0.5l6-5C41.1,17.8,41.2,16.6,40.5,15.7z"/>
<path fill="#FF9800" d="M11.7,23.1l3.4-5.1l4.6,0.6l1.5-3.1c0.4-0.9,1.2-1.4,2.1-1.5c-0.1,0-0.2,0-0.2,0h-9c-0.7,0-1.3,0.3-1.7,0.9 l-4,6c-0.6,0.9-0.4,2.2,0.6,2.8C9.2,23.9,9.6,24,10,24C10.6,24,11.3,23.7,11.7,23.1z"/>
</symbol>
<path id="txtPath" d="m22 366c0 0 59-24 74-50C132 253 129 213 128 161 125 33 200 2 200 2" style="fill:none;stroke:#00796B;stroke-width:3"/>
<use xlink:href="#grow" x="123" y="10" />
<text dx="0" dy="-10px" font-size="20" font-family="Times New Roman" fill="#414141" >
<textPath id="result" startOffset="5%" xlink:href="#txtPath"> Stock growth in the first half of the year </textPath>
</text>
</svg>
One more example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
<symbol id="Cactus" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);">
<path fill="#7CB342" d="M35.3,9.6c-1.6-0.2-1.3,0.9-1.9,2.7l-1,4.3c-0.3,1-0.7,1.4-2,1.3L25,17.3c-1.6-0.2-3.1,1-3.2,2.6 c-0.2,1.6,1,3.1,2.6,3.2l6.3,0.7c3,0.3,5.5-0.9,6-5.4c0,0,0.6-4.7,0.3-6.6C36.7,10.2,36.6,9.7,35.3,9.6z"/>
<path fill="#7CB342" d="M12.2,13.6c1.6-0.1,1.3,0.9,1.9,2.8l1.3,6.3c0.3,1,0.7,1.4,2,1.3l5.4-0.4c1.6-0.1,3,1.1,3.2,2.7 c0.1,1.6-1.1,3-2.7,3.2l-6.3,0.5c-3,0.2-5.5-1-5.9-5.5c0,0-0.8-6.7-0.5-8.5C10.7,14.2,10.8,13.7,12.2,13.6z"/>
<path fill="#8BC34A" d="M24,5c-2.4,0-4,0.6-4.5,3.2c0,0-2.1,16.9,0,32.1c0.3,3.2,2,1.2,4.4,1.2s3.8,2.7,4.4-0.8 c2.5-15.1,0-32.6,0-32.6C27.7,5.2,26.4,5,24,5z"/>
<path fill="#FFB74D" d="M38.8,43H9.2c0,0,4.9-2.3,14.8-2.3S38.8,43,38.8,43z"/>
</symbol>
<path id="txtPath" d="m200 2c0 0 36 31 57 42 15 8 34 6 47 16 15 11 26 27 33 43 8 18 2 41 11 58 9 17 41 40 41 40" fill="none" stroke="green" stroke-width="2"/>
<use xlink:href="#Cactus" x="355" y="150" />
<text font-size="20" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#txtPath">
<tspan dx="0" dy="-5" fill="black" >Decrease in stocks per year </tspan>
</textPath>
</text>
</svg>
As a starting point here is the workaround I mentioned.
It uses some invisible placeholder text and extracts the transformation information with
placeHolder.getBoundingClientRect();
and
placeHolder.getRotationOfChar(0);
The result is only an approximation that depends on the font size and on the character of the placeholder.
var svg = document.getElementById('svg');
var text = document.createElement('text');
text.setAttribute('fill','black');
svg.appendChild(text);
var placeHolder = document.getElementById('placeholder');
var placeHolderBounds = placeHolder.getBoundingClientRect();
var angle = placeHolder.getRotationOfChar(0);
var group = document.getElementById('my-group');
var groupBounds = group.getBoundingClientRect();
var dx = 0; //groupBounds.width/2;
var dy = -groupBounds.height;
var x = placeHolderBounds.x;
var y = placeHolderBounds.y;
var transform = 'translate(' + x +','+ y +') '+
'rotate('+ angle +') '+
'translate('+ dx +','+ dy +')';
group.setAttribute('transform', transform);
<svg id='svg' width="400" height="400" viewBox="0 0 400 400">
<path id="my-path" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<g id="my-group">
<rect width="30" height="20" style="fill:red"/>
</g>
<text font-size="12px" >
<textPath startOffset="10%" xlink:href="#my-path">
<tspan>Hello World</tspan><tspan id='placeholder' visibility="hidden" >-</tspan>
</textPath>
</text>
</svg>

Svg path not closing correctly

I'm trying to create a bridge-like shape with an svg using javascript. With the following html I get the overall shape, but the close path is wrong:
<svg height="897" width="414" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 414 897">
<path stroke-width="3" stroke="blue" style="fill:transparent; fill-opacity: 1"
d="M 0 0 V 207 H 30
M 30 207 q 0 -177 177 -177
M 207 30 q 177 0 177 177
H 414 V 0 H 0 z">
</path>
</svg>
This produces the following shape:
It is closing in a strange way which means that it isn't filling correctly. The strange vertical line from the top of the arch to the top left shouldn't be there. How do I get it to close properly and fill properly?
The path will close from your last point to the last declared M. You can fix this by removing all the M calls except the first one. Since you are making a continuous line you don't need to move to a new point every time.
<svg height="897" width="414" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 414 897">
<path stroke-width="3" stroke="blue" style="fill:transparent; fill-opacity: 1"
d="M 0 0 V 207 H 30
q 0 -177 177 -177
q 177 0 177 177
H 414 V 0 H 0 z">
</path>
</svg>

Tootlip text of svg image is not fetched - Selenium Webdriver

<span id="tooltip" class="tooltip">
<svg class="svg-inline--fa fa-question-circle fa-w-16" data-fa-transform="grow-6" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="question-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg="" style="transform-origin: 0.5em 0.5em;">
<g transform="translate(256 256)">
<g transform="translate(0, 0) scale(1.375, 1.375) rotate(0 0 0)">
<path fill="currentColor" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z" transform="translate(-256 -256)">
</path>
</g>
</g>
</svg>
<!-- <i class="fas fa-question-circle" data-fa-transform="grow-6"></i> -->
<span>Use this button to show/hide the calipers.<br>When the calipers are shown:<br>- Click and hold the caliper lines to drag them.<br>- Click and hold the caliper measurement to drag both calipers together.
</span>
</span>
<span id="tooltip" class="tooltip">
<svg class="svg-inline--fa fa-question-circle fa-w-16" data-fa-transform="grow-6" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="question-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg="" style="transform-origin: 0.5em 0.5em;">
<g transform="translate(256 256)">
<g transform="translate(0, 0) scale(1.375, 1.375) rotate(0 0 0)">
<path fill="currentColor" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z" transform="translate(-256 -256)">
</path>
</g>
</g>
</svg>
<!-- <i class="fas fa-question-circle" data-fa-transform="grow-6"></i> -->
<span>Use this button to show/hide the calipers.<br>When the calipers are shown:<br>- Click and hold the caliper lines to drag them.<br>- Click and hold the caliper measurement to drag both calipers together.
</span>
</span>
** Please find attached code snippet.
Unable to retrieve tooltip message when moving mouse to element.
what is happening , at few instance tooltip is displayed but it is getting disappeared within fraction of seconds so text is not getting retrieved.
Various options tried out :
1.
Actions action = new Actions(driver);<br/>
action.MoveToElement(ElementHandler.FindElement(By.XPath("(//*[name()='svg' and #class='svg-inline--fa fa-question-circle fa-w-16']")));<br/>
Thread.Sleep(2000);<br/>
action.Perform();<br/>
action.MoveByOffset(1, 1).Build().Perform();
Actions action = new Actions(driver);<br/>
action.MoveToElement(ElementHandler.FindElement(By.XPath("//span[#id='tooltip']")).Perform();<br/>
string theTextIWant = (string)((IJavaScriptExecutor)driver).ExecuteScript("return arguments[0].value;", driver.FindElement(By.Xpath("//span[#id='tooltip']//span")));
** Span tag text of tooltip is fetched only on hovering.
None of the options are working.
The main challenge is tooltip is disappearing within seconds, hence unable to get text. Other than ClickAndHold method if any other solution is provided will be really helpful.
Will be really gratefully if any solution/approach is provided.
You can try to get the text from the tooltip asap it's displayed
Actions action = new Actions(driver);
action.MoveToElement(ElementHandler.FindElement(By.XPath("//span[#id='tooltip']")).Perform();
WebElement toolTip = driver.findElement(By.xpath("//*[#id="tooltip"]"));
String toolTipText = toolTip.getText();
System.out.println("toolTipText-->"+toolTipText);

SVG path arc elements not working

I am trying to draw a donut with an SVG path. I do this by drawing two arcs and a line. The first arc is the outer circle. It works fine until the radius is high. When the outer circle radius decreases, the doughnut does not appear.
<svg height="400" width="400">
<path d="M 200 143 A 57 57 0 1 1 199.99994299999997 143 L 199.9999772 177.2000000000114 A 22.8 22.8 1 1 0 200 177.2 z" fill="transparent" stroke="blue" />
</svg>
The following screen shot shows the original image.
My code is in this jsfiddle.
The problem is that you're only closing the second arc. You should close the first arc before you draw the second arc.
Demonstration:
<svg height="400" width="400">
<path d="M 200 143 A 57 57 0 1 1 199 143 z M 199.9999772 177.2000000000114 A 22.8 22.8 1 1 0 200 177.2 z" fill="transparent" stroke="blue" />
</svg>
I'm not 100% sure what you are intending to draw, but one issue that comes up with SVG and arcs is that when you try to draw a complete circle, you will end up with beginning and ending points coinciding, which for the rendering engine will mean that the path segment is a null op (yeah weird) and will not be rendered. To get around this, use 2 Arcs.
<!DOCTYPE html>
<html>
<body>
<svg height="400" width="400">
<path d="M 200 143 A 57 57 0 1 1 200 257 A 57 57 0 1 1 200 143Z L 200 177 A 22.8 22.8 0 1 0 200 222.6 A 22.8 22.8 0 1 0 200 177 z" fill="transparent" stroke="blue" />
</svg>
</body>
</html>
Also your inner circle had a small (1 degree) tilt (3rd parameter) in it which I assume was unintentional. And if you don't want that vertical line, replace the L with an M.

Categories

Resources