Announcement

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

    SmartGWT - Facing issue with ClickMask on a custom TypeAhead componenent

    Hi Isomorphic,

    We are using a custom component acting as a TypeAhead (code similar to http://forums.smartclient.com/forum/...lete-component).
    We have been using this code and component without any issues till recently (on SmartGwt 4.1 build - v9.1p_2014-06-22/Enterprise Deployment 2014-06-22)
    However, when evaluating version 6.1 (Isomorphic SmartClient/SmartGWT Framework (SNAPSHOT_v11.1d_2016-09-06/EVAL Deployment 2016-09-06)), we noticed some issues with it.

    In the TypeAhead class, my code for ClickHandler looks like:
    Code:
    ----
    private Window listWindow;
    private ListGrid listGrid;
    
    ----
    
    listWindow.addItem(listGrid);
    
    ----
    
    
    addClickHandler(new ClickHandler() {
        @Override
        public void onClick(com.smartgwt.client.widgets.form.fields.events.ClickEvent event) {
            GenericDimension dimensionBean = dimensionManager.getDimensionBean(dimension);
            if (dimensionBean != null && dimensionBean.isTypeAheadOn()) {
                String searchText = getValueToSearch();
                if (searchText == null) {
                    setValue(StringSharedDefinitions.EMPTY);
                }
                setupListGridOnEvent(createCriteria(searchText));
                if (dimensionManager.getDimensionBean(dimension).isTypeAheadOn()) {
                    listWindow.show();
                    listWindow.moveTo(getPageLeft(), getPageTop() + getHeight());
                    [B]listWindow.showClickMask(new DismissClickHandler(), ClickMaskMode.HARD, new Canvas[]{listWindow});[/B]
                }
                focusInItem();
            }
        }
    });
    The expectation is that when the user clicks on the component, a ListGrid (contained in a Window) pops open and let's user select anything if need be, however, the user can still continue typing without the focus being lost from the TextItem!
    However, with the upgrade, after the click event, the focus shifts to the window, thus, if the user needs to type, he/she has to expend an extra click!
    Unfortunately, the same showClickMask code is being used in multiple places in our code, and also on addChangedHandler event, thus focus being lost on every character typing as well!

    Please let me know if you need any more information in this regard.
    Thanks!
    Attached Files

    #2
    As written, it looks like your code should not have worked in any version. You are putting up a hard click mask over everything on the screen except the "listWindow", so focus should not be allowed anywhere else, including the text field where you want the user to continue typing.

    To allow your text field to continue to have focus, you need to provide the component that holds the text field as one of the unmasked targets. However, note that the way the built-in ComboBoxItem works is not to use a clickmask, but rather to listen for a mouseDown anywhere on the page as a means of dismissing the picklist. This avoids the problem that the input text field alone cannot be unmasked; its containing Canvas would have to be unmasked instead, which probably unmasks more than you want.

    Comment


      #3
      Thanks for the reply.
      However, I am not sure I understand the problem or whether I have been able to explain the problem.

      We use a regular TextItem with a Window that pops up showing the grid. We do not use ComboBox.
      Also, the same code without any changes works fine in the 4.1 versions of SmartGWT.

      Below is the subset of the code that we have in the class. I have removed some code, and kept only the minimum that we still need to run the application to reproduce this problem:
      Code:
      import com.google.gwt.user.client.Timer;
      import com.sabre.apd.mi.smartgwt.client.user.ClientProfile;
      import com.sabre.apd.mi.smartgwt.client.util.DataSourceProperties;
      import com.sabre.apd.mi.smartgwt.client.util.IntegerConst;
      import com.sabre.apd.mi.smartgwt.common.reportUtils.ReportUtil;
      import com.sabre.apd.mi.smartgwt.common.typeAhead.*;
      import com.sabre.apd.mi.smartgwt.common.util.StringClientDefinitions;
      import com.sabre.apd.mi.smartgwt.common.util.StringSharedDefinitions;
      import com.smartgwt.client.core.Function;
      import com.smartgwt.client.data.*;
      import com.smartgwt.client.types.*;
      import com.smartgwt.client.widgets.Canvas;
      import com.smartgwt.client.widgets.IButton;
      import com.smartgwt.client.widgets.Window;
      import com.smartgwt.client.widgets.events.CloseClickEvent;
      import com.smartgwt.client.widgets.events.CloseClickHandler;
      import com.smartgwt.client.widgets.form.fields.TextItem;
      import com.smartgwt.client.widgets.form.fields.events.*;
      import com.smartgwt.client.widgets.grid.ListGrid;
      import com.smartgwt.client.widgets.grid.ListGridField;
      import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
      import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
      
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;
      
      public class AutoCompleteTextItem extends TextItem {
      
          private Window listWindow;
          private ListGrid listGrid;
      
          private IButton allButton;
          private IButton clearButton;
      
          private String dimension;
          private String codeValues = "";
      
          private String module;
      
          public void setModule(String module) {
              this.module = module;
          }
      
          public String getModule() {
              return module;
          }
      
          public void setDimensionValue(String newValue) {
              GenericDimension tempDimension = dimensionManager.getDimensionBean(dimension);
          }
      
          public class DismissClickHandler implements Function {
              @Override
              public void execute() {
                  updateItemOnExit();
              }
          }
      
          private DimensionManager dimensionManager;
      
          public AutoCompleteTextItem getItem() {
              return this;
          }
      
          public String getCodeValues() {
              return codeValues;
          }
      
          public void setCodeValues(String codeValues) {
              this.codeValues = codeValues;
          }
      
          public String getDimension() {
              return dimension;
          }
      
          public final void setDimension(String dimension) {
              this.dimension = dimension;
          }
      
          public GenericDimension getDimensionBean() {
              return dimensionManager.getDimensionBean(dimension);
          }
      
          public AutoCompleteTextItem() {
              super();
              dimension = null;
              dimensionManager = new DimensionManager();
              initializeDimensionManager();
              setValue(StringClientDefinitions.EMPTY);
              setCharacterCasing(CharacterCasing.UPPER);
              initializeListWindow();
              initializeListGrid();
      
              listGrid.addDataArrivedHandler(new DataArrivedHandler() {
                  @Override
                  public void onDataArrived(DataArrivedEvent dataArrivedEvent) {
                      updateSelectedRecords();
                  }
              });
      
              listWindow.addCloseClickHandler(new CloseClickHandler() {
                  @Override
                  public void onCloseClick(CloseClickEvent closeClickEvent) {
                      updateItemOnExit();
                      getItem().validate();
                  }
              });
      
              addKeyPressHandler(new KeyPressHandler() {
                  @Override
                  public void onKeyPress(KeyPressEvent event) {
                      if ("Tab".equalsIgnoreCase(event.getKeyName())) {
                          updateItemOnExit();
                      } else if ("Arrow_Down".equalsIgnoreCase(event.getKeyName())) {
                          listGrid.focus();
                      }
                  }
              });
      
              addChangedHandler(new ChangedHandler() {
                  @Override
                  public void onChanged(ChangedEvent changedEvent) {
                      new Timer() {
                          String currentValue = (getEnteredValue() != null && getEnteredValue().contains(StringClientDefinitions.COMMA)) ? getEnteredValue().substring
                                  (getEnteredValue().lastIndexOf(StringClientDefinitions.COMMA) + 1).trim() : getEnteredValue();
      
                          @Override
                          public void run() {
                              if (dimensionManager.getDimensionBean(dimension) != null) {
                                  runnableCode(currentValue);
                              }
                          }
                      }.schedule(IntegerConst.SCHDULE_TIME);
                  }
              });
      
              addClickHandler(new ClickHandler() {
                  @Override
                  public void onClick(com.smartgwt.client.widgets.form.fields.events.ClickEvent event) {
                      GenericDimension dimensionBean = dimensionManager.getDimensionBean(dimension);
                      if (dimensionBean != null && dimensionBean.isTypeAheadOn()) {
                          String searchText = getValueToSearch();
                          if (searchText == null) {
                              setValue(StringSharedDefinitions.EMPTY);
                          }
                          runnableCode(searchText);
                      }
                  }
              });
      
              listWindow.addItem(listGrid);
      
          }
      
          public String getValueToSearch() {
              if (getEnteredValue() == null) {
                  return null;
              }
              String searchText = (getEnteredValue().contains(StringClientDefinitions.COMMA)) ? getEnteredValue().substring(getEnteredValue().lastIndexOf(StringClientDefinitions
                      .COMMA) + 1).trim() : getEnteredValue();
              if (searchText.equalsIgnoreCase(StringSharedDefinitions.ALL)) {
                  return null;
              }
              return searchText;
          }
      
          private void initializeDimensionManager() {
              dimensionManager.setAirportDimension(new AirportDimension());
          }
      
          private void runnableCode(String currentValue) {
              String searchText = (getEnteredValue() != null && getEnteredValue().contains(StringClientDefinitions.COMMA)) ? getEnteredValue().substring(getEnteredValue().lastIndexOf
                      (StringClientDefinitions.COMMA) + 1).trim() : getEnteredValue();
              if (currentValue != null && currentValue.equalsIgnoreCase(searchText)) {
                  setupListGridOnEvent(createCriteria(searchText));
                  setupListWindowOnEvent();
              }
              focusInItem();
          }
      
          public void setupListWindowOnEvent() {
              if (dimensionManager.getDimensionBean(dimension).isTypeAheadOn()) {
                  listWindow.show();
                  listWindow.moveTo(getPageLeft(), getPageTop() + getHeight());
                  [B]listWindow.showClickMask(new DismissClickHandler(), ClickMaskMode.HARD, new Canvas[]{listWindow})[/B];
              }
          }
      
          public void setupListGridOnEvent(Criteria criteria) {
              GenericDimension genericDimension = dimensionManager.getDimensionBean(dimension);
              listGrid.setFields(getAppropriateColumns());
      
              List<String> hiddenColumns = genericDimension.getHiddenColumns();
              if (!hiddenColumns.isEmpty()) {
                  listGrid.hideFields(hiddenColumns.toArray(new String[hiddenColumns.size()]));
              }
              if (genericDimension instanceof UserDimension || genericDimension instanceof ClientDimension) {
                  if (genericDimension instanceof UserDimension && ClientProfile.getUserList() != null && ClientProfile.getUserList().length > 0) {
                      listGrid.invalidateCache();
                      if (criteria.getAttributeAsBoolean("isTypeAhead")) {
                          listGrid.setData(getSearchedSet(criteria, ClientProfile.getUserList()));
                          return;
                      }
                      listGrid.setData(ClientProfile.getUserList());
                  } else if (genericDimension instanceof ClientDimension && ClientProfile.getClientList() != null && ClientProfile.getClientList().length > 0) {
                      listGrid.invalidateCache();
                      if (criteria.getAttributeAsBoolean("isTypeAhead")) {
                          listGrid.setData(getSearchedSet(criteria, ClientProfile.getClientList()));
                          return;
                      }
                      listGrid.setData(ClientProfile.getClientList());
                  } else {
                      if ((ClientProfile.getClientData().getModules().toUpperCase().contains(StringSharedDefinitions.CLIENT_ADMIN)) && getDimension().equalsIgnoreCase
                              (StringClientDefinitions.USER)) {
                          criteria.addCriteria("CLIENT_ID", ClientProfile.getClientData().getClientId());
                      }
                      DSRequest userRequest = new DSRequest();
                      userRequest.setOperationId(dimensionManager.getDimensionBean(dimension).getFetchOperationID());
                      DataSource dataSource = DataSource.get("dimensions");
                      dataSource.fetchData(criteria, new DSCallback() {
                          @Override
                          public void execute(DSResponse dsResponse, Object o, DSRequest dsRequest) {
                              if (dsResponse.getTotalRows() != 0) {
                                  if (getDimension().equalsIgnoreCase(StringClientDefinitions.USER)) {
                                      ClientProfile.setUserList((dsResponse.getData()));
                                  } else {
                                      ClientProfile.setClientList(dsResponse.getData());
                                  }
                                  listGrid.invalidateCache();
                                  listGrid.setData(dsResponse.getData());
                              }
                          }
                      }, userRequest);
                  }
              } else {
                  listGrid.setFetchOperation(dimensionManager.getDimensionBean(dimension).getFetchOperationID());
                  listGrid.invalidateCache();
                  listGrid.fetchData(criteria);
              }
          }
      
          private RecordList getSearchedSet(Criteria criteria, Record[] originalRecords) {
              RecordList searchedRecords = new RecordList();
              String enteredText = criteria.getAttributeAsString(StringClientDefinitions.CRITERIA_SEARCHTEXT);
              if (enteredText == null || enteredText.trim().length() == 0) {
                  searchedRecords.addList(originalRecords);
                  return searchedRecords;
              }
              for (int i = 0; i < originalRecords.length; i++) {
                  if (originalRecords[i].getAttributeAsString(getDimensionBean().getDisplayValueColumn()).contains(enteredText) ||
                          ((originalRecords[i].getAttributeAsString(getDimensionBean().getNameValueColumn()) != null) && originalRecords[i].getAttributeAsString(getDimensionBean()
                                  .getNameValueColumn()).contains(enteredText))) {
                      searchedRecords.add(originalRecords[i]);
                  }
              }
              return searchedRecords;
      
      
          }
      
          public ListGridField[] getAppropriateColumns() {
              List listGridFields = new ArrayList();
      
              for (String columnName : dimensionManager.getDimensionBean(dimension).getColumnList()) {
                  ListGridField listGridField = new ListGridField(columnName);
                  listGridFields.add(listGridField);
              }
              ListGridField[] listGridFieldsArray = new ListGridField[listGridFields.size()];
              return (ListGridField[]) listGridFields.toArray(listGridFieldsArray);
          }
      
          private void updateSelectedRecords() {
              RecordList recordList = listGrid.getDataAsRecordList();
              listGrid.deselectAllRecords();
              String newCodeValues = "";
              if (getEnteredValue() != null && getEnteredValue().endsWith(StringSharedDefinitions.COMMA)) {
                  String[] selectedItems = getEnteredValue().substring(0, getEnteredValue().lastIndexOf(StringClientDefinitions.COMMA)).split(StringClientDefinitions.COMMA);
                  for (String item : selectedItems) {
                      if (recordList.find(getDimensionBean().getDisplayValueColumn(), item) != null) {
                          listGrid.selectRecord(recordList.find(getDimensionBean().getDisplayValueColumn(), item));
                          newCodeValues += (recordList.find(getDimensionBean().getDisplayValueColumn(), item)).getAttributeAsString(getDimensionBean().getCodeValueColumn()) + ",";
                      }
                  }
                  setCodeValues(newCodeValues);
              }
          }
      
          private void updateItemOnExit() {
              GenericDimension dimensionBean = dimensionManager.getDimensionBean(dimension);
              if (dimensionBean != null) {
                  String enteredValue = getEnteredValue();
                  if (!ReportUtil.hasValue(enteredValue) || dimensionBean.getCodeValueColumn().equalsIgnoreCase(dimensionBean.getDisplayValueColumn())) {
                      setCodeValues(StringSharedDefinitions.EMPTY);
                      listWindow.hideClickMask();
                      listWindow.hide();
                  } else {
                      if (dimensionBean instanceof UserDimension || dimensionBean instanceof ClientDimension) {
                          updateCodeValuesOnExit(enteredValue);
                          listWindow.hideClickMask();
                          listWindow.hide();
      
                      } else {
                          Criteria criteria = createCriteria(null);
                          criteria.addCriteria("displayValues", getEnteredValue());
                          DataSource dataSource = listGrid.getDataSource();
                          DSRequest dsRequest = new DSRequest();
                          dsRequest.setOperationId(dimensionBean.getFetchOperationID());
                          dataSource.invalidateCache();
                          dataSource.fetchData(criteria, new DSCallback() {
                              @Override
                              public void execute(DSResponse dsResponse, Object o, DSRequest dsRequest) {
                                  updateCodeValuesOnExit(dsResponse);
                                  listWindow.hideClickMask();
                                  listWindow.hide();
                              }
                          }, dsRequest);
                      }
                  }
              }
          }
      
          private void updateCodeValuesOnExit(String enteredValue) {
              Record[] records = null;
              if (getDimensionBean() instanceof UserDimension || getDimensionBean() instanceof ClientDimension) {
                  records = ClientProfile.getUserList();
              }
              String newCodeValues = "";
              if (records != null) {
                  for (int i = 0; i < records.length; i++) {
                      if (enteredValue.contains(records[i].getAttributeAsString(getDimensionBean().getDisplayValueColumn()))) {
                          newCodeValues += records[i].getAttributeAsString(getDimensionBean().getCodeValueColumn()) + StringSharedDefinitions.COMMA;
                      }
                  }
              }
              setCodeValues(newCodeValues);
          }
      
          private void updateCodeValuesOnExit(DSResponse dsResponse) {
              String newCodeValues = "";
              Record[] records = dsResponse.getData();
              if (records.length > 0) {
                  for (int i = 0; i < records.length; i++) {
                      newCodeValues += records[i].getAttributeAsString(getDimensionBean().getCodeValueColumn()) + StringSharedDefinitions.COMMA;
                  }
              }
              setCodeValues(newCodeValues);
          }
      
          public final void initializeListWindow() {
              listWindow = new Window();
              listWindow.setShowHeader(false);
              listWindow.setAutoSize(true);
              listWindow.setCanDrag(false);
              listWindow.setCanDragReposition(false);
              listWindow.setCanDragResize(false);
              listWindow.setScClassName("WindowNoHeader");
              listWindow.setShowCloseButton(false);
              listWindow.setShowMinimizeButton(false);
              listWindow.setAlign(Alignment.CENTER);
              listWindow.setAlign(VerticalAlignment.CENTER);
          }
      
          public final void initializeListGrid() {
              listGrid = new ListGrid();
              listGrid.setDataSource(DataSource.get(DataSourceProperties.DIMENSIONS));
              listGrid.setSelectionProperty("selection");
              listGrid.setShowHeader(false);
              listGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
              listGrid.setCanSelectAll(false);
              listGrid.setArrowKeyAction("focus");
              listGrid.setCanTabToHeader(false);
              listGrid.setGenerateClickOnEnter(true);
              listGrid.setShowFilterEditor(false);
      
              listGrid.setAutoFitData(Autofit.BOTH);
              listGrid.setAutoFitMaxRecords(IntegerConst.LIST_GRID_AUTO_FIT_RECORDS);
              listGrid.setAutoFitFieldWidths(true);
              listGrid.setAutoFitFieldsFillViewport(true);
              listGrid.setAutoFitWidthApproach(AutoFitWidthApproach.VALUE);
          }
      
          public Criteria createCriteria(String searchText) {
              Criteria criteria = new Criteria();
              criteria.addCriteria(StringClientDefinitions.CRITERIA_SEARCHTEXT, (searchText != null && searchText.equalsIgnoreCase(StringSharedDefinitions.ALL)) ? null : searchText);
              criteria.addCriteria(StringClientDefinitions.CRITERIA_DIMENSION, getDimension());
              criteria.addCriteria("isTypeAhead", true);
              GenericDimension dimensionBean = dimensionManager.getDimensionBean(dimension);
              dimensionBean.setModule(getModule());
              Map<String, String> criteriaMap = dimensionBean.getDimensionCriteria();
              for (String dimensionCriteria : criteriaMap.keySet()) {
                  criteria.addCriteria(dimensionCriteria, criteriaMap.get(dimensionCriteria));
              }
              if ((ClientProfile.getClientData().getModules().toUpperCase().contains(StringSharedDefinitions.CLIENT_ADMIN)) && getDimension().equalsIgnoreCase(StringClientDefinitions
                      .USER)) {
                  criteria.addCriteria("CLIENT_ID", ClientProfile.getClientData().getClientId());
              }
      
              return criteria;
          }
      }
      Attached along is the control screenshot after the window pops open on the 'onChangedEvent' (the focus is lost on the click and the onchanged events, due to the 'showClickMask' method being called.
      I also verified this with the 4.1 build of around 5th May, 2016 and this code was still working fine that build.
      Attached Files

      Comment


        #4
        Please re-read our response. We understand the problem, we understand that you are not using the built-in ComboBoxItem.

        Your code is flawed (both versions) and never should have worked in any version of SmartGWT. Some bugfix that happened after 4.1 broke your code, by making the framework behavior correct, which meant that your incorrect usage no longer works. You need to correct your incorrect usage.

        Comment


          #5
          Thanks!
          I'll try and implement the change that you suggested.
          Will let you know if we still have any issues with that.

          Comment

          Working...
          X