[OPEN] [#296] Charts - Bar labels show/hide

Page 1 of 2 12 LastLast
  1. #1

    [OPEN] [#296] Charts - Bar labels show/hide

    How can I show/hide bar chart labels based on context menu CheckMenuItem;

    I tried the following javascript handler, but the chart will not redraw:

    function chartLabels(checked) {
    
       var chart = Ext.getCmp('CrtsChart');
       var series = chart.series.items[0];
    
       if (checked === false) {
          series.label.display = "none";
       }
       else {
          series.label.display = "insideEnd";
       }
    
       chart.redraw();
    }
    Last edited by Daniil; Jul 12, 2013 at 4:40 AM. Reason: [OPEN] [#296]
  2. #2
    Hi Chris,

    Please try this.

    Hide
    App.Chart1.series.items[0].hideLabels();
    Show
    App.Chart1.series.items[0].renderLabels()
  3. #3
    Looked good at first, but a slight issue. If you move the mouse across any of the bars the chart rerenders again and the labels show back up after they were hidden. I could get around it with:

    function chartLabels(checked) {
       var chart = Ext.getCmp('CrtsChart');
       var series = chart.series.items[0];
    
       if (checked === false) {
          series.label.display = "none";
          series.hideLabels();
       }
       else {
          series.label.display = "insideEnd";
          series.renderLabels();
       }
    }
    But that is causing an issue when the chart is initially created with a display of "none". I can't get the labels to show up at all.

    Let me work up a full sample.
  4. #4
    Hopefully this details everything.

    Click image for larger version. 

Name:	BarChart.OptionLabelsAndTips.PNG 
Views:	25 
Size:	26.4 KB 
ID:	6491Click image for larger version. 

Name:	BarChart.OptionLabelsOnly.PNG 
Views:	26 
Size:	26.1 KB 
ID:	6492Click image for larger version. 

Name:	BarChart.OptionTipsOnly.PNG 
Views:	23 
Size:	23.7 KB 
ID:	6493Click image for larger version. 

Name:	BarChart.OptionsNone.PNG 
Views:	20 
Size:	23.9 KB 
ID:	6494

    #1: Issue
    I added the following line so that after the chart is rendered it would properly show/hide the data labels based on the context menu option. The problem with this is that the if the ShowLabel is false the labels are still animated and then removed.
    byOrgChart.Series[0].Listeners.AfterRender.Handler = "chartLabels(Ext.getCmp('ShowLabels').checked);";
    You can duplicate the problem by letting the chart display, turn off the Data Labels via the context menu, select another year to be displayed and watch how the animation occurs and then the labels are hidden.

    #2: Issue
    So instead of the listener I was just going to set the label.display in the behind code to "none" or "insideEnd" based on the ShowLabels.Checked value. But if I write the code that way the labels will not show up in subsequent displays.
    //byOrgChart.Series[0].Listeners.AfterRender.Handler = "chartLabels(Ext.getCmp('ShowLabels').checked);";
    cSeries.Label.Display = SeriesLabelDisplay.None;
    if (ShowLabels.Checked == true)
       cSeries.Label.Display = SeriesLabelDisplay.InsideEnd;
    You can duplicate the problem by letting the chart display, turn off the Data Labels via the context menu, select another year to be display, try to turn on the Data Labels via the context menu.

    #3: Observation
    I made a slight modification to your suggestion for the javascript listeners that handle the hiding/showing of the data labels. Instead of just calling hideLabels/renderLabels I needed to reset the label.display to "none" or "insideEnd" because if I didn't the labels would redisplay when I moved the mouse over a bar series.

    function chartLabels(checked) {
    
       var chart = Ext.getCmp('CrtsChart');
       var series = chart.series.items[0];
    
       if (checked === false) {
          series.label.display = "none";
          series.hideLabels();
       }
       else {
          series.label.display = "insideEnd";
          series.renderLabels();
       }
    }
    You can duplicate the observation by commenting out the label.display = "..." and let the chart display, turn off the Data Labels via the context menu and move the mouse over any bar series, the labels are redisplayed.


    Here is a full example.
    <%@ Page Language="C#" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    <%@ Import Namespace="System.Collections.Generic" %>
    <%@ Import Namespace="System.Globalization" %>
    <script runat="server">
    
        public class ChartByOrg
        {
            public static string[] Orgs = new string[] { "Accounting", "HR", "Corporate", "Graphics" };
    
            public string Name { get; set; }
            public double? Y2013 { get; set; }
            public double? Y2012 { get; set; }
            public double? Y2011 { get; set; }
            public double? Y2010 { get; set; }
            public double? Y2009 { get; set; }
    
            public static Dictionary<String, ChartByOrg> GenerateData(int n = 4)
            {
                var data = new Dictionary<String, ChartByOrg>();
                for (int i = 0; i < n; i++)
                {
                    string org = Orgs[i];
                    data.Add(org, new ChartByOrg { Name = org });
                }
                return data;
            }
        }
    
        public class RequestsInfo
        {
            public string RequestOrg { get; set; }
            public int RequestYear { get; set; }
            public int? Requests { get; set; }
        }
    
        protected void Page_Init(object sender, EventArgs e)
        {
            BuildChartYearCheckBoxes();
        }
    
        protected void Page_Load(Object sender, EventArgs e)
        {
            if (X.IsAjaxRequest)
                return;
    
            ((Ext.Net.Checkbox)ChartYearsCbGroup.Items[0]).Checked = true;
            BuildChart();
    
        }
    
        private void BuildChartYearCheckBoxes()
        {
            // Just hardcode years for this example
            for (int year = 2013; year >= 2009; year--)
            {
                ChartYearsCbGroup.Items.Add(new Ext.Net.Checkbox
                {
                    ID = "Y" + year.ToString(),
                    BoxLabel = year.ToString(),
                    InputValue = year.ToString(),
                    StyleSpec = "StyleSpec='font-size: 11px;'",
                    ClientIDMode = ClientIDMode.Static
                });
            }
    
    
        }
        protected void ChartYearsChange(object sender, DirectEventArgs e)
        {
            BuildChart();
        }
    
        private void BuildChart()
        {
            if (ChartPanelSouth.Hidden) return;
    
            CheckboxGroup cbGroup = X.GetCmp<CheckboxGroup>("ChartYearsCbGroup");
            List<Checkbox> yrsSelected = cbGroup.CheckedItems;
            if (yrsSelected.Count == 0)
            {
                ChartPanel.RemoveAll();
                ChartPanel.Update("<p>Select a Request Year to display a chart.</p>");
                ChartPanel.BodyStyle = "text-align: center; display: table-cell; vertical-align: middle;";
                ChartPanelSouth.Title = "Charts";
                Ext.Net.X.Mask.Hide();
                return;
            }
            else
            {
                //ChartPanel.ClearContent();
                ChartPanel.BodyStyle = "text-align: left; display:inline; vertical-align: top;";
            }
    
            ChartRequestsByOrg(yrsSelected);
    
        }
    
        private void ChartRequestsByOrg(List<Checkbox> yrsSelected)
        {
            int yrsSelectedCount = yrsSelected.Count();
    
            string[] yFields = new string[yrsSelectedCount];
            string[] yTitles = new string[yrsSelectedCount];
            for (int i = 0; i < yrsSelectedCount; i++)
            {
                yFields[i] = "Y" + yrsSelected[i].InputValue;
                yTitles[i] = yrsSelected[i].InputValue;
            }
    
            // Create: Line Chart (Requests by Months)
            Chart byOrgChart = new Chart();
            byOrgChart.ID = "CrtsChart";
            byOrgChart.ClientIDMode = ClientIDMode.Static;
            byOrgChart.StyleSpec = "background:#fff";
            byOrgChart.StandardTheme = StandardChartTheme.Category1;
            byOrgChart.ContextMenuID = "CrtsChart_ContextMenu";
    
            if (!(Ext.Net.RequestManager.IsIE7 || Ext.Net.RequestManager.IsIE8))
            {
                byOrgChart.Animate = true;
                byOrgChart.AnimateConfig = new AnimConfig { Easing = Easing.EaseIn, Duration = 1000 };
                byOrgChart.AnimateConfig.Listeners.AfterAnimate.Fn = "chartAnimateComplete";
            }
            else
                byOrgChart.Listeners.AfterRender.Handler = "Ext.net.Mask.hide();";
    
            // Configure: Chart Legend
            byOrgChart.LegendConfig = new ChartLegend();
            byOrgChart.LegendConfig.Position = LegendPosition.Right;
    
            // Create: Category Axis
            CategoryAxis cAxis = new CategoryAxis();
            cAxis.Position = Position.Bottom;
            cAxis.Title = "Organization";
            cAxis.Fields = new String[] { "Name" };
            byOrgChart.Axes.Add(cAxis);
    
            // Create: Numeric Axis
            NumericAxis nAxis = new NumericAxis();
            nAxis.Position = Position.Left;
            nAxis.Title = "Requests";
            nAxis.Fields = yFields;
            nAxis.MinorTickSteps = 1;
            nAxis.Minimum = 0;
            nAxis.Grid = true;
            nAxis.GridConfig = new AxisGrid { Odd = new SpriteAttributes { Opacity = 1, Fill = "#ddd", Stroke = "#bbb", StrokeWidth = 0.5 } };
            byOrgChart.Axes.Add(nAxis);
    
            // Create: Column Series
            ColumnSeries cSeries = new ColumnSeries();
            cSeries.Axis = Position.Left;
            cSeries.Highlight = true;
            cSeries.XField = new String[] { "Name" };
            cSeries.YField = yFields;
            cSeries.Titles = yTitles;
    
            // Configure: Column Series Tips
            cSeries.Tips = new ChartTip();
            cSeries.Tips.TrackMouse = true;
            cSeries.Tips.TitleAlign = TitleAlign.Center;
            cSeries.Tips.BodyStyle = "text-align: center; font-size: 9px; ";
            cSeries.Tips.Renderer.Handler = "this.update('<b>' + String(item.yField) + '<br/>' + String(item.value[0]) + '<br/>Requests</b><hr><font color=blue>' + String(item.value[1]) + '</font>');";
    
            // Configure: Column Series Data Labels
            cSeries.Label = new SeriesLabel();
            cSeries.Label.Contrast = true;
            cSeries.Label.Display = SeriesLabelDisplay.InsideEnd;
            cSeries.Label.Color = "#000";
            cSeries.Label.TextAnchor = "top";
            cSeries.Label.Field = yFields;
            cSeries.Label.Orientation = Ext.Net.Orientation.Vertical;
    
            if (ShowLabels.Checked == true)
                cSeries.Label.Display = SeriesLabelDisplay.InsideEnd;
    
            byOrgChart.Series.Add(cSeries);
    
            // Configure: Enable/Disable series tooltips based on Context Menu option.
            byOrgChart.Series[0].Listeners.AfterRender.Handler = "chartTips(Ext.getCmp('ShowTips').checked);";
            byOrgChart.Series[0].Listeners.AfterRender.Handler = "chartLabels(Ext.getCmp('ShowLabels').checked);";
    
            // Create: Store
            Store store = new Store();
            store.ID = "ChartStore";
            store.ClientIDMode = ClientIDMode.Static;
    
            // Create: Model based on the years checked and add it to the store.
            store.Model.Add(createModel(yrsSelected));
    
            // Populate: Build the data for the store
            store.DataSource = generateData(yrsSelected).Values.ToList();
            //store.DataBind();
            byOrgChart.Store.Add(store);
    
            ChartPanel.RemoveAll();
            byOrgChart.AddTo(ChartPanel);
    
            ChartPanelSouth.Title = "Requests by Organization";
    
    
        }
    
        // Create a model based on the years checked
        private Model createModel(List<Checkbox> yrsSelected)
        {
            Model model = new Model();
            model.ID = "ModelByOrg";
            model.Fields.Add("Name");
    
            for (int i = 0; i < yrsSelected.Count(); i++)
            {
                ModelField field = new ModelField();
                field.Name = "Y" + yrsSelected[i].InputValue;
                field.Type = ModelFieldType.Float;
    
                // Allow special interpretation of the data only for this line chart.
                field.Convert.Handler = "if (value === null) {value = undefined;} return value;";
                model.Fields.Add(field);
            }
    
            return model;
        }
    
        private Dictionary<String, ChartByOrg> generateData(List<Checkbox> yrsSelected)
        {
            var theData = ChartByOrg.GenerateData();
            Random random = new Random();
            double p = (random.NextDouble() * 4) + 1;
    
            RequestsInfo[] byOrgRequests = new RequestsInfo[yrsSelected.Count() * 4];
            for (int y = 0; y < yrsSelected.Count(); y++)
            {
                for (int m = 0; m < 4; m++)
                {
                    RequestsInfo ri = new RequestsInfo();
                    ri.RequestOrg = ChartByOrg.Orgs[m];
                    ri.RequestYear = Convert.ToInt32(yrsSelected[y].InputValue);
                    ri.Requests = Convert.ToInt32(Math.Floor(Math.Max(random.NextDouble() * 100, 0)));
    
                    byOrgRequests[y * 4 + m] = ri;
                }
            }
    
            foreach (var reqCnts in byOrgRequests)
            {
                if (!theData.ContainsKey(reqCnts.RequestOrg))
                    theData.Add(reqCnts.RequestOrg, new ChartByOrg { Name = reqCnts.RequestOrg });
                
                string org = reqCnts.RequestOrg;
    
                switch (reqCnts.RequestYear)
                {
    
                    case 2013:
                        theData[reqCnts.RequestOrg].Y2013 = reqCnts.Requests;
                        break;
    
                    case 2012:
                        theData[reqCnts.RequestOrg].Y2012 = reqCnts.Requests;
                        break;
    
                    case 2011:
                        theData[reqCnts.RequestOrg].Y2011 = reqCnts.Requests;
                        break;
    
                    case 2010:
                        theData[reqCnts.RequestOrg].Y2010 = reqCnts.Requests;
                        break;
    
                    case 2009:
                        theData[reqCnts.RequestOrg].Y2009 = reqCnts.Requests;
                        break;
    
                    default:
                        break;
                }
    
            };
    
            return theData;
        }
        
    </script>
    <!DOCTYPE html >
    <html>
    <head id="Head1" runat="server">
        <title>Window issue IE7</title>
    </head>
    <body>
        <form id="Form1" runat="server">
        <ext:ResourceManager ID="ResourceManager1" runat="server" />
        <ext:Viewport ID="Viewport1" runat="server" Layout="BorderLayout">
            <Items>
                <ext:Panel ID="Center" runat="server" Region="Center" Title="Center" />
                <ext:Panel ID="ChartPanelSouth" runat="server" ClientIDMode="Static" Region="South"
                    Title="Charts" TitleAlign="Center" Icon="ChartBar" Height="240" Split="true"
                    Collapsible="true" Layout="BorderLayout" Collapsed="false">
                    <HtmlBin>
                        <script type="text/javascript">
    
                            function commonChartInit() {
                                Ext.net.Mask.show({ el: Ext.get('ChartPanel'), msg: 'Building Chart ...' });
                            }
    
                            var chartAnimateComplete = Ext.Function.createBuffered(function () { Ext.net.Mask.hide(); }, 1200);
    
    
                        </script>
                    </HtmlBin>
                    <DockedItems>
                        <ext:Toolbar ID="Toolbar1" runat="server" Dock="Left" Vertical="true">
                            <Items>
                                <ext:Button ID="ChartYears" runat="server" ToolTip="years" Icon="Calendar" ArrowAlign="Right"
                                    MenuAlign="tl-tr" AutoShow="true">
                                    <Menu>
                                        <ext:Menu ID="ChartYearsMenu" runat="server" Title="Request Years" TitleAlign="Center"
                                            ShowSeparator="false" RenderToForm="true">
                                            <Items>
                                                <ext:CheckboxGroup ID="ChartYearsCbGroup" runat="server" ClientIDMode="Static" ColumnsWidths="80,80"
                                                    Vertical="true">
                                                    <Listeners>
                                                        <Change Fn="commonChartInit" />
                                                    </Listeners>
                                                    <DirectEvents>
                                                        <Change OnEvent="ChartYearsChange" />
                                                    </DirectEvents>
                                                </ext:CheckboxGroup>
                                            </Items>
                                        </ext:Menu>
                                    </Menu>
                                </ext:Button>
                            </Items>
                        </ext:Toolbar>
                    </DockedItems>
                    <Items>
                        <ext:Panel ID="ChartPanel" runat="server" ClientIDMode="Static" Region="Center" Layout="BorderLayout">
                            <HtmlBin>
                                <script type="text/javascript">
                                    function chartLabels(checked) {
    
                                        var chart = Ext.getCmp('CrtsChart');
                                        var series = chart.series.items[0];
    
                                        if (checked === false) {
                                            series.label.display = "none";
                                            series.hideLabels();
                                        }
                                        else {
                                            series.label.display = "insideEnd";
                                            series.renderLabels();
                                        }
                                    }
    
                                    function chartTips(checked) {
    
                                        var chart = Ext.getCmp('CrtsChart');
    
                                        for (var i = 0; i < chart.series.length; i++) {
                                            var series = chart.series.items[i];
    
                                            if (checked === false) {
                                                // No reason to set originalTooltip if tooltip is undefined
                                                // OriginalTooltip might already have been set and do not want to clear it.
                                                if (series.tooltip != undefined)
                                                    series.originalTooltip = series.tooltip;
                                                delete series.tooltip;
                                            }
                                            else {
                                                // Just incase we start out as true, there is nothing in the original.
                                                if (series.originalTooltip != undefined)
                                                    series.tooltip = series.originalTooltip;
                                                delete series.originalTooltip;
                                            }
                                        }
                                    }
                                </script>
                            </HtmlBin>
                            <Bin>
                                <ext:Menu ID="CrtsChart_ContextMenu" runat="server" ClientIDMode="Static" RenderToForm="true"
                                    Title="Chart Options" TitleAlign="Center">
                                    <Items>
                                        <ext:CheckMenuItem ID="ShowLabels" runat="server" ClientIDMode="Static" Checked="true"
                                            Text="Data Labels">
                                            <Listeners>
                                                <CheckChange Handler="chartLabels(this.checked)" />
                                            </Listeners>
                                        </ext:CheckMenuItem>
                                        <ext:CheckMenuItem ID="ShowTips" runat="server" ClientIDMode="Static" Checked="true"
                                            Text="Tips">
                                            <Listeners>
                                                <CheckChange Handler="chartTips(this.checked)" />
                                            </Listeners>
                                        </ext:CheckMenuItem>
                                    </Items>
                                </ext:Menu>
                            </Bin>
                            <Items>
                            </Items>
                        </ext:Panel>
                    </Items>
                </ext:Panel>
            </Items>
        </ext:Viewport>
        </form>
    </body>
    </html>
  5. #5
    Hello!

    Try the following:

    function chartLabels(checked) {
    
    	var chart = Ext.getCmp('CrtsChart');
    	var series = chart.series.items[0];
    
    	if (checked === false) {
    		series.label.display = "none";
    		series.hideLabels();
    	}
    	else {
    		series.label.display = "insideEnd";
    		series.labelsGroup = series.chart.surface.getGroup(series.seriesId + '-labels');
    		var animate = series.chart.animate;
    		series.chart.animate = null;
    		series.renderLabels();
    		series.chart.animate = animate;
    	}
    }
  6. #6
    Based on your recommendations I now notice in the Ext.chart.Label function constructor that if the original display is "None" the labelsGroup will never be set and thus during the renderLabels function the labels will never be drawn.

    It would be nice if the class would allow you to reset the display and the labelsGroup would be rebuilt if needed, instead of having to know this relationship and perform it outside the class.

    I have taken your recommendation for the updated javascript code. I was going to remove the code that temporarily disabled the animation, but finally figured out that you added those 3 lines to mimic how labels are really shown after a chart has been displayed. If the chart is displayed without labels and then the user selects the context menu option to display them the labels would not be animated. But if those 3 lines are commented out and this is the first time for the labels to be displayed in the chart they were being animated.

    function chartLabels(checked) {
       var chart = Ext.getCmp('CrtsChart');
       var series = chart.series.items[0];
       if (checked === false) {
          series.label.display = "none";
          series.hideLabels();
       } else {
          series.label.display = "insideEnd";
          series.labelsGroup = series.chart.surface.getGroup(series.seriesId + '-labels');
          var animate = series.chart.animate;
          series.chart.animate = null;
          series.renderLabels();
          series.chart.animate = animate;
         }
     }
    You can close this thread. Please consider any overrides that would be convenient to the developer.
  7. #7
    Please see post above.

    You can close this thread. Please consider any overrides that would be convenient to the developer.
  8. #8
    Please clarify are you talking about a feature request to have a more convenient way to hide and show labels on the fly?
  9. #9
    Yea, I guess my situation would call for a feature request to have a more convenient way to hide and show labels on the fly.

    I was looking at this as a learning experience on how to extend/override the ExtJS javascript code to understand setDisplay(mode) and have it perform a couple of internal actions like:

    • Set the display attribute to function parameter mode;
    • Assign lablesGroup if not already assign;
  10. #10
    It is a nice suggestion. I posted a thread on the Sencha forums.
    http://www.sencha.com/forum/showthread.php?267656

    Hopefully, they will answer something.

    By the way, I would wrap the following in an "if" statement.
    if (!series.labelsGroup) {
        series.labelsGroup = series.chart.surface.getGroup(series.seriesId + '-labels');
    }
Page 1 of 2 12 LastLast

Similar Threads

  1. [OPEN] [#40] How can show the labels over each point of the LineSeries?
    By tactime10 in forum 2.x Legacy Premium Help
    Replies: 5
    Last Post: Nov 17, 2012, 12:43 AM
  2. Show/Hide fieldset
    By JosefTrbusek in forum 2.x Help
    Replies: 2
    Last Post: Aug 03, 2012, 7:04 AM
  3. Show/Hide tabs
    By stone216 in forum 1.x Help
    Replies: 2
    Last Post: Oct 01, 2009, 8:21 PM
  4. [CLOSED] Field Labels don't show
    By gokcemutlu in forum 1.x Legacy Premium Help
    Replies: 6
    Last Post: Jul 15, 2009, 9:18 AM
  5. How to hide/show ImageButton in JavaScript?
    By dbassett74 in forum 1.x Help
    Replies: 2
    Last Post: Jun 16, 2009, 3:47 PM

Posting Permissions