Announcement

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

    list grid - when group by, sorting is not working in chrome

    Be sure your post includes:

    1. SmartGWT version: 2.5 PRO edition
    2. Browser: Chrome 27.0.1453.94, Firefox 10.0.2, IE 9

    I have a list grid with few columns. When the list grid is group by, the sorting is not working correctly. With the same piece of code, it is only happened on chrome. Firefox and IE9 is working perfectly fine.
    Please see the attached picture.
    Attached Files
    Last edited by hong6663; 6 Jun 2013, 05:59. Reason: attach file

    #2
    test case as below:

    Code:
    package com.example.GridSmartGWT2_5.client;
    
    import com.smartgwt.client.widgets.Canvas;  
    import com.smartgwt.client.widgets.IButton;  
    import com.smartgwt.client.widgets.events.ClickEvent;  
    import com.smartgwt.client.widgets.events.ClickHandler;  
    import com.smartgwt.client.widgets.grid.ListGrid;  
    import com.smartgwt.client.widgets.grid.ListGridField;  
    import com.example.GridSmartGWT2_5.client.data.SampleData;
    
    import com.google.gwt.core.client.EntryPoint;
    
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class GridSmartGWT2_5 implements EntryPoint {
    	/**
    	 * This is the entry point method.
    	 */
    	public void onModuleLoad() {
    		Canvas canvas = new Canvas();  
    		  
            final ListGrid sampleGrid = new ListGrid();  
            sampleGrid.setWidth(700);  
            sampleGrid.setHeight(800);  
            sampleGrid.setShowAllRecords(true);  
      
            ListGridField titleField = new ListGridField("title", "Title");  
            ListGridField ownerField = new ListGridField("owner", "Owner");  
            ListGridField sectionField = new ListGridField("section", "Section");  
            sampleGrid.setFields(titleField, ownerField, sectionField);  
            sampleGrid.setCanResizeFields(true);  
            sampleGrid.setData(SampleData.getRecords());  
            canvas.addChild(sampleGrid);          
      
            canvas.draw();  
    	}
    }
    
    package com.example.GridSmartGWT3_1.client.data;
      
    public class SampleData {  
      
        private static SampleRecord[] records;  
      
        public static SampleRecord[] getRecords() {  
            if (records == null) {  
                records = getNewRecords();  
            }  
            return records;  
        }  
      
        public static SampleRecord[] getNewRecords() {  
            return new SampleRecord[]{  
            		new SampleRecord("Prerelease Builder", "yong", "Supplement"),
                    new SampleRecord("Adeline Open Records", "yong", "Supplement"),
                    new SampleRecord("Prerelease Web", "yong", "Supplement"),
                    new SampleRecord("Documents", "yong", "Folder"),
                    new SampleRecord("My Owned Records", "yong", "Supplement"),
                    new SampleRecord("Web Awaiting", "yong", "Supplement"),
                    new SampleRecord("Open Web", "yong", "Supplement"),
                    new SampleRecord("My Closed Records", "yong", "Supplement"),
                    new SampleRecord("My Open Excel", "yong", "Supplement"),
                    new SampleRecord("Issues Found", "yong", "Supplement"),
                    new SampleRecord("New Daily Open", "yong", "Supplement"),
                    new SampleRecord("Open in last 7 days", "yong", "Supplement"),
                    new SampleRecord("Web New Release", "yong", "Supplement"),
                    new SampleRecord("Open Web Record", "yong", "Supplement"),
                    new SampleRecord("My Open Builder", "yong", "Supplement"),
                    
                    new SampleRecord("issue", "kay", "Supplement"),
                    new SampleRecord("Closed in last 14 days", "kay", "Supplement"),
                    new SampleRecord("New Daily Open Issue", "kay", "Supplement"),
                    new SampleRecord("feature", "kay", "Supplement")
            };  
        }  
    }  
    
    package com.example.GridSmartGWT2_5.client.data; 
    
    import com.smartgwt.client.widgets.grid.ListGridRecord;  
      
    public class SampleRecord extends ListGridRecord {  
      
        public SampleRecord() {  
        }  
      
        public SampleRecord(String title, String owner, String section) {  
            setTitle(title);  
            setOwner(owner);  
            setSection(section);    
        }  
      
        public void setTitle(String title) {  
            setAttribute("title", title);  
        }  
      
        public String getTitle() {  
            return getAttributeAsString("title");  
        }  
      
        public void setOwner(String owner) {  
            setAttribute("owner", owner);  
        }  
      
        public String getOwner() {  
            return getAttributeAsString("owner");  
        }  
      
        public void setSection(String section) {  
            setAttribute("section", section);  
        }  
      
        public String getSection() {  
            return getAttributeAsString("section");  
        }  
    }
    Last edited by Isomorphic; 13 Jun 2013, 19:27. Reason: formatted code block

    Comment


      #3
      Interesting that it should be a Chrome-specific bug.
      Natively, there is a difference in the way Chrome handles sorting arrays compared to other browsers, so this may be some manifestation of that issue.
      Regardless - thanks for the test case - we'll take a look and let you know what we find.

      Also - we see you're testing against 2.5. Is moving to 3.1 [or even the upcoming 4.0] likely to be a possibility for you?

      Thanks

      Isomorphic Software

      Comment


        #4
        We are still investigating this issue.
        A couple of things:

        Firstly - we are not seeing a difference between Chrome and other browsers with your attached sample code, running against either the latest 2.5p nightly build or the original 2.5 release (which had a build date of "2011-08-02").

        However we are seeing what looks like incorrect sorting behavior in both Chrome and Firefox. The culprit appears to be a bad interaction with the "title" field. If you rename this field something other than "title", the problem goes away.

        We are looking to resolve this issue, but wanted to check in with you to confirm that it matches your experience. Here's a reworked version with the title field renamed. Can you confirm that it is indeed fixing the problem for you?
        Code:
        /**
         * Entry point classes define <code>onModuleLoad()</code>.
         */
        public class GroupBySortBug implements EntryPoint {
        	/**
        	 * This is the entry point method.
        	 */
        	public void onModuleLoad() {
        		Canvas canvas = new Canvas();  
        		  
                final ListGrid sampleGrid = new ListGrid();  
                sampleGrid.setWidth(700);  
                sampleGrid.setHeight(800);  
                sampleGrid.setShowAllRecords(true);  
          
                ListGridField titleField = new ListGridField("xtitle", "Title");  
                ListGridField ownerField = new ListGridField("owner", "Owner");  
                ListGridField sectionField = new ListGridField("section", "Section");  
                sampleGrid.setFields(titleField, ownerField, sectionField);  
                sampleGrid.setCanResizeFields(true);  
                sampleGrid.setData(SampleData.getRecords());  
                canvas.addChild(sampleGrid);          
          
                canvas.draw();  
        	}
        	  
        	public static class SampleData {  
        	  
        	    private static SampleRecord[] records;  
        	  
        	    public static SampleRecord[] getRecords() {  
        	        if (records == null) {  
        	            records = getNewRecords();  
        	        }  
        	        return records;  
        	    }  
        	  
        	    public static SampleRecord[] getNewRecords() {  
        	        return new SampleRecord[]{  
        	        		new SampleRecord("Prerelease Builder", "yong", "Supplement"),
        	                new SampleRecord("Adeline Open Records", "yong", "Supplement"),
        	                new SampleRecord("Prerelease Web", "yong", "Supplement"),
        	                new SampleRecord("Documents", "yong", "Folder"),
        	                new SampleRecord("My Owned Records", "yong", "Supplement"),
        	                new SampleRecord("Web Awaiting", "yong", "Supplement"),
        	                new SampleRecord("Open Web", "yong", "Supplement"),
        	                new SampleRecord("My Closed Records", "yong", "Supplement"),
        	                new SampleRecord("My Open Excel", "yong", "Supplement"),
        	                new SampleRecord("Issues Found", "yong", "Supplement"),
        	                new SampleRecord("New Daily Open", "yong", "Supplement"),
        	                new SampleRecord("Open in last 7 days", "yong", "Supplement"),
        	                new SampleRecord("Web New Release", "yong", "Supplement"),
        	                new SampleRecord("Open Web Record", "yong", "Supplement"),
        	                new SampleRecord("My Open Builder", "yong", "Supplement"),
        	                
        	                new SampleRecord("issue", "kay", "Supplement"),
        	                new SampleRecord("Closed in last 14 days", "kay", "Supplement"),
        	                new SampleRecord("New Daily Open Issue", "kay", "Supplement"),
        	                new SampleRecord("feature", "kay", "Supplement")
        	        };  
        	    }  
        	}  
        	
        	  
        	public static class SampleRecord extends ListGridRecord {  
        	  
        	    public SampleRecord() {  
        	    }  
        	  
        	    public SampleRecord(String title, String owner, String section) {  
        	        setTitle(title);  
        	        setOwner(owner);  
        	        setSection(section);    
        	    }  
        	  
        	    public void setTitle(String title) {  
        	        setAttribute("xtitle", title);  
        	    }  
        	  
        	    public String getTitle() {  
        	        return getAttributeAsString("title");  
        	    }  
        	  
        	    public void setOwner(String owner) {  
        	        setAttribute("owner", owner);  
        	    }  
        	  
        	    public String getOwner() {  
        	        return getAttributeAsString("owner");  
        	    }  
        	  
        	    public void setSection(String section) {  
        	        setAttribute("section", section);  
        	    }  
        	  
        	    public String getSection() {  
        	        return getAttributeAsString("section");  
        	    }  
        	}
        }
        If you're seeing an additional problem which only manifests on Chrome, we may need more information, including a way to reproduce that specific problem.


        Secondly, the thread here appears to be a duplicate of this thread, and indicates that moving from 2.5 to 3.1 is likely not an option for you, and nor is upgrading to a new patched version for 2.5.
        This leads us to believe you'd prefer a "hot patch" (snippet of JavaScript) to drop into your live deployment to fix the problem.
        This is something we typically recommend against - this kind of hot patch is inherently less stable than picking up a fresh patched build as it doesn't run through our internal testing process. However we can proceed down this route if deploying a new nightly (2.5p branch) build with the patch applied is not going to be an option for you. Let us know.

        Also - let's consider the other thread closed and proceed on this thread rather than having two active reports of the same problem

        Regards
        Isomorphic Software

        Comment


          #5
          The following code snippet should resolve this issue for you against your current build:

          Code:
          <script>
          if (window.isc && isc.version.startsWith("SC_SNAPSHOT-2011-12-05")) {
          isc.Tree.addProperties({}, {
          
          $27n:function isc_Tree__makeOpenNormalizer(){
              var _1=this.sortProp,
                  _2=this.sortDirection,
                  _3=this.separateFolders!=false;
              var _4=isc.SB.create();
              _4.append(
                  "var __tree__ = ",this.getID(),";\rvar value = '';"
              );
              if(_3){
                  var _5,_6;
                  if(this.sortFoldersBeforeLeaves){
                      _5="0:";
                      _6="1:"
                  }else{
                      _5="1:";
                      _6="0:"
                  }
                  _4.append("value+=(__tree__.isFolder(obj) ? '"+_5+"' : '"+_6+"');")
              }
              if(_1 &&_1!=this.titleProperty) {
                  _4.append(
                      "var prop = obj['",_1,"'];",
                      "if (isc.isA.Number(prop)) {",
                          "if (prop > 0) prop = '1' + prop.stringify(12,true);",
                      "else {",
                          "prop = 999999999999 + prop;",
                          "prop = '0' + prop.stringify(12,true);",
                      "}",
                      "} else if (isc.isA.Date(prop)) prop = prop.getTime();",
                      "if (prop != null) value += prop + ':';"
                  )
              }
              if(_1){
                  _4.append(
                      "var title = __tree__.getTitle(obj);",
                      "if (isc.isA.Number(title)) {",
                      "if (title > 0) title = '1' + title.stringify(12,true);",
                      "else {","title = 999999999999 + prop;",
                          "title = '0' + title.stringify(12,true);",
                      "}",
                      "} else if (isc.isA.Date(title)) title = title.getTime();",
                      "if (title != null) {title = title + ''; value += title.toLowerCase()}"
                  )
              }
              _4.append("return value;");
              this.addMethods({
                  $27i:new Function("obj,property",_4.toString())
              })
          }
          
          });
          }
          </script>
          You can add this to your bootstrap HTML file, after loading the SmartClient libraries.
          If this doesn't fix the problem for you, please let us know.

          Regards
          Isomorphic Software

          Comment


            #6
            I put the snippet code to default.html file, as shown below, but, i am still seeing the issue in Chrome
            Code:
            <!doctype html>
            <!-- The DOCTYPE declaration above will set the     -->
            <!-- browser's rendering engine into                -->
            <!-- "Standards Mode". Replacing this declaration   -->
            <!-- with a "Quirks Mode" doctype is not supported. -->
            
            <html>
            <head>
            <meta http-equiv="content-type" content="text/html; charset=UTF-8">
            
            <!--                                                               -->
            <!-- Consider inlining CSS to reduce the number of requested files -->
            <!--                                                               -->
            <link type="text/css" rel="stylesheet" href="GridSmartGWT2_5.css">
            
            <!--                                           -->
            <!-- Any title is fine                         -->
            <!--                                           -->
            <title>Web Application Starter Project</title>
            
            <!--                                           -->
            <!-- This script loads your compiled module.   -->
            <!-- If you add any GWT meta tags, they must   -->
            <!-- be added before this line.                -->
            <!--                                           -->
            	<script>
                 var isomorphicDir = "gridsmartgwt2_5/sc/";
                 </script>
            <script type="text/javascript" language="javascript" src="gridsmartgwt2_5/gridsmartgwt2_5.nocache.js"></script>
            <script>
            if (window.isc && isc.version.startsWith("SC_SNAPSHOT-2011-12-05")) {
            isc.Tree.addProperties({}, {
            
            $27n:function isc_Tree__makeOpenNormalizer(){
                var _1=this.sortProp,
                    _2=this.sortDirection,
                    _3=this.separateFolders!=false;
                var _4=isc.SB.create();
                _4.append(
                    "var __tree__ = ",this.getID(),";\rvar value = '';"
                );
                if(_3){
                    var _5,_6;
                    if(this.sortFoldersBeforeLeaves){
                        _5="0:";
                        _6="1:"
                    }else{
                        _5="1:";
                        _6="0:"
                    }
                    _4.append("value+=(__tree__.isFolder(obj) ? '"+_5+"' : '"+_6+"');")
                }
                if(_1 &&_1!=this.titleProperty) {
                    _4.append(
                        "var prop = obj['",_1,"'];",
                        "if (isc.isA.Number(prop)) {",
                            "if (prop > 0) prop = '1' + prop.stringify(12,true);",
                        "else {",
                            "prop = 999999999999 + prop;",
                            "prop = '0' + prop.stringify(12,true);",
                        "}",
                        "} else if (isc.isA.Date(prop)) prop = prop.getTime();",
                        "if (prop != null) value += prop + ':';"
                    )
                }
                if(_1){
                    _4.append(
                        "var title = __tree__.getTitle(obj);",
                        "if (isc.isA.Number(title)) {",
                        "if (title > 0) title = '1' + title.stringify(12,true);",
                        "else {","title = 999999999999 + prop;",
                            "title = '0' + title.stringify(12,true);",
                        "}",
                        "} else if (isc.isA.Date(title)) title = title.getTime();",
                        "if (title != null) {title = title + ''; value += title.toLowerCase()}"
                    )
                }
                _4.append("return value;");
                this.addMethods({
                    $27i:new Function("obj,property",_4.toString())
                })
            }
            
            });
            }
            </script>
            </head>
            
            <!--                                           -->
            <!-- The body can have arbitrary html, or      -->
            <!-- you can leave the body empty if you want  -->
            <!-- to create a completely dynamic UI.        -->
            <!--                                           -->
            <body>
            
            	<!-- OPTIONAL: include this if you want history support -->
            	<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
            		style="position: absolute; width: 0; height: 0; border: 0"></iframe>
            
            	<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
            	<noscript>
            		<div
            			style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
            			Your web browser must have JavaScript enabled in order for this
            			application to display correctly.</div>
            	</noscript>
            </body>
            </html>
            Last edited by Isomorphic; 18 Jun 2013, 09:01. Reason: Formatted code block

            Comment


              #7
              As we noted earlier, we were not able to reproduce a Chrome-specific issue. However we will re-test and let you know what we find.
              Perhaps it would help if you could describe exactly the steps you are taking to perform the sort (clicking in the header vs something else), and clarify which field you are sorting against.

              Comment


                #8
                We have retested against Chrome (27.x), running on Windows 7, using your original test block of code, as well as our patch code (added to the bootstrap file, exactly how you have it displayed).
                We are still unable to reproduce the problem.

                Our steps to attempt to reproduce the problem are:
                - run the project as a web application via Eclipse
                - run a GWT compile (remember that it is invalid to test in dev mode in Chrome)
                - access the app via Chrome by going to the appropriate URL (with the "gwt.codesvr..." parameter omitted)
                - right click the "Owner" field header and group by owner
                - single click on the "Title" field to sort.
                Result - everything sorts as expected ("Adeline Open Records" --> "Web New Release"). Clicking the header again reverses the sort.

                Some thoughts on debugging this:
                1) Make sure you are testing in compiled mode (You should be accessing the web application with no codesvr param)
                2) Ensure the patch code is running. The easiest way to do this is to add an alert to it - something like this:
                Code:
                if (window.isc && isc.version.startsWith("SC_SNAPSHOT-2011-12-05")) {
                alert("Patch code running, and isc.Tree is defined?:" + (isc.Tree != null));
                
                isc.Tree.addProperties({}, {
                ... // Rest of the code follows here
                If you don't see the alert, the patch is not being applied - most likely the isc.version check is incorrect - you could just remove this check or correct it based on what isc.version reports as in your test case.

                3) Your screenshots don't match the data in the test case you posted - it is possible there is some difference between the cases. If you're reproducing the problem in the app, but not in the standalone test case, we will need to see a test case where we actually can reproduce the problem.

                Regards
                Isomorphic Software

                Comment


                  #9
                  Please revert the steps

                  - single click on the "Title" field to sort.
                  - right click the "Owner" field header and group by owner

                  We are seeing issue not only on 1 single grid with "title" column header. In our application, there are different grids with different columns headers, having the same issue.

                  Comment


                    #10
                    Ok we see the problem now. The order of the steps was significant.
                    Here's a patch for this problem.
                    Code:
                    <script>
                    
                    if (window.isc && isc.version.startsWith("SC_SNAPSHOT-2011-12-05")) {
                    
                    Array.prototype.sortByProperties = 
                    function isc_Arra_sortByProperties(){
                    var _1=isc.$gh,
                    _2=isc.$gi;
                    if(isc.isAn.Array(arguments[0])){this.sortProps=arguments[0];this.sortDirections=arguments[1]||[];
                    this.normalizers=arguments[2]||[];this.contexts=arguments[3]||[]}else{if(!this.sortProps){this.sortProps=[];
                    this.normalizers=[];this.sortDirections=[];this.contexts=[]}else{this.sortProps.clear();this.sortDirections.clear();
                    this.normalizers.clear();this.contexts.clear()}
                    for(var i=0;i<arguments.length;i++){this.sortProps[i]=arguments[i].property;this.sortDirections[i]=arguments[i].direction;
                    this.normalizers[i]=arguments[i].normalizer;this.contexts[i]=arguments[i].context}}
                    var _4=this.sortProps,
                    _5=this.normalizers,_6=this.contexts;var _7=isc.timestamp();for(var i=0;i<_4.length;i++){isc.$506[i]=this.sortDirections[i];var _8=_4[i],_9=_5[i],_10=_6[i];var _11;if(_9==null){_11=this.$gj(_4[i])}else if(isc.isA.String(_9)){_11=_9}
                    if(_11!=null)_9=Array.$gk(_11);if(_9==null)_9=Array.$gl;
                    this.normalizers[i]=_9;
                    if(this.length==0)continue;_1[i]=[];_2[i]=[];if(isc.isA.Function(_9)){for(var _12=0,l=this.length,_14;_12<l;_12++){_14=this[_12];if(_14==null){isc.$gq=true;continue}
                    _14.$gm=_12;var _15=_9(_14,this.sortProps[i],_10);_1[i][_12]=_15;if(_11!=null&&!Array.$gn(_14[this.sortProps[i]],_11)){_2[i][_12]=_14[this.sortProps[i]]}
                    var _16;if(isc.isA.SpecialNumber(_15)&&isNaN(_15)){_1[i][_12]=0-Number.MAX_VALUE}}}else{
                    var _17=this.normalizers[i];
                    for(var _12=0,l=this.length,_14;_12<l;_12++){
                     _14=this[_12];
                     if(_14==null){
                         isc.$gq=true;continue
                     }
                     var _18=_14[this.sortProps[i]];
                     if(_18==null)_18='';
                     var _15=_17[_18];
                     if(_15==null)_15=_18;
                     _14.$gm=_12;
                     _1[i][_12]=_15
                    }
                    }
                    }
                    // Patch code to compensate for unstable sort in Chrome
                    if (isc.Browser.compensateForUnstableSort == null) {
                        isc.Browser.compensateForUnstableSort =
                                // Webkit covers Chrome, Safari, Android
                                isc.Browser.isWebKit || isc.Browser.isOpera ||
                                (isc.Browser.isIE && isc.Browser.version>=9);
                                
                    }
                    if (isc.Browser.compensateForUnstableSort) {
                        var numProps = _1.length;
                        _1[numProps] = [];
                        for (var i = 0; i < this.length; i++) {
                            _1[numProps][i] = i;
                        }
                        
                        var wrongTypeArrayNumPos = _2.length;
                        if (wrongTypeArrayNumPos != 0) {
                            _2[wrongTypeArrayNumPos] = [];
                            for (var i = 0; i < this.length; i++) {
                                _2[wrongTypeArrayNumPos][i] = i;
                            }            
                        }
                        isc.$506[numProps] = true;
                    }
                    // end of patch code to compensate for unstable sort
                    var _19=false;
                    for(var i=0;i<isc.$gi.length;i++){if(isc.$gi[i].length>0){_19=true;break}}
                    isc.$752=_19;var _20=isc.$gh,_21=isc.$506,_19=isc.$752;var _22=this;_22.compareAscending=Array.compareAscending;_22.compareDescending=Array.compareDescending;var _23=function(_32,_33){var _24=(_32!=null?_32.$gm:null),_25=(_33!=null?_33.$gm:null);for(var i=0;i<_20.length;i++){var _26=_20[i][_24],_27=_20[i][_25];if(_19&&_26!=null&&_27!=null){var _28=isc.$gi,_29=_28[i][_24],_30=_28[i][_25];if(_29!=null&&_30!=null){_26=_29;_27=_30}}
                    var _31=(_21[i]?_22.compareAscending(_26,_27):_22.compareDescending(_26,_27));if(_31!=0)return _31}
                    return 0};var _7=isc.timeStamp();this.sort(_23);if(isc.$gq){isc.Log.logWarn("Attempt to sort array by property hit null entry where a record should be. Array:"+isc.Log.echo(this));isc.$gq=null}
                    this.clearProperty("$gm");_1.clear();_2.clear();isc.$506.clear();this.dataChanged();return this
                    }
                    }
                    
                    </script>

                    Comment


                      #11
                      Fixed my issue

                      Thank you so much for this patch! We've been wrestling with this Chrome specific behavior and developed a messy workaround a while back. I've tested this patch and it works great for Chrome. Thanks!

                      Comment

                      Working...
                      X