Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Getting x-axis value from ChartPointClickEvent

    I'm using SmartGWT 3.1d 11/19/2012 build with Firefox 11.

    I'm using the inlined-Facet approach in this post to create line charts where I wind up with a reduced number of x-axis labels, and one CellRecord for each line on the chart. For rendering purposes, this solution has worked well.

    I have a need to be able to click on the points and take action depending on what point is clicked. I've set a ChartPointClickHandler and am calling setShowDataPoints(true).

    The Handler is being called, but the API of the ChartPointClickEvent only provides for getting the Record and the value(), which corresponds to a y-axis value in my case. The problem is the Record contains all of the y-values as distinct attribute names and there is no way to tell which of the particular attribute names was actually clicked. Theoretically, if every x-value (ie, unique attribute name) had a distinct y-value, I could iterate over all of the record attributes and match the event.getValue() to a particular attribute value. But if two or more attributes have the same double value, that technique will not work.

    Is there any workaround to this, given that I still have the need to limit the number of x-axis labels?

    Given that you're correctly determining which x-axis value in my series is being clicked, if you could pass that information back to me in the event, I think I could work out some solution.

    Thanks in advance.

    #2
    getNearestDrawnValue, added in 3.1, is a much more general-purpose API that can be applied to solve this use case.

    Comment


      #3
      Sounds promising... I tried making use of it from within the onPointClick(ChartPointClickEvent event) callback. I called FacetChart.getNearestDrawnValue(), and from that, called getFacetValues(), since that seemed to be the path to my data. This is what I got:

      Code:
      (BaseWidget.java:-1) 2012-11-19 21:12:08,256 [ERROR] Error using getNearestDrawnValue()
      com.google.gwt.core.client.JavaScriptException: (TypeError): $wnd.isc[scClassName] is undefined
          at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:248)
          at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
          at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
          at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
          at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
          at com.smartgwt.client.widgets.BaseWidget.getAttributeAsJavaScriptObject(BaseWidget.java)
          at com.smartgwt.client.widgets.chart.DrawnValue.getFacetValues(DrawnValue.java:181)
      The text "Error using getNearestDrawnValue()" is my own message emitted from com.allen_sauer.gwt.log.client.Log.error(String,Throwable)

      Please advise... thanks.

      Comment


        #4
        Any update on this?

        Comment


          #5
          Sorry, this was fixed several days ago, we forgot to notify you.

          Comment


            #6
            I downloaded the 11/30/2012 build and am still getting the error:

            Code:
            (BaseWidget.java:-1) 2012-11-30 11:58:51,406 [ERROR] Error getting facetValues: 
            com.google.gwt.core.client.JavaScriptException: (TypeError): $wnd.isc[scClassName] is undefined
                at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:248)
                at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
                at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
                at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
                at com.smartgwt.client.widgets.BaseWidget.getAttributeAsJavaScriptObject(BaseWidget.java)
                at com.smartgwt.client.widgets.chart.DrawnValue.getFacetValues(DrawnValue.java:181)
                at com.mycode.$16.onPointClick(MyCode.java:1043)
            Here's the setup code:
            Code:
            chart.setShowDataPoints(true);
            chart.setPointClickHandler(new ChartPointClickHandler()
            {
                public void onPointClick(ChartPointClickEvent chartPointClickEvent)
                {
                     DrawnValue nearestDrawnValue = chart.getNearestDrawnValue();
            
                     try{
                          FacetValueMap facetValues = nearestDrawnValue.getFacetValues();
            
                          String[] facetIds = facetValues.getFacetIds();
            
                          Log.warn("break here.");
                      }
                      catch (Throwable t){
                          Log.error("Error getting facetValues: ",t);
                      }
                 }
            });
            My intention with the "Log.warn("break here.");" was to break in my debugger, inspect the resulting data and code from there...

            Can you provide the coding pattern that works in your test suite? I'll gladly just use that and move on. Or, set me straight with where I'm going astray...

            Thanks.

            Comment


              #7
              This is now fixed for 3.1p builds. A mixup related to the release meant the previous fix was only committed for 4.0.

              Comment


                #8
                The method is working correctly, however, I'm in a similar position. Asking the DrawnValue for its FacetValueMap yields a map that contains one attribute for each of the x-axis points on the graph, with no indication of which point in a given series was actually clicked. In practice, it appears that the FacetValueMap's attributes are no different than those I can via ChartPointClickEvent.getRecord().getAttributes().

                Given the data structures that you specified in your solution to doing multi-line graphs with a limited number x-axis labels (see reference within original post), I need an API that upon clicking a point in the graph will yield the following:

                1. Which time series on the graph was clicked
                2. Which point in that time series was clicked, expressed not in screen coordinates, but as an ordinal value relative to the length of the series.

                For example, if graphing the daily closing prices of three stocks A, B and C for three years (roughly 750 data points), with an x-axis label placed on the first trading day of each month, upon trapping a mouse click on the graph, I'd want to know that the user clicked (say) stock B, point # 452.

                From there, I can get to my own data structures and I'm off to the races.

                I do acknowledge that if in the above examples two or more of the stocks had the same price on a given day, determining exactly which series, A, B or C the user clicked would be ambiguous on that day. If your API returned an array of series identifiers, that would work well. Maybe in addition to getRecord(), a "public Record[] getRecords()" method could be added.

                I think I can answer requirement #1, above:

                chartPointClickEvent.getRecord().getAttribute("description") will return the series name ("stock B"), because my chart has one CellRecord per series, and "description" is a Facet that differentiates each series.

                I'm still stuck on requirement #2.

                If you had a different approach in mind in your Nov 19th reply, can you please specify short code example or provide more details of your thoughts?

                Thanks.

                Comment


                  #9
                  We're not quite following - you have the Record object and you have the list of Records. Can't you determine the index of the Record via indexOf()?

                  It seems like our APIs are already providing information that uniquely identifies the point.

                  Comment


                    #10
                    With this single-axis implementation, the data model uses one CellRecord for each series. (See also, my other outstanding issue, "Dual Axis Charts with Sparse X-axis labels").

                    Therefore, my "list of Records" only describes a collection of time series, not a given point within the time series. Put differently, the Record I get back from your event handler IS the ENTIRE time series. Within the Record, there is one attribute set for each y-value, there may be hundreds of them, and I see no way of knowing which of them is the one that corresponds to the clicked point.

                    If you attach this code
                    Code:
                    chart.setPointClickHandler(new ChartPointClickHandler()
                            {
                                public void onPointClick(ChartPointClickEvent event)
                                {
                                    Record record = event.getRecord();
                    
                                   String[] attributes = record.getAttributes();
                                   for (String a : attributes){
                                       Log.warn(a);
                                   }
                    
                                }
                            });
                    to the single-axis example in that other post, and click a point on the chart, I think you'll see what I mean.

                    Comment


                      #11
                      getNearestDrawnValue() gives you the specific facetValues that apply for the click. The record can be ambiguous, but the facetValues are not: they provide you which specific property name has the value for the nearest point to the click.

                      Comment


                        #12
                        To demonstrate the problem, I've applied an elaboration of the code suggested in my last post, to the demo code of my other outstanding post. The code dumps the faceValues for the clicked point:
                        Code:
                        chart.setPointClickHandler(new ChartPointClickHandler()
                                {
                                    public void onPointClick(ChartPointClickEvent chartPointClickEvent)
                                    {
                                        DrawnValue nearestDrawnValue = chart.getNearestDrawnValue();
                        
                                        try{
                                            FacetValueMap facetValues = nearestDrawnValue.getFacetValues();
                        
                                            String[] facets = facetValues.getFacetIds();
                        
                                            Log.warn("Clicked record, value was " + chartPointClickEvent.getValue());
                                            StringBuilder facetNames = new StringBuilder();
                                            for (String facet : facets){
                                                facetNames.append("\n'").append(facet).append("'");
                                            }
                                            Log.warn("\n\n" + facetNames.toString());
                        
                        //                    Log.warn("break here.");
                                        }
                                        catch (Throwable t){
                                            Log.error("Error getting facetValues: ", t);
                                        }
                                    }
                                });
                        Upon running that code, I click the third point of Series A in the chart. The event handler detects the click, and here is the output:

                        Code:
                        (DualYAxisSparseXAxisTester.java:91) 2012-12-11 23:09:32,293 [WARN ] Clicked record, value was 200.0
                        (DualYAxisSparseXAxisTester.java:96) 2012-12-11 23:09:32,306 [WARN ] 
                        
                        
                        '__ref'
                        'description'
                        'id_1'
                        'id_2'
                        'id_3'
                        'id_5'
                        With my debugger, I can see that
                        chartPointClickEvent.getRecord().getAttribute("description") is "A label"

                        Two issues:
                        1. Using the facet names above, can you please tell me how I can know that the user clicked the third point on the chart?
                        2. The code very clearly specifies five xAxisAttributes for series A "id_1..id_5" What happened to id_4?

                        Comment


                          #13
                          Take a look at the API for FacetValueMap - it provides a mapping from facetIds to facetValueIds. Your code is just dumping the facetIds, you need to call getMapping to get the values.

                          The missing point 4 appears to be the same issue we're already looking at from the other thread.

                          Comment


                            #14
                            In my example, the user has clicked the 3rd point on a line containing five points.

                            I've experimented with the API of FacetValueMap...

                            What argument to 'getMapping' would you have me use, such that I will be told by that method that the user clicked the 3rd point on the line, instead of say, the 2nd point, or the 5th?

                            Comment


                              #15
                              We've fixed a bug where the FacetValueMap could actually end up being the Record object. Now that it's really the FacetValueMap, the facetValue for the "xLabels" facet will be, for instance, id_3, uniquely identifying a point. This is in tomorrow's 3.1p and 4.0d builds.

                              Comment

                              Working...
                              X