How to create an SVG "tooltip"-like box? - popup

Given an existing valid SVG document, what's the best way to create "informational popups", so that when you hover or click on certain elements (let's say ) you popup a box with an arbitrary amount (i.e. not just a single line tooltip) of extra information?
This should display correctly at least in Firefox and be invisible if the image was rasterized to a bitmap format.

This question was asked in 2008. SVG has improved rapidly in the intervening four years. Now tooltips are fully supported in all platforms I'm aware of. Use a <title> tag (not an attribute) and you will get a native tooltip.
Here are the docs:
https://developer.mozilla.org/en-US/docs/SVG/Element/title

<svg>
<text id="thingyouhoverover" x="50" y="35" font-size="14">Mouse over me!</text>
<text id="thepopup" x="250" y="100" font-size="30" fill="black" visibility="hidden">Change me
<set attributeName="visibility" from="hidden" to="visible" begin="thingyouhoverover.mouseover" end="thingyouhoverover.mouseout"/>
</text>
</svg>
Further explanation can be found here.

Since the <set> element doesn't work with Firefox 3, I think you have to use ECMAScript.
If you add the following script element into your SVG:
<script type="text/ecmascript"> <![CDATA[
function init(evt) {
if ( window.svgDocument == null ) {
// Define SGV
svgDocument = evt.target.ownerDocument;
}
tooltip = svgDocument.getElementById('tooltip');
}
function ShowTooltip(evt) {
// Put tooltip in the right position, change the text and make it visible
tooltip.setAttributeNS(null,"x",evt.clientX+10);
tooltip.setAttributeNS(null,"y",evt.clientY+30);
tooltip.firstChild.data = evt.target.getAttributeNS(null,"mouseovertext");
tooltip.setAttributeNS(null,"visibility","visible");
}
function HideTooltip(evt) {
tooltip.setAttributeNS(null,"visibility","hidden");
}
]]></script>
You need to add onload="init(evt)" into the SVG element to call the init() function.
Then, to the end of the SVG, add the tooltip text:
<text id="tooltip" x="0" y="0" visibility="hidden">Tooltip</text>
Finally, to each of the element that you want to have the mouseover function add:
onmousemove="ShowTooltip(evt)"
onmouseout="HideTooltip(evt)"
mouseovertext="Whatever text you want to show"
I've written a more detailed explanation with improved functionality at http://www.petercollingridge.co.uk/interactive-svg-components/tooltip
I haven't yet included multi-line tooltips, which would require multiple <tspan> elements and manual word wrapping.

This should work:
nodeEnter.append("svg:element")
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; })
.append("svg:title")
.text(function(d) {return d.Name+"\n"+d.Age+"\n"+d.Dept;}); // It shows the tool tip box with item [Name,Age,Dept] and upend to the svg dynamicaly

Related

sap.ui.table.Table inside of Scroll Container: visibleRowCountMode=“Auto” not working

This is a follow-up question to this question. Basically, I have the same problem as described there where the table does not have as many rows as possible, there is more space there but it is unused.
I got it working for my table with the help of the answers in the last question. Now I had to adda horizontal Scroll-Container (the height is fixed) arround this table. Then the problem came up again.
I built a demo version with which you can see the problem and try arround with here.
The wanted result is just like as if you removed the ScrollContainer, then the table fills the entire page.
The same problem occurs when using this table inside of an IconTabBar but I was able to find an ugly work-around which does not work here. After the table was rendered I added the style height: 100% manually to the html-parents of the table (these are generated divs of the IconTabBar). This enabled the Table to receive the full height from its parents. With the ScrollContainer this tactic does not seem to work.
You can fix it like this:
onInit: function () {
this.oTable = this.byId("TableID");
this.oTable.onAfterRendering = function () {
const table = this.getTable();
const aColumns = table.getColumns();
for (let i = 0; i < aColumns.length; i++) {
aColumns[i].setProperty("width", "auto");
}
this.setHeight("100%");
};
}
And you may try these properties:
flexible: true/false,
resizable: true/false,
autoResizable: true/false,
width : "auto"
Please have a look at the restrictions of visibleRowCountMode="Auto"
https://ui5.sap.com/#/api/sap.ui.table.Table%23methods/getVisibleRowCountMode
See here the the layoutData definition for the HBox so that it gains the height from its parent
<layoutData>
<FlexItemData growFactor="1" />
</layoutData>
and also height: 100% style for the ScrollContainer's inner element which also let the table know the height of its container.

Get value from checkbox in SapUI5

I have a main.controller.js where I want to check the value of a Checkbox. If the checkbox has been checked, the first flexbox will be shown and the second flexbox will not be shown in the fragment.
This my controller.js:
checkDone: function () {
var checkV = this.byId("ch1").getSelected();// not working
}
This my fragment.xml
<CheckBox id="ch1" select ="checkDone" text="Check"></CheckBox>
<FlexBox class="sapUiSmallMarginEnd" id="f1">
<Input value=""></Input>
</FlexBox>
<FlexBox direction="Column" id="f2">
<Input value=""></Input>
</FlexBox>
This code works (see example with sap.m.Checkbox here).
Just a recommendation: in your checkbox's 'select' handler you use:
this.byId("ch1").getSelected();
in order to whether the checkbox is selected or not, but this value is already given as a parameter of the select handler:
checkDone: function (oEvent) {
var bSelected = oEvent.getParameter('selected'));
}
Simmilar is for the sap.ui.commons.Checkbox API. Check change event.
It looks like the View.byId function returns an element in its initial form. When you find element from DOM, getSelected() function works as expected.
Instead of getSelected() try getChecked().
getChecked() will return true or false based on checked/unchecked.

UI5 MessageBox remain transparent

I have a message box that I want to do some extra editing on a line. But once I show it, it remains transparent. Is there something that I'm missing to give it a normal background.
The fragment for the form:
<Label text="UnitPrice"/>
<Input id='unitpriceid' type="Text" text="{path: 'UnitPrice' }"/>
<Label text="Quantity"/>
<Input type="Text" text="{path: 'Quantity' }"/>
</form:SimpleForm>
</core:FragmentDefinition>
How I call the fragment.
handleLineItemPress : function (evt) {
var context = evt.getSource().getBindingContext();
var oLayout = sap.ui.xmlfragment("ApproveSESComponent.DO_SES.view.LinePopup", this);
var oModelTemp = this.getView().getModel().getData();
// get the view and add the layout as a dependent. Since the layout is being put
// into an aggregation any possible binding will be 'forwarded' to the layout.
var oView = this.getView();
oView.addDependent(oLayout);
var that = this;
sap.m.MessageBox.show(oLayout, {
icon: sap.m.MessageBox.Icon.INFORMATION,
title: "My message box title",
styleClass: "sapUiSizeCompact",
actions: [sap.m.MessageBox.Action.YES, sap.m.MessageBox.Action.NO],
onClose: function(oAction) { / * do something * / }
});}
I change the styleClass: "sapUiSizeCompact" to soemthing else and then added a background-color to this style.
Then the box was no longer transperant.
I don't think sap.m.MessageBox is designed for input other than simple button-based choices. Certainly that's how I read the documentation (and that's how message boxes typically work in other APIs):
Provides easier methods to create sap.m.Dialog with type sap.m.DialogType.Message, such as standard alerts, confirmation dialogs, or arbitrary message dialogs.
You may be able to shoehorn it into allowing you to add an input field but I don't think that's how it's designed (it looks undocumented to me) and don't be surprised if it breaks in a future release. Rather use sap.m.Dialog.
Same problem here...
Solution: I used the sap.m.MessageBox in a project based on sap.ui.common elements. Replaced it with sap.ui.common.MessageBox and I had a well working Message Box.

p:barChart y axis format

I use primefaces 4.0 barchart, but i want to modify some default proprieties. This is my xhtml page
<p:barChart id="chart" value="#{marchebean.model}" legendPosition="ne" xaxisLabel="Année" yaxisLabel="Montant en DT" title="Factures payés par années" />
What i want to do
1.I want to separate between hundreds , thousands and millions in y axis by a space i.e changing the format of my numbers , i use NumberFormat.getNumberInstance(Locale.FRANCE).format(mynumber); in java but i don't know how to achieve this with charts in primefaces.
I want to display on the top of every bar the value setted in backing bean and change it's size.
Edit
Separation between thousand done, but i still don't know how display values above every bar or change their size. this is my new code
<p:barChart id="chart" value="#{marchebean.model}" extender="ext" style="height:600px;" legendPosition="ne" xaxisLabel="Année" yaxisLabel="Montant en DT" title="Factures payés par années" />
<script type="text/javascript">
function ext() {
this.cfg.axes.yaxis.tickOptions = {
formatString: "%'i"
};
this.cfg.seriesDefaults={
renderer: $.jqplot.BarRenderer,
pointLabels:{show:true}
},
$.jqplot.sprintf.thousandsSeparator = ' ';
}
</script>
First question
You can fulfill your need #1 using an extender.
Here's the related excerpt from Primefaces' manual regarding extenders:
3.14.15 Extender Chart API provide high level access to commonly used jqplot options however there are many more customization options
available in jqplot. Extender feature provide access to low level apis
to do advanced customization by enhancing the configuration object,
here is an example to increase shadow depth of the line series where
model's extender property is set to "ext".
<p:chart type="line" model="#{bean.model}" />
function ext() {
//this = chart widget instance
//this.cfg = options
this.cfg.seriesDefaults = {
shadowDepth: 5
};
}
Refer to jqPlot docs for available options.
Note: in Primefaces 4.0, the extender function name is provided as an attribute of the component tag, eg. <p:barChart extender="ext" .../>
To use whitespaces as thousands separator, use the following extender:
function ext() {
this.cfg.axes.yaxis.tickOptions = {
formatString: "%'i"
};
$.jqplot.sprintf.thousandsSeparator = ' ';
}
Second question
You will also manage to do it making some tweaking in your extender.
For example, the following piece of configuration will display values above every bar:
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
pointLabels:{show:true}
},
And just use some CSS to change the size!
--
Zim

How to create a Multinline textbox growing dynamically without scrollbars?

I need to use a text-box (multiline) in my application. It need to grow as the user inputs text into it. I want that textbox to grow without any scrollbars. I tried allow=resize:null but it just prevents textbox from being stretched.All i want is a textbox as we see in facebook comment /share area which grows simply without any scrollbars on sides. I hope i have neatly explained it.
You can use something like this: (Source: Expandable or Auto-Resize TextBox Height by Colt Kwong)
<asp:TextBox ID="txtMsg" runat="server" TextMode="MultiLine"
style="overflow:hidden" onkeyup="AutoExpand(this, event)" Rows="2" />
using this javascript:
function AutoExpand(txtBox, event)
{
if (event.keyCode == "13" || event.keyCode == "8") {
var therows = 0
var thetext = document.getElementById(txtBox.id).value;
var newtext = thetext.split("\n");
therows += newtext.length
document.getElementById(txtBox.id).rows = therows;
return false;
}
}
Or if you like jquery you should take a look at the jQuery autoResize Plugin.
A plugin for jQuery which changes the dimensions of input elements to
suit the amount of data entered. It operates on textarea,
input[type=text] and input[type=password] elements.
Usage is as follows:
$('textarea#foo').autoResize();
You can pass options:
$('textarea#foo').autoResize({
maxHeight: 200,
minHeight: 100
});