Announcement

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

    valueMap in Chrome gets resorted

    Hello,

    In FF and IE6 the drop down in the select items shows the expected order, however in Chrome (v2 and v3) it does not.
    A debug string is printed out which shows the expected order, which makes me believe it is not a GWT issue.


    Case:
    The valueMap here is sorted on value, rather than on key.
    But in Chrome the valueMap is sorted on key.

    tested on SmartGWT build 815


    Code:
    private Canvas getSortingTestSC() {
    	VLayout layout = new VLayout();
    	
    	DynamicForm form = new DynamicForm();
    	SelectItem select = new SelectItem("value");
    	
    	SortedSet<SomeObject> sortMeFirst = new TreeSet<SomeObject>();
    	sortMeFirst.add(new SomeObject("9", "AAA"));
    	sortMeFirst.add(new SomeObject("1", "ZZZ"));
    	sortMeFirst.add(new SomeObject("5", "NNN"));
    	
    	
    	StringBuffer sb = new StringBuffer();
    	
    	
    	LinkedHashMap<String, String> valueMap  = new LinkedHashMap<String, String>();
    	for (SomeObject obj : sortMeFirst) {
    		valueMap.put(obj.getKey(), obj.getValue());
    		sb.append(obj.getKey()).append("=").append(obj.getValue()).append(", ");
    	}
    	
    	//expected result after sort: AAA, NNN, ZZZ
    	select.setValueMap(valueMap);
    	
    	form.setFields(select);
    	
    	layout.addMember(form);
    	
    	//string contains correct order, selectItem does not show correct order in Chrome
    	//IE, FF are fine
    	SC.say(sb.toString());
    	
    	return layout;
    }
    
    private class SomeObject implements Serializable, Comparable<SomeObject> {
    	private static final long serialVersionUID = 1L;
    	private String key;
    	private String value;
    	
    	public SomeObject(String key, String value) {
    		this.key = key;
    		this.value = value;
    	}
    	
    	public void setKey(String key) {
    		this.key = key;
    	}
    	public String getKey() {
    		return key;
    	}
    	public void setValue(String value) {
    		this.value = value;
    	}
    	public String getValue() {
    		return value;
    	}
    
    	public int compareTo(SomeObject o) {
    		return this.getValue().compareTo(o.getValue());
    	}
    }

    #2
    This is almost certain to be a core GWT bug with TreeSet. Try removing the SmartGWT code (probably unnecessary to reproduce the problem) and posting it to the GWT forums.

    Comment


      #3
      Hello,

      this is now done with SmartGWT 2.0 and GWT 2.0.1.

      Screenshot from development mode:
      * In Chrome the GWT dropdown shows the values in expected sorted order.
      * I cannot click the drop-down on the SmartGWT component in development mode (works in compiled mode). I have this behavior in a lot of SelectItems in development mode.
      * You can browse the SmartGWT dropdown with the up & down keys, it shows the incorrect order ZZZ NNN AAA.
      * Expected and wrong order (as returned by SmartGWT component) is printed again.
      * Dropdown and printed values show a a weird "gwt_ObjectId" property.

      Screenshot 2 shows exactly the same done in IE development mode.
      * I can click the drop down and it shows the correct order.



      Any hints on how to discover this is a GWT bug rather than a SmartGWT bug would be appreciated.

      Code:
      public void onModuleLoad() {
      	VLayout layout = new VLayout();
      	layout.setWidth100();
      	DynamicForm form = new DynamicForm();
      	SelectItem select = new SelectItem("SmartGWT");
      	ListBox box = new ListBox(false);
      	box.setTitle("A GWT component");
      	SortedSet<SomeObject> sortMeFirst = new TreeSet<SomeObject>();
      	sortMeFirst.add(new SomeObject("9", "AAA"));
      	sortMeFirst.add(new SomeObject("1", "ZZZ"));
      	sortMeFirst.add(new SomeObject("5", "NNN"));
      	
      	//expected result after sort: AAA, NNN, ZZZ
      	//NOT sorted on key, which would be ZZZ NNN AAA
      	
      	StringBuffer sb = new StringBuffer();
      	LinkedHashMap<String, String> valueMap  = new LinkedHashMap<String, String>();
      	for (SomeObject obj : sortMeFirst) {
      		valueMap.put(obj.getKey(), obj.getValue());
      		box.addItem(obj.getValue(), obj.getKey());
      		sb.append(obj.getKey()).append("=").append(obj.getValue()).append(", ");
      	}
      	
      	//string contains correct order, selectItem does not show correct order in Chrome
      	//IE, FF are fine
      //		Window.alert(sb.toString());
      	
      	select.setValueMap(valueMap);
      	form.setFields(select);
      	layout.addMember(form);
      	Label label1 = new Label("<b>Order before being in ValueMap (expected order)</b>: " + sb.toString());
      	layout.addMember(label1);
      	sb.setLength(0);
      	Map newMap = select.getAttributeAsMap("valueMap");
      	for (Object key : newMap.keySet()) {
      		sb.append(key).append("=").append(valueMap.get(key)).append(", ");
      	}
      	Label label2 = new Label("<b>Order after being in ValueMap (WRONG)</b>: " + sb.toString());
      	layout.addMember(label2);
      	RootPanel.get().add(box);
      	RootPanel.get().add(layout);
      }
      
      private class SomeObject implements Serializable, Comparable<SomeObject> {
      	private static final long serialVersionUID = 1L;
      	private String key;
      	private String value;
      	
      	public SomeObject(String key, String value) {
      		this.key = key;
      		this.value = value;
      	}
      	
      	public void setKey(String key) {
      		this.key = key;
      	}
      	public String getKey() {
      		return key;
      	}
      	public void setValue(String value) {
      		this.value = value;
      	}
      	public String getValue() {
      		return value;
      	}
      
      	public int compareTo(SomeObject o) {
      		return this.getValue().compareTo(o.getValue());
      	}
      	
      }
      Attached Files

      Comment


        #4
        This is a bug with Chrome where for loops do not return properties in the order that they were added. See this issue.

        Sanjiv

        Comment


          #5
          Thanks for that link, Sanjiv.
          Seems like there are a lot of issues on that topic but up until now Chromium always responded with "won't fix".

          general info:
          The bug seems to happen because of the keys being numeric, and a workaround would be to add a character in front of the key which should make the dropdown look sorted also in Chrome (works fine in IE, FF).

          Comment


            #6
            Hi,

            From the looks of it, the Chrome team does not accept this as being an issue (as the specification does not define what should happen).
            Even worse, reports are out that Opera now also has this 'bug' so even more browsers might show this behavior in the future.

            I'm wondering if the SmartClient JavaScript developers maybe have a better suggestion/solution to this problem.


            Issue recap:
            create a LinkedHashMap to use as ValueMap. The keys are integers, the values are Strings. You want the ValueMap to be sorted on String value, not on keys.
            As the keys are integers, in Chrome, the ValueMap will not show up sorted by value anymore.

            A workaround is prepending a letter to all the keys, however hardly a good solution: records coming from a backend will have the integer as field, so it would be very impractical to change the number into a sortable-key.

            Comment


              #7
              They continue to receive tremendous pressure to switch back to the defacto standard behavior that all other browsers have implemented since the 90s. We are taking a wait and see approach since hacking in support for Chrome would be both a performance and expressiveness degradation.

              If you care about this issue, the best thing to do is to have all your developers "star" it, so that the Chrome team knows how many people are being affected.

              Comment


                #8
                I think this also affects DataSource objects and its Fields property in JS.
                When I check my ds.xml dump, the fields are described in expected order, but in Chrome, they show up in the GUI in a different order.
                In the client, I do a ds.getFields() and log these, and the fields are not anymore in the order they are defined in the ds.xml.

                Note that I create the form via JS calls, not by doing form.setDataSource(ds).
                Code:
                DynamicForm form =  new DynamicForm(_getFormFromDS(ds.getOrCreateJsObj()));
                
                private static native JavaScriptObject _getFormFromDS(JavaScriptObject myDS) /*-{
                   var fields = $wnd.isc.getValues(myDS.getFields());
                   return $wnd.isc.DynamicForm.create({
                       fields: fields,
                       autoFetchData: false,
                   });
                }-*/;
                IE8 and FF3.5.7 still work fine. Haven't tried the IE9 RC or FF4 beta's yet.


                I guess a workaround/solution would be to follow the Chromium's people advice and not rely on the JS implementation anymore of getting an object's properties and expect them to be in the same order as they were added, but add some kind of sequenceNr in the field tag. A call to ds.getFields() would then return the fields in the order via this property then. (+ also, I kind of believe that specifying data in an xml should never be used as 'in that defined order', but that's an xml philosophy discussion ;))

                I haven't found something like this in the server docs, could be maybe a nice addition?

                Comment


                  #9
                  This effects lots and lots of things, and there are various performance-sucking approaches to fixing it. We are still hoping to see Google respond to the massive outcry this has provoked.

                  Comment


                    #10
                    Yep, as expected. Same problem we see in Chrome is also seen in IE9. I think we have little chance now to blame it on the JS engine of Chrome.

                    Comment


                      #11
                      Actually, the standardization process seems to be leaning toward defining IE9's behavior as wrong (note current discussions in es-discuss mailing list) or at least, it's still up in the air.

                      Note, this should not affect fields unless the field has an entirely numeric name, which is technically invalid (a number is not a valid identifier).

                      Comment


                        #12
                        Originally posted by Isomorphic
                        a number is not a valid identifier
                        Hehe, ok, I guess you mean in SmartClient or JS then? As a lot of applications, databases, invoice systems, ... use numbers as identifiers to anything :)

                        And yes, that is the case with us. I'll see if I can make it non-numerical (which pretty much is the workaround for this problem) or do a re-sort on the client as discussed before.


                        Does it technically can break anything; using dsfield.name=1 ?

                        Comment


                          #13
                          A number is not an identifier in JavaScript, Java, C, C++, C#, Python, Ruby...

                          We haven't audited the code to see the consequences, but it's definitely not supported usage.

                          Comment


                            #14
                            Currently, what is solution for this problem?

                            Comment

                            Working...
                            X