I am using Extjs for creating UI. So I created grid, with column. My task is to add tool tip to some cells but only on part of text.
I tried to use meta.tdAttr = 'data-qtip="Activity is in use"'; looks like it works, but sets tooltip on whole cell, when I want only on some text.
Here is my realization:
{
hideable : false,
width : 200,
flex : 1,
dataIndex : 'name',
text : 'Name',
renderer : function(value, meta, record) {
meta.tdCls += ' '
+ this.getValidation()
.getHighestLevelCls(
record.modelType,
record.id);
var inUseClass = '';
if (record.get('descendants').length > 0) {
meta.tdAttr = 'data-qtip="Activity is in use"'; // here is tool tip setter
inUseClass = Glyphs
.getIconClass('dot-circle-o');
} else {
inUseClass = Glyphs
.getIconClass('circle-o');
}
return Glyphs.wrapClass(inUseClass,
'font-size:10; color:black;',
' ')
+ value;
}
}
As you can see in cell I print Glyph (it is some kind of icon interpretated as text, taken from AwesomeFonts.com) + value (text value), so I need to show tooltip when I hover with mouse only Glyth. Maybe someone can suggest me any sollution?
You could try returning a <span> from the renderer, applying all the attributes to it instead:
renderer: function(value) {
return '<span data-qtitle="QTip Example" data-qwidth="200" '+
'data-qtip="This is a quick tip from a custom renderer!">'+
value+'</span>';
}},
A fiddle here. (I tried with normal text, but the concept is similar)
Related
I have created a Stockchart using Amcharts available in https://codepen.io/Volabos/pen/PyzmYd
Where everything looks good, I however want to get rid of the Thousand-k suffix from Y-axis lables as well as from Baloon, instead I desire to have Thousand seperator + rounded value upto 2.
Is there any possibility to achieve such?
Besides, I also want to set various CSS properties of the div class = 'Right' dynamically based on the value of "value2" e.g. if its value is greater than 500 then Font-color would be green otherwise red.
Any pointer would be highly appreciated.
For the y-axis, change usePrefixes in your panelSettings to false:
"panelsSettings": {
"usePrefixes": false
},
For the balloon, implement balloonFunction to customize the formatting:
stockGraphs: [{
"id": "g1",
...
"balloonFunction": function(graphDataItem, graph) {
var value = graphDataItem.values.value;
return "<div>Value<br/>" + Math.round(value).toLocaleString('en-us'); + "</div>";
}
}]
Updated pen
EDIT
Here is the updated pen to include dynamic balloon colors based on value2. The new balloonFunction looks like this:
function(graphDataItem, graph) {
var value = graphDataItem.values.value;
var value2 = graphDataItem.dataContext.rawData[0].value2;
return "<div style='color:" + (value2 > 500 ? 'green' : 'red') + "'>Value<br/>" +
Math.round(value).toLocaleString('en-us'); +
"</div>";
}
You can clean this up with string interpolation and CSS classes as well, but this is basically the technique.
I'm using qooxdoo to build a custom virtualTree, which works fine as expected until I open/close/reopen a node.
It's a mess then. I don't know which part I'm missing.
here's a code sample:
virtual tree
To reproduce, please open a node (for example "Dep1"). You can hover childrens and everything is fine. Now close the node and reopen it. Now icons get changed in node and node receives the hover effect, which is not the case when we initially opened it.
Am I missing something?
Regards
code below:
var data = {
"label": "ROOT",
"children" : [
{
"LDEP" : "Dep1",
"children" : [
{
"CVEH" : 1,
"LVEH" : "veh1_1"
},
{
"CVEH" : 2,
"LVEH" : "veh1_2"
}
]
},
{
"LDEP" : "Dep2",
"children" : [
{
"CVEH" : 3,
"LVEH" : "veh2_1"
},
{
"CVEH" : 4,
"LVEH" : "veh2_2"
}
]
},
]
};
var model = qx.data.marshal.Json.createModel(data, false);
var vtree = new qx.ui.tree.VirtualTree(model, "children", "children");
this.getRoot().add(vtree,
{
left : 100,
right : 100,
top : 50
});
vtree.set({
showTopLevelOpenCloseIcons : true,
hideRoot : true,
backgroundColor : "gray"
});
/* label options */
vtree.setLabelOptions({
converter : function(value, model)
{
if (value){
return "<b>" + model.get("LDEP") + "</b>";
}
else
{
return model.get("LVEH");
}
}
});
/*
* icon options, if a dep then return a generic symbol else return
* vehicle icon
*/
vtree.setIconPath("children");
vtree.setIconOptions({
converter : function(value, model)
{
if (value){
return "icon/22/mimetypes/text-html.png";
}
else
{
return "icon/22/mimetypes/media-image.png"
}
}
});
var delegate = {
bindItem : function(controller, item, index)
{
controller.bindDefaultProperties(item, index);
//set icon size to 24x24 for leaves
var icon = item.getChildControl("icon");
if(item.getModel().getChildren){
//dept
item.setBackgroundColor("gray");
} else {
//vehicle
item.setBackgroundColor("white");
icon.set({
width : 32,
height : 32,
scale : true,
marginTop : -4
});
}
//labels, accept html
var lbl = item.getChildControl("label");
lbl.set({
rich : true,
textColor : "black"
});
//change color on pointerin and pointerout of vehicles
if (!item.getModel().getChildren){
item.addListener("pointerover", function(){
item.getChildControl("label").fadeIn(100);
item.setBackgroundColor("blue");
item.getChildControl("label").setTextColor("orange");
});
item.addListener("pointerout", function(){
item.setBackgroundColor("white");
item.getChildControl("label").setTextColor("black");
});
}
},
/*
* sorting
*/
sorter : function(a, b){
var A = (a.getChildren? a.get("LDEP") : a.get("LVEH")).toUpperCase(),
B = (b.getChildren? b.get("LDEP") : b.get("LVEH")).toUpperCase();
return A > B ? 1 : A < B ? -1 : 0;
}
};
vtree.setDelegate(delegate);
To understand the effects you are observing, it needs understanding on how virtual widgets work in qooxdoo.
Virtual widget means that you are able do display huge amounts of data, only having a few widgets rendering the visible content. Imagine a tree with hundreds of nodes and child nodes, but you only have 10 nodes visible at one time. The virtual widget then instantiates as many real widgets as needed and re-uses those widgets to display the visible part of the tree.
The virtual tree widget, which diplays nodes an leaves of a tree, reuses the instantiated widgets by changing the model of the widget and it's appearance. This way it may happen that on user interaction, a virtual tree node is rendered by an item which formely displayed a leafe.
All this is done via the delegates bindItem member function which is called every time a real widget is re-used for a virtual item. So adding an event listener in bindItem adds subsequent more and more event listeners to a single widget tree/leaf instance, showing the effects you described.
To achieve what you want, you have to add your logic into the configureItem delegate member, which is only called once on instantiation of a tree item widget. There you have to differentiate between the item currently displaying a node or a leaf which you can simply accomplish by getting the current appearance of that item via item.getAppearance(). The result will be either virtual-tree-file for a leaf and virtual-tree-folder for a node.
The event listeners which are added for pointerover and pointerout should then add the styles needed depending on the appearance.
Note all this should better be handeled by a custom appearance theme, where you could add most styles you used based on the widgets states like hover, besides the animation for the label child control with the fading in label.
Please paste the following gist into the qooxdoo playground where I've created an example which demonstrates all the speech above:
https://gist.github.com/level420/ba4e25f98618064f91f5aa6cb6bb1124
I have a data set which looks something like this.
var toolTip = [ ["IN001", "IN002"], "IN003", "IN004", ["IN005", "IN006", "IN007"] ];
I have a scatter plot which uses these tooltips to show data in it.
{
type: 'scatter',
name: 'incidents',
yAxis: 1,
data: [ [0,100],[1,100],[2,100],[3,100] ],
tooltip: {
pointFormatter: function(){
return "Incident " + toolTip[this.series.data.indexOf( this )] ;
}
}
},
Now this shows the data in a line in tooltip. I want a next line in case there is more than one data in a tooltip. For example
IN0001
IN0002
instead of IN0001, IN0002.
How do i get the next line. I don't know how to parse this data in this case.
One more doubt i have is, Each name should be a hyperlink.
How do i make every word in the toolTip array to appear as a link in the tooltip?
Any help is appreciated.
Here is a working model of the following.
jsFiddle
You can change your pointFormatter function so you will meet your requirements. You can add breaking lines using 'br' and you can add links using 'a' like in normal HTML. You can use Highcharts.each() for iterating over your array and adding next elements to your string.
pointFormatter: function() {
var string = '';
Highcharts.each(toolTip[this.series.data.indexOf(this)], function(p) {
string += '' + p + '<br>'
})
return "Incident<br>" + string + "<br />";
}
Here you can see an example how it can work: http://jsfiddle.net/o2zmLngr/5/
I need to display an image in a PropertyGrid. This is usually achieved using the customRenderers config, explicitly overriding the rendered for a specific field:
grid = new Ext.grid.PropertyGrid({
customRenderers: {
"picture": function(v)
{
return "<img src=\"" + feature.attributes["picture"] + "\" />";
}
}
});
But in my case the field on which to apply the custom rendering function is only known at run-time (I have to search for a string like "http:"). But adding the custom renderer dynamically at that time does no seem to work.
Is there any way to do this? Thank you.
Here is how the dynamic property is found:
for (var key in feature.attributes)
{
value = feature.attributes[key];
if ((value != null) && (value.substring(0, 4) == "http"))
grid.customRenderers[key] = Function("v", "return \"<img src=\\\"" + value + "\\\" />\";");
}
After trying a great deal of different strategies I finally got to something that functions:
grid = new Ext.grid.PropertyGrid();
for (var key in feature.attributes)
{
value = feature.attributes[key];
if ((value != null) && (value.substring(0, 4) == "http"))
grid.customRenderers[key] = Function("v", "return \"<img src=\\\"" + value + "\\\" />\";");
}
The feature.attributes is a dictionary containing the data to be displayed; a cycle iterates through each of its keys, searching for the fields that might contain image URLs.
There were two key elements that brought me to this solution:
Understanding that customRenderers can be used itself as a dictionary, thus dispensing the hard-coding of fields names.
The usage of Function as a means to encode the exact value to be rendered, this way avoiding any scope issues.
Even though customRenderers is a config property, it is still accessible after the component is created. You can dynamically add them after the grid is created.
Have a look at this jsfiddle: http://jsfiddle.net/Wxx3M/1/
HTML:
<p id="button-container"></p>
<div id="prop-grid"></div>
JS:
Ext.onReady(function(){
var propsGrid = new Ext.grid.PropertyGrid({
renderTo: 'prop-grid',
width: 300,
autoHeight: true,
propertyNames: {
tested: 'QA',
borderWidth: 'Border Width'
},
source: {
'(name)': 'Properties Grid',
grouping: false,
autoFitColumns: true,
productionQuality: false,
created: new Date(Date.parse('10/15/2006')),
tested: false,
version: 0.01,
borderWidth: 1
},
viewConfig : {
forceFit: true,
scrollOffset: 2 // the grid will never have scrollbars
}
});
// simulate updating the grid data via a button click
new Ext.Button({
renderTo: 'button-container',
text: 'Update custom renderer',
handler: function(){
var targetProp = null;
for (var key in feature.attributes)
{
value = feature.attributes[key];
if ((value != null) && (value.substring(0, 4) == "http"))
targetProp = key;
}
propsGrid.customRenderers[targetProp] = function(v){
return v ? 'XXX' : '';
}
propsGrid.getView().refresh();
}
});
});
Initially there is no custom renderers. If you click the button, a new dynamic custom renderer is added.
I saw many people recommend JavaScript Visualization Toolkit (The JIT) for org chart. I am trying to use SpaceTree of JavaScript InfoVis Toolkit for org chart. The nodes in my org chart is like a component in itself that has employee profile pic, two different icons that show up overlays on click and some 3 lines of simple text having name, title, and number of reports ... each line is separated by a light horizontal line. Something like:
My question is, is it possible to customize the spacetree nodes to such an extent? Can I have Node almost like another "component" or JavaScript object that has its own render method?
I researched on forums and some options I considered are:
$jit.ST.NodeTypes.implement() ... but based on examples I saw, this
seem to be helping in customizing node in terms of shapes etc but
not like layout drawn above. I am referring to customization
something like:
http://groups.google.com/group/javascript-information-visualization-toolkit/browse_thread/thread/a4a059cbeb10ba23/ebf472366cdbbdef?lnk=gst&q=spacetree+nodetype#ebf472366cdbbdef
I tried to set innerHtml in onCreateLabel method in example5.js at:
but it seems to be doing nothing. Although, I'm not sure if that
will be a good way of node customization. Example5 is at the JIT website (I am not allowed to post more than one hyperlink)
Extending Graph.Node ... I am still looking into this option and it
this point of time, I don't know how complicated it is to have space
tree use Graph.myNode and what will Graph.myNode even look like? I
need to think more on those lines and see if it is even feasible.
The Spacetree can be customized very much. The nodes can display images or anything we want. We can have custom click events for the nodes. To have custom events, you will have to redraw the whole tree in the onclick event.
Here is an example. On the success function of the click event. Here I have called the click event on the class "clickable"
$.ajaxSetup({ cache: false });
$(".clickable").live("click", function () {
$.ajax({
url: url + "?id=" + parentId + "&ts=" + new Date().getMilliseconds(),
type: "POST",
cache: false,
dataType: "html",
success: function (html) {
init(html);
}
});
});
The name property can be used to give the image like this:
{id:"90", name:"<a href='javascript:;' class='clickable' name='90'><img src='images/picture.gif' width='30' height='30' alt='pic' /></a>", data:{}, children:[]}
Mark as Answer if useful. thanks.
You could make yourNode the prototype ancestor of Graph.node, set up the slots you want, then add the appropriate render / force code customizations.
I'm using spacetrees and I just set the label type to HTML (which is the default) and you can just use regular HTML and CSS to style your labels. I have images, links, text, etc.
Note that you're working with the label and not the node. The node is the graph component; the label is the visual that you see which represents the node.
When you initialize the spacetree pass in a function for "onCreateLabel":
var myOnCreateLabel = function(label, node) {
label.onclick = function(event) {/* setup onclick handler */};
label.innerHTML = "<img src='myImage.png' />"; // use image in label
};
var myST = new $jit.ST({/*other settings*/ onCreateLabel: myOnCreateLabel});
if you don't mind working with HTML5/Canvas only, try this as well http://orgplot.codeplex.com, simple interface support image node as well.
this.st=new $jit.ST(
{
onCreateLabel: function (label, node)
{
var labelContent = $('<table cellpadding="0" cellspacing="0" class="nodeContainer"><tr><td>' +
'<div class="buttonContainer">' +
'</div></td></tr><tr><td>' +
'<table class="nodeBox" cellpadding="0" cellspacing="0">' +
'<tr>' +
'<td class="iconTd"></td>' +
'<td class="center nodeName">' + node.name + '</td>' +
'</tr></table>' +
'</td></tr></table>');
thisObject.onCreateLabel.raise(thisObject, { labelContent: labelContent, node: node });
if (node.data && node.data.Icon && node.data.Icon != "")
{
labelContent.find(".iconTd").append($("<img src='" + node.data.Icon + "' alt=''>"));
}
else
{
labelContent.find(".iconTd").remove();
}
var lblCtl = $(label).append(labelContent);
if (node.data.Data.ChildrenCount)
{
labelContent.append("<tr><td class='subnode'></td></tr>");
}
if (node.name.length > 40)
{
lblCtl.attr("title", node.name);
node.name = node.name.substr(0, 37);
node.name = node.name + "...";
}
lblCtl.click(function (sender)
{
//thisObject.isNodeClicked = true;
var target = $(sender.target);
if (!target.hasClass("subnode"))
{
if (thisObject.currentSelectedNode)
{
thisObject.currentSelectedNode.buttonContainer.hide();
}
var btnContainer = labelContent.find(".buttonContainer");
thisObject.currentSelectedNode = { nodeElement: lblCtl, node: node, buttonContainer: btnContainer, event: sender };
btnContainer.append(thisObject.$globalButtonContainer.show()).show();
var button = target.closest(".chartActionButton");
if (button.length > 0)
{
thisObject.onNodeAction.raise(thisObject, { name: button.attr("name"), nodeElement: lblCtl, node: node, button: target });
}
else
{
thisObject.onNodeClick.raise(thisObject, thisObject.currentSelectedNode);
}
}
else
{
thisObject.st.onClick(node.id);
}
});
label.id = node.id;
//set label styles
thisObject.setNodeStyle(node.data.Style, label.style);
}
});