Skip to content

Commit

Permalink
Fix problem with InlineTextFieldView causing an infinite loop when it…
Browse files Browse the repository at this point in the history
… was losing first responder. Also check to see if the target of an event is within the ITFV in root responder when automatically resiging its first responder
  • Loading branch information
ColinCampbell committed Sep 27, 2011
1 parent 7e21a87 commit ceaeda4
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
37 changes: 28 additions & 9 deletions frameworks/core_foundation/system/root_responder.js
Original file line number Diff line number Diff line change
Expand Up @@ -1742,16 +1742,10 @@ SC.RootResponder = SC.Object.extend(
this._lastMouseDownX = evt.clientX ;
this._lastMouseDownY = evt.clientY ;

var fr, view = this.targetViewForEvent(evt) ;
var view = this.targetViewForEvent(evt);

// InlineTextField needs to loose firstResponder whenever you click outside
// the view. This is a special case as textfields are not supposed to loose
// focus unless you click on a list, another textfield or an special
// view/control.

if(view) fr=view.getPath('pane.firstResponder');

if(fr && fr.kindOf(SC.InlineTextFieldView) && fr!==view){
if (view && this.shouldResignFirstResponder(view)) {
var fr = view.getPath('pane.firstResponder');
fr.resignFirstResponder();
}

Expand All @@ -1767,6 +1761,31 @@ SC.RootResponder = SC.Object.extend(
return ret;
},

/**
There are specific cases where we want to force a view to resign being
this first responder before we continue. InlineTextField needs to loose
firstResponder whenever you click outside the view. This is a special case
as textfields are not supposed to loose focus unless you click on a list,
another textfield or an special view/control.
@param {SC.View} targetView The target view of the event
@returns {Boolean} true if it should resign the first responder, false otherwise
*/
shouldResignFirstResponder: function(targetView) {
var firstResponder = targetView.getPath('pane.firstResponder'),
shouldResign = false;

if (firstResponder && firstResponder.kindOf(SC.InlineTextFieldView)) {
// we first want to check if the targetView is a child of the text field
// ie. it could be an accessory view
if (firstResponder !== targetView && !SC.$.contains(firstResponder.get('layer'), targetView.get('layer'))) {
shouldResign = true;
}
}

return shouldResign;
},

/**
mouseUp only gets delivered to the view that handled the mouseDown evt.
we also handle click and double click notifications through here to
Expand Down
10 changes: 5 additions & 5 deletions frameworks/foundation/views/text_field.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,9 @@ SC.TextFieldView = SC.FieldView.extend(SC.StaticLayout, SC.Editable,
// passing the original event here instead that was potentially set from
// loosing the responder on the inline text editor so that we can
// use it for the delegate to end editing
this.resignFirstResponder();
this.fieldDidBlur(this._origEvent || evt);

var val = this.get('value');
if(!SC.platform.input.placeholder && ((!val) || (val && val.length===0))) {
this._hintON = YES;
Expand Down Expand Up @@ -818,8 +820,6 @@ SC.TextFieldView = SC.FieldView.extend(SC.StaticLayout, SC.Editable,
},

fieldDidBlur: function(evt) {
this.resignFirstResponder() ;

if(this.get('commitOnBlur')) this.commitEditing(evt);

// get the pane we hid intercept pane for (if any)
Expand Down Expand Up @@ -961,9 +961,9 @@ SC.TextFieldView = SC.FieldView.extend(SC.StaticLayout, SC.Editable,
the hint text if needed.
*/
didLoseKeyResponderTo: function(keyView) {
SC.RunLoop.begin();
this.fieldDidBlur();
SC.RunLoop.end();
SC.run(function() {
this.fieldDidBlur();
}, this);
this.invokeLater("scrollToOriginIfNeeded", 100);
},

Expand Down

0 comments on commit ceaeda4

Please sign in to comment.