angularjs dygraph how to show only positive values? - angularjs

is there a way just to show positive values on my dygraph.. my Y and X axis start both at 0 ?
Is there a option I can add or I need to go trow customRange for y axis option and calculate each max/min per graph?
My options are:
var options = {
labels: labels,
showRangeSelector: true,
legend: 'always',
ylabel: units,
title: graphTitle,
includeZero: true,
axes: {
y: {
valueFormatter: function (value, opts, seriesName, dygraph, row, col) {
if (seriesName == "Mode") {
return modemMode[value];
} else if (seriesName == "Submode") {
return modemSubmode[value];
} else if (seriesName == "Sysmode") {
return modemSysmode[value];
} else if (seriesName == "Roaming") {
return modemRoaming[value];
}
return value;
}
}
},
underlayCallback: function(canvas, area, g) {
for (var i=0; i<highlightArea.length; i++) {
var left = g.toDomXCoord(highlightArea[i][0]);
var right = g.toDomXCoord(highlightArea[i][1]);
canvas.fillStyle = "rgba(217, 101, 87, 0.2)";
canvas.fillRect(left, area.y, right - left, area.h);
}
}
}

You can use the valueRange option to achieve this:
new Dygraph(div, data, {
valueRange: [0, null] // null means "calculate max from the data"
});
Here's a full example.

Related

Go JS Tree Mapping view in React TS

I want to achieve Tree Mapping from Gojs in React typescript.
I found one example of Go js in react but it's still confusing for me to make Tree Mapping in react. Any help would be appreciated to start with Tree Mapping in React TS.
Here is my repo: https://github.com/AdarshPawar29/map-tree-gojs
I manage to create the tree mapping but still some work to be done. I commented on some of the not working functions. I'm also looking for the functional component.
import React, { useState } from "react";
import * as go from "gojs";
import { ReactDiagram } from "gojs-react";
import "./App.css";
class TreeNode extends go.Node {
constructor() {
super();
this.treeExpandedChanged = (node) => {
if (node.containingGroup !== null) {
node.containingGroup
.findExternalLinksConnected()
.each((l) => l.invalidateRoute());
}
};
}
// findVisibleNode() {
// // redirect links to lowest visible "ancestor" in the tree
// var n = this;
// while (n !== null && !n.isVisible()) {
// n = n.findTreeParentNode();
// }
// return n;
// }
}
// end TreeNode
// Control how Mapping links are routed:
// - "Normal": normal routing with fixed fromEndSegmentLength & toEndSegmentLength
// - "ToGroup": so that the link routes stop at the edge of the group,
// rather than going all the way to the connected nodes
// - "ToNode": so that they go all the way to the connected nodes
// but only bend at the edge of the group
var ROUTINGSTYLE = "Normal";
// If you want the regular routing where the Link.[from/to]EndSegmentLength controls
// the length of the horizontal segment adjacent to the port, don't use this class.
// Replace MappingLink with a go.Link in the "Mapping" link template.
class MappingLink extends go.Link {
getLinkPoint(
node: go.Node | null | any,
port: go.GraphObject,
spot: go.Spot,
from: boolean,
ortho: boolean,
othernode: go.Node | null | any,
otherport: go.GraphObject
) {
if (ROUTINGSTYLE !== "ToGroup") {
return super.getLinkPoint(
node,
port,
spot,
from,
ortho,
othernode,
otherport
);
} else {
var r = port.getDocumentBounds();
var group = node.containingGroup;
var b = group !== null ? group.actualBounds : node.actualBounds;
var op = othernode.getDocumentPoint(go.Spot.Center);
var x = op.x > r.centerX ? b.right : b.left;
return new go.Point(x, r.centerY);
}
}
computePoints() {
var result = super.computePoints();
if (result && ROUTINGSTYLE === "ToNode") {
var fn = this.fromNode;
var tn = this.toNode;
if (fn && tn) {
var fg = fn.containingGroup;
var fb = fg ? fg.actualBounds : fn.actualBounds;
var fpt = this.getPoint(0);
var tg = tn.containingGroup;
var tb = tg ? tg.actualBounds : tn.actualBounds;
var tpt = this.getPoint(this.pointsCount - 1);
this.setPoint(
1,
new go.Point(fpt.x < tpt.x ? fb.right : fb.left, fpt.y)
);
this.setPoint(
this.pointsCount - 2,
new go.Point(fpt.x < tpt.x ? tb.left : tb.right, tpt.y)
);
}
}
return result;
}
}
// end MappingLink
// Create some random trees in each group
var nodeDataArray = [
{ isGroup: true, key: -1, text: "Left Side", xy: "0 0", width: 150 },
{ isGroup: true, key: -2, text: "Right Side", xy: "300 0", width: 150 },
];
var linkDataArray = [
{ from: 6, to: 1012, category: "Mapping" },
{ from: 4, to: 1006, category: "Mapping" },
{ from: 9, to: 1004, category: "Mapping" },
{ from: 1, to: 1009, category: "Mapping" },
{ from: 14, to: 1010, category: "Mapping" },
];
export default function App() {
// All links must go from a node inside the "Left Side" Group to a node inside the "Right Side" Group.
function checkLink(
fn: {
[x: string]: any;
containingGroup: { data: { key: number } } | null;
},
fp: any,
tn: {
[x: string]: any;
containingGroup: { data: { key: number } } | null;
},
tp: any,
link: any
) {
// make sure the nodes are inside different Groups
if (fn.containingGroup === null || fn.containingGroup.data.key !== -1)
return false;
if (tn.containingGroup === null || tn.containingGroup.data.key !== -2)
return false;
//// optional limit to a single mapping link per node
if (
fn.linksConnected.any(
(l: { category: string }) => l.category === "Mapping"
)
)
return false;
if (
tn.linksConnected.any(
(l: { category: string }) => l.category === "Mapping"
)
)
return false;
return true;
}
function initDiagram() {
const $ = go.GraphObject.make;
// set your license key here before creating the diagram: go.Diagram.licenseKey = "...";
const diagram = $(go.Diagram, {
"undoManager.isEnabled": true, // must be set to allow for model change listening
"undoManager.maxHistoryLength": 0, // uncomment disable undo/redo functionality
"clickCreatingTool.archetypeNodeData": {
text: "new node",
color: "lightblue",
},
"commandHandler.copiesTree": true,
"commandHandler.deletesTree": true,
// newly drawn links always map a node in one tree to a node in another tree
"linkingTool.archetypeLinkData": { category: "Mapping" },
"linkingTool.linkValidation": checkLink,
"relinkingTool.linkValidation": checkLink,
model: new go.GraphLinksModel({
linkKeyProperty: "key", // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
}),
});
// // define a simple Node template
// diagram.nodeTemplate = $(
// go.Node,
// "Auto", // the Shape will go around the TextBlock
// new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
// go.Point.stringify
// ),
// $(
// go.Shape,
// "RoundedRectangle",
// { name: "SHAPE", fill: "white", strokeWidth: 0 },
// // Shape.fill is bound to Node.data.color
// new go.Binding("fill", "color")
// ),
// $(
// go.TextBlock,
// { margin: 8, editable: true }, // some room around the text
// new go.Binding("text").makeTwoWay()
// )
// );
diagram.nodeTemplate = $(
TreeNode,
{ movable: false, copyable: false, deletable: false }, // user cannot move an individual node
// no Adornment: instead change panel background color by binding to Node.isSelected
{
selectionAdorned: false,
background: "white",
mouseEnter: (e, node) => (node.background = "aquamarine"),
// mouseLeave: (e, node) =>
// (node.background = node.isSelected ? "skyblue" : "white"),
},
new go.Binding("background", "isSelected", (s) =>
s ? "skyblue" : "white"
).ofObject(),
// whether the user can start drawing a link from or to this node depends on which group it's in
new go.Binding("fromLinkable", "group", (k) => k === -1),
new go.Binding("toLinkable", "group", (k) => k === -2),
$(
"TreeExpanderButton", // support expanding/collapsing subtrees
{
width: 14,
height: 14,
"ButtonIcon.stroke": "white",
"ButtonIcon.strokeWidth": 2,
"ButtonBorder.fill": "goldenrod",
"ButtonBorder.stroke": null,
"ButtonBorder.figure": "Rectangle",
_buttonFillOver: "darkgoldenrod",
_buttonStrokeOver: null,
_buttonFillPressed: null,
}
),
$(
go.Panel,
"Horizontal",
{ position: new go.Point(16, 0) },
//// optional icon for each tree node
//$(go.Picture,
// { width: 14, height: 14,
// margin: new go.Margin(0, 4, 0, 0),
// imageStretch: go.GraphObject.Uniform,
// source: "images/defaultIcon.png" },
// new go.Binding("source", "src")),
$(go.TextBlock, new go.Binding("text", "key", (s) => "item " + s))
) // end Horizontal Panel
); // end Node
// These are the links connecting tree nodes within each group.
diagram.linkTemplate = $(go.Link); // without lines
diagram.linkTemplate = // with lines
$(
go.Link,
{
selectable: false,
routing: go.Link.Orthogonal,
fromEndSegmentLength: 4,
toEndSegmentLength: 4,
fromSpot: new go.Spot(0.001, 1, 7, 0),
toSpot: go.Spot.Left,
},
$(go.Shape, { stroke: "lightgray" })
);
// These are the blue links connecting a tree node on the left side with one on the right side.
diagram.linkTemplateMap.add(
"Mapping",
$(
MappingLink,
{
isTreeLink: false,
isLayoutPositioned: false,
layerName: "Foreground",
},
{ fromSpot: go.Spot.Right, toSpot: go.Spot.Left },
{ relinkableFrom: true, relinkableTo: true },
$(go.Shape, { stroke: "blue", strokeWidth: 2 })
)
);
function updateNodeWidths(
group: {
memberParts: {
each: (arg0: {
(n: any): void;
(n: any): void;
(n: any): void;
}) => void;
};
},
width: number
) {
if (isNaN(width)) {
group.memberParts.each((n: { width: number }) => {
if (n instanceof go.Node) n.width = NaN; // back to natural width
});
} else {
var minx = Infinity; // figure out minimum group width
group.memberParts.each((n: { actualBounds: { x: number } }) => {
if (n instanceof go.Node) {
minx = Math.min(minx, n.actualBounds.x);
}
});
if (minx === Infinity) return;
var right = minx + width;
group.memberParts.each(
(n: { width: number; actualBounds: { x: number } }) => {
if (n instanceof go.Node)
n.width = Math.max(0, right - n.actualBounds.x);
}
);
}
}
function makeGroupLayout() {
return $(
go.TreeLayout, // taken from samples/treeView.html
{
alignment: go.TreeLayout.AlignmentStart,
angle: 0,
compaction: go.TreeLayout.CompactionNone,
layerSpacing: 16,
layerSpacingParentOverlap: 1,
nodeIndentPastParent: 1.0,
nodeSpacing: 0,
setsPortSpot: false,
setsChildPortSpot: false,
// after the tree layout, change the width of each node so that all
// of the nodes have widths such that the collection has a given width
// commitNodes: function () {
// // overriding TreeLayout.commitNodes
// go.TreeLayout.prototype.commitNodes();
// if (ROUTINGSTYLE === "ToGroup") {
// updateNodeWidths(group, group.data.width || 100);
// }
// },
}
);
}
diagram.groupTemplate = $(
go.Group,
"Auto",
{ deletable: false, layout: makeGroupLayout() },
new go.Binding("position", "xy", go.Point.parse).makeTwoWay(
go.Point.stringify
),
new go.Binding("layout", "width", makeGroupLayout),
$(go.Shape, { fill: "white", stroke: "lightgray" }),
$(
go.Panel,
"Vertical",
{ defaultAlignment: go.Spot.Left },
$(
go.TextBlock,
{ font: "bold 14pt sans-serif", margin: new go.Margin(5, 5, 0, 5) },
new go.Binding("text")
),
$(go.Placeholder, { padding: 5 })
)
);
// initialize tree on left side
var root: any = { key: 0, group: -1 };
nodeDataArray.push(root);
for (var i = 0; i < 11; ) {
i = makeTree(3, i, 17, nodeDataArray, linkDataArray, root, -1, root.key);
}
// initialize tree on right side
root = { key: 1000, group: -2 };
nodeDataArray.push(root);
for (var i = 0; i < 15; ) {
i = makeTree(3, i, 15, nodeDataArray, linkDataArray, root, -2, root.key);
}
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
// help create a random tree structure
function makeTree(
level: number,
count: number,
max: number,
nodeDataArray:
| {
isGroup: boolean;
key: number;
text: string;
xy: string;
width: number;
}[]
| { key: any; group: any }[],
linkDataArray: { from: any; to: any }[],
parentdata: { key: any; group?: any },
groupkey: number,
rootkey: number
) {
var numchildren = Math.floor(Math.random() * 10);
for (var i = 0; i < numchildren; i++) {
if (count >= max) return count;
count++;
var childdata: any = { key: rootkey + count, group: groupkey };
nodeDataArray.push(childdata);
linkDataArray.push({ from: parentdata.key, to: childdata.key });
if (level > 0 && Math.random() > 0.5) {
count = makeTree(
level - 1,
count,
max,
nodeDataArray,
linkDataArray,
childdata,
groupkey,
rootkey
);
}
}
return count;
}
return diagram;
}
function handleModelChange(changes: any) {
alert("GoJS model changed!");
}
return (
<div>
<ReactDiagram
initDiagram={initDiagram}
divClassName="diagram-component"
nodeDataArray={nodeDataArray}
linkDataArray={linkDataArray}
onModelChange={handleModelChange}
/>
</div>
);
}

I want to set checkbox to true based on a condition in ag-grid

I have a button which basically imports some data. This imported data needs to be compared with the data inside already loaded ag-grid and if there is a match, set the cehckbox of that particlar row node to true.
This is the button which checks for the condition:
enableCheck() {
alert('works');
if (this.DataService.isNotBlank(this.rowDataImport)) {
for (let i = 0; i < this.rowDataImport.length; i++) {
if (this.DataService.isNotBlank(this.rowData)) {
for (let j = 0; j < this.rowData.length; j++) {
if (this.DataService.isNotBlank(this.rowData[j].calDate)) {
for (const calDates of this.rowData[j].calDate) {
if (
this.rowDataImport[i].isin === calDates.isin ||
this.rowDataImport[i].portfolioName === calDates.portfolioName ||
this.rowDataImport[i].valuationDate === calDates.valuationDate
)
{
// alert('true')
this.checkValue = true;
} else {
this.checkValue = false;
}
}
}
}
}
}
}
}
The this.checkValue is a flag which will be true if match is found.
public gridColumnDefs = [
{
headerName: 'Portfolio Name',
field: 'portfolioName',
cellRenderer: 'agGroupCellRenderer',
headerCheckboxSelection: true,
headerCheckboxSelectionFilteredOnly: true,
checkboxSelection: true,
pinned: 'left',
filter: true,
cellRendererParams:(params) => {
console.log(params);
if (this.checkValue) {
params.node.selected = true;
}
}
},
]
here I used cellRendererParams. But this will only for on load I guess. What to do if I want to update the ag-grid row from a value outside i.e. from import check as given above?
First of all, you should add id for each row in defaultColDef
this.defaultColDef = {
getRowNodeId: data => data.id,
};
Then you can find this id and set the checkbox to true.
Also, you can find separate field by name.
It is really easy, you should use the next combination
selectRow() {
this.gridApi.forEachNode(node => {
if (node.id == 1 || node.id == 2 || node.data.country == 'Australia') {
node.setSelected(true);
}
});
}
Working example:
https://plnkr.co/edit/ijgg6bXVleOAmNL8
In this example when we click on the button - we set the checkbox to true for two rows with id 1 and 2 and for each field that has country 'Australia'
And in your case, you are using incorrect configuration.
You should you cellRenderer
cellRenderer: params => {
if(params.value === 'Ireland') {
params.node.setSelected(true)
}
return params.value
},
One more example: https://plnkr.co/edit/PcBklnJVT2NsNbm6?preview
I manpulated a bit and did the below which worked like a charm.
this.gridApi.forEachNode(node => {
if (node.data.isin === this.rowDataImport[i].isin &&
node.data.portfolioName === this.rowDataImport[i].portfolioName &&
node.data.valuationDate === this.rowDataImport[i].valuationDate
) {
node.setSelected(true);
}

how can i draw dynamic highchart. the y-axis and the number of charts are dynamic from json

im new in angular js and i need to use highchart in my angular page . the problem is that i must draw chart with dynamic data from json and the number of charts will be dynamic too , maybe it should draw 3 or 4 different chart from one json . I searched alot but couldnt solve my problem.
this code works but show the data in one chart in different series. I need to show each series in different charts, and in this case the json send 4 data but it will be changed .
1. List item
$scope.draw_chart = function(){
Highcharts.chart('container2', {
chart:{
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
var this_chart = this;
$scope.ws = ngSocket('ws://#');
$scope.ws.onOpen(function () {
});
var k = 0 ;
var time=0;
$scope.points_avarage = [];
$scope.ws.onMessage(function (message) {
listener(JSON.parse(message.data));
var z = JSON.parse(message.data);
var line_to_draw = z.result.length;
var j = 0 ;
for(i=0 ; i < line_to_draw*2 ; i+=2)
{
$scope.data_to_draw[i] = {
name : z.result[j][0]['name'] ,
y : z.result[j][0]['rx-bits-per-second']
}
$scope.data_to_draw[i+1] = {
name : z.result[j][0]['name'] ,
y : z.result[j][0]['tx-bits-per-second']
}
j++;
}
this_chart.series[0].name= $scope.data_to_draw[0].name;
this_chart.series[1].name= $scope.data_to_draw[1].name;
this_chart.series[2].name= $scope.data_to_draw[2].name;
this_chart.series[3].name= $scope.data_to_draw[3].name;
for(i=0; i < line_to_draw*2; i++) {
var x = (new Date()).getTime(); // current time
var y = parseInt($scope.data_to_draw[i].y);
this_chart.series[i].addPoint([x, y], true, true);
}
});
var d = new Date().toTimeString();
}
}
},
global: {
useUTC: false
},
title: {
text: 'Live data'
},
xAxis: {
type: 'datetime'//,
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
width: 1,
color: '#808080'
}
]
}
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: [{
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -5; i <= 0; i += 1) {
data.push({
x: time ,
y: 0
});
}
return data;
}())
},
{
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -5; i <= 0; i += 1) {
data.push({
x: time ,
y: 0
});
}
return data;
}())
},
{
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -5; i <= 0; i += 1) {
data.push({
x: time ,
y: 0
});
}
return data;
}())
},
{
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -5; i <= 0; i += 1) {
data.push({
x: time ,
y: 0
});
}
return data;
}())
}
]
});
};
<div id="containet" ng-init="draw_chart()"></div>

Is there a extJS tri state/three state checkbox?

Looking for a checkbox that can hold three states.
Use:
True, False, Unknown.
Expected behavior:
[x], [ ], [~]
Anyone know of anything?
Ext 3.* Tri-state from this website
Ext 6.2.1
This code exerpt is from sencha forums
{
name: 'optionalChange',
fieldLabel: 'Optional change',
xtype: 'tri-checkbox',
value: 'null'
},
.x-checkbox-null .x-form-checkbox-default {
border: 1px inset #a0a0a0;
background: lightgrey;
box-shadow: 0 0 0 1px hsl(0, 0%, 80%);
}
/**
* Tri-state Checkbox.
* Author: ontho & nux
* Source: https://www.sencha.com/forum/showthread.php?138664-Ext.ux.form.TriCheckbox&p=619810
*
* Note! You must add `x-checkbox-null` style for yourself.
* This might work for classic theme:
.x-checkbox-null .x-form-checkbox-default {
background-position: -39px -26px;
}
*
*/
Ext.define('Ext.ux.form.TriCheckbox', {
extend: 'Ext.form.field.Checkbox',
alias: ['widget.xtricheckbox', "widget.tri-checkbox"],
triState: true, // triState can dynamically be disabled using enableTriState
values: ['null', '0', '1'], // The values which are toggled through
checkedClasses: ['x-checkbox-null', '', Ext.baseCSSPrefix + 'form-cb-checked'], // The classes used for the different states
currentCheck: 0, // internal use: which state we are in?
getSubmitValue: function()
{
return this.value;
},
getRawValue: function()
{
return this.value;
},
getValue: function()
{
return this.value;
},
initValue: function()
{
var me = this;
me.originalValue = me.lastValue = me.value;
me.suspendCheckChange++;
me.setValue(me.value);
me.suspendCheckChange--;
},
setRawValue: function(v)
{
var me = this;
if (v === false || v == 0)
v = '0';
if (v === true || v == 1)
v = '1';
if (v == null || v == '' || v === undefined)
{
if (!this.triState)
v = '0';
else
v = 'null';
}
var oldCheck = me.currentCheck;
me.currentCheck = me.getCheckIndex(v);
me.value = me.rawValue = me.values[me.currentCheck];
// Update classes
var inputEl = me.inputEl;
if (inputEl)
{
inputEl.dom.setAttribute('aria-checked', me.value == '1' ? true : false);
}
me['removeCls'](me.checkedClasses)
me['addCls'](me.checkedClasses[this.currentCheck]);
},
// this is a defaul Checkbox style setter we need to override to remove defult behaviour
updateCheckedCls: function(checked) {
},
// Returns the index from a value to a member of me.values
getCheckIndex: function(value)
{
for (var i = 0; i < this.values.length; i++)
{
if (value === this.values[i])
{
return i;
}
}
return 0;
},
// Handels a click on the checkbox
listeners: {
afterrender: function()
{
var me = this;
this.el.dom.onclick = function(){
me.toggle();
return false;
};
}
},
// Switches to the next checkbox-state
toggle: function()
{
var me = this;
if (!me.disabled && !me.readOnly)
{
var check = me.currentCheck;
check++;
if (check >= me.values.length) {
check = (me.triState == false) ? 1 : 0;
}
this.setValue(me.values[check]);
}
},
// Enables/Disables tristate-handling at runtime (enableTriState(false) gives a 'normal' checkbox)
enableTriState: function(bTriState)
{
if (bTriState == undefined)
bTriState = true;
this.triState = bTriState;
if (!this.triState)
{
this.setValue(this.value);
}
},
// Toggles tristate-handling ar runtime
toggleTriState: function()
{
this.enableTriState(!this.triState);
}
});

Extjs alter label in chart(bar,pie...)

How can i alter the label over a sprite?I found that inside series i can have the following and i can alter the renderer but the problem is that i also need the corresponding storeitem.
label: {
display: 'insideEnd',
field: 'litres',
renderer: function(n) {
return n;
},
orientation: 'horizontal',
color: '#333',
'text-anchor': 'middle'
}
I also found here that there are two functions: onCreateLabel and onPlaceLabel but i don't find the way to use them.
Any help?
onCreateLabel and onPlaceLabel are used in series config. You have to do something like this:
series: [{
// ...
label: {
field: 'data1',
renderer: function(val) {
return val;
}
},
onCreateLabel: function(storeItem, item, i, display) {
var me = this,
group = me.labelsGroup,
config = me.label,
bbox = me.bbox,
endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
return me.chart.surface.add(Ext.apply({
'type': 'text',
'text-anchor': 'middle',
'group': group,
'x': item.point[0],
'y': bbox.y + bbox.height / 2
}, endLabelStyle || {}));
},
onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
var me = this,
chart = me.chart,
resizing = chart.resizing,
config = me.label,
format = config.renderer,
field = config.field,
bbox = me.bbox,
x = item.point[0],
y = item.point[1],
bb, width, height;
label.setAttributes({
text: format(storeItem.get(field[index])),
hidden: true
}, true);
bb = label.getBBox();
width = bb.width / 2;
height = bb.height / 2;
x = x - width < bbox.x? bbox.x + width : x;
x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
y = y - height < bbox.y? bbox.y + height : y;
y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
if (me.chart.animate && !me.chart.resizing) {
label.show(true);
me.onAnimate(label, {
to: {
x: x,
y: y
}
});
} else {
label.setAttributes({
x: x,
y: y
}, true);
if (resizing) {
me.animation.on('afteranimate', function() {
label.show(true);
});
} else {
label.show(true);
}
}
}
// ...
}
Copy and Paste onCreateLabel and onPlaceLabel from the code above (or the ExtJS source) then change them the way you want.

Resources