PDA

View Full Version : Event Tap on Background



gabrielstuff
5 Oct 2010, 1:21 AM
Hi all,

I would like to have the closest form to the iphone standard.
If you tap somewhere out of the field mostly background the keyboard will go away and hidding.
I am trying to reproduce this... by using one of the method in "bad" native application coding :

1. Make a big space under your form
2. Make it tap event responsive
3. draw the form panel on this component.

Here is the code (I take the touch log from the kitchenSink), the problem is that I get well the "tap" event... but I can not get my form field... everything is black...



TouchPad = Ext.extend(Ext.Component, {
id: 'touchpad',
style: 'background:#000',
html: 'Touch here!',

initComponent: function(){
this.addEvents('log');
TouchPad.superclass.initComponent.call(this);
},

afterRender: function(){
TouchPad.superclass.afterRender.call(this);

this.mon(this.el, {
tap: this.handleEvent,
scope: this
});
},

handleEvent: function(e){
this.fireEvent('log', e.type, e);
}
});

Ext.ux.alertForm = Ext.extend(Ext.form.FormPanel, {
scroll: 'vertical',
standardSubmit: false,
style: 'padding:0px 8px;',
frame: true,
id: 'alertform',
flex: 1,
height: 'auto',

initComponent: function(){

this.t_storeEcole = new Ext.data.Store({
autoLoad: true,
model: 'ecole',
proxy: {
url: pwc.fluxoutschool,
type: 'scripttag',
reader: {
root: 'data'
}
}
});

this.t_storeVille = new Ext.data.Store({
autoLoad: true,
model: 'town',
proxy: {
url: pwc.fluxouttown,
type: 'scripttag',
reader: {
root: 'data'
}
}
});

this.submitButton = new Ext.Button({
cls: 'bluebtn',
style: 'font-size:1em',
text: 'GO',
scope: this,
handler: function(){
this.submit({
url: out.register,
method: 'POST',
reset: false,
});
}
});

this.items = [{
html: '<div class="spacer"></div>'
},
{
style: 'font-size:1.1em',
html: '<p>Foo</p>'
},
{
xtype: 'fieldset',
title: 'Name',
items: [{
xtype: 'textfield',
name: 'name',
id: 'name'
}],
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
}
}
},
{
xtype: 'fieldset',
title: 'First name',
items: [{
xtype: 'textfield',
name: 'fname'
}],
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
}
}
},
{
xtype: 'fieldset',
title: 'School :',
items: [
{
xtype: 'select',
name: 'schoolname',
emptyText: 'No school',
valueField: 'schoolname',
displayField: 'schoolname',
store: this.t_storeEcole,
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
}
}
}]
},
this.submitButton,
];

this.addListener("beforeactivate", this.onDisplayWin);

this.touchPad = new TouchPad({
listeners: {
log: this.onLog,
scope: this
}
});

this.dockedItems = [{
dock: 'top',
id: 'touchinfopanel',
layout: 'fit',
items: [this.touchPad]
}];


Ext.ux.alertForm.superclass.initComponent.call(this);

},
onLog: function(type, e){
console.log('tap');
},
onDisplayWin: function(){
this.doLayout();
}
});


This result in a nice black Panel responsive to tap... but nothing more, no field no form.

Thank you !

gabrielstuff
5 Oct 2010, 3:27 AM
Adding an afterRender function :


afterRender: function() {
Ext.ux.alertForm.superclass.afterRender.call(this);

this.mon(this.el, {
tap: this.handleEvent,
scope: this
});
}


and then the handleEvent :



handleEvent: function(el){
if((el.target.className != 'x-input-text')&&(el.target.className != 'x-field-mask'))
{
Ext.getCmp('name').fieldEl.dom.focus();
Ext.getCmp('name').fieldEl.dom.blur();
console.log('touch' + el.target.className);
}
}

gabrielstuff
5 Oct 2010, 4:23 AM
Ok... I'm getting crazy...
I do not know why but under iPhone... the name field become unselectable... No focus"in" :(

meQ
5 Oct 2010, 6:08 AM
Your solution looks interesting!

Is your first post obsolete and you just added the listener to every form you want to handle or is it just an addition?
Does it solve the resizing problem of the tabPanel as well?

Thanks!

gabrielstuff
5 Oct 2010, 8:28 AM
Yes the first one is obsolete.
Now I have the keyboard that go away anytime I touch the done button.
Everything is resizing well... a little bit to much.

I think the main problem is "undoNativeScroll"

If I make a function like this :


function hideKeyboard(el){
el = Ext.get('name');
var parent = el.parent();
while (parent) {
if (parent.getStyle('overflow') == 'hidden') {
alert('Top with hidden: '+parent.dom.scrollTop);
parent.dom.scrollTop = 0;
parent.dom.scrollLeft = 0;
}
else
alert('Top : '+parent.dom.scrollTop);
parent = parent.parent();
}
}

The panel goes up well and I can use prev and next like native app.

If I code :



function hideKeyboard(el){
el = Ext.get('name');
var parent = el.parent();
while (parent) {
alert('Top with hidden: '+parent.dom.scrollTop);
parent.dom.scrollTop = 0;
parent.dom.scrollLeft = 0;
parent = parent.parent();
}
}

Then The panel resize good, as I am stuck up but I can not use next and prev iPhone button as the parent.dom have been set to 0, the iphone seems not to replace the focus on the field... and I end up with a field behind the keyboard.

Full Extend here :


/*******************************CRAPY ADDD***************************************************************************************************/
pwc.cptHide = 0;
function hideKeyboard(el){
el = Ext.get('name');
var parent = el.parent();
while (parent) {
if (parent.getStyle('overflow') == 'hidden') {
alert('Top with hidden: '+parent.dom.scrollTop);
parent.dom.scrollTop = 0;
parent.dom.scrollLeft = 0;

parent = parent.parent();
}
}

Ext.regModel('ecole', {
fields: [
{
name: 'schoolname',
type: 'string'
}
]
});

Ext.regModel('town', {
fields: [
{
name: 'town',
type: 'string'
}
]
});


Ext.ux.alertForm = Ext.extend(Ext.form.FormPanel, {
scroll: 'vertical',
standardSubmit: false,
style: 'padding:0px 8px;',
id: 'alertform',
flex: 1,
height: 'auto',

initComponent: function(){

this.t_storeEcole = new Ext.data.Store({
autoLoad: true,
model: 'ecole',
proxy: {
url: http://www,
type: 'scripttag',
reader: {
root: 'data'
}
}
});

this.t_storeVille = new Ext.data.Store({
autoLoad: true,
model: 'town',
proxy: {
url: pwc.fluxouttown,
type: 'scripttag',
reader: {
root: 'data'
}
}
});

this.submitButton = new Ext.Button({
cls: 'bluebtn',
style: 'font-size:1em',
text: 'Je m\'inscris',
scope: this,
handler: function(){
this.submit({
url: pwc.regmobile,
method: 'POST',
reset: false,

});
//fin du submit
}
});

this.items = [
{
style: 'font-size:1.1em;padding-top:10px',
html: '<p>FOO</p>'
},
{
xtype: 'fieldset',
title: 'Name',
items: [{
xtype: 'textfield',
name: 'name',
id: 'name',
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}]
},
{
xtype: 'fieldset',
title: 'First Name',
items: [{
xtype: 'textfield',
name: 'fname',
id: 'fname',
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
},
focus: function(fld,e){

}
}
}]
},
{
xtype: 'fieldset',
title: 'Email',
items: [{
xtype: 'emailfield',
name: 'email',
id: 'email',
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}]
},
{
xtype: 'fieldset',
title: 'Votre ville :',
items: [
{
xtype: 'select',
name: 'townname',
emptyText: 'Aucune ville dans la liste',
valueField: 'town',
displayField: 'town',
store: this.t_storeVille,
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}]
},
{
xtype: 'fieldset',
title: 'Autre',
items: [{
xtype: 'textfield',
name: 'othertown',
id: 'othertown',
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}]
},
{
xtype: 'fieldset',
title: 'Votre école :',
items: [
{
xtype: 'select',
name: 'schoolname',
emptyText: 'Aucune école dans la liste',
valueField: 'schoolname',
displayField: 'schoolname',
store: this.t_storeEcole,
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}]
},
{
xtype: 'fieldset',
title: 'Autre',
items: [{
xtype: 'textfield',
name: 'other',
id: 'other',
listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}
}],

},
{
html: '<div class="spacer"></div>'
},
this.submitButton,
{
html: '<div class="spacer"></div>'
}];

Ext.ux.alertForm.superclass.initComponent.call(this);

},

afterRender: function() {
Ext.ux.alertForm.superclass.afterRender.call(this);

this.mon(this.el, {
tap: this.handleEvent,
scope: this
});
},

onDisplayWin: function(){
//Do no use this or all the html content disapear 0_°.
/** this.doLayout();
*
*/
},
handleEvent: function(el){
//alert('View');
//alert(el.target.className + ' ou ba : ' + el.target.name);
if((el.target.className != 'x-field-mask x-hidden-display')&&(el.target.className != 'x-input-text')&&(el.target.className !='x-input-email'))
{
// alert('touch' + el.target.className);
Ext.getCmp('name').fieldEl.dom.focus();
Ext.getCmp('name').fieldEl.dom.blur();
alert('touch' + el.target.className);
}
else
{
Ext.getCmp(el.target.name).fieldEl.dom.focus();
alert('focus');
}
}
});



Well... the other thing which is not easy is that safari on iPhone seems to add other class to the form :(

gabrielstuff
5 Oct 2010, 8:48 AM
So calling the function hideKeyboard on blur event was not a bad idea.
The thing is that now, I can not go under 3 forms.
I mean that prev and next are broken.

Using this :



function hideKeyboard(el){
el = Ext.get('name');
var parent = el.parent();
while (parent) {
alert('Top with hidden: '+parent.dom.scrollTop);
parent.dom.scrollTop = 0;
parent.dom.scrollLeft = 0;
parent = parent.parent();
}}


But no more gap !
Instead if I am using this :

function hideKeyboard(el){
el = Ext.get('name');
var parent = el.parent();
while (parent) {
if (parent.getStyle('overflow') == 'hidden') {
alert('Top with hidden: '+parent.dom.scrollTop);
parent.dom.scrollTop = 0;
parent.dom.scrollLeft = 0;
}
else
alert('Top : '+parent.dom.scrollTop);
parent = parent.parent();
}

The gap still full until I touch/clicked into an other field.

It is like if an event was not fired.

You have to had to your textfield :

listeners: {
keyup: function(fld, e){
if (e.browserEvent.keyCode == 13){
e.stopEvent();
fld.fieldEl.dom.blur();
}
},
blur: function(fld, e){
hideKeyboard(fld);
}
}

lreategui
5 Oct 2010, 1:55 PM
Ok... I'm getting crazy...
I do not know why but under iPhone... the name field become unselectable... No focus"in" :(


Did you get a resolution for this? I added an
else{
Ext.getCmp('name').fieldEl.dom.focus();
}

but the field remains unselectable. Seems like the blur event is taking over

gabrielstuff
5 Oct 2010, 2:00 PM
Yes I have one.. but the post that explain it is in the hand of the administrator... I tried to post it again later to night :)

lreategui
5 Oct 2010, 2:27 PM
great thanks :)

gabrielstuff
8 Oct 2010, 7:05 AM
Yes, everything is up there.
On the iphone there is kind of an other mask. I saw it while using alert on any touch.
That Is why I've wrote this :


handleEvent: function(el){
//alert('View');
//alert(el.target.className + ' ou ba : ' + el.target.name);
if((el.target.className != 'x-field-mask x-hidden-display')&&(el.target.className != 'x-input-text')&&(el.target.className !='x-input-email'))
{
// alert('touch' + el.target.className);
Ext.getCmp('name').fieldEl.dom.focus();
Ext.getCmp('name').fieldEl.dom.blur();
alert('touch' + el.target.className);
}
else
{
Ext.getCmp(el.target.name).fieldEl.dom.focus();
alert('focus');
}
}

gabrielstuff
8 Oct 2010, 7:22 AM
Ok, i've been back to Sencha 0.93... and this bug wasn't existing...
Instead of what the panel was sometime going very very up...

Now, the renderTPL is not the same :
0.93 :

renderTpl: [
'<div <tpl if="id">id="{id}" </tpl>class="{baseCls}<tpl if="required"> {required}</tpl><tpl if="cls"> {cls}</tpl><tpl if="cmpCls"> {cmpCls}</tpl><tpl if="ui"> {uiBase}-{ui}</tpl> <tpl if="label">{labelAlign}</tpl>" <tpl if="style"> style="{style}"</tpl>>',
'<tpl if="label"><label <tpl if="fieldEl">for="{inputId}"</tpl>><span>{label}</span></label></tpl>',
'<tpl if="fieldEl"><input id="{inputId}" type="{type}" name="{name}" class="{fieldCls}"',
'<tpl if="tabIndex">tabIndex="{tabIndex}" </tpl>',
'<tpl if="placeholder">placeholder="{placeholder}" </tpl>',
'<tpl if="style">style="{style}" </tpl>',
'<tpl if="maxlength">maxlength="{maxlength}" </tpl>',
'<tpl if="autoComplete">autocomplete="{autoComplete}" </tpl>',
'<tpl if="autoCapitalize">autocapitalize="{autoCapitalize}" </tpl>',
'<tpl if="autoCorrect">autocorrect="{autoCorrect}" </tpl>',
'/></tpl>',
'<tpl if="showClear"><div class="x-field-clear x-hidden-display"></div></tpl>',
'<tpl if="maskField"><div class="x-field-mask"></div></tpl>',
'</div>'
],

0.95:

renderTpl: [
'<tpl if="label"><label <tpl if="fieldEl">for="{inputId}"</tpl>><span>{label}</span></label></tpl>',
'<tpl if="fieldEl"><input id="{inputId}" type="{type}" name="{name}" class="{fieldCls}"',
'<tpl if="tabIndex">tabIndex="{tabIndex}" </tpl>',
'<tpl if="placeHolder">placeholder="{placeHolder}" </tpl>',
'<tpl if="style">style="{style}" </tpl>',
'<tpl if="maxlength">maxlength="{maxlength}" </tpl>',
'<tpl if="autoComplete">autocomplete="{autoComplete}" </tpl>',
'<tpl if="autoCapitalize">autocapitalize="{autoCapitalize}" </tpl>',
'<tpl if="autoCorrect">autocorrect="{autoCorrect}" </tpl>',
'<tpl if="autoFocus">autofocus="{autoFocus}" </tpl>',
'/></tpl>',
'<tpl if="showClear"><div class="x-field-clear x-hidden-display"></div></tpl>',
'<tpl if="maskField"><div class="x-field-mask"></div></tpl>'
],


0.92 :

onEnable : function() {
this.getActionEl().removeClass(this.disabledClass);
this.el.dom.disabled = false;
this.fieldEl.dom.disabled = false;
this.checkClear();
},


onDisable : function() {
this.getActionEl().addClass(this.disabledClass);
this.el.dom.disabled = true;
this.fieldEl.dom.disabled = true;
this.checkClear(true);
},

0.95:

onEnable : function() {
this.el.removeClass(this.disabledClass);
this.el.dom.disabled = false;
this.fieldEl.dom.disabled = false;
this.checkClear();
},


onDisable : function() {
this.el.addClass(this.disabledClass);
this.el.dom.disabled = true;
this.fieldEl.dom.disabled = true;
this.checkClear(true);
},

0.93:

onBlur :

onBlur : function() {
this.beforeBlur();
if (this.focusClass) {
this.el.removeClass(this.focusClass);
}
this.hasFocus = false;
var v = this.getValue();
if (String(v) !== String(this.startValue)){
this.fireEvent('change', this, v, this.startValue);
}
this.fireEvent('blur', this);
if (this.maskField) {
this.mask.show();
}
this.postBlur();
},

0.95 :

onBlur : function() {
this.beforeBlur();
if (this.focusClass) {
this.el.removeClass(this.focusClass);
}
this.hasFocus = false;
var v = this.getValue();
if (String(v) != String(this.startValue)){
this.fireEvent('change', this, v, this.startValue);
}
this.fireEvent('blur', this);
this.checkClear();
if (this.maskField) {
this.mask.show();
}
this.postBlur();
},

On of the "big" difference is that we now have for 0.95 :

getElConfig : function() {
return Ext.apply(Ext.form.FormPanel.superclass.getElConfig.call(this), {
tag: 'form'
});
},

without any TPL.

Instead of
renderTpl: [
'<form <tpl if="id">id="{id}"</tpl> class="{baseCls} {cls} {cmpCls}<tpl if="ui"> {uiBase}-{ui}</tpl>" <tpl if="style"> style="{style}"</tpl>>',
'<div class="{baseCls}-body"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>',
'</form>'
], for the 0.93....

Hope someone will see the light :)