Clicking on stroke of dynamic path using Selenium - selenium

In SVG you can have things which are only clickable at the stroke, e.g. because there is no fill or because of pointer-events: stroke.
Example:
document.querySelector("#path1").addEventListener("click", function(e) {
console.log("Click1!")
})
document.querySelector("#path2").addEventListener("click", function(e) {
console.log("Click2!")
})
#path1:hover {
stroke: red;
}
#path2:hover {
stroke: green;
}
<svg height="300" width="300">
<path d="M64,116 C100,100 400,100 96,39" stroke="blue" stroke-width="7" fill="none" id="path1" />
<path d="M134,186 C100,100 400,100 126,69" stroke="blue" stroke-width="7" fill="none" id="path2" />
</svg>
In my project I want to write Selenium tests for I have a dynamically generated SVG <path>s which I want to click at using Selenium, the problem is that the center of the element1 is not necessarily clickable (since only the stroke of the path is).
Some ideas I had:
Clicking at a fixed offset: A possibility but since the generated path is highly dynamic it would mean a lot of tinkering with the offset value to get it right and possibly having to change the test a lot of the future.
Triggering click event through code: Would work but make the test less useful since this way it would not test whether the stroke of the path is indeed clickable. Certain bugs could evade being detected by the test this way.
Setting a non-none fill through code or replacing/adding filled a rect around the <path>: Setting fill might not guarantee either that the center is clickable. A <rect> would work but then the clickable areas of multiple paths would overlap which could mean that the wrong path gets the click.
None of these approaches are ideal. Are there any other possibilities?
(I am using Selenium for Python but I am OK with solutions with Selenium for other programming languages since normally it's easy to port.)
1) This is the default position Selenium clicks at if using the function where no offset is specified, or rather it's the center of the visible area of the element since the newest version of the WebDriver protocol but in my use case everything can be assumed to be fully visible.
P.S.
Demo showing why setting fill to something other than none wouldn't help (or pointer-events to all):
document.querySelector("#path1").addEventListener("click", function(e) {
console.log("Click1!")
})
document.querySelector("#path2").addEventListener("click", function(e) {
console.log("Click2!")
})
#path1:hover {
stroke: red;
}
#path2:hover {
stroke: green;
}
<svg height="300" width="300">
<path d="M64,116 C100,100 400,100 96,39" stroke="blue" stroke-width="7" fill="turquoise" id="path1" />
<path d="M134,186 C100,100 400,100 126,69" stroke="blue" stroke-width="7" fill="yellow" id="path2" />
</svg>

Related

Some areas inside the Vuetify Dialog box don't close it even if there is no content there

See this image here of my custom Lightbox component.
One should be able to simply exit the component and go back to the page by clicking on anywhere outside the image or the v-sheet component on the right (which by the way, is supposed to be touching the image, but I can't figure out how to move it without using margin).
Unfortunately, the red boxes exist - they are areas where clicking should close the dialog, but don't. This is because the entire Dialog component is the green box - it believes even those red boxed areas are part of the component.
I've been attempting to use #click and v-click-outside directives where possible to try and exclude the image and the sheet component can be clicked but everything else closes the dialog, but unfortunately I only get strange behaviors that donn't help at all.
Also, I found out using margin: auto will create another unclickable area, so I need to find out another way to move it over.
Source Code
Problem 1:
"is supposed to be touching the image, but I can't figure out how to move it without using margin"
Instead of lg="10" on the first col, you can use lg="auto" so it will shrink to fit its contents.
justify="center"
class="fill-height"
>
<v-col
- lg="10"
+ lg="auto"
md="12"
offset-lg="0"
class="fill-height text-right"
>
Problem 2:
"areas where clicking should close the dialog, but don't"
You can use pointer-events: none on the dialog body to disable click event capturing, then pointer-events: auto on specific elements to selectively enable it.
<v-col
lg="2"
md="4"
align-self="top"
- #click="dialog = false"
>
<v-sheet
class="rounded-tr-lg text-left"
...
- <style lang="scss">
- .v-dialog {
+ <style lang="scss" scoped>
+ ::v-deep .v-dialog {
margin: 0;
padding-left: 24px;
padding-right: 24px;
box-shadow: none !important;
+ pointer-events: none;
+ }
+ .v-image,
+ .v-btn,
+ .v-sheet {
+ pointer-events: auto;
}
</style>
Option 1: Use flexbox and #click function to close whatever
Basically, if you get your css to do a similar layout, but fill those red boxes with a background: blue you in turn can put an #click on that same div, which will close whatever you need.
Option 2: Use Modals
I would use a parent component that communicates to an "image component" and "image details component" (such that the two components are siblings.
Moreover, I would personally use v--modal for both of these sibling components, and have the closed event tied to a single instance of closing both modals by names
The shiftX and shiftY should be enough for placement.
https://www.npmjs.com/package/vue-js-modal

Does CanvasDrawingSession.DrawSvg() work in C++/winrt?

I've loaded a series of svg images by creating and storing a CanvasSvgDocument for each, and using its LoadAsync() method to load the svg:
nextSvg = CanvasSvgDocument(resourceCreator.Device());
auto fileStream = co_await nextFile.OpenReadAsync();
co_await nextSvg.LoadAsync(resourceCreator.Device(),fileStream);
This appears to load the svg, but when I use that stored svg in a drawing session nothing appears in the CanvasControl. Other items draw fine: shapes, lines, etc. - just not svgs:
session.DrawSvg(m_svg, boxSize, top, left);
In an attempt to discover the problem I've tried using GetXml() on the svg document in the hope that would show me its contents. The result is an abbreviated svg with no drawing information. I provide that here in case it's a hint:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>
Perhaps that is all that GetXml() is supposed to return?
I have successfully drawn svgs if they loaded as imagesources; the resulting bitmap image works. But is it possible that session.DrawSvg() is just not completely implemented yet in Win2D? I'd rather render the svg directly this way if it can be done.
[Update] p.s. The svgs are version 1.1 svgs converted from pdfs by one of the online conversion services. As I mentioned, they render fine if opened in Edge or other browsers.
[Update2] Thinking perhaps there is something in the svgs that Win2D doesn't like, I tried creating a simple one using as a model an online example - it just has a rectangle and a circle, as follows. But it also does not draw:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 140"
preserveAspectRatio="xMidYMid meet">
<title>Scalable Vector Graphics (SVG) Demo</title>
<circle cx="100" cy="100" r="50" stroke="#000" stroke-width="1" fill="#ccc" />
<rect x="200" y="50" width="250" height="100" rx="5" ry="5"
stroke="#000" stroke-width="1" fill="#ccc" />
</svg>
[Update] It appears that the problem lies in the way the svg is read from the Storage File. I'll post my own answer as soon as I have enough that it might be useful to someone.
The answer is that my code contains an egregious error: As was pointed out to me at GitHub, LoadAsync() is a static method. In my first line above, I create a CanvasSvgDocument, but in the third line I ignore the results of LoadAsync. LoadASync is also a constructor, so the proper code is
auto fileStream = co_await nextFile.OpenReadAsync();
nextSvg = co_await CanvasSvgDocument::LoadAsync(resourceCreator.Device(),fileStream);
That works! Only trouble is that what I really want is to use LoadFromXaml(), another static method, and there is a different issue with that to be addressed later. Probably also my error.

Relative positioning of custom controls with OpenLayers 3

A map that I am building with OpenLayers 3 has some buttons, which may or may not be available depending on some other things. So I want to keep the unavailable buttons hidden, and others will use their space. The available options can change, so sometimes a button may become (in)visible.
There are some tutorials for creating custom controls with OpenLayers 3. The problem is that all samples I have seen use absolute positioning for the controls. One needs to know how many controls will be visible, and hard-code the coordinates in CSS. Or change the coordinates using Javascript. I.e., from the above link:
.rotate-north {
top: 65px;
left: .5em;
}
I have tried just setting the element with position:relative, but then they appear below the map, as the controls are added to the page after the map. So, one could use relative positioning with negative coordinates, but then if the map changes size you have to rewrite the coordinates in Javascript.
.ol-control.left-top {
position: relative;
top: -400px; /*map height*/
}
Is there a way to elegantly implement relative-positioned custom controls with OpenLayers 3, ideally with only CSS?
I guess I am trying to get a similar functionality as in the Google Maps API:
map.controls[google.maps.ControlPosition.LEFT_TOP].push(controlDiv);
Though it is not a good solution for my use case, since it is not supported by Android 4.3 and earlier, one could use CSS calc as suggested by #Jonatas:
html:
<div class="parent">
<div class="map"></div>
<div class="control"><button>CONTROL</button></div>
</div>
css:
.map {
width: 100%;
height: calc(100vh - 2em);
background-color: green;
}
.control {
position: relative;
left: .5em;
top: calc(-100vh + 2em + .5em);
}
This would probably have to use viewport units (also not supported by Android 4.3 and earlier), as calc can only calculate values based on the parent element.
jsfiddle: https://jsfiddle.net/adlerhn/zjt53nmf/

Safari a:hover changing sibling in fixed element

I am making a simple fixed SoMe sharing button set for a blog. Everything is fine and dandy except in Safari. Hovering over one of the buttons changes the background-color of the siblings to a color I do not specify anywhere in my CSS. This behavior goes away as soon as I change the wrapper from fixed to relative/static/absolute.
Has anyone ever run into this?
Am I doing something wrong?
If not, is there a hack/fix/workaround?
HTML:
<div id="share-links">
<a class="share-twitter" href="#">a</a>
<a class="share-facebook"href="#">a</a>
<a class="share-linkedin" href="#">a</a>
</div>
CSS:
#share-links{
left:0;
top:5em;
position:fixed;
}
#share-links a{
display:block;
height:2em;
width:2em;
color:white;
background-color:#a16159;
}
#share-links a:hover{
background-color:#8a392e;
}
Fiddle: https://jsfiddle.net/u6vzq192/26/
I discovered this problem in a slightly different situation. I have pagination dots in a fixed div using links like you have set up. I am adding a class to the links with Javascript which in turn changes the background color. Every time this happens the background colors of all the other links go crazy. I believe that it is a rendering bug in Safari inverting the background of the links when one changes.
After much experimentation with your example I discovered that it stops if either the links themselves are much larger or the container is much larger. Since setting the links to be giant buttons affects design, it seems the best solution is to set the container to be larger. Since your example is a vertical set of links you would set the height of the container to be something much larger than the links. I used height: 100%; but a large px should work too. If you had links laid out horizontally you might need to make that width: 100%; instead.
CSS:
#share-links{
left:0;
top:5em;
position:fixed;
height: 100%;
}
#share-links a{
display:block;
height:2em;
width:2em;
color:white;
background-color:#a16159;
}
#share-links a:hover{
background-color:#8a392e;
}
I encountered a similar problem. As well as being fixed, one of the inside elements had transform:rotate 90 deg and had a hover effect that changed its position slightly (pulled out from the side of the screen). The background color of this element and its sibling were the same, and both would flicker randomly when elements on the page were changed / rendered.
I finally found a combination of styles that stopped the background colour flickering altogether.
I added the following to the parent element from here: https://stackoverflow.com/a/27863860/6260201
-webkit-transform:translate3d(0,0,0);
-webkit-transform-style: preserve-3d;
That stopped the flickering of the transformed/sliding element.
And I added the following to the remaining element from here: https://stackoverflow.com/a/19817217/6260201
-webkit-backface-visibility: hidden;
This then stopped the flickering of the background colour for the sibling element.

Sencha Touch 2 RC: show() not working on Ext.Container with card layout

I've just upgraded from ST 2 Beta 3 to the Release Candidate that came out yesterday. I have a menu bar with buttons, so that when you tap them, a new card will be shown - just like a tabpanel. It worked before the upgrade, but now nothing is shown. It's like the show() method doesn't work any longer. If I look at the source code (inspect element in Chrome) i see that there is a class called x-item-hidden on the div and it has the inline style display: none; ... like this:
<div class="x-container x-panel x-item-hidden x-fullscreen" id="ext-panel-1" style="display: none !important; height: 100% !important; width: 100% !important; ">
When I remove "display: none !important;" the content is shown.
Has anyone seen this problem and how do i solve it?
Edit:
Sorry for not adding code, but didn't know which parts to add. However I've now narrowed the problem a bit down.
In my controller I have:
config: {
refs: {
calendarPanel: '#idCalendar',
...
}
Then I call this member function to hide its content:
hidePanels : function(){
this.getCalendarPanel().hide();
...
},
The this.getCalendarPanel().hide(); hides the panel as it's supposed to, but subsequent calls to this.getCalendarPanel().show(); does not show the panel again as it did in the last versions of ST2.