You found a bug! We've classified it as TOUCH-2841 . We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Sencha User
    Join Date
    Jan 2012
    Posts
    18
    Vote Rating
    0
    jochenp is on a distinguished road

      0  

    Default [ST 2.0.1] Event is not prevented causing keyboard to popup

    [ST 2.0.1] Event is not prevented causing keyboard to popup


    REQUIRED INFORMATION

    Ext version tested:
    • Sencha Touch 2.0.1 final
    Browser versions tested against:
    • Android mobile browser 2/3/4
    • iOS 5 Safari
    DOCTYPE tested against:
    • HTML5
    Description:
    • When having a list visible and opening a new view on item select which has an input field on the same location as you tap, the keyboard will popup.
    Steps to reproduce the problem:
    • Select item in list
    • opens new windows with input field on same screen location.
    The result that was expected:
    • simple view of the UI
    The result that occurs instead:
    • the keyboard pops up, because the input gets focus
    Test Case: Added example as attachement. It's a packaged version, but it shows the behavior.

    HELPFUL INFORMATION

    Example code steps:
    • package.zip attached
    • Open the app, press the 'do' button to add a record to the store (localstorage)
    • Press the 'Hello World!!!' list item to open the next window
    Example only shows searchfield in toolbar, but this also happens when opening forms with text inputs.

    The focus doesn't seem to happen on Chrome or Safari on Mac OS X
    Attached Files

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    37,073
    Vote Rating
    854
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Do you have an unminified version of app.js?
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha User
    Join Date
    Jan 2012
    Posts
    18
    Vote Rating
    0
    jochenp is on a distinguished road

      0  

    Default


    yes, but I think you need more, I will added the source files.
    PS: this is a sandbox for testing all kind of issues, so the code is not example worthy
    Attached Files

  4. #4
    Sencha User
    Join Date
    Mar 2012
    Location
    Denver, CO
    Posts
    26
    Vote Rating
    1
    CarlosMS is on a distinguished road

      0  

    Default


    Confirming this behavior in my application running under 2.0.1 FINAL. In my effort to find a work around I ended up stopping the event in my listener with mixed results. My current Ext.Container (which has the Ext.dataview.List component) includes these code fragments:
    Code:
    ...
            var itemList = {
                xtype: 'itemlist',
                store: Ext.getStore('Items'),
                listeners: {
                    disclose: {
                        fn: this.onItemListDisclose,
                        scope: this
                    },
                    itemtap: {
                        fn: this.onItemTap,
                        scope: this
                    }
                }
            };
    
    
            this.add([topToolbar, itemList]);
        },
    
        onItemListDisclose: function(list, record, target, index, evt, options) {
            console.log("onItemListDisclose");
            evt.stopEvent();
            this.fireEvent('editItemCommand', this, record);
        },
        onItemTap: function(list, index, target, record, evt, options) {
            console.log("onItemTap");
            evt.stopEvent();
            this.fireEvent('editItemCommand', this, record);
        },
    ...
    The "stopEvent()" seems to have worked around the issue described in this report under mobile Safari (iOS 5.1 in an iPhone 4S device), but did not work in the mobile browser of an arbitrary Android phone I just happened to test my app. in (Android 2.2.2 in an LG Ally device).

  5. #5
    Sencha User
    Join Date
    Mar 2012
    Location
    Denver, CO
    Posts
    26
    Vote Rating
    1
    CarlosMS is on a distinguished road

      0  

    Default


    Also confirming that in addition to the Android device I mentioned, this is also reproducible in the Android SDK emulator (R19, Intel Atom x86 System Image w/API level 10).

  6. #6
    Ext JS Premium Member bobringer's Avatar
    Join Date
    Apr 2007
    Location
    New Jersey
    Posts
    54
    Vote Rating
    4
    bobringer is on a distinguished road

      0  

    Default Yep

    Yep


    I'm only testing in the iOS Simulator, but I can in fact reproduce this 100% of the time...

  7. #7
    Sencha User
    Join Date
    Jan 2011
    Posts
    2
    Vote Rating
    0
    rickyguff is on a distinguished road

      0  

    Default Similar issue with email addresses or phone numbers.

    Similar issue with email addresses or phone numbers.


    Hello,

    I think I've encountered a similar problem with email addresses or phone numbers.
    When you tap on a list item of some panel to show a detailed panel and at the exact place you tap, there is a email address shown on the detailed panel, the Android device opens an email engine. This is the same with phone numbers where Android opens the phone pad.
    It's easy enough to reproduce.

    The 'stopEvent' function does not work in order to "stop" the propagation of the 'tap' event from the list panel to the detailed panel.

    Hope that can help for further investigation.

    Best regards

    Eric.

  8. #8
    Sencha User
    Join Date
    Jan 2011
    Posts
    2
    Vote Rating
    0
    rickyguff is on a distinguished road

      0  

    Default


    Here is an example of what I described in the previous thread. This source code is working well with 2.0.0 but not with 2.0.1 (or the recent 2.0.1.1 version). Impossible to stop the event propagation even with the "stopEvent" method.

    If you click on the first list item (Sandra Bullock) where the phone number is located on the detailed panel, Android opens the dialer.
    Tested on my Samsung Galaxy S2 with Android 2.3.6.

    Code:
    Ext.define('TestApp.model.Artist', {
      extend: 'Ext.data.Model',
      config: {
        idProperty: 'idcom',
        fields : ['idcom', 'firstname', 'name', 'email', 'phone']
      }
    });
    
    Ext.define('TestApp.store.ArtistStore', {
      extend: 'Ext.data.Store',
      requires: ['TestApp.model.Artist'],
      config: {
        storeId: 'artistStore',
        model: 'TestApp.model.Artist',
        autoLoad : true,
        data: 
          [{idcom: '1', firstname: 'Sandra', name: 'Bullock', email: 'sandra.bullock@mail.com', phone: '+3222222222'},
           {idcom: '2', firstname: 'Tom', name: 'Hanks', email: 'tom.hanks@mail.com', phone: '+3222222222'},
           {idcom: '3', firstname: 'Sean', name: 'Connery', email: 'sean.connery@mail.com', phone: '+3222222222'}]
      }
    });
    
    Ext.define('TestApp.view.DetailPanel', {
      extend: 'Ext.Panel',
      xtype: 'detailPanel',
      config: {
        scrollable: {
          direction: 'vertical'
        }
      },
      initialize: function() {
        this.callParent(arguments);
      }
      
    });
    
    Ext.define('TestApp.view.ArtistDetailPanel', {
      extend: 'TestApp.view.DetailPanel',
      xtype: 'artistDetailPanel',
      config: {
        styleHtmlContent : false,
        data: {}, 
        title: '',
        tpl: '<span>{firstname} {name} {email} {phone}<span>'
      },
      initialize: function() {
        this.callParent(arguments);  
      }
    });
    
    Ext.define('TestApp.view.ArtistList', {
      extend: 'Ext.List',
      requires: ['TestApp.store.ArtistStore'],
      xtype: 'artistList',
      config: {
        store : 'artistStore',
        scrollable : {
          direction : 'vertical',
        },
        itemTpl : '<div>{firstname} {name} </div>',
        autoHeight : true,
        singleSelect : true,
        emptyText : 'Pas de r├ęsultat',
        loadingText : 'Chargement',
        onItemDisclosure: true,
        title : ''
      },
      initialize: function() {
        this.callParent(arguments);
        
        this.addListener('itemtap', function(list, index, target, record, e, opts) {
          
          this.deselect(record);
          
          Ext.getCmp('back-button').show();
    
          e.stopEvent();
          
          var port = Ext.getCmp('home-tab-port').getActiveItem();
          
          var detailpanel = Ext.getCmp('artist-detail-panel');
          detailpanel.setRecord(record);
          
          port.setActiveItem(detailpanel);
          
          Ext.getCmp('home-toolbar').setTitle(port.getActiveItem().getTitle());
               
          
        });
        
      }
    
    });
    
    Ext.define("TestApp.view.Port", {
      extend: 'Ext.Container',
      xtype: 'port',
      config: {
        fullscreen : false,
        scrollable : false,
        layout : {
          type: 'card',
        }
      },
      initialize: function() {
        this.callParent(arguments);
      }
    });
    
    Ext.define("TestApp.view.HomeTabPort", {
      extend: 'Ext.tab.Panel',
      xtype: 'homeTabPort',
      config: {
        id: 'home-tab-port',
        fullscreen: false,
        cardSwitchAnimation: 'slide',
        tabBar:{
          docked: 'bottom',
          layout: {
            pack: 'center'
          }
        }
      },
      initialize: function() {
        
        this.callParent(arguments);
     
        var backButton = {
            xtype: 'button',
            text: 'Retour',
            id: 'back-button',
            ui: 'back',
            hidden: true,
            handler: function() {
    
              var port = Ext.getCmp('home-tab-port').getActiveItem();         
    
              port.setActiveItem(0, {
                type: 'slide',
                direction: 'right'
              });
    
              this.hide();
    
              Ext.getCmp('home-toolbar').setTitle(port.getActiveItem().getTitle());
    
            }
        };
        
        var homeToolbar = {
            xtype: 'toolbar',
            id: 'home-toolbar',
            docked: 'top',
            title: 'Com├ędien',
            items: [backButton]
        };
        
        var artistPort = {
            xtype: 'port',
            id: 'artist-port',
            title: "Artistes",
            iconCls: 'user',
            items : [{
              xtype: 'artistList',
              id: 'artist-list',
              title:'Artistes'
            },{
              xtype: 'artistDetailPanel',
              id: 'artist-detail-panel',
              title: 'Artiste'
            }]
        };
    
        this.add([homeToolbar, artistPort]);
        
      }
    });
    
    
    Ext.application({
      name: 'TestApp',
      models: ['Artist'],
      stores: ['ArtistStore'],
      views: ['HomeTabPort', 'ArtistList', 'DetailPanel', 'ArtistDetailPanel'],
      launch : function() {
    
        Ext.Viewport.add(Ext.create('TestApp.view.HomeTabPort'));
    
      }
    
    });
    Thank you in advance to give me a clue about how to solve this problem.

    Best regards,

    Eric.

  9. #9
    Sencha User siebmanb's Avatar
    Join Date
    Aug 2011
    Location
    Geneva (CH) - Grenoble (FR)
    Posts
    253
    Vote Rating
    15
    siebmanb will become famous soon enough

      0  

    Default


    A quick and dirty fix I use is to delay the display of the view containing the field by 1/2sec using setTimeout.

    Code:
    yourButtonHandler: function() {
            var _this = this;   // use _this instead of this in the timeout if you wish
    
    
            setTimeout(function() { 
                [open your next view]
            }, 500);
        },
    You can actually decrease the 500ms I am using, but I found out that under 300ms the bug comes back again.

    I will work asap on a function using stopEvent for iOS and a timeout for Android, and I will post it here.

  10. #10
    Sencha User siebmanb's Avatar
    Join Date
    Aug 2011
    Location
    Geneva (CH) - Grenoble (FR)
    Posts
    253
    Vote Rating
    15
    siebmanb will become famous soon enough

      0  

    Default


    Important : the bug does not only concern fields and keyboard poping, it appears also on html link being tapped accidentally

    Here is a function I prepared to combine both my fix on Android and the known fix for iOS. The goal here is to avoid the use of the setTimeout on iOS, as it is not really good for UX.

    The function

    Code:
    preventClicThrough: function(event,scope,callback) {
           // For iOS
            if (!Ext.os.is.Android) {
               // Stop the event bubbling
                if (event) event.stopEvent();
    
               // Execute the code, passing the scope
                callback(scope);
               return true;
            } 
    
           // For Android
           // Delays execution of code
            setTimeout(function() { 
                callback(scope);
            }, 500);
        },
    Usage Example
    Code:
    buttonHandler: function(a,event) {
            APPLI.preventClicThrough(event, 
                   this, 
                   function callback(_this) {
                         _this.myView = createMyViewFromClass('myViewClassName');
                          _this.getContainer().setActiveItem(_this.myView);
            });
        }
    Obviously createMyViewFromClass is a personal function, do not try to find it in the documentation . Passing this as an argument is important to be able to pass on the scope to the callback executed.

    It was tested on iOS, and will be tested on Android in a few minutes.