API  1.0.0
CPTextField.j
Go to the documentation of this file.
1 /*
2  * CPTextField.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 @global CPApp
26 @global CPStringPboardType
27 @global CPCursor
28 
29 @protocol CPTextFieldDelegate <CPControlTextEditingDelegate>
30 
31 @end
32 
39 
40 
41 @typedef CPTextFieldBezelStyle
45 CPTextFieldDidFocusNotification = @"CPTextFieldDidFocusNotification";
46 CPTextFieldDidBlurNotification = @"CPTextFieldDidBlurNotification";
47 
62 
64 
65 function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resigning, didBlurRef)
66 {
67  if (owner && domElement != inputElement.parentNode)
68  return;
69 
70  var ownerWindow = [owner window];
71 
72  if (!resigning && [ownerWindow isKeyWindow] && [ownerWindow firstResponder] === owner)
73  {
74  /*
75  Previously we had code here which would force the input to regain focus if the input lost focus without the CPTextField having actually lost first responder status. This typically happened because the user clicked away from the input in the browser, without clicking on something that could become the first responder. In the browser, clicking outside of an input blurs it, but in Cocoa and Cappuccino it does not (unless you actually click something that will become the first responder).
76 
77  That refocusing code has now been removed because we simply prevent the default action on clicks in the browser instead, which combined with the fix in 58d5d7d7, successfully prevents unintentional focus loss in (at least) Safari 9.1.1, Chrome 51 and Safari for iOS 9.3 when you click outside of a text field.
78 
79  Now we can still lose focus unexpectedly: this is when the 'done' button is tapped on the virtual keyboard of a mobile device. In this case we actually do want to resign first responder status, because that is what the done button should do (and if we did not the keyboard would go away and then immediately come back which looks dumb and isn't what the user wanted).
80  */
81  [ownerWindow makeFirstResponder:nil];
82  }
83 
84  CPTextFieldHandleBlur(anEvent, @ref(owner));
85  @deref(didBlurRef) = YES;
86 
87  return true;
88 }
89 
90 function CPTextFieldHandleBlur(anEvent, ownerRef)
91 {
92  @deref(ownerRef) = nil;
93 
94  [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
95 }
96 
97 
99 
103 - (CPString)string
104 {
105  return self;
106 }
107 
108 @end
109 
110 CPTextFieldStateRounded = CPThemeState("rounded");
111 CPTextFieldStatePlaceholder = CPThemeState("placeholder");
112 
117 @implementation CPTextField : CPControl
118 {
119  BOOL _isEditing;
120 
121  BOOL _isEditable;
122  BOOL _isSelectable;
123  BOOL _isSecure;
124  BOOL _willBecomeFirstResponderByClick;
125  BOOL _invokedByUserEvent;
126 
127  BOOL _drawsBackground;
128 
129  CPColor _textFieldBackgroundColor;
130 
131  CPString _placeholderString;
132  CPString _stringValue;
133 
134  id <CPTextFieldDelegate> _delegate;
135  unsigned _implementedDelegateMethods;
136 
137  // NS-style Display Properties
138  CPTextFieldBezelStyle _bezelStyle;
139  BOOL _isBordered;
140  BOOL _usesSingleLineMode;
141  BOOL _wraps;
142  BOOL _scrolls;
143 }
144 
145 + (Class)_binderClassForBinding:(CPString)aBinding
146 {
147  if (aBinding === CPValueBinding)
148  return [_CPTextFieldValueBinder class];
149  else if ([aBinding hasPrefix:CPDisplayPatternValueBinding])
150  return [_CPTextFieldPatternValueBinder class];
151  else if ([aBinding hasPrefix:CPEditableBinding])
152  return [CPMultipleValueAndBinding class];
153 
154  return [super _binderClassForBinding:aBinding];
155 }
156 
157 + (CPTextField)textFieldWithStringValue:(CPString)aStringValue placeholder:(CPString)aPlaceholder width:(float)aWidth
158 {
159  return [self textFieldWithStringValue:aStringValue placeholder:aPlaceholder width:aWidth theme:[CPTheme defaultTheme]];
160 }
161 
162 + (CPTextField)textFieldWithStringValue:(CPString)aStringValue placeholder:(CPString)aPlaceholder width:(float)aWidth theme:(CPTheme)aTheme
163 {
164  var textField = [[self alloc] initWithFrame:CGRectMake(0.0, 0.0, aWidth, 29.0)];
165 
166  [textField setTheme:aTheme];
167  [textField setStringValue:aStringValue];
168  [textField setPlaceholderString:aPlaceholder];
169  [textField setBordered:YES];
170  [textField setBezeled:YES];
171  [textField setEditable:YES];
172 
173  [textField sizeToFit];
174 
175  return textField;
176 }
177 
178 + (CPTextField)roundedTextFieldWithStringValue:(CPString)aStringValue placeholder:(CPString)aPlaceholder width:(float)aWidth
179 {
180  return [self roundedTextFieldWithStringValue:aStringValue placeholder:aPlaceholder width:aWidth theme:[CPTheme defaultTheme]];
181 }
182 
183 + (CPTextField)roundedTextFieldWithStringValue:(CPString)aStringValue placeholder:(CPString)aPlaceholder width:(float)aWidth theme:(CPTheme)aTheme
184 {
185  var textField = [[CPTextField alloc] initWithFrame:CGRectMake(0.0, 0.0, aWidth, 29.0)];
186 
187  [textField setTheme:aTheme];
188  [textField setStringValue:aStringValue];
189  [textField setPlaceholderString:aPlaceholder];
190  [textField setBezelStyle:CPTextFieldRoundedBezel];
191  [textField setBordered:YES];
192  [textField setBezeled:YES];
193  [textField setEditable:YES];
194 
195  [textField sizeToFit];
196 
197  return textField;
198 }
199 
200 + (CPTextField)labelWithTitle:(CPString)aTitle
201 {
202  return [self labelWithTitle:aTitle theme:[CPTheme defaultTheme]];
203 }
204 
205 + (CPTextField)labelWithTitle:(CPString)aTitle theme:(CPTheme)aTheme
206 {
207  var textField = [[self alloc] init];
208 
209  [textField setStringValue:aTitle];
210  [textField sizeToFit];
211 
212  return textField;
213 }
214 
215 + (CPString)defaultThemeClass
216 {
217  return "textfield";
218 }
219 
220 + (CPDictionary)themeAttributes
221 {
222  return @{
223  @"bezel-inset": CGInsetMakeZero(),
224  @"content-inset": CGInsetMake(1.0, 0.0, 0.0, 0.0),
225  @"bezel-color": [CPNull null],
226  };
227 }
228 
229 
230 #pragma mark -
231 #pragma mark Control Size
232 
233 - (void)setControlSize:(CPControlSize)aControlSize
234 {
235  [super setControlSize:aControlSize];
236 
237  if ([self isBezeled])
238  [self _sizeToControlSize];
239 }
240 
241 
242 #pragma mark -
243 
244 #if PLATFORM(DOM)
245 - (DOMElement)_inputElement
246 {
248  {
249  CPTextFieldDOMTextAreaElement = document.createElement("textarea");
250  CPTextFieldDOMTextAreaElement.style.position = "absolute";
251  CPTextFieldDOMTextAreaElement.style.border = "0px";
252  CPTextFieldDOMTextAreaElement.style.padding = "0px";
253  CPTextFieldDOMTextAreaElement.style.margin = "0px";
254  CPTextFieldDOMTextAreaElement.style.background = "transparent";
255  CPTextFieldDOMTextAreaElement.style.outline = "none";
256  CPTextFieldDOMTextAreaElement.style.resize = "none";
257  CPTextFieldDOMTextAreaElement.style.overflow = "hidden";
258  CPTextFieldDOMTextAreaElement.spellcheck = NO;
259  }
260 
262  {
263  CPTextFieldDOMStandardInputElement = document.createElement("input");
264  CPTextFieldDOMStandardInputElement.style.position = "absolute";
265  CPTextFieldDOMStandardInputElement.style.border = "0px";
266  CPTextFieldDOMStandardInputElement.style.padding = "0px";
267  CPTextFieldDOMStandardInputElement.style.margin = "0px";
268  CPTextFieldDOMStandardInputElement.style.whiteSpace = "pre";
269  CPTextFieldDOMStandardInputElement.style.background = "transparent";
270  CPTextFieldDOMStandardInputElement.style.outline = "none";
271  CPTextFieldDOMStandardInputElement.spellcheck = NO;
272  }
273 
275  {
276  CPTextFieldDOMPasswordInputElement = document.createElement("input");
277  CPTextFieldDOMPasswordInputElement.style.position = "absolute";
278  CPTextFieldDOMPasswordInputElement.style.border = "0px";
279  CPTextFieldDOMPasswordInputElement.style.padding = "0px";
280  CPTextFieldDOMPasswordInputElement.style.margin = "0px";
281  CPTextFieldDOMPasswordInputElement.style.whiteSpace = "pre";
282  CPTextFieldDOMPasswordInputElement.style.background = "transparent";
283  CPTextFieldDOMPasswordInputElement.style.outline = "none";
284  CPTextFieldDOMPasswordInputElement.type = "password";
285  CPTextFieldDOMPasswordInputElement.spellcheck = NO;
286  }
287 
289  {
290  CPTextFieldBlurHandler = function(anEvent)
291  {
293  anEvent,
295  CPTextFieldInputOwner ? CPTextFieldInputOwner._DOMElement : nil,
299  };
300  }
301 
303  {
305  return;
306 
307  CPTextFieldInputFunction = function(anEvent)
308  {
310  return;
311 
312  var cappEvent = [CPEvent keyEventWithType:CPKeyUp
313  location:CGPointMakeZero()
314  modifierFlags:0
316  windowNumber:[[CPApp keyWindow] windowNumber]
317  context:nil
318  characters:nil
320  isARepeat:NO
321  keyCode:nil];
322 
323  [CPTextFieldInputOwner keyUp:cappEvent];
324 
325  [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
326  };
327 
330 
333 
336  }
337 
338 
339  if ([self isSecure])
341  else if (_usesSingleLineMode)
343  else
345 
347 }
348 #endif
349 
350 - (id)initWithFrame:(CGRect)aFrame
351 {
352  self = [super initWithFrame:aFrame];
353 
354  if (self)
355  {
356  [self setStringValue:@""];
357  [self setPlaceholderString:@""];
358 
359  _sendActionOn = CPKeyUpMask | CPKeyDownMask;
360 
361  [self setValue:CPNaturalTextAlignment forThemeAttribute:@"alignment"];
362  }
363 
364  return self;
365 }
366 
367 #pragma mark Controlling Editability and Selectability
368 
373 - (void)setEditable:(BOOL)shouldBeEditable
374 {
375  if (_isEditable === shouldBeEditable)
376  return;
377 
378  _isEditable = shouldBeEditable;
379 
380  if (shouldBeEditable)
381  _isSelectable = YES;
382 
383  if (_isEditable)
384  [self setThemeState:CPThemeStateEditable];
385  else
386  [self unsetThemeState:CPThemeStateEditable];
387 
388  // We only allow first responder status if the field is enabled, and editable or selectable.
389  if (!(shouldBeEditable && ![self isSelectable]) && [[self window] firstResponder] === self)
390  [[self window] makeFirstResponder:nil];
391 
392  if (shouldBeEditable)
393  [self setThemeState:CPThemeStateEditable];
394  else
395  [self unsetThemeState:CPThemeStateEditable];
396 
397  [self updateTrackingAreas];
398 }
399 
403 - (BOOL)isEditable
404 {
405  return _isEditable;
406 }
407 
412 - (void)setEnabled:(BOOL)shouldBeEnabled
413 {
414  [super setEnabled:shouldBeEnabled];
415 
416  // We only allow first responder status if the field is enabled.
417  if (!shouldBeEnabled && [[self window] firstResponder] === self)
418  [[self window] makeFirstResponder:nil];
419 
420  [self updateTrackingAreas];
421 }
422 
427 - (void)setSelectable:(BOOL)aFlag
428 {
429  _isSelectable = aFlag;
430 
431  [self updateTrackingAreas];
432 }
433 
437 - (BOOL)isSelectable
438 {
439  return _isSelectable;
440 }
441 
446 - (void)setSecure:(BOOL)aFlag
447 {
448  _isSecure = aFlag;
449 }
450 
454 - (BOOL)isSecure
455 {
456  return _isSecure;
457 }
458 
459 // Setting the Bezel Style
464 - (void)setBezeled:(BOOL)shouldBeBezeled
465 {
466  if (shouldBeBezeled)
467  [self setThemeState:CPThemeStateBezeled];
468  else
469  [self unsetThemeState:CPThemeStateBezeled];
470 }
471 
475 - (BOOL)isBezeled
476 {
477  return [self hasThemeState:CPThemeStateBezeled];
478 }
479 
484 - (void)setBezelStyle:(CPTextFieldBezelStyle)aBezelStyle
485 {
486  var shouldBeRounded = aBezelStyle === CPTextFieldRoundedBezel;
487 
488  if (shouldBeRounded)
489  [self setThemeState:CPTextFieldStateRounded];
490  else
491  [self unsetThemeState:CPTextFieldStateRounded];
492 }
493 
497 - (CPTextFieldBezelStyle)bezelStyle
498 {
499  if ([self hasThemeState:CPTextFieldStateRounded])
501 
502  return CPTextFieldSquareBezel;
503 }
504 
509 - (void)setBordered:(BOOL)shouldBeBordered
510 {
511  if (shouldBeBordered)
512  [self setThemeState:CPThemeStateBordered];
513  else
514  [self unsetThemeState:CPThemeStateBordered];
515 }
516 
520 - (BOOL)isBordered
521 {
522  return [self hasThemeState:CPThemeStateBordered];
523 }
524 
529 - (void)setDrawsBackground:(BOOL)shouldDrawBackground
530 {
531  if (_drawsBackground == shouldDrawBackground)
532  return;
533 
534  _drawsBackground = shouldDrawBackground;
535 
536  [self setNeedsLayout];
537  [self setNeedsDisplay:YES];
538 }
539 
543 - (BOOL)drawsBackground
544 {
545  return _drawsBackground;
546 }
547 
552 - (void)setTextFieldBackgroundColor:(CPColor)aColor
553 {
554  if (_textFieldBackgroundColor == aColor)
555  return;
556 
557  _textFieldBackgroundColor = aColor;
558 
559  [self setNeedsLayout];
560  [self setNeedsDisplay:YES];
561 }
562 
566 - (CPColor)textFieldBackgroundColor
567 {
568  return _textFieldBackgroundColor;
569 }
570 
572 - (void)_setUsesSingleLineMode:(BOOL)aFlag
573 {
574  _usesSingleLineMode = aFlag;
575 }
576 
578 - (void)_setWraps:(BOOL)aFlag
579 {
580  _wraps = aFlag;
581 }
582 
584 - (void)_setScrolls:(BOOL)aFlag
585 {
586  _scrolls = aFlag;
587 }
588 
590 - (BOOL)acceptsFirstResponder
591 {
592  return [self isEnabled] && ([self isEditable] || [self isSelectable]) && [self _isWithinUsablePlatformRect];
593 }
594 
596 - (BOOL)becomeFirstResponder
597 {
598  if (![self isEnabled] || ![super becomeFirstResponder])
599  return NO;
600 
601  // As long as we are the first responder we need to monitor the key status of our window.
602  [self _setObserveWindowKeyNotifications:YES];
603 
604  _isEditing = NO;
605 
606  if ([[self window] isKeyWindow] && [self isEditable])
607  return [self _becomeFirstKeyResponder];
608 
609  return YES;
610 }
611 
612 /*
613  A text field can be the first responder without necessarily being the focus of keyboard input. For example, it might be the first responder of window A but window B is the main and key window. It's important we don't put a focused input field into a text field in a non-key window, even if that field is the first responder, because the key window might also have a first responder text field which the user will expect to receive keyboard input.
614 
615  Since a first responder but non-key window text field can't receive input it should not even look like an active text field (Cocoa has a "slightly active" text field look it uses when another window is the key window, but Cappuccino doesn't today.)
616 
617  It's also possible for a text field to be non-editable but selectable in which case it can also become the first responder -
618  this is what allows text to be copied from it.
619 */
620 - (BOOL)_becomeFirstKeyResponder
621 {
622  // If the text field is still not completely on screen, refuse to become
623  // first responder, because the browser will scroll it into view out of our control.
624  if (![self _isWithinUsablePlatformRect])
625  return NO;
626 
627  // A selectable but non-editable text field may be the first responder, but never the
628  // first key responder (first key responder indicating editability.)
629  if (![self isEditable])
630  return NO;
631 
632  [self setThemeState:CPThemeStateEditing];
633 
634  [self _updatePlaceholderState];
635 
636  [self setNeedsLayout];
637 
638  _stringValue = [self stringValue];
639 
640 
641 #if PLATFORM(DOM)
642 
643  [self _setCSSStyleForInputElement];
644 
645  var element = [self _inputElement];
646  element.value = _stringValue;
647  _DOMElement.appendChild(element);
648 
650 
651  if (document.attachEvent)
652  {
653  CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
654  CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
655 
656  [[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
657  [[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
658  }
659 
660  CPTextFieldInputOwner = self;
661 
662  [[CPRunLoop mainRunLoop] performBlock:function()
663  {
664  if (CPTextFieldInputOwner !== self)
665  return;
666 
667  // This will prevent to jump to the focused element
668  var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
669 
670  element.focus();
671 
672  [self _restorePreviousScrollingOrigin:previousScrollingOrigin];
673 
674  // Select the text if the textfield became first responder through keyboard interaction
675  if (!_willBecomeFirstResponderByClick)
676  {
677  [self _selectText:self immediately:YES];
678  }
679  else
680  {
681  var point = CGPointMake([self convertPointFromBase:[[CPApp currentEvent] locationInWindow]].x - [self currentValueForThemeAttribute:@"content-inset"].left, 0),
682  position = [CPPlatformString charPositionOfString:[self stringValue] withFont:[self font] forPoint:point];
683 
684  [self setSelectedRange:CPMakeRange(position, 0)];
685  }
686 
687  _willBecomeFirstResponderByClick = NO;
688 
689  [self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
690  } argument:nil order:0 modes:[CPDefaultRunLoopMode]];
691 
692 #endif
693 
694  return YES;
695 }
696 
701 - (void)_setEnableCSSSelection:(BOOL)shouldEnable
702 {
703 #if PLATFORM (DOM)
705  CPTexFieldCurrentCSSSelectableField._DOMElement.style[CPBrowserStyleProperty(@"user-select")] = @"none";
706 
708  _DOMElement.style[CPBrowserStyleProperty(@"user-select")] = shouldEnable ? @"text" : @"none";
709 #endif
710 }
711 
716 - (void)_setCSSStyleForInputElement
717 {
718 #if PLATFORM(DOM)
719 
720  var element = [self _inputElement],
721  font = [self currentValueForThemeAttribute:@"font"],
722  lineHeight = [font defaultLineHeightForFont],
723  contentRect = [self contentRectForBounds:[self bounds]],
724  verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"],
725  left = CGRectGetMinX(contentRect);
726 
727  // If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
729  left -= 1;
730 
731  switch (verticalAlign)
732  {
734  var topPoint = CGRectGetMinY(contentRect) + "px";
735  break;
736 
738  var topPoint = (CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
739  break;
740 
742  var topPoint = (CGRectGetMaxY(contentRect) - lineHeight) + "px";
743  break;
744 
745  default:
746  var topPoint = CGRectGetMinY(contentRect) + "px";
747  break;
748  }
749 
750  if ([self hasThemeState:CPTextFieldStatePlaceholder])
751  element.style.color = [[self valueForThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder] cssString];
752  else
753  element.style.color = [[self valueForThemeAttribute:@"text-color" inState:CPThemeStateEditing] cssString];
754 
755  switch ([self alignment])
756  {
758  element.style.textAlign = "center";
759  break;
760 
762  element.style.textAlign = "right";
763  break;
764 
766  element.style.textAlign = "";
767  break;
768 
769  default:
770  element.style.textAlign = "left";
771  }
772 
773  var isTextArea = element.nodeName.toUpperCase() == "TEXTAREA";
774 
775  element.style.zIndex = 1000;
776  element.style.top = topPoint;
777  element.style.lineHeight = ROUND(lineHeight) + "px";
778  element.style.height = isTextArea ? CGRectGetHeight(contentRect) + "px" : ROUND(lineHeight) + "px";;
779  element.style.width = CGRectGetWidth(contentRect) + "px";
780  element.style.left = left + "px";
781  element.style.verticalAlign = "top";
782  element.style.cursor = "auto";
783  element.style.font = [font cssString];
784 
785  if (isTextArea)
786  element.style.whiteSpace = _wraps ? "pre" : "nowrap";
787 
788 #endif
789 }
790 
792 - (BOOL)resignFirstResponder
793 {
794 #if PLATFORM(DOM)
795  // We might have been the first responder without actually editing.
796  if (_isEditing && CPTextFieldInputOwner === self)
797  {
798  var element = [self _inputElement],
799  newValue = element.value,
800  error = @"";
801 
802  if (newValue !== _stringValue)
803  {
804  [self _setStringValue:newValue];
805  }
806 
807  // If there is a formatter, always give it a chance to reject the resignation,
808  // even if the value has not changed.
809  if ([self _valueIsValid:newValue] === NO)
810  {
811  // This will prevent to jump to the focused element
812  var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
813 
814  element.focus();
815 
816  [self _restorePreviousScrollingOrigin:previousScrollingOrigin];
817 
818  return NO;
819  }
820  }
821 #endif
822 
823  // When we are no longer the first responder we don't worry about the key status of our window anymore.
824  [self _setObserveWindowKeyNotifications:NO];
825 
826  if ([[self window] isKeyWindow])
827  [self _resignFirstKeyResponder];
828 
829  _isEditing = NO;
830 
831  if ([self isEditable])
832  {
833  [self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
834 
835  if ([self sendsActionOnEndEditing])
836  [self sendAction:[self action] to:[self target]];
837  }
838 
839  [self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
840 
841  return YES;
842 }
843 
844 - (void)_resignFirstKeyResponder
845 {
846  [self unsetThemeState:CPThemeStateEditing];
847 
848  // Cache the formatted string
849  _stringValue = [self stringValue];
850 
851  _willBecomeFirstResponderByClick = NO;
852 
853  [self _updatePlaceholderState];
854  [self setNeedsLayout];
855 
856 #if PLATFORM(DOM)
857 
858  var element = [self _inputElement];
859 
861 
863  element.blur();
864 
867 
868  if (element.parentNode == _DOMElement)
869  element.parentNode.removeChild(element);
870 
871  // Previosly, we unflagged CPTextFieldInputDidBlur and CPTextFieldInputResigning before
872  // the call to removeChild. This resulted in DOM exceptions in Chrome under certain conditions.
873  // See https://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node
874  // for why we need to unflag CPTextFieldInputDidBlur and CPTextFieldInputResigning
875  // only after removing the element.
876 
879 
881 
882  if (document.attachEvent)
883  {
884  [[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
885  [[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
886 
889  }
890 
891 #endif
892 }
893 
894 - (void)_setObserveWindowKeyNotifications:(BOOL)shouldObserve
895 {
896  if (shouldObserve)
897  {
898  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:) name:CPWindowDidResignKeyNotification object:[self window]];
899  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:) name:CPWindowDidBecomeKeyNotification object:[self window]];
900  }
901  else
902  {
903  [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidResignKeyNotification object:[self window]];
904  [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidBecomeKeyNotification object:[self window]];
905  }
906 }
907 
908 - (void)_removeObservers
909 {
910  if (!_isObserving)
911  return;
912 
913  [super _removeObservers];
914  [self _setObserveWindowKeyNotifications:NO];
915 }
916 
917 - (void)_addObservers
918 {
919  if (_isObserving)
920  return;
921 
922  [super _addObservers];
923 
924  if ([[self window] firstResponder] === self)
925  [self _setObserveWindowKeyNotifications:YES];
926 }
927 
928 - (void)_windowDidResignKey:(CPNotification)aNotification
929 {
930  if (![[self window] isKeyWindow])
931  [self _resignFirstKeyResponder];
932 }
933 
934 - (void)_windowDidBecomeKey:(CPNotification)aNotification
935 {
936  if (!([self isEnabled] && [self isEditable]))
937  return;
938 
939  var wind = [self window];
940 
941  if ([wind isKeyWindow] && [wind firstResponder] === self)
942  if (![self _becomeFirstKeyResponder])
943  [wind makeFirstResponder:nil];
944 }
945 
946 - (BOOL)_valueIsValid:(CPString)aValue
947 {
948 #if PLATFORM(DOM)
949 
950  var error = @"";
951 
952  if ([self _setStringValue:aValue isNewValue:NO errorDescription:@ref(error)] === NO)
953  {
954  var acceptInvalidValue = NO;
955 
957  acceptInvalidValue = [_delegate control:self didFailToFormatString:aValue errorDescription:error];
958 
959  if (acceptInvalidValue === NO)
960  return NO;
961  }
962 
963 #endif
964 
965  return YES;
966 }
967 
972 - (BOOL)needsPanelToBecomeKey
973 {
974  return [self acceptsFirstResponder];
975 }
976 
980 - (BOOL)acceptsFirstMouse:(CPEvent)anEvent
981 {
982  return [self acceptsFirstResponder];
983 }
984 
985 - (void)_didEdit
986 {
987  if (!_isEditing)
988  {
989  _isEditing = YES;
990  [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
991  }
992 
993  [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
994 }
995 
996 - (void)mouseDown:(CPEvent)anEvent
997 {
998  if (![self isEnabled])
999  return [[self nextResponder] mouseDown:anEvent];
1000 
1001  // Don't track! (ever?)
1002  if ([self isEditable] && [self isEnabled])
1003  {
1004  _willBecomeFirstResponderByClick = YES;
1005  [[self window] makeFirstResponder:self];
1006  }
1007  else if ([self isSelectable])
1008  {
1009  [self _setEnableCSSSelection:YES];
1010  if (document.attachEvent)
1011  {
1012  CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
1013  CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
1014 
1015  [[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
1016  [[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
1017  }
1018  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1019  }
1020  else
1021  return [[self nextResponder] mouseDown:anEvent];
1022 }
1023 
1024 - (void)mouseUp:(CPEvent)anEvent
1025 {
1026  if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
1027  [[self nextResponder] mouseUp:anEvent];
1028  else if ([self isSelectable])
1029  {
1030  if (document.attachEvent)
1031  {
1032  [[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
1033  [[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
1034 
1037  }
1038 
1039  // TODO clickCount === 2 should select the clicked word.
1040 
1041  if ([[CPApp currentEvent] clickCount] === 3)
1042  {
1043  [self selectText:nil];
1044  return;
1045  }
1046 
1047  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1048  }
1049 }
1050 
1051 - (void)rightMouseDown:(CPEvent)anEvent
1052 {
1053  if ([self menuForEvent:anEvent] || [[self nextResponder] isKindOfClass:CPView])
1054  [super rightMouseDown:anEvent];
1055  else
1056  [[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
1057 }
1058 
1059 - (void)mouseDragged:(CPEvent)anEvent
1060 {
1061  if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
1062  [[self nextResponder] mouseDragged:anEvent];
1063  else if ([self isSelectable])
1064  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1065 }
1066 
1067 - (void)keyUp:(CPEvent)anEvent
1068 {
1069  if (!([self isEnabled] && [self isEditable]))
1070  return;
1071 
1072 #if PLATFORM(DOM)
1073  var newValue = [self _inputElement].value;
1074 
1075  if (newValue !== _stringValue)
1076  {
1077  [self _setStringValue:newValue];
1078  [self _didEdit];
1079  }
1080 
1081  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1082 #endif
1083 }
1084 
1085 - (void)keyDown:(CPEvent)anEvent
1086 {
1087  if (!([self isEnabled] && [self isEditable]))
1088  return;
1089 
1090  // CPTextField uses an HTML input element to take the input so we need to
1091  // propagate the dom event so the element is updated. This has to be done
1092  // before interpretKeyEvents: though so individual commands have a chance
1093  // to override this (escape to clear the text in a search field for example).
1094  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1095 
1096  // Set a flag so that key handling methods (such as deleteBackward:)
1097  // know they were invoked from a user event.
1098  _invokedByUserEvent = !!anEvent._DOMEvent;
1099  [self interpretKeyEvents:[anEvent]];
1100  _invokedByUserEvent = NO;
1101 
1102  [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
1103 }
1104 
1114 - (void)doCommandBySelector:(SEL)aSelector
1115 {
1116  if ([self respondsToSelector:aSelector])
1117  [self performSelector:aSelector];
1118 }
1119 
1120 - (void)insertNewline:(id)sender
1121 {
1122  if (!([self isEnabled] && [self isEditable]))
1123  return;
1124 
1125  var newValue = [self _inputElement].value;
1126 
1127  if (newValue !== _stringValue)
1128  {
1129  [self _setStringValue:newValue];
1130  [self _didEdit];
1131  }
1132 
1133  if ([self _valueIsValid:_stringValue])
1134  {
1135  // If _isEditing == YES then the target action can also be called via
1136  // resignFirstResponder, and it is possible that the target action
1137  // itself will change this textfield's responder status, so start by
1138  // setting the _isEditing flag to NO to prevent the target action being
1139  // called twice (once below and once from resignFirstResponder).
1140  if (_isEditing)
1141  {
1142  _isEditing = NO;
1143  [self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
1144  }
1145 
1146  // If there is no target action, or the sendAction call returns
1147  // success.
1148  if (![self action] || [self sendAction:[self action] to:[self target]])
1149  {
1150  [self selectAll:nil];
1151  }
1152  }
1153 
1154  [[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
1155 }
1156 
1157 - (void)insertNewlineIgnoringFieldEditor:(id)sender
1158 {
1159  [self _insertCharacterIgnoringFieldEditor:CPNewlineCharacter];
1160 }
1161 
1162 - (void)insertTabIgnoringFieldEditor:(id)sender
1163 {
1164  [self _insertCharacterIgnoringFieldEditor:CPTabCharacter];
1165 }
1166 
1167 - (void)_insertCharacterIgnoringFieldEditor:(CPString)aCharacter
1168 {
1169  if (!([self isEnabled] && [self isEditable]))
1170  return;
1171 
1172 #if PLATFORM(DOM)
1173 
1174  var oldValue = _stringValue,
1175  range = [self selectedRange],
1176  element = [self _inputElement];
1177 
1178  // we don't need to do this in case of textarea
1179  // or we will end up with 2 carriage returns
1180  if (aCharacter != CPNewlineCharacter || element.nodeName.toUpperCase() != "TEXTAREA" || !CPFeatureIsCompatible(CPAltEnterTextAreaFeature))
1181  element.value = [element.value stringByReplacingCharactersInRange:[self selectedRange] withString:aCharacter];
1182 
1183  [self _setStringValue:element.value];
1184 
1185  // NOTE: _stringValue is now the current input element value
1186  if (oldValue !== _stringValue)
1187  {
1188  [self _didEdit];
1189  }
1190 
1191 #endif
1192 }
1193 
1194 - (void)textDidBlur:(CPNotification)note
1195 {
1196  // this looks to prevent false propagation of notifications for other objects
1197  if ([note object] != self)
1198  return;
1199 
1200  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBlur_)
1201  [_delegate controlTextDidBlur:note];
1202 
1204 }
1205 
1206 - (void)textDidFocus:(CPNotification)note
1207 {
1208  // this looks to prevent false propagation of notifications for other objects
1209  if ([note object] !== self)
1210  return;
1211 
1212  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_)
1213  [_delegate controlTextDidFocus:note];
1214 
1216 }
1217 
1218 - (void)textDidChange:(CPNotification)note
1219 {
1220  if ([note object] !== self)
1221  return;
1222 
1223  [self _continuouslyReverseSetBinding];
1224 
1225  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidChange_)
1226  [_delegate controlTextDidChange:note];
1227 
1228  [super textDidChange:note];
1229 }
1230 
1231 - (void)textDidBeginEditing:(CPNotification)note
1232 {
1233  //this looks to prevent false propagation of notifications for other objects
1234  if ([note object] != self)
1235  return;
1236 
1237  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
1238  [_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]];
1239 
1240  [super textDidBeginEditing:note];
1241 }
1242 
1243 - (void)textDidEndEditing:(CPNotification)note
1244 {
1245  //this looks to prevent false propagation of notifications for other objects
1246  if ([note object] != self)
1247  return;
1248 
1249  [super textDidEndEditing:note];
1250 
1251  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidEndEditing_)
1252  [_delegate controlTextDidEndEditing:note];
1253 }
1254 
1258 - (id)objectValue
1259 {
1260  return [super objectValue];
1261 }
1262 
1263 /*
1264  Sets the internal string value without updating the value in the input element.
1265  This should only be invoked when the underlying text element's value has changed.
1266 */
1267 - (BOOL)_setStringValue:(CPString)aValue
1268 {
1269  return [self _setStringValue:aValue isNewValue:YES errorDescription:nil];
1270 }
1271 
1276 - (BOOL)_setStringValue:(CPString)aValue isNewValue:(BOOL)isNewValue errorDescription:(CPStringRef)anError
1277 {
1278  _stringValue = aValue;
1279 
1280  var objectValue = aValue,
1281  formatter = [self formatter],
1282  result = YES;
1283 
1284  if (formatter)
1285  {
1286  var object = nil;
1287 
1288  if ([formatter getObjectValue:@ref(object) forString:aValue errorDescription:anError])
1289  objectValue = object;
1290  else
1291  {
1292  objectValue = undefined; // Mark the value as invalid
1293  result = NO;
1294  }
1295 
1296  isNewValue |= objectValue !== [super objectValue];
1297  }
1298 
1299  if (isNewValue)
1300  {
1301  [self willChangeValueForKey:@"objectValue"];
1302  [super setObjectValue:objectValue];
1303  [self _updatePlaceholderState];
1304  [self didChangeValueForKey:@"objectValue"];
1305  }
1306 
1307  return result;
1308 }
1309 
1310 - (void)setObjectValue:(id)aValue
1311 {
1312  [self _setObjectValue:aValue useFormatter:YES];
1313 }
1314 
1315 - (void)_setObjectValue:(id)aValue useFormatter:(BOOL)useFormatter
1316 {
1317  [super setObjectValue:aValue];
1318 
1319  var formatter = [self formatter];
1320 
1321  if (useFormatter && formatter)
1322  {
1323  // If there is a formatter, make sure the object value can be formatted successfully
1324  var formattedString = [self hasThemeState:CPThemeStateEditing] ? [formatter editingStringForObjectValue:aValue] : [formatter stringForObjectValue:aValue];
1325 
1326  if (formattedString === nil)
1327  {
1328  var value = nil;
1329 
1330  // Formatting failed, get an "empty" object by formatting an empty string.
1331  // If that fails, the value is undefined.
1332  if ([formatter getObjectValue:@ref(value) forString:@"" errorDescription:nil] === NO)
1333  value = undefined;
1334 
1335  [super setObjectValue:value];
1336  _stringValue = (value === nil || value === undefined) ? @"" : String(value);
1337  }
1338  else
1339  _stringValue = formattedString;
1340  }
1341  else
1342  _stringValue = [self stringValue];
1343 
1344 #if PLATFORM(DOM)
1345 
1346  if ((CPTextFieldInputOwner === self || [[self window] firstResponder] === self) && [[self window] isKeyWindow])
1347  [self _inputElement].value = _stringValue;
1348 
1349 #endif
1350 
1351  [self _updatePlaceholderState];
1352 }
1353 
1354 - (void)_updatePlaceholderState
1355 {
1356  if (!_stringValue || _stringValue.length === 0)
1357  [self setThemeState:CPTextFieldStatePlaceholder];
1358  else
1359  [self unsetThemeState:CPTextFieldStatePlaceholder];
1360 }
1361 
1366 - (void)setPlaceholderString:(CPString)aStringValue
1367 {
1368  if (_placeholderString === aStringValue)
1369  return;
1370 
1371  _placeholderString = aStringValue;
1372 
1373  // Only update things if we need to show the placeholder
1374  if ([self hasThemeState:CPTextFieldStatePlaceholder])
1375  {
1376  [self setNeedsLayout];
1377  [self setNeedsDisplay:YES];
1378  }
1379 }
1380 
1384 - (CPString)placeholderString
1385 {
1386  return _placeholderString;
1387 }
1388 
1409 - (void)sizeToFit
1410 {
1411  [self setFrameSize:[self _minimumFrameSize]];
1412 }
1413 
1414 - (CGSize)_minimumFrameSize
1415 {
1416  var frameSize = [self frameSize],
1417  contentInset = [self currentValueForThemeAttribute:@"content-inset"],
1418  minSize = [self currentValueForThemeAttribute:@"min-size"],
1419  maxSize = [self currentValueForThemeAttribute:@"max-size"],
1420  lineBreakMode = [self lineBreakMode],
1421  text = (_stringValue || @" "),
1422  textSize = CGSizeMakeCopy(frameSize),
1423  font = [self currentValueForThemeAttribute:@"font"];
1424 
1425  textSize.width -= contentInset.left + contentInset.right;
1426  textSize.height -= contentInset.top + contentInset.bottom;
1427 
1428  if (frameSize.width !== 0 &&
1429  ![self isBezeled] &&
1430  (lineBreakMode === CPLineBreakByWordWrapping || lineBreakMode === CPLineBreakByCharWrapping))
1431  {
1432  textSize = [text sizeWithFont:font inWidth:textSize.width];
1433  }
1434  else
1435  {
1436  textSize = [text sizeWithFont:font];
1437 
1438  // Account for possible fractional pixels at right edge
1439  textSize.width += 1;
1440  }
1441 
1442  // Account for possible fractional pixels at bottom edge
1443  textSize.height += 1;
1444 
1445  frameSize.height = textSize.height + contentInset.top + contentInset.bottom;
1446 
1447  if ([self isBezeled])
1448  {
1449  frameSize.height = MAX(frameSize.height, minSize.height);
1450 
1451  if (maxSize.width > 0.0)
1452  frameSize.width = MIN(frameSize.width, maxSize.width);
1453 
1454  if (maxSize.height > 0.0)
1455  frameSize.height = MIN(frameSize.height, maxSize.height);
1456  }
1457  else
1458  frameSize.width = textSize.width + contentInset.left + contentInset.right;
1459 
1460  frameSize.width = MAX(frameSize.width, minSize.width);
1461 
1462  return frameSize;
1463 }
1464 
1468 - (void)selectText:(id)sender
1469 {
1470  [self _selectText:sender immediately:NO];
1471 }
1472 
1473 - (void)_selectText:(id)sender immediately:(BOOL)immediately
1474 {
1475  // Selecting the text in a field makes it the first responder
1476  if ([self isEditable] || [self isSelectable])
1477  {
1478  var wind = [self window];
1479 
1480 #if PLATFORM(DOM)
1481  if ([self isEditable])
1482  {
1483  var element = [self _inputElement];
1484 
1485  if ([wind firstResponder] === self)
1486  {
1487  if (immediately)
1488  element.select();
1489  else
1490  [[CPRunLoop mainRunLoop] performBlock:function(){ element.select(); } argument:nil order:0 modes:[CPDefaultRunLoopMode]];
1491  }
1492  else if (wind !== nil && [wind makeFirstResponder:self])
1493  [self _selectText:sender immediately:immediately];
1494  }
1495  else
1496  {
1497  [self setSelectedRange:CPMakeRange(0, _stringValue.length)];
1498  }
1499 #else
1500  // Even if we can't actually select the text we need to preserve the first
1501  // responder side effect.
1502  if (wind !== nil && [wind firstResponder] !== self)
1503  [wind makeFirstResponder:self];
1504 #endif
1505  }
1506 
1507 }
1508 
1509 - (void)copy:(id)sender
1510 {
1511  // First write to the Cappuccino clipboard.
1512  var stringToCopy = nil;
1513 
1514  if ([self isEditable])
1515  {
1516  var selectedRange = [self selectedRange];
1517 
1518  if (selectedRange.length < 1)
1519  return;
1520 
1521  stringToCopy = [_stringValue substringWithRange:selectedRange];
1522  }
1523  else
1524  {
1525  // selectedRange won't work if we're displaying our text using a <div>. Instead we have to ask the browser
1526  // what's selected and hope it's right in a Cappuccino context as well.
1527 #if PLATFORM(DOM)
1528  stringToCopy = [[[self window] platformWindow] _selectedText];
1529 #endif
1530  }
1531 
1532  var pasteboard = [CPPasteboard generalPasteboard];
1533 
1534  [pasteboard declareTypes:[CPStringPboardType] owner:nil];
1535  [pasteboard setString:stringToCopy forType:CPStringPboardType];
1536 
1537  if ([CPPlatform isBrowser])
1538  {
1539  // Then also allow the browser to capture the copied text into the system clipboard.
1540  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1541  }
1542 }
1543 
1544 - (void)cut:(id)sender
1545 {
1546  if (![self isEnabled])
1547  return;
1548 
1549  [self copy:sender];
1550 
1551  if (![self isEditable])
1552  return;
1553 
1554  if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
1555  {
1556  [self deleteBackward:sender];
1557  }
1558  else
1559  {
1560  // Allow the browser's standard cut handling. This should also result in the deleteBackward: happening.
1561  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1562 
1563  // If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
1566  }
1567 }
1568 
1569 - (void)paste:(id)sender
1570 {
1571  if (!([self isEnabled] && [self isEditable]))
1572  return;
1573 
1574  if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
1575  {
1576  var pasteboard = [CPPasteboard generalPasteboard];
1577 
1578  if (![[pasteboard types] containsObject:CPStringPboardType])
1579  return;
1580 
1581  [self deleteBackward:sender];
1582 
1583  var selectedRange = [self selectedRange],
1584  pasteString = [pasteboard stringForType:CPStringPboardType],
1585  newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
1586 
1587  [self setStringValue:newValue];
1588  [self _didEdit];
1589  [self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
1590  }
1591  // If we don't have an oninput listener, we won't detect the change made by the cut and need to fake a key up "soon".
1592  else
1593  {
1594  // Allow the browser's standard paste handling.
1595  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1596 
1599  }
1600 }
1601 
1602 - (CPRange)selectedRange
1603 {
1604  // TODO Need a way to figure out the selected range if we're not using an input. Need
1605  // to get whole document selection and somehow see which part is inside of this text field.
1606  if ([[self window] firstResponder] !== self)
1607  return CPMakeRange(0, 0);
1608 
1609 #if PLATFORM(DOM)
1610 
1611  // we wrap this in try catch because firefox will throw an exception in certain instances
1612  try
1613  {
1614  var inputElement = [self _inputElement],
1615  selectionStart = inputElement.selectionStart,
1616  selectionEnd = inputElement.selectionEnd;
1617 
1618  if ([selectionStart isKindOfClass:CPNumber])
1619  return CPMakeRange(selectionStart, selectionEnd - selectionStart);
1620 
1621  // browsers which don't support selectionStart/selectionEnd (aka IE).
1622  var theDocument = inputElement.ownerDocument || inputElement.document,
1623  selectionRange = theDocument.selection.createRange(),
1624  range = inputElement.createTextRange();
1625 
1626  if (range.inRange(selectionRange))
1627  {
1628  range.setEndPoint('EndToStart', selectionRange);
1629  return CPMakeRange(range.text.length, selectionRange.text.length);
1630  }
1631  }
1632  catch (e)
1633  {
1634  // fall through to the return
1635  }
1636 
1637 #endif
1638 
1639  return CPMakeRange(0, 0);
1640 }
1641 
1642 - (void)setSelectedRange:(CPRange)aRange
1643 {
1644  if (![[self window] firstResponder] === self)
1645  return;
1646 
1647 #if PLATFORM(DOM)
1648 
1649  if (![self isEditable])
1650  {
1651  // No input element - selectable text field only.
1652  var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
1653  positioned:CPWindowAbove
1654  relativeToEphemeralSubviewNamed:@"bezel-view"];
1655 
1656  if (contentView)
1657  [contentView setSelectedRange:aRange];
1658  }
1659  else
1660  {
1661  // Input element
1662  var inputElement = [self _inputElement];
1663 
1664  try
1665  {
1666  if ([inputElement.selectionStart isKindOfClass:CPNumber])
1667  {
1668  inputElement.selectionStart = aRange.location;
1669  inputElement.selectionEnd = CPMaxRange(aRange);
1670  }
1671  else
1672  {
1673  // browsers which don't support selectionStart/selectionEnd (aka IE).
1674  var theDocument = inputElement.ownerDocument || inputElement.document,
1675  existingRange = theDocument.selection.createRange(),
1676  range = inputElement.createTextRange();
1677 
1678  if (range.inRange(existingRange))
1679  {
1680  range.collapse(true);
1681  range.move('character', aRange.location);
1682  range.moveEnd('character', aRange.length);
1683  range.select();
1684  }
1685  }
1686  }
1687  catch (e)
1688  {
1689  }
1690  }
1691 #endif
1692 }
1693 
1694 - (void)selectAll:(id)sender
1695 {
1696  [self selectText:sender];
1697 }
1698 
1699 - (void)deleteBackward:(id)sender
1700 {
1701  if (!([self isEnabled] && [self isEditable]))
1702  return;
1703 
1704  var selectedRange = [self selectedRange];
1705 
1706  if (selectedRange.length === 0)
1707  {
1708  if (selectedRange.location < 1)
1709  return;
1710 
1711  // Delete a single element backward from the insertion point if there's no selection.
1712  selectedRange.location -= 1;
1713  selectedRange.length += 1;
1714  }
1715 
1716  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1717 }
1718 
1719 - (void)delete:(id)sender
1720 {
1721  if (!([self isEnabled] && [self isEditable]))
1722  return;
1723 
1724  // delete: only works when there's a selection (as opposed to deleteForward: and deleteBackward:).
1725  var selectedRange = [self selectedRange];
1726 
1727  if (selectedRange.length < 1)
1728  return;
1729 
1730  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1731 }
1732 
1733 - (void)deleteForward:(id)sender
1734 {
1735  if (!([self isEnabled] && [self isEditable]))
1736  return;
1737 
1738  var selectedRange = [self selectedRange];
1739 
1740  if (selectedRange.length === 0)
1741  {
1742  if (selectedRange.location >= _stringValue.length)
1743  return;
1744 
1745  // Delete a single element forward from the insertion point if there's no selection.
1746  selectedRange.length += 1;
1747  }
1748 
1749  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1750 }
1751 
1752 - (void)_replaceCharactersInRange:(CPRange)range withCharacters:(CPString)characters
1753 {
1754  var newValue = [_stringValue stringByReplacingCharactersInRange:range withString:characters];
1755 
1756  if (_invokedByUserEvent)
1757  {
1758  [self _setStringValue:newValue];
1759  }
1760  else
1761  {
1762  [self _setObjectValue:newValue useFormatter:NO];
1763  [self setSelectedRange:CPMakeRange(range.location, 0)];
1764 
1765 #if PLATFORM(DOM)
1766  // Since we just performed the deletion manually, we don't need the browser to do anything else.
1767  [[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
1768 #endif
1769  }
1770 
1771  [self _didEdit];
1772 }
1773 
1774 #pragma mark Setting the Delegate
1775 
1776 - (void)setDelegate:(id <CPTextFieldDelegate>)aDelegate
1777 {
1778  if (_delegate === aDelegate)
1779  return;
1780 
1781  _delegate = aDelegate;
1782  _implementedDelegateMethods = 0;
1783 
1784  if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
1786 
1787  if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
1788  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
1789 
1790  if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
1791  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidChange_;
1792 
1793  if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
1794  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidEndEditing_;
1795 
1796  if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)])
1797  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidFocus_;
1798 
1799  if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)])
1800  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBlur_;
1801 }
1802 
1804 {
1805  return _delegate;
1806 }
1807 
1808 - (CGRect)contentRectForBounds:(CGRect)bounds
1809 {
1810  var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
1811 
1812  return CGRectInsetByInset(bounds, contentInset);
1813 }
1814 
1815 - (CGRect)bezelRectForBounds:(CGRect)bounds
1816 {
1817  var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
1818 
1819  return CGRectInsetByInset(bounds, bezelInset);
1820 }
1821 
1822 - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
1823 {
1824  if (aName === "bezel-view")
1825  return [self bezelRectForBounds:[self bounds]];
1826 
1827  else if (aName === "content-view")
1828  return [self contentRectForBounds:[self bounds]];
1829 
1830  return [super rectForEphemeralSubviewNamed:aName];
1831 }
1832 
1833 - (CPView)createEphemeralSubviewNamed:(CPString)aName
1834 {
1835  if (aName === "bezel-view")
1836  {
1837  var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
1838 
1839  [view setHitTests:NO];
1840 
1841  return view;
1842  }
1843  else
1844  {
1845  var view = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
1846 
1847  [view setHitTests:NO];
1848 
1849  return view;
1850  }
1851 
1852  return [super createEphemeralSubviewNamed:aName];
1853 }
1854 
1855 - (void)layoutSubviews
1856 {
1857  var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
1858  positioned:CPWindowBelow
1859  relativeToEphemeralSubviewNamed:@"content-view"];
1860 
1861  if (bezelView)
1862  [bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
1863 
1864  var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
1865  positioned:CPWindowAbove
1866  relativeToEphemeralSubviewNamed:@"bezel-view"];
1867 
1868  if (contentView)
1869  {
1870  [contentView setHidden:(_stringValue && _stringValue.length > 0) && [self hasThemeState:CPThemeStateEditing]];
1871 
1872  var string = "";
1873 
1874  if ([self hasThemeState:CPTextFieldStatePlaceholder])
1875  string = [self placeholderString];
1876  else
1877  {
1878  string = _stringValue;
1879 
1880  if ([self isSecure])
1881  string = secureStringForString(string);
1882  }
1883 
1884  [contentView setText:string];
1885 
1886  [contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
1887  [contentView setFont:[self currentValueForThemeAttribute:@"font"]];
1888  [contentView setAlignment:[self currentValueForThemeAttribute:@"alignment"]];
1889  [contentView setVerticalAlignment:[self currentValueForThemeAttribute:@"vertical-alignment"]];
1890  [contentView setLineBreakMode:[self currentValueForThemeAttribute:@"line-break-mode"]];
1891  [contentView setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
1892  [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
1893  }
1894 
1895  if (_isEditing)
1896  [self _setCSSStyleForInputElement];
1897 }
1898 
1899 - (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
1900 {
1901  var count = objects.length,
1902  value = [objects[0] valueForKeyPath:aKeyPath];
1903 
1904  [self setStringValue:value];
1905  [self setPlaceholderString:@""];
1906 
1907  while (count-- > 1)
1908  if (value !== [objects[count] valueForKeyPath:aKeyPath])
1909  {
1910  [self setPlaceholderString:@"Multiple Values"];
1911  [self setStringValue:@""];
1912  }
1913 }
1914 
1915 #pragma mark Overrides
1916 
1922 - (void)setTextColor:(CPColor)aColor
1923 {
1924  // We don't want to change the text-color of the placeHolder of the textField
1925  var placeholderColor = [self valueForThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
1926 
1927  [super setTextColor:aColor];
1928  [self setValue:placeholderColor forThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
1929 }
1930 
1931 - (void)viewDidHide
1932 {
1933  [super viewDidHide];
1934 
1935  if ([[self window] firstResponder] === self)
1936  [self _resignFirstKeyResponder];
1937 }
1938 
1939 - (void)viewDidUnhide
1940 {
1941  [super viewDidUnhide];
1942 
1943  if ([self isEditable] && [[self window] firstResponder] === self)
1944  [self _becomeFirstKeyResponder];
1945 }
1946 
1947 - (BOOL)validateUserInterfaceItem:(id /*<CPValidatedUserInterfaceItem>*/)anItem
1948 {
1949  var theAction = [anItem action];
1950 
1951  if (![self isEditable] && (theAction == @selector(cut:) || theAction == @selector(paste:) || theAction == @selector(delete:)))
1952  return NO;
1953 
1954  // FIXME - [self selectedRange] is always empty if we're not an editable field, so we must assume yes here.
1955  if (![self isEditable])
1956  return YES;
1957 
1958  if (theAction == @selector(copy:) || theAction == @selector(cut:) || theAction == @selector(delete:))
1959  return [self selectedRange].length;
1960 
1961  return YES;
1962 }
1963 
1964 #pragma mark Private
1965 
1966 - (BOOL)_isWithinUsablePlatformRect
1967 {
1968  // Make sure the text field is completely within the platform window
1969  // so the browser will not scroll it into view.
1970 
1971  var wind = [self window];
1972 
1973  // If the field is not yet within a window, it can't be first responder
1974  if (!wind)
1975  return NO;
1976 
1977  var scrollView = [self enclosingScrollView],
1978  previousContentViewBoundsOrigin;
1979 
1980  // Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
1981  var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
1982 
1983  var frame = [self convertRectToBase:[self contentRectForBounds:[self bounds]]],
1984  usableRect = [[wind platformWindow] usableContentFrame];
1985 
1986  frame.origin = [wind convertBaseToGlobal:frame.origin];
1987 
1988  // Here we restore the previous scrolling posiition
1989  [self _restorePreviousScrollingOrigin:previousScrollingOrigin];
1990 
1991  return (CGRectGetMinX(frame) >= CGRectGetMinX(usableRect) &&
1992  CGRectGetMaxX(frame) <= CGRectGetMaxX(usableRect) &&
1993  CGRectGetMinY(frame) >= CGRectGetMinY(usableRect) &&
1994  CGRectGetMaxY(frame) <= CGRectGetMaxY(usableRect));
1995 }
1996 
2000 - (CGPoint)_scrollToVisibleRectAndReturnPreviousOrigin
2001 {
2002  var scrollView = [self enclosingScrollView],
2003  previousContentViewBoundsOrigin;
2004 
2005  // Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
2006  if ([scrollView isKindOfClass:[CPScrollView class]])
2007  {
2008  previousContentViewBoundsOrigin = CGPointMakeCopy([[scrollView contentView] boundsOrigin]);
2009 
2010  if (![[self superview] scrollRectToVisible:[self frame]])
2011  previousContentViewBoundsOrigin = nil;
2012  }
2013 
2014  return previousContentViewBoundsOrigin;
2015 }
2016 
2020 - (void)_restorePreviousScrollingOrigin:(CGPoint)scrollingOrigin
2021 {
2022  if (scrollingOrigin)
2023  [[[self enclosingScrollView] contentView] setBoundsOrigin:scrollingOrigin];
2024 }
2025 
2026 @end
2027 
2028 var secureStringForString = function(aString)
2029 {
2030  // This is true for when aString === "" and null/undefined.
2031  if (!aString)
2032  return "";
2033 
2034  return Array(aString.length + 1).join(CPSecureTextFieldCharacter);
2035 };
2036 
2037 
2038 var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
2039  CPTextFieldIsSelectableKey = "CPTextFieldIsSelectableKey",
2040  CPTextFieldIsBorderedKey = "CPTextFieldIsBorderedKey",
2041  CPTextFieldIsBezeledKey = "CPTextFieldIsBezeledKey",
2042  CPTextFieldBezelStyleKey = "CPTextFieldBezelStyleKey",
2043  CPTextFieldDrawsBackgroundKey = "CPTextFieldDrawsBackgroundKey",
2044  CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
2045  CPTextFieldAlignmentKey = "CPTextFieldAlignmentKey",
2046  CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
2047  CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey",
2048  CPTextFieldUsesSingleLineMode = "CPTextFieldUsesSingleLineMode",
2049  CPTextFieldWraps = "CPTextFieldWraps",
2050  CPTextFieldScrolls = "CPTextFieldScrolls";
2051 
2052 
2053 @implementation CPTextField (CPCoding)
2054 
2060 - (id)initWithCoder:(CPCoder)aCoder
2061 {
2062  self = [super initWithCoder:aCoder];
2063 
2064  if (self)
2065  {
2066  [self setEditable:[aCoder decodeBoolForKey:CPTextFieldIsEditableKey]];
2067  [self setSelectable:[aCoder decodeBoolForKey:CPTextFieldIsSelectableKey]];
2068 
2069  [self setDrawsBackground:[aCoder decodeBoolForKey:CPTextFieldDrawsBackgroundKey]];
2070 
2071  [self setTextFieldBackgroundColor:[aCoder decodeObjectForKey:CPTextFieldBackgroundColorKey]];
2072 
2073  [self setLineBreakMode:[aCoder decodeIntForKey:CPTextFieldLineBreakModeKey]];
2074  [self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
2075 
2076  [self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
2077 
2078  [self _setUsesSingleLineMode:[aCoder decodeBoolForKey:CPTextFieldUsesSingleLineMode]];
2079  [self _setWraps:[aCoder decodeBoolForKey:CPTextFieldWraps]];
2080  [self _setScrolls:[aCoder decodeBoolForKey:CPTextFieldScrolls]];
2081  }
2082 
2083  return self;
2084 }
2085 
2090 - (void)encodeWithCoder:(CPCoder)aCoder
2091 {
2092  [super encodeWithCoder:aCoder];
2093 
2094  [aCoder encodeBool:_isEditable forKey:CPTextFieldIsEditableKey];
2095  [aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey];
2096 
2097  [aCoder encodeBool:_drawsBackground forKey:CPTextFieldDrawsBackgroundKey];
2098 
2099  [aCoder encodeObject:_textFieldBackgroundColor forKey:CPTextFieldBackgroundColorKey];
2100 
2101  [aCoder encodeInt:[self lineBreakMode] forKey:CPTextFieldLineBreakModeKey];
2102  [aCoder encodeInt:[self alignment] forKey:CPTextFieldAlignmentKey];
2103 
2104  [aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
2105 
2106  [aCoder encodeBool:_usesSingleLineMode forKey:CPTextFieldUsesSingleLineMode];
2107  [aCoder encodeBool:_wraps forKey:CPTextFieldWraps];
2108  [aCoder encodeBool:_scrolls forKey:CPTextFieldScrolls];
2109 }
2110 
2111 @end
2112 @implementation _CPTextFieldValueBinder : CPBinder
2113 {
2114  id __doxygen__;
2115 }
2116 
2117 - (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding
2118 {
2119  [super _updatePlaceholdersWithOptions:options];
2120 
2121  [self _setPlaceholder:@"Multiple Values" forMarker:CPMultipleValuesMarker isDefault:YES];
2122  [self _setPlaceholder:@"No Selection" forMarker:CPNoSelectionMarker isDefault:YES];
2123  [self _setPlaceholder:@"Not Applicable" forMarker:CPNotApplicableMarker isDefault:YES];
2124  [self _setPlaceholder:@"" forMarker:CPNullMarker isDefault:YES];
2125 }
2126 
2127 - (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
2128 {
2129  [_source setPlaceholderString:aValue];
2130  [_source setObjectValue:nil];
2131 }
2132 
2133 - (void)setValue:(id)aValue forBinding:(CPString)aBinding
2134 {
2135  if (!aValue || (aValue.isa && [aValue isMemberOfClass:CPNull]))
2136  [_source setPlaceholderString:[self _placeholderForMarker:CPNullMarker]];
2137 
2138  [_source setObjectValue:aValue];
2139 }
2140 
2141 - (void)reverseSetValueFor:(CPString)aBinding
2142 {
2143  var destination = [_info objectForKey:CPObservedObjectKey],
2144  keyPath = [_info objectForKey:CPObservedKeyPathKey],
2145  options = [_info objectForKey:CPOptionsKey],
2146  newValue = [self valueForBinding:aBinding],
2147  value = [destination valueForKeyPath:keyPath];
2148 
2149  if (CPIsControllerMarker(value) && newValue === nil)
2150  return;
2151 
2152  newValue = [self reverseTransformValue:newValue withOptions:options];
2153 
2154  [self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
2155  [destination setValue:newValue forKeyPath:keyPath];
2156  [self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
2157 }
2158 
2159 @end
2160 @implementation _CPTextFieldPatternValueBinder : CPValueWithPatternBinding
2161 {
2162  id __doxygen__;
2163 }
2164 
2165 - (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
2166 {
2167  [_source setPlaceholderString:aValue];
2168  [_source setObjectValue:nil];
2169 }
2170 
2171 - (void)setValue:(id)aValue forBinding:(CPString)aBinding
2172 {
2173  if (!aValue || (aValue.isa && [aValue isMemberOfClass:CPNull]))
2174  [_source setPlaceholderString:[self _placeholderForMarker:CPNullMarker]];
2175 
2176  [_source setObjectValue:aValue];
2177 }
2178 
2179 @end
2180 
2182 {
2183  CPTrackingArea _textFieldTrackingArea;
2184 }
2185 
2186 - (void)updateTrackingAreas
2187 {
2188  if (_textFieldTrackingArea)
2189  {
2190  [self removeTrackingArea:_textFieldTrackingArea];
2191  _textFieldTrackingArea = nil;
2192  }
2193 
2194  if ([self isEnabled] && (_isEditable || _isSelectable))
2195  {
2196  var myBounds = CGRectMakeCopy([self bounds]),
2197  contentInset = [self currentValueForThemeAttribute:@"content-inset"];
2198 
2199  _textFieldTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectInsetByInset(myBounds, contentInset)
2200  options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
2201  owner:self
2202  userInfo:nil];
2203 
2204  [self addTrackingArea:_textFieldTrackingArea];
2205  }
2206 
2207  [super updateTrackingAreas];
2208 }
2209 
2210 - (void)cursorUpdate:(CPEvent)anEvent
2211 {
2212  [[CPCursor IBeamCursor] set];
2213 }
2214 
2215 @end
2216 
2217 #pragma mark -
2218 
2220 
2221 // We overide here _CPObject+Theme setValue:forThemeAttribute as CPTextField can be used as tableView data view
2222 // So, when outside a table data view, setValue:forThemeAttribute should store the value with the CPThemeStateNormal (default behavior)
2223 // When inside a table data view, it should store the value with the CPThemeStateTableDataView. If not, the value won't be used if the
2224 // theme defined a value for this attribute for state CPThemeStateTableDataView
2225 
2226 - (void)setValue:(id)aValue forThemeAttribute:(CPString)aName
2227 {
2228  [super setValue:aValue forThemeAttribute:aName];
2229  [super setValue:aValue forThemeAttribute:aName inState:CPThemeStateTableDataView];
2230 }
2231 
2232 @end
2233 
2234 
CPEvent keyEventWithType:location:modifierFlags:timestamp:windowNumber:context:characters:charactersIgnoringModifiers:isARepeat:keyCode:(CPEventType anEventType, [location] CGPoint aPoint, [modifierFlags] unsigned int modifierFlags, [timestamp] CPTimeInterval aTimestamp, [windowNumber] int aWindowNumber, [context] CPGraphicsContext aGraphicsContext, [characters] CPString characters, [charactersIgnoringModifiers] CPString unmodCharacters, [isARepeat] BOOL repeatKey, [keyCode] unsigned short code)
Definition: CPEvent.j:106
BOOL makeFirstResponder:(CPResponder aResponder)
Definition: CPWindow.j:1632
void setDrawsBackground:(BOOL shouldDrawBackground)
Definition: CPTextField.j:529
var CPTextFieldDOMStandardInputElement
Definition: CPTextField.j:50
void postNotification:(CPNotification aNotification)
var CPTextFieldIsBorderedKey
Definition: CPTextField.j:2040
var CPTextFieldIsBezeledKey
Definition: CPTextField.j:2041
var CPTextFieldAlignmentKey
Definition: CPTextField.j:2045
BOOL isEnabled()
Definition: CPControl.j:970
BOOL setThemeState:(ThemeState aState)
Definition: CPView.j:3255
CGRect frame
var CPTextFieldTextDidChangeValue
Definition: CPTextField.j:53
void selectText:(id sender)
Definition: CPTextField.j:1468
void setValue:forThemeAttribute:inState:(id aValue, [forThemeAttribute] CPString aName, [inState] ThemeState aState)
Definition: CPView.j:3371
An object representation of nil.
Definition: CPNull.h:2
CPStringPboardType
Definition: CPPasteboard.j:37
var CPTextFieldCachedSelectStartFunction
Definition: CPTextField.j:57
void setSelectedRange:(CPRange aRange)
Definition: CPTextField.j:1642
var CPTextFieldDelegate_controlTextDidBeginEditing_
Definition: CPTextField.j:34
The main run loop for the application.
Definition: CPRunLoop.h:2
CPRightTextAlignment
Definition: CPText.j:77
id generalPasteboard()
Definition: CPPasteboard.j:83
var CPTextFieldDelegate_controlTextDidEndEditing_
Definition: CPTextField.j:36
CPTextField labelWithTitle:theme:(CPString aTitle, [theme] CPTheme aTheme)
Definition: CPTextField.j:205
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
void setLineBreakMode:(CPLineBreakMode mode)
Definition: CPControl.j:823
var CPTextFieldInputOwner
Definition: CPTextField.j:52
CPResponder firstResponder()
Definition: CPWindow.j:1657
void textDidChange:(CPNotification note)
Definition: CPControl.j:703
var CPTextFieldDelegate_controlTextDidBlur_
Definition: CPTextField.j:38
var CPTextFieldInputFunction
Definition: CPTextField.j:60
function CPTextFieldHandleBlur(anEvent, ownerRef)
Definition: CPTextField.j:90
void viewDidHide()
Definition: CPView.j:1805
CPInputOnInputEventFeature
void selectAll:(id sender)
Definition: CPTextField.j:1694
CPLineBreakByCharWrapping
Definition: CPControl.j:46
CPTextField textFieldWithStringValue:placeholder:width:theme:(CPString aStringValue, [placeholder] CPString aPlaceholder, [width] float aWidth, [theme] CPTheme aTheme)
Definition: CPTextField.j:162
id delegate()
Definition: CALayer.j:965
void textDidBeginEditing:(CPNotification note)
Definition: CPControl.j:694
void textDidEndEditing:(CPNotification note)
Definition: CPControl.j:712
id initWithFrame:(CGRect aFrame)
Definition: CPControl.j:183
CGRect bounds()
Definition: CPView.j:1326
CPTextFieldDidBlurNotification
Definition: CPTextField.j:46
void deleteBackward:(id sender)
Definition: CPTextField.j:1699
void copy:(id sender)
Definition: CPTextField.j:1509
void setControlSize:(CPControlSize aControlSize)
Definition: CPControl.j:211
void setEnabled:(BOOL isEnabled)
Definition: CPControl.j:959
CPKeyUpMask
void setValue:forThemeAttribute:(id aValue, [forThemeAttribute] CPString aName)
Definition: CPView.j:3384
CPTextFieldBezelStyle CPTextFieldSquareBezel
Definition: CPTextField.j:42
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
void rightMouseDown:(CPEvent anEvent)
Definition: CPView.j:1926
var CPTextFieldIsSelectableKey
Definition: CPTextField.j:2039
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
var CPTextFieldWraps
Definition: CPTextField.j:2049
void setEditable:(BOOL shouldBeEditable)
Definition: CPTextField.j:373
void textDidBlur:(CPNotification note)
Definition: CPTextField.j:1194
CGRect bounds()
Definition: CALayer.j:203
CPWindow window()
Definition: CPView.j:527
CPRange selectedRange()
Definition: CPTextField.j:1602
var CPTextFieldCachedDragFunction
Definition: CPTextField.j:58
CPView createEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3397
CPNaturalTextAlignment
Definition: CPText.j:80
id initWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
void setPlaceholderString:(CPString aStringValue)
Definition: CPTextField.j:1366
function CPMaxRange(aRange)
Definition: CPRange.j:70
An immutable string (collection of characters).
Definition: CPString.h:2
CPNull null()
Definition: CPNull.j:51
CPAltEnterTextAreaFeature
if(CPFeatureIsCompatible(CPHTMLCanvasFeature))
CPRunLoop mainRunLoop()
Definition: CPRunLoop.j:240
var CPTextFieldInputIsActive
Definition: CPTextField.j:56
BOOL sendAction:to:(SEL anAction, [to] id anObject)
Definition: CPControl.j:319
function CPFeatureIsCompatible(aFeature)
SEL action()
Definition: CPControl.j:290
id initWithCoder:(CPCoder aCoder)
Definition: CPControl.j:1092
var CPTextFieldBezelStyleKey
Definition: CPTextField.j:2042
void performBlock:argument:order:modes:(Function aBlock, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
Definition: CPRunLoop.j:270
BOOL acceptsFirstResponder()
Definition: CPTextField.j:590
void setTextColor:(CPColor aColor)
Definition: CPControl.j:841
var CPTextFieldDOMPasswordInputElement
Definition: CPTextField.j:51
CGRect contentRectForBounds:(CGRect bounds)
Definition: CPTextField.j:1808
BOOL isEditable()
Definition: CPTextField.j:403
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2597
var CPTextFieldPlaceholderStringKey
Definition: CPTextField.j:2047
var CPTextFieldDelegate_controlTextDidChange_
Definition: CPTextField.j:35
CPTextFieldStateRounded
Definition: CPTextField.j:110
CPTextAlignment alignment()
Definition: CPControl.j:784
var CPSecureTextFieldCharacter
Definition: CPTextField.j:63
CGRect bezelRectForBounds:(CGRect bounds)
Definition: CPTextField.j:1815
CPWindow window()
Definition: CPEvent.j:341
int length()
Definition: CPString.j:186
CPVerticalTextAlignment CPTopVerticalTextAlignment
Definition: CPControl.j:53
var secureStringForString
Definition: CPTextField.j:2028
void setStringValue:(CPString aString)
Definition: CPControl.j:629
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
CPDate limitDateForMode:(CPString aMode)
Definition: CPRunLoop.j:342
CPTextFieldRoundedBezel
Definition: CPTextField.j:43
var CPTextFieldIsEditableKey
Definition: CPTextField.j:2038
CPTheme defaultTheme()
Definition: CPTheme.j:44
void setNeedsLayout()
Definition: CPView.j:2748
id target()
Definition: CPControl.j:308
CPBottomVerticalTextAlignment
Definition: CPControl.j:55
var CPTextFieldDOMCurrentElement
Definition: CPTextField.j:48
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
BOOL isSelectable()
Definition: CPTextField.j:437
void setAlignment:(CPTextAlignment alignment)
Definition: CPControl.j:776
BOOL unsetThemeState:(ThemeState aState)
Definition: CPView.j:3268
Sends messages (CPNotification) between objects.
CPNotification notificationWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
CPString placeholderString()
Definition: CPTextField.j:1384
void addTrackingArea:(CPTrackingArea trackingArea)
Definition: CPView.j:3552
Definition: CPTheme.h:2
void setSelectable:(BOOL aFlag)
Definition: CPTextField.j:427
CPNewlineCharacter
Definition: CPText.j:52
CPLineBreakMode lineBreakMode()
Definition: CPControl.j:831
CPTimeInterval currentTimestamp()
Definition: CPEvent.j:84
void setValue:forThemeAttribute:(id aValue, [forThemeAttribute] CPString aName)
Definition: CPTextField.j:2226
var CPTextFieldDelegate_controlTextDidFocus_
Definition: CPTextField.j:37
var CPTextFieldLineBreakModeKey
Definition: CPTextField.j:2044
var CPTextFieldBlurHandler
Definition: CPTextField.j:59
void textDidEndEditing:(CPNotification note)
Definition: CPTextField.j:1243
CPTextField roundedTextFieldWithStringValue:placeholder:width:theme:(CPString aStringValue, [placeholder] CPString aPlaceholder, [width] float aWidth, [theme] CPTheme aTheme)
Definition: CPTextField.j:183
var CPTextFieldInputDidBlur
Definition: CPTextField.j:55
CPLineBreakMode CPLineBreakByWordWrapping
Definition: CPControl.j:45
void setFrameSize:(CGSize aSize)
Definition: CPView.j:1124
var CPTextFieldUsesSingleLineMode
Definition: CPTextField.j:2048
var CPTextFieldDOMTextAreaElement
Definition: CPTextField.j:49
void updateTrackingAreas()
Definition: CPTextField.j:2186
CPTextFieldStatePlaceholder
Definition: CPTextField.j:111
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
var CPTexFieldCurrentCSSSelectableField
Definition: CPTextField.j:61
void set()
Definition: CPCursor.j:128
var CPTextFieldDrawsBackgroundKey
Definition: CPTextField.j:2043
Definition: CPEvent.h:2
void setTextFieldBackgroundColor:(CPColor aColor)
Definition: CPTextField.j:552
var CPTextFieldBackgroundColorKey
Definition: CPTextField.j:2046
CPKeyDownMask
CPTrackingArea initWithRect:options:owner:userInfo:(CGRect aRect, [options] CPTrackingAreaOptions options, [owner] id owner, [userInfo] CPDictionary userInfo)
CPCenterTextAlignment
Definition: CPText.j:78
CPPlatformWindow platformWindow()
Definition: CPWindow.j:389
void updateTrackingAreas()
Definition: CPControl.j:1056
CPTextFieldDidFocusNotification
Definition: CPTextField.j:45
var CPTextFieldInputResigning
Definition: CPTextField.j:54
A bridged object to native Javascript numbers.
Definition: CPNumber.h:2
void viewDidUnhide()
Definition: CPView.j:1819
void encodeWithCoder:(CPCoder aCoder)
Definition: CPControl.j:1121
var CPTextFieldScrolls
Definition: CPTextField.j:2050
CPRange function CPMakeRange(location, length)
Definition: CPRange.j:37
function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resigning, didBlurRef)
Definition: CPTextField.j:65
id objectValue()
Definition: CPControl.j:526
var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
Definition: CPTextField.j:33
CPCursor IBeamCursor()
Definition: CPCursor.j:256
CPView layoutEphemeralSubviewNamed:positioned:relativeToEphemeralSubviewNamed:(CPString aViewName, [positioned] CPWindowOrderingMode anOrderingMode, [relativeToEphemeralSubviewNamed] CPString relativeToViewName)
Definition: CPView.j:3407
void removeTrackingArea:(CPTrackingArea trackingArea)
Definition: CPView.j:3570
CPCenterVerticalTextAlignment
Definition: CPControl.j:54
id alloc()
Definition: CPObject.j:130
CGRect rectForEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3402
Definition: CPView.j:137
CPInput1PxLeftPadding