OpenUI5 after closing dialog fragment controls disappear - svg

I´m pretty new to UI5 and I don´t understand why my controls disappear. But let me explain the problem step-by-step
I have created a view, a corresponding controller and a custom graphic control using D3.
The troubling part of the view looks like that:
<Page ...>
<!-- some FlexBoxes here... -->
<html:div style="clear:both; overflow-x:hidden; overflow-y:hidden; height: 94%;" class="sapUiNoMargin">
<html:div id="graphs" style="background-color:white; border: 1px solid lightgray; height:89%; width:100%;" >
<core:HTML id="htmlCanvasWrapper" content="<svg id='htmlCanvas' height='65%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas2Wrapper" content="<svg id='htmlCanvas2' height='23%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas3Wrapper" content="<svg id='htmlCanvas3' height='12%'></svg>"></core:HTML>
</html:div>
<!-- the closing elements follow here... -->
If someone wonders what I try to do above: the svg-elements are holding my graphics and the surrounding 'core:HTML' element is used for showing/hiding the charts via jquery (not everyone is allowed to see everything. In addition the 3 graphics should use the full remaining space on the page (the graphics are scaling) that is not used by the filter (FlexBoxes above), by the header and the footer.
Until now everything works as expected. That means the graphics are drawn and everything looks alright so far.
Now I want to show a legend for the graphics (which color means what and so on). That I have accomplished by showing a dialog from a fragment
Dialog definition:
<core:FragmentDefinition xmlns="sap.m" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:core="sap.ui.core">
<Dialog title="{i18n>VollePfanneLegende.Title}">
<html:style>
<!-- style definitions for the legend -->
</html:style>
<l:VerticalLayout>
<l:content>
<FlexBox>
<html:div class="icon" style="background-color: #68ACE9; border-color: #68ACE9; border-radius: 50%;"/>
<html:div class="hspacer"/>
<Text text="{i18n>VollePfanneLegende.IstTemp}"/>
</FlexBox>
<html:div class="vspacer"/>
<FlexBox>
<html:div class="icon" style="background-color: #F70206; border-color: #F70206; border-radius: 50%;"/>
<html:div class="hspacer"/>
<Text text="{i18n>VollePfanneLegende.SollTemp}"/>
</FlexBox>
<!-- ... -->
In the footer is a button to show the dialog (fragment) which also works as it should (the graphics are still shown in the background), BUT: when I close the dialog the dialogs are only visible for some fractions of a second and then they disappear! When select the now empty space with the debugger it shows that the div with the id "graphs" is empty!
<div id="__xmlview1--graphs" style="border: 1px solid lightgray; border-image: none; width: 100%; height: 89%; background-color: white;"></div>
But now I find a new div AFTER the content div that holds my graphics
<div class="sapUiHidden sapUiForcedHidden" id="sap-ui-preserve" aria-hidden="true" style="width: 0px; height: 0px; overflow: hidden;">
<svg id="htmlCanvas" height="65%" data-sap-ui-preserve="__xmlview1--htmlCanvasWrapper>...</svg>
<svg id="htmlCanvas2" height="23%" data-sap-ui-preserve="__xmlview1--htmlCanvas2Wrapper>...</svg>
<svg id="htmlCanvas3" height="12%" data-sap-ui-preserve="__xmlview1--htmlCanvas3Wrapper>...</svg>
</div>
EDIT1: Code for opening/closing the dialog fragment.
The "onShowLegend" function shows the dialog, the "legendClose" function is called when you click the close button on the dialog.
onShowLegend: function() {
if (! this._oLegendDialog) {
this._oLegendDialog = sap.ui.xmlfragment("portal.view.vollePfanneLegende", this);
}
// toggle compact style
this.getView().addDependent(this._oLegendDialog);
jQuery.sap.syncStyleClass("sapUiSizeCompact", this.getView(), this._oLegendDialog);
this._oLegendDialog.open();
},
legendClose: function() {
if (this._oLegendDialog) {
this._oLegendDialog.destroy();
}
this._oLegendDialog=null;
}
I don´t have a clue how to prevent UI5 to hide my graphics. Please help. Thanks in advance
EDIT 2: if I wrap the "core:HTML" elements e.g. in a VerticalLayout the graphics are not removed after closing the dialog. BUT: The height of VerticalLayout can´t be set. I need something that uses the full height of the unused page, because the graphics are scaling depending on their parent control height.
<html:div id="graphs" style="background-color:white; border: 1px solid lightgray; height:89%; width:100%;" >
<l:VerticalLayout width="100%">
<l:content>
<core:HTML id="htmlCanvasWrapper" content="<svg id='htmlCanvas' height='65%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas2Wrapper" content="<svg id='htmlCanvas2' height='23%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas3Wrapper" content="<svg id='htmlCanvas3' height='12%'></svg>"></core:HTML>
</l:content>
</l:VerticalLayout>
</html:div>
Best regards
Jochen

After some hours of trial and error and a lot of Internet surfing I have come up with the following code that does exactly what I want
<html:div style="clear:both; overflow-x:hidden; overflow-y:hidden; height: 94%;" class="sapUiNoMargin">
<html:style>
.graphs {
background-color:white;
border: 1px solid lightgray;
width:100%;
height: calc(100% - 85px); /* Height of RangeSlider area */
}
.sapMScrollContScroll {
height: 100%;
}
</html:style>
<html:div id="graphs" class="graphs">
<ScrollContainer width="100%" height="100%" focusable="false" horizontal="false">
<core:HTML id="htmlCanvasWrapper" content="<svg id='htmlCanvas' height='65%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas2Wrapper" content="<svg id='htmlCanvas2' height='23%'></svg>"></core:HTML>
<core:HTML id="htmlCanvas3Wrapper" content="<svg id='htmlCanvas3' height='12%'></svg>"></core:HTML>
</ScrollContainer>
</html:div>
<!-- Rest of the view here... -->
</html:div>
As I understand the solution the wrapping in a UI5 container makes sure that the redraw event after closing the dialog has a control that can handle it.

Related

Responsive inline svg?

This SVG icon is 640x640px. The toolbar is 48px high.
The icon should now automatically adjust to the height of the toolbar.
Accordingly, the blue area would have to be 48x48px.
However, the icon now occupies much more space than it needs.
I gave the svg a height of 48px. Better would be height: 100% but that does not work.
my codepen
Changing only the height to 48px leaves the width at 640px. Because you have width="640px" specified on your <SVG>.
So the fix is simply to remove the width and height attributes from <svg>.
body {
margin: 5%;
}
.toolbar {
position: realive;
color: #fff;
display: flex;
align-items:center;
justify-content: space-between;
background: red;
height: 48px;
}
.toolbar__section.flex-grow {
flex-grow: 1;
}
.toolbar__section.bg-green {
background: green;
}
svg {
display: flex;
height: 48px;
background: blue;
}
<p><strong>Responsive inline svg?</strong></p>
<p>
This SVG icon is 640x640px. The toolbar is 48px high.
The icon should now automatically adjust to the height of the toolbar.
Accordingly, the blue area would have to be 48x48px.
However, the icon now occupies much more space than it needs.
I gave the svg a height of 48px. Better would be "height: 100%" but that does not work.
</p>
<div class="toolbar">
<div class="toolbar__section bg-green flex-grow">
Logo
</div>
<div class="toolbar__section">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" preserveAspectRatio="xMinYMin meet">
<title></title>
<g id="icomoon-ignore">
</g>
<path fill="#000" d="M603.794 613.188l-190.189-207.478c42.858-44.846 66.395-103.468 66.395-165.71 0-64.106-24.964-124.375-70.294-169.706s-105.6-70.294-169.706-70.294-124.375 24.964-169.706 70.294-70.294 105.6-70.294 169.706 24.964 124.376 70.294 169.706 105.6 70.294 169.706 70.294c55.226 0 107.595-18.542 150.027-52.655l190.178 207.467c3.156 3.442 7.471 5.188 11.799 5.188 3.862 0 7.736-1.391 10.808-4.205 6.513-5.972 6.954-16.093 0.982-22.607zM32 240c0-114.691 93.309-208 208-208s208 93.309 208 208-93.309 208-208 208-208-93.309-208-208z"></path>
</svg>
</div>
<div class="toolbar__section bg-green">
Login Icon
</div>
</div>
Delete the width attribute from the svg element. You may have to adjust the flex-grow attributes in your toolbar afterwards.
See it live on CodePen.
Tested on Chrome 63.0.3239.132

Horizontal align text below flex-items

Image captions are aligned bottom by flexbox within a gallery where images have different heights. How can I achieve that first lines of text (titles) are aligned horizontally?
<style type="text/css">
* {
box-sizing: border-box; }
.flex-container {
display: flex;
flex-wrap: wrap; }
.flex-item {
width: 50%;
padding: 20px;
display: flex;
flex-direction: column; }
.flex-item img {
width: 100%;
height: auto; }
.flex-image {
flex: 1 0 auto; }
</style>
<div class="flex-container">
<div class="flex-item">
<div class="flex-image">
<img src="img-1.jpg" alt="" />
</div>
<p>title</p>
</div>
<div class="flex-item">
<div class="flex-image">
<img src="img-2.jpg" alt="" />
</div>
<p>title<br>Lorem ipsum dolor sit amet.</p>
</div>
</div>
Please check my codepen: https://codepen.io/tinusmile/pen/MoeORG
Many thanks!
With the existing markup, where the images can have different heights, you need to do something like this, where you give the p a height.
As an element's overflow defaults to visible, it will flow out of its boundaries, so I recommend to set the height so it can accommodate 2-3 lines of text.
On smaller screens you might need to add a #media query to adjust that height, as if the text is very long it might overflow any element below itself.
.flex-item p {
height: 50px; }
Updated codepen
Note, using min-height instead would solve the might overflow any element below itself issue, though it will make the first line to not align horizontally if the value does not accommodate all the possible amount of lines.
Another option is to remove the flex-item wrapper and use Flexbox's order property, as I suggested in a previous question of yours, align-horizontally-3-elements-over-3-divs

Vertical align a button in an absolute positioned div

Usually I vertically center a button, inside an absolute positioned div with top:50%, and margin-left:-(height/2), but today I realised it's not perfect, or I don't know how to use it correctly.
For example I did 2 examples. In the first example the <a> tag is an inline element, in the second example it's a block element. The positioning with block element is perfect, but unfortunately the width is 100%.
Please explain that why is the second example works well, with display:block;?
I'm really interested in your cross browser solution. How do you do this simple stuff?
Here is my css:
.container {
height:240px;
position:relative;
}
.box {
width:200px;
height:100%;
position:absolute;
left:0;
top:0;
background:yellow;
text-align:center;
padding:20px;
}
#example2 { left: 250px; }
.btn {
display:inline-block;
padding:5px 12px;
line-height:34px;
color:#fff;
background:red;
position:relative;
top:50%;
margin-top:-17px;
}
#example2 .btn { display:block; }
..and html
<div class="container">
<div id="example1" class="box">
button
</div>
<div id="example2" class="box">
button
</div>
</div>
The online version is available at http://jsfiddle.net/79hqgabq/2/
The alignment issue you see is being caused by the margin-top: -17px line as seen by this updated fiddle with that line removed on the .btn class: Updated Demo
On another note, vertical alignment is notoriously problematic with old CSS selectors, and it would be a good idea to transition over to Flexbox unless you needed to support older browsers.
Here's your problem with the new display: flex selector and corresponding sub-selectors: Demo w/ Flexbox. This removes the emphasis on having to pixel fudge to get proper vertical alignment.
New .box class
.box {
width:200px;
height:100%;
position:absolute;
left:0;
top:0;
background:yellow;
text-align:center;
padding:20px;
/* New lines for alignment */
display: flex;
align-items: center;
justify-content: center;
}
New .btn class (just removed the old tags)
.btn {
display:inline-block;
padding:5px 12px;
line-height:34px;
color:#fff;
background:red;
}
EDIT: After researching block elements have the property to expand to 100% of the parent container. This can be explained in more detail here. This is why display:block div expands until it reaches the padding on the .box class.
To answer why the display: inline-block element is slightly misaligned is because by default it is aligned on the baseline. See here for reference. Changing the vertical alignment of the div to be vertical-align: top will fix this.
Here is the new fiddle that uses all your previous syntax just with the added vertical-align: middle property.

Show scrollbars if SVG elements overflows their container

I have an embedded SVG with dynamic content inside, which may grow in all directions.
This content may be grow bigger than the fix sized container around.
My expected behavoir is, to show scrollbars, if any element inside the SVG needs more place than the container provides.
See the following simplified example:
<html>
<head>
</head>
<body>
<div style="overflow: auto; position: absolute; top: 60px; left: 60px; background-color: gray; height: 200px; width: 300px;">
<svg style="height: 190px;">
<rect x="-50" y="0" width="100" height="50" fill="red"></rect>
</svg>
</div>
</body>
</html>
What is the way to do this?
Is it really true, there is no concept in SVG to support such behavoir?
Any suggestions how to do it right "by hand"?
Svg does'nt support auto resizing to inside elements of itself.
So, you should resize manually the svg graphic to be able to scroll by outer svg element.
var svg = document.querySelector("svg");
var bbox = svg.getBBox();
svg.setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height]);
svg.width.baseVal.valueAsString = bbox.width;
svg.height.baseVal.valueAsString = bbox.height;

CSS: issue with background color

I want to make the header and footer backgrounds to be repeated on x. So it takes all the width size of any page resolution.
This is how I want it to look like:
An this how is being displayed:
I'm using the 960 gs, every div is limited to 960px. Is there a way to expand the color of the div through x?
See the project here:
http://gabrielmeono.com/yonature/
yes there is
you have to split the page into 3 parts: header, body, footer
what we're gonna do is create divs with a little bit of CSS. we will have a div that goes all the way to the sides of the website, and a div which is centered.
i'll show you how to do it for the header, and you make the same thing for body/footer:
<html>
<head>
<style type="text/css">
html{}
body { margin: 0px; width: 100%; }
#headerCenter { float: left; width: 100%; text-align: center; color: #00AA00; height: 120px; }
#headerContainer { margin: 0 auto; width: 960px; }
#header { width: 100%; float: left; height: 120px; }
</style>
</head>
<body>
<div id="headerCenter">
<div id="headerContainer">
<div id="header">HEADER</div>
</div>
</div>
.. same for body/footer....
</body>
</html>
so the trick is:
a div (#headerCenter) which goes all the way across the page. we will define height for it, paint it's background, and set 'text-align: center;'
inside we put a div with 'margin: 0 auto;' and the desired width. NO FLOAT on this div! this will create a div with height 0, placed in the center of the parent div.
inside we put the header. we can set float left etc... width can be 100% (or 960px)
repeat this for body and for footer
another method btw is using HTML tables, which i don't like to use for layouts.
if you have any trouble setting this up, let me know and i'll do the layout for you

Resources