Announcement

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

    ListGrid shifts upward on click

    SmartClient Version: v8.2p_2012-08-14/Enterprise Deployment (built 2012-08-14)

    Happens in: IE 9, IE 9 Compatability Mode, Chrome 21.0.1180.79 m

    Does not happen in FireFox 8.0.1

    I have a ListGrid inside of a section stack panel. The first time I navigate to the page, it works correctly. If I navigate to another page, and then come back, when I click on a row in the grid, the entire grid shifts upward 44 pixels, putting the header under the section stack header.

    Also, if I resize the page, the header returns to the correct position.

    I used IE developer console to take a snapshot of the HTML before and after clicking on the row, and did a comparison, and the only difference is as follows:

    Before (working):
    Code:
    <DIV onblur=if(window.isc)isc.EH.blurFocusCanvas(isc_ListGrid_2_body,true); style="Z-INDEX: 201926; POSITION: absolute; WIDTH: 946px; HEIGHT: 392px; OVERFLOW: hidden; CURSOR: default; TOP: 44px; LEFT: 0px" onscroll="return isc_ListGrid_2_body.$lh()" id=isc_71 class=gridBody onfocus=isc.EH.focusInCanvas(isc_ListGrid_2_body,true); tabIndex=1248 eventProxy="isc_ListGrid_2_body" $ys="0" $yt="0">
    After (Shifted up):
    Code:
    <DIV onblur=if(window.isc)isc.EH.blurFocusCanvas(isc_ListGrid_2_body,true); style="Z-INDEX: 201926; POSITION: absolute; WIDTH: 946px; HEIGHT: 392px; OVERFLOW: hidden; CURSOR: default; TOP: 44px; LEFT: 0px" onscroll="return isc_ListGrid_2_body.$lh()" id=isc_71 class=gridBody onfocus=isc.EH.focusInCanvas(isc_ListGrid_2_body,true); tabIndex=1248 eventProxy="isc_ListGrid_2_body" $ys="0" $yt="0" $yu="44" $yv="44">
    At the end, the attributes $yu and $yv change from 0 to 44.

    Custom Widget
    Code:
    public class CallCenterListGrid extends SectionStack implements HasRecordDoubleClickHandlers {
    
    	private final ListGrid grid;
    	private final boolean wrapHeaders;
    	private final Autofit autoFitApproach;
    
    	public CallCenterListGrid(boolean showFilterEditor, String gridTitle, boolean wrapHeaders, Autofit autoFitApproach)
    	{
    		this(showFilterEditor, gridTitle, wrapHeaders, autoFitApproach, null);
    	}
    	
    	public CallCenterListGrid(boolean showFilterEditor, String gridTitle, boolean wrapHeaders, Autofit autoFitApproach, Integer height)
    	{
    		this.wrapHeaders = wrapHeaders;
    		this.autoFitApproach = autoFitApproach;
    
    		this.setWidth100();
    		
    		if (height == null){
    			this.setHeight100();
    		} else {
    			this.setHeight(height);
    		}
    		
    		this.setMinHeight(200);
    
    		SectionStackSection section = new SectionStackSection(gridTitle);  
    		section.setCanCollapse(false);
    		section.setExpanded(true);
    		
    		HeaderControl refresh = new HeaderControl(HeaderControl.REFRESH, new ClickHandler() {
    			
    			@Override
    			public void onClick(ClickEvent event) {
    				CallCenterListGrid.this.grid.invalidateCache();
    			}
    		});  
    
    		section.setControls(refresh);
    
    		grid = new ListGrid();
    		
    		if (wrapHeaders){
    			this.grid.setHeaderHeight(33);
    		} else {
    			this.grid.setHeaderHeight(22);
    		}
    
    		this.grid.setWidth100();
    		this.grid.setHeight100();
    		this.grid.setCanResizeFields(true);
    		this.grid.setAutoFetchData(true);
    		this.grid.setAutoFitFieldWidths(true);
    		this.grid.setAutoFitWidthApproach(AutoFitWidthApproach.BOTH);
    		this.grid.setShowFilterEditor(showFilterEditor);  
    		
    		if (autoFitApproach.equals(Autofit.VERTICAL) || autoFitApproach.equals(Autofit.BOTH)) {
    			this.grid.setWrapCells(true);
    			this.grid.setFixedRecordHeights(false);
    		}
    		
    		this.setStyleName("sectionStack list-grid");
    
    		section.setItems(grid);
    		this.addSection(section);		
    	}
    
    	@Override
    	public HandlerRegistration addRecordDoubleClickHandler(
    			RecordDoubleClickHandler handler) {
    		return this.grid.addRecordDoubleClickHandler(handler);
    	}
    
    	public ListGrid getGrid() {
    		return grid;
    	}
    
    	public void setDataSource(DataSource datasource){
    		this.grid.setDataSource(datasource);
    
    		for (ListGridField field : this.grid.getFields()) {
    			// Wrap the headers
    			if (this.wrapHeaders){
    				String title = field.getTitle();
    
    				String[] parts = title.split(" ");
    
    				if (parts.length > 1) {
    					if (parts[0].length() > 1 && parts[parts.length - 1].length() > 1){
    						field.setWrap(true);
    					}
    				}
    			}
    			
    			// Format all decimal fields as 0.00
    			if (field.getType() == ListGridFieldType.FLOAT){
    				field.setCellFormatter(new CellFormatter() {  
    		            public String format(Object value, ListGridRecord record, int rowNum, int colNum) {  
    		                if(value == null) return null;  
    		  
    		                String val = null;  
    		                try {  
    		                    NumberFormat nf = NumberFormat.getFormat("0.00");  
    		                    val = nf.format(((Number) value).doubleValue());  
    		                } catch (Exception e) {  
    		                    return value.toString();  
    		                }  
    		                return val;  
    		            }  
    		        });  
    			}
    		}
    	}
    
    }
    CSS
    Code:
    .list-grid {
      margin-bottom: 5px;
    }
    View
    Code:
    public class TransmitSessionDetailPageView extends ViewImpl implements TransmitSessionDetailPagePresenter.MyView {
    
    	// Overall layout of page.  Root container.
    	private VLayout layout;
    
    	// Transmit Session Error Log
    	private HLayout errorLogBar;
    
    	// Transmit Session Details
    	private DetailGroupForm detailForm;
    	
    	// In Process Transaction Grid
    	private CallCenterListGrid inProcessTransactionGrid;
    
    	// Transaction grid
    	private CallCenterListGrid transactionGrid;
    
    	private Button errorLogButton;
    
    	@Inject
    	public TransmitSessionDetailPageView() {
    		this.layout = new VLayout();
    		this.layout.setWidth100();
    		this.layout.setHeight100();
    
    		this.errorLogBar = new HLayout();
    		this.errorLogBar.setWidth100();
    		this.errorLogBar.setHeight(25);
    		this.errorLogBar.setAlign(Alignment.RIGHT);
    
    		errorLogButton = new Button("View Error Log");  
    		errorLogButton.setShowRollOver(true);  
    		errorLogButton.setShowDisabled(true);  
    		errorLogButton.setShowDown(true);  
    		errorLogButton.setWidth(150);
    		errorLogButton.setIcon("[SKIN]/FileBrowser/file.png");  
    		this.errorLogBar.addMember(errorLogButton);
    
    		this.layout.addMember(errorLogBar);
    
    
    		this.detailForm = new DetailGroupForm();
    		this.layout.addMember(detailForm);
    		
    		this.inProcessTransactionGrid = new CallCenterListGrid(true, "In Process Transactions", false, Autofit.HORIZONTAL, 200);
    		this.layout.addMember(inProcessTransactionGrid);
    
    		this.transactionGrid = new CallCenterListGrid(true, "Completed Transactions", false, Autofit.HORIZONTAL);
    		this.layout.addMember(transactionGrid);
    	}
    
    	@Override
    	public Widget asWidget() {
    		return this.layout;
    	}
    
    	@Override
    	public HasText getDetailGroup() {
    		return this.detailForm;
    	}
    
    	@Override
    	public void bindTransmissionDetail(DataSource transmissionDataSource, Integer id) {
    		this.detailForm.setDataSource(transmissionDataSource);
    
    		// Format Error Message
    		FormItem error = this.detailForm.getField("errorMessage");
    		error.setColSpan(10);
    		error.setRowSpan(3);
    
    		this.detailForm.fetchData(new Criteria("transmitSessionId", id.toString()), new DSCallback() {
    
    			@Override
    			public void execute(DSResponse response, Object rawData, DSRequest request) {
    				// Show error log icon if it exists
    				Boolean errorLogExists = response.getData()[0].getAttributeAsBoolean("errorLogExists");
    
    				if (errorLogExists != null && errorLogExists){
    					TransmitSessionDetailPageView.this.errorLogBar.show();
    				} else {
    					TransmitSessionDetailPageView.this.errorLogBar.hide();
    				}
    
    
    			}
    		});
    	}
    
    	@Override
    	public void bindTransactions(DataSource transactionDataSource, Integer id) {
    		this.transactionGrid.setDataSource(transactionDataSource);
    		this.transactionGrid.getGrid().fetchData(new Criteria("transmitSessionId", id.toString()), null);
    	}
    	
    	@Override
    	public void bindInProcessTransactions(DataSource transactionDataSource, Integer id) {
    		this.inProcessTransactionGrid.setDataSource(transactionDataSource);
    		this.inProcessTransactionGrid.getGrid().fetchData(new Criteria("transmitSessionId", id.toString()), null);
    	}
    
    	@Override
    	public HasClickHandlers getViewErrorLogButton() {
    		return this.errorLogButton;
    	}
    
    	@Override
    	public HasRecordDoubleClickHandlers getTransactionSelected() {
    		return this.transactionGrid;
    	}
    
    
    }
    Main Page View
    Code:
    public class MainPageView extends ViewImpl implements MainPagePresenter.MyView {
    	// Layout values
    	private static final Integer PAGE_WIDTH = 960;
    	private static final Integer CONTENT_HEIGHT = 720;
    	private static final Integer DEFAULT_PADDING = 5;
    	private static final Integer HEADER_HEIGHT = 50;
    	private static final Integer TITLE_LOGO_WIDTH = 103;
    	private static final Integer TITLE_TEXT_WIDTH = (PAGE_WIDTH - (2 * TITLE_LOGO_WIDTH) - (4 * DEFAULT_PADDING)); 
    	private static final Integer TITLEBAR_HEIGHT = (int) (HEADER_HEIGHT * .8);
    	
    	
    	// Overall layout of page.  Root container.
    	private VLayout layout;
    	
    	// Header section common to all pages.  Parent: layout
    	private VLayout masthead;
    	// Top of header, contains login info and title.  Parent: masthead
    	private ToolStrip titleBar;
    	
    	private Label usernameLabel;
    	
    	// Bottom of header, contains breadcrumb navigation.  Parent: masthead
    	private BreadCrumbs breadCrumbs;
    	
    	// Main content section where pages will be revealed.  Parent: layout
    	private VLayout workArea;
    	private ToolStripButton homeButton;
    	
    	
    	@Inject
    	public MainPageView() {
    		this.layout = new VLayout();
    		//this.layout.setPadding(DEFAULT_PADDING);
    		this.layout.setWidth(PAGE_WIDTH);
    		this.layout.setHeight100();
    		this.layout.setStyleName("main-layout");
    
    		this.masthead = new VLayout();
    		this.masthead.setHeight(HEADER_HEIGHT);
    		this.masthead.setWidth100();
    		this.masthead.setMargin(DEFAULT_PADDING);
    		this.layout.addMember(this.masthead);
    		
    		this.titleBar = new ToolStrip();
    		this.titleBar.setHeight(TITLEBAR_HEIGHT);
    		this.titleBar.setPadding(DEFAULT_PADDING);
    		this.titleBar.setWidth100();
    		
    		homeButton = new ToolStripButton();
    		homeButton.setIcon("ag-logo.png");
    		homeButton.setIconWidth(TITLE_LOGO_WIDTH);
    		homeButton.setIconHeight(31);
    		homeButton.setHeight(41);
    		
    		homeButton.addClickHandler(new ClickHandler() {
    			
    			@Override
    			public void onClick(ClickEvent event) {
    				
    				
    			}
    		});
    		
    		Label titleLabel = new Label("Telxon USB Call Center");
    		titleLabel.setWidth(TITLE_TEXT_WIDTH);
    		titleLabel.setAlign(Alignment.CENTER);
    		titleLabel.setStyleName("title");
    		
    		VLayout userNamePanel = new VLayout();
    		userNamePanel.setWidth("*");
    		userNamePanel.setAlign(Alignment.RIGHT);
    		userNamePanel.setAlign(VerticalAlignment.CENTER);
    		
    		Label welcomeLabel = new Label("Welcome");
    		welcomeLabel.setHeight(22);
    		welcomeLabel.setAlign(Alignment.RIGHT);
    		welcomeLabel.setValign(VerticalAlignment.BOTTOM);
    		userNamePanel.addMember(welcomeLabel);
    		
    		usernameLabel = new Label();
    		usernameLabel.setHeight(22);
    		usernameLabel.setAlign(Alignment.RIGHT);
    		usernameLabel.setValign(VerticalAlignment.TOP);
    		userNamePanel.addMember(usernameLabel);
    		
    		this.titleBar.addButton(homeButton);
    		this.titleBar.addMember(titleLabel);
    		this.titleBar.addMember(userNamePanel);
    		
    		this.masthead.addMember(this.titleBar);
    		
    		this.breadCrumbs = new BreadCrumbs();
    		this.masthead.addMember(breadCrumbs);
    		
    		
    		this.workArea = new VLayout();
    		this.workArea.setWidth100();
    		this.workArea.setMargin(DEFAULT_PADDING);
    		this.workArea.setHeight("*");
    		this.layout.addMember(this.workArea);
    	}
    	
    	@Override
    	public void setInSlot(Object slot, Widget content) {
    		this.workArea.removeMembers(this.workArea.getMembers());
    		if (slot == MainPagePresenter.TYPE_SetWorkAreaContent && content != null) {
    			this.workArea.setMembers((Canvas) content);
    		} else {
    			super.setInSlot(slot, content);
    		}
    	}
    
    	@Override
    	public Widget asWidget() {
    		return this.layout;
    	}
    	
        @Override
        public Canvas getMasthead() {
            return this.masthead;
        }
    
        @Override
        public Canvas getBody() {
            return this.workArea;
        }
        
        @Override
        public void setUsername(String username) {
        	this.usernameLabel.setContents(username);
        }
    
        @Override
        public HasClickHandlers getBreadcrumbs() {
            return this.breadCrumbs;
        }
    
    	@Override
    	public void refreshBreadcrumbs(PlaceManager placeManager) {
    		this.breadCrumbs.refreshBreadcrumbs(placeManager);
    	}
    
    	@Override
    	public HasClickHandlers getTitleLogoButton() {
    		return homeButton;
    	}
    
    }
    I can supply additional code if necessarily, if this is not enough to be of help.
    Attached Files
    Last edited by habermanm; 15 Aug 2012, 11:00.

    #2
    Your "after" screenshot doesn't necessarily look like something is going wrong at a DOM level, it just looks like the result of a call to setShowFilterEditor(false). We'd recommend checking if you're somehow making this call, and checking the value getShowFilterEditor() when in the "after" state.

    If that's not the problem, it's likely to be something in your CSS styles, of which you've only shown one. Try removing all custom styles and see if the problem is still reproducible, then reintroducing styles to find which is the issue.

    Comment


      #3
      They are still there, just hidden behind the stack header. You can see them peeking out from beneath, and if you click in the part that is peeking out, the grid pops back down again.

      I do not call setShowFilterEditor(false) at any point.

      I will try removing other custom css, and see if that helps.

      Comment


        #4
        Ah, that wasn't clear from the screenshots.

        This strongly suggests that CSS margins are involved. CSS margins are dangerous and unpredictable, since the CSS standard specifies bizarre and widely-criticized rules for automatic collapse of adjacent margins.

        If this is the cause, enhancements implemented for 8.3d (see listGrid.gridComponents) would happen to resolve the problem as well.

        Comment


          #5
          I removed all custom css and it is still happening.

          What sets those $yu="44" $yv="44" attributes on the grid? Are those causing the grid header to move, or are they a symptom of the grid header moving on it's own because of layout issues?


          Looking into it more it appears as though the grid is too long. Even though I set height 100, it appears to extend 44 pixels beyond the section stack container. When I click on the grid, I think it shifts up to show the entire grid. I'm not sure why the height is not getting set correctly.

          The listGrid itself appears to be sized correctly, but the body is too long even with no records present.

          I uploaded two images, you can see the blue bounding rectangle showing the size and location of the ListGrid and GridBody.

          I also tried upgrading to 8.3d, which did not help.

          Also, the first time you hit the page after clearing the browser cache, the size of the grid body is correct. It's not until you leave the page and come back that the size is too long, and it stays that way until the cache is refreshed again.
          Attached Files
          Last edited by habermanm; 16 Aug 2012, 05:28.

          Comment


            #6
            Never mind $yu/$yv, these are deep internals and simply reflect that height/position has been miscalculated, which is already obvious.

            Your issue really, really strongly suggests an issue with CSS margins. Are you sure that you've really removed *all* custom CSS *and* all calls to setStyleName() so that you are now just working with the unmodified skin?

            Have you also eliminated all styles that might cascade, or that apply page-wide to certain elements (eg all "tr" tags, that kind of thing)?

            If so, the sure-fire way to solve the problem is to provide code we can run to reproduce the problem - the current code isn't close to runnable, and the problem may not be in the posted code at all.

            Comment


              #7
              I'll try to put together a project to reproduce.

              Any insight as to why it would size properly on the first visit to the page, but not on subsequent?

              Comment


                #8
                Probably caching, specifically, if you have CSS styles that are interfering in some way, on a first visit the CSS may not be loaded when layout occurs, but are loaded (cached) when layout occurs on a second visit.

                Comment


                  #9
                  I removed the link to the CSS in the HTML page. I have no CSS defined whatsoever, and it is still happening.

                  I have cleared caches and shift-refreshed web browser to make sure everything was cleared, and my custom styles are gone for sure.

                  I will attempt to make a small sample.

                  Comment

                  Working...
                  X