API  0.9.10
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 
870 
871  if (element.parentNode == _DOMElement)
872  element.parentNode.removeChild(element);
873 
875 
876  if (document.attachEvent)
877  {
878  [[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
879  [[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
880 
883  }
884 
885 #endif
886 }
887 
888 - (void)_setObserveWindowKeyNotifications:(BOOL)shouldObserve
889 {
890  if (shouldObserve)
891  {
892  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResignKey:) name:CPWindowDidResignKeyNotification object:[self window]];
893  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidBecomeKey:) name:CPWindowDidBecomeKeyNotification object:[self window]];
894  }
895  else
896  {
897  [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidResignKeyNotification object:[self window]];
898  [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidBecomeKeyNotification object:[self window]];
899  }
900 }
901 
902 - (void)_removeObservers
903 {
904  if (!_isObserving)
905  return;
906 
907  [super _removeObservers];
908  [self _setObserveWindowKeyNotifications:NO];
909 }
910 
911 - (void)_addObservers
912 {
913  if (_isObserving)
914  return;
915 
916  [super _addObservers];
917 
918  if ([[self window] firstResponder] === self)
919  [self _setObserveWindowKeyNotifications:YES];
920 }
921 
922 - (void)_windowDidResignKey:(CPNotification)aNotification
923 {
924  if (![[self window] isKeyWindow])
925  [self _resignFirstKeyResponder];
926 }
927 
928 - (void)_windowDidBecomeKey:(CPNotification)aNotification
929 {
930  if (!([self isEnabled] && [self isEditable]))
931  return;
932 
933  var wind = [self window];
934 
935  if ([wind isKeyWindow] && [wind firstResponder] === self)
936  if (![self _becomeFirstKeyResponder])
937  [wind makeFirstResponder:nil];
938 }
939 
940 - (BOOL)_valueIsValid:(CPString)aValue
941 {
942 #if PLATFORM(DOM)
943 
944  var error = @"";
945 
946  if ([self _setStringValue:aValue isNewValue:NO errorDescription:@ref(error)] === NO)
947  {
948  var acceptInvalidValue = NO;
949 
951  acceptInvalidValue = [_delegate control:self didFailToFormatString:aValue errorDescription:error];
952 
953  if (acceptInvalidValue === NO)
954  return NO;
955  }
956 
957 #endif
958 
959  return YES;
960 }
961 
966 - (BOOL)needsPanelToBecomeKey
967 {
968  return [self acceptsFirstResponder];
969 }
970 
974 - (BOOL)acceptsFirstMouse:(CPEvent)anEvent
975 {
976  return [self acceptsFirstResponder];
977 }
978 
979 - (void)_didEdit
980 {
981  if (!_isEditing)
982  {
983  _isEditing = YES;
984  [self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
985  }
986 
987  [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
988 }
989 
990 - (void)mouseDown:(CPEvent)anEvent
991 {
992  if (![self isEnabled])
993  return [[self nextResponder] mouseDown:anEvent];
994 
995  // Don't track! (ever?)
996  if ([self isEditable] && [self isEnabled])
997  {
998  _willBecomeFirstResponderByClick = YES;
999  [[self window] makeFirstResponder:self];
1000  }
1001  else if ([self isSelectable])
1002  {
1003  [self _setEnableCSSSelection:YES];
1004  if (document.attachEvent)
1005  {
1006  CPTextFieldCachedSelectStartFunction = [[self window] platformWindow]._DOMBodyElement.onselectstart;
1007  CPTextFieldCachedDragFunction = [[self window] platformWindow]._DOMBodyElement.ondrag;
1008 
1009  [[self window] platformWindow]._DOMBodyElement.ondrag = function () {};
1010  [[self window] platformWindow]._DOMBodyElement.onselectstart = function () {};
1011  }
1012  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1013  }
1014  else
1015  return [[self nextResponder] mouseDown:anEvent];
1016 }
1017 
1018 - (void)mouseUp:(CPEvent)anEvent
1019 {
1020  if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
1021  [[self nextResponder] mouseUp:anEvent];
1022  else if ([self isSelectable])
1023  {
1024  if (document.attachEvent)
1025  {
1026  [[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
1027  [[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
1028 
1031  }
1032 
1033  // TODO clickCount === 2 should select the clicked word.
1034 
1035  if ([[CPApp currentEvent] clickCount] === 3)
1036  {
1037  [self selectText:nil];
1038  return;
1039  }
1040 
1041  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1042  }
1043 }
1044 
1045 - (void)rightMouseDown:(CPEvent)anEvent
1046 {
1047  if ([self menuForEvent:anEvent] || [[self nextResponder] isKindOfClass:CPView])
1048  [super rightMouseDown:anEvent];
1049  else
1050  [[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
1051 }
1052 
1053 - (void)mouseDragged:(CPEvent)anEvent
1054 {
1055  if (![self isEnabled] || !([self isSelectable] || [self isEditable]))
1056  [[self nextResponder] mouseDragged:anEvent];
1057  else if ([self isSelectable])
1058  return [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
1059 }
1060 
1061 - (void)keyUp:(CPEvent)anEvent
1062 {
1063  if (!([self isEnabled] && [self isEditable]))
1064  return;
1065 
1066 #if PLATFORM(DOM)
1067  var newValue = [self _inputElement].value;
1068 
1069  if (newValue !== _stringValue)
1070  {
1071  [self _setStringValue:newValue];
1072  [self _didEdit];
1073  }
1074 
1075  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1076 #endif
1077 }
1078 
1079 - (void)keyDown:(CPEvent)anEvent
1080 {
1081  if (!([self isEnabled] && [self isEditable]))
1082  return;
1083 
1084  // CPTextField uses an HTML input element to take the input so we need to
1085  // propagate the dom event so the element is updated. This has to be done
1086  // before interpretKeyEvents: though so individual commands have a chance
1087  // to override this (escape to clear the text in a search field for example).
1088  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1089 
1090  // Set a flag so that key handling methods (such as deleteBackward:)
1091  // know they were invoked from a user event.
1092  _invokedByUserEvent = !!anEvent._DOMEvent;
1093  [self interpretKeyEvents:[anEvent]];
1094  _invokedByUserEvent = NO;
1095 
1096  [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
1097 }
1098 
1108 - (void)doCommandBySelector:(SEL)aSelector
1109 {
1110  if ([self respondsToSelector:aSelector])
1111  [self performSelector:aSelector];
1112 }
1113 
1114 - (void)insertNewline:(id)sender
1115 {
1116  if (!([self isEnabled] && [self isEditable]))
1117  return;
1118 
1119  var newValue = [self _inputElement].value;
1120 
1121  if (newValue !== _stringValue)
1122  {
1123  [self _setStringValue:newValue];
1124  [self _didEdit];
1125  }
1126 
1127  if ([self _valueIsValid:_stringValue])
1128  {
1129  // If _isEditing == YES then the target action can also be called via
1130  // resignFirstResponder, and it is possible that the target action
1131  // itself will change this textfield's responder status, so start by
1132  // setting the _isEditing flag to NO to prevent the target action being
1133  // called twice (once below and once from resignFirstResponder).
1134  if (_isEditing)
1135  {
1136  _isEditing = NO;
1137  [self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
1138  }
1139 
1140  // If there is no target action, or the sendAction call returns
1141  // success.
1142  if (![self action] || [self sendAction:[self action] to:[self target]])
1143  {
1144  [self selectAll:nil];
1145  }
1146  }
1147 
1148  [[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
1149 }
1150 
1151 - (void)insertNewlineIgnoringFieldEditor:(id)sender
1152 {
1153  [self _insertCharacterIgnoringFieldEditor:CPNewlineCharacter];
1154 }
1155 
1156 - (void)insertTabIgnoringFieldEditor:(id)sender
1157 {
1158  [self _insertCharacterIgnoringFieldEditor:CPTabCharacter];
1159 }
1160 
1161 - (void)_insertCharacterIgnoringFieldEditor:(CPString)aCharacter
1162 {
1163  if (!([self isEnabled] && [self isEditable]))
1164  return;
1165 
1166 #if PLATFORM(DOM)
1167 
1168  var oldValue = _stringValue,
1169  range = [self selectedRange],
1170  element = [self _inputElement];
1171 
1172  // we don't need to do this in case of textarea
1173  // or we will end up with 2 carriage returns
1174  if (aCharacter != CPNewlineCharacter || element.nodeName.toUpperCase() != "TEXTAREA" || !CPFeatureIsCompatible(CPAltEnterTextAreaFeature))
1175  element.value = [element.value stringByReplacingCharactersInRange:[self selectedRange] withString:aCharacter];
1176 
1177  [self _setStringValue:element.value];
1178 
1179  // NOTE: _stringValue is now the current input element value
1180  if (oldValue !== _stringValue)
1181  {
1182  [self _didEdit];
1183  }
1184 
1185 #endif
1186 }
1187 
1188 - (void)textDidBlur:(CPNotification)note
1189 {
1190  // this looks to prevent false propagation of notifications for other objects
1191  if ([note object] != self)
1192  return;
1193 
1194  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBlur_)
1195  [_delegate controlTextDidBlur:note];
1196 
1198 }
1199 
1200 - (void)textDidFocus:(CPNotification)note
1201 {
1202  // this looks to prevent false propagation of notifications for other objects
1203  if ([note object] !== self)
1204  return;
1205 
1206  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_)
1207  [_delegate controlTextDidFocus:note];
1208 
1210 }
1211 
1212 - (void)textDidChange:(CPNotification)note
1213 {
1214  if ([note object] !== self)
1215  return;
1216 
1217  [self _continuouslyReverseSetBinding];
1218 
1219  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidChange_)
1220  [_delegate controlTextDidChange:note];
1221 
1222  [super textDidChange:note];
1223 }
1224 
1225 - (void)textDidBeginEditing:(CPNotification)note
1226 {
1227  //this looks to prevent false propagation of notifications for other objects
1228  if ([note object] != self)
1229  return;
1230 
1231  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
1232  [_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]]
1233 
1234  [super textDidBeginEditing:note];
1235 }
1236 
1237 - (void)textDidEndEditing:(CPNotification)note
1238 {
1239  //this looks to prevent false propagation of notifications for other objects
1240  if ([note object] != self)
1241  return;
1242 
1243  [super textDidEndEditing:note];
1244 
1245  if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidEndEditing_)
1246  [_delegate controlTextDidEndEditing:note];
1247 }
1248 
1252 - (id)objectValue
1253 {
1254  return [super objectValue];
1255 }
1256 
1257 /*
1258  Sets the internal string value without updating the value in the input element.
1259  This should only be invoked when the underlying text element's value has changed.
1260 */
1261 - (BOOL)_setStringValue:(CPString)aValue
1262 {
1263  return [self _setStringValue:aValue isNewValue:YES errorDescription:nil];
1264 }
1265 
1270 - (BOOL)_setStringValue:(CPString)aValue isNewValue:(BOOL)isNewValue errorDescription:(CPStringRef)anError
1271 {
1272  _stringValue = aValue;
1273 
1274  var objectValue = aValue,
1275  formatter = [self formatter],
1276  result = YES;
1277 
1278  if (formatter)
1279  {
1280  var object = nil;
1281 
1282  if ([formatter getObjectValue:@ref(object) forString:aValue errorDescription:anError])
1283  objectValue = object;
1284  else
1285  {
1286  objectValue = undefined; // Mark the value as invalid
1287  result = NO;
1288  }
1289 
1290  isNewValue |= objectValue !== [super objectValue];
1291  }
1292 
1293  if (isNewValue)
1294  {
1295  [self willChangeValueForKey:@"objectValue"];
1296  [super setObjectValue:objectValue];
1297  [self _updatePlaceholderState];
1298  [self didChangeValueForKey:@"objectValue"];
1299  }
1300 
1301  return result;
1302 }
1303 
1304 - (void)setObjectValue:(id)aValue
1305 {
1306  [self _setObjectValue:aValue useFormatter:YES];
1307 }
1308 
1309 - (void)_setObjectValue:(id)aValue useFormatter:(BOOL)useFormatter
1310 {
1311  [super setObjectValue:aValue];
1312 
1313  var formatter = [self formatter];
1314 
1315  if (useFormatter && formatter)
1316  {
1317  // If there is a formatter, make sure the object value can be formatted successfully
1318  var formattedString = [self hasThemeState:CPThemeStateEditing] ? [formatter editingStringForObjectValue:aValue] : [formatter stringForObjectValue:aValue];
1319 
1320  if (formattedString === nil)
1321  {
1322  var value = nil;
1323 
1324  // Formatting failed, get an "empty" object by formatting an empty string.
1325  // If that fails, the value is undefined.
1326  if ([formatter getObjectValue:@ref(value) forString:@"" errorDescription:nil] === NO)
1327  value = undefined;
1328 
1329  [super setObjectValue:value];
1330  _stringValue = (value === nil || value === undefined) ? @"" : String(value);
1331  }
1332  else
1333  _stringValue = formattedString;
1334  }
1335  else
1336  _stringValue = [self stringValue];
1337 
1338 #if PLATFORM(DOM)
1339 
1340  if ((CPTextFieldInputOwner === self || [[self window] firstResponder] === self) && [[self window] isKeyWindow])
1341  [self _inputElement].value = _stringValue;
1342 
1343 #endif
1344 
1345  [self _updatePlaceholderState];
1346 }
1347 
1348 - (void)_updatePlaceholderState
1349 {
1350  if (!_stringValue || _stringValue.length === 0)
1351  [self setThemeState:CPTextFieldStatePlaceholder];
1352  else
1353  [self unsetThemeState:CPTextFieldStatePlaceholder];
1354 }
1355 
1360 - (void)setPlaceholderString:(CPString)aStringValue
1361 {
1362  if (_placeholderString === aStringValue)
1363  return;
1364 
1365  _placeholderString = aStringValue;
1366 
1367  // Only update things if we need to show the placeholder
1368  if ([self hasThemeState:CPTextFieldStatePlaceholder])
1369  {
1370  [self setNeedsLayout];
1371  [self setNeedsDisplay:YES];
1372  }
1373 }
1374 
1378 - (CPString)placeholderString
1379 {
1380  return _placeholderString;
1381 }
1382 
1403 - (void)sizeToFit
1404 {
1405  [self setFrameSize:[self _minimumFrameSize]];
1406 }
1407 
1408 - (CGSize)_minimumFrameSize
1409 {
1410  var frameSize = [self frameSize],
1411  contentInset = [self currentValueForThemeAttribute:@"content-inset"],
1412  minSize = [self currentValueForThemeAttribute:@"min-size"],
1413  maxSize = [self currentValueForThemeAttribute:@"max-size"],
1414  lineBreakMode = [self lineBreakMode],
1415  text = (_stringValue || @" "),
1416  textSize = CGSizeMakeCopy(frameSize),
1417  font = [self currentValueForThemeAttribute:@"font"];
1418 
1419  textSize.width -= contentInset.left + contentInset.right;
1420  textSize.height -= contentInset.top + contentInset.bottom;
1421 
1422  if (frameSize.width !== 0 &&
1423  ![self isBezeled] &&
1424  (lineBreakMode === CPLineBreakByWordWrapping || lineBreakMode === CPLineBreakByCharWrapping))
1425  {
1426  textSize = [text sizeWithFont:font inWidth:textSize.width];
1427  }
1428  else
1429  {
1430  textSize = [text sizeWithFont:font];
1431 
1432  // Account for possible fractional pixels at right edge
1433  textSize.width += 1;
1434  }
1435 
1436  // Account for possible fractional pixels at bottom edge
1437  textSize.height += 1;
1438 
1439  frameSize.height = textSize.height + contentInset.top + contentInset.bottom;
1440 
1441  if ([self isBezeled])
1442  {
1443  frameSize.height = MAX(frameSize.height, minSize.height);
1444 
1445  if (maxSize.width > 0.0)
1446  frameSize.width = MIN(frameSize.width, maxSize.width);
1447 
1448  if (maxSize.height > 0.0)
1449  frameSize.height = MIN(frameSize.height, maxSize.height);
1450  }
1451  else
1452  frameSize.width = textSize.width + contentInset.left + contentInset.right;
1453 
1454  frameSize.width = MAX(frameSize.width, minSize.width);
1455 
1456  return frameSize;
1457 }
1458 
1462 - (void)selectText:(id)sender
1463 {
1464  [self _selectText:sender immediately:NO];
1465 }
1466 
1467 - (void)_selectText:(id)sender immediately:(BOOL)immediately
1468 {
1469  // Selecting the text in a field makes it the first responder
1470  if ([self isEditable] || [self isSelectable])
1471  {
1472  var wind = [self window];
1473 
1474 #if PLATFORM(DOM)
1475  if ([self isEditable])
1476  {
1477  var element = [self _inputElement];
1478 
1479  if ([wind firstResponder] === self)
1480  {
1481  if (immediately)
1482  element.select();
1483  else
1484  [[CPRunLoop mainRunLoop] performBlock:function(){ element.select(); } argument:nil order:0 modes:[CPDefaultRunLoopMode]];
1485  }
1486  else if (wind !== nil && [wind makeFirstResponder:self])
1487  [self _selectText:sender immediately:immediately];
1488  }
1489  else
1490  {
1491  [self setSelectedRange:CPMakeRange(0, _stringValue.length)];
1492  }
1493 #else
1494  // Even if we can't actually select the text we need to preserve the first
1495  // responder side effect.
1496  if (wind !== nil && [wind firstResponder] !== self)
1497  [wind makeFirstResponder:self];
1498 #endif
1499  }
1500 
1501 }
1502 
1503 - (void)copy:(id)sender
1504 {
1505  // First write to the Cappuccino clipboard.
1506  var stringToCopy = nil;
1507 
1508  if ([self isEditable])
1509  {
1510  var selectedRange = [self selectedRange];
1511 
1512  if (selectedRange.length < 1)
1513  return;
1514 
1515  stringToCopy = [_stringValue substringWithRange:selectedRange];
1516  }
1517  else
1518  {
1519  // selectedRange won't work if we're displaying our text using a <div>. Instead we have to ask the browser
1520  // what's selected and hope it's right in a Cappuccino context as well.
1521 #if PLATFORM(DOM)
1522  stringToCopy = [[[self window] platformWindow] _selectedText];
1523 #endif
1524  }
1525 
1526  var pasteboard = [CPPasteboard generalPasteboard];
1527 
1528  [pasteboard declareTypes:[CPStringPboardType] owner:nil];
1529  [pasteboard setString:stringToCopy forType:CPStringPboardType];
1530 
1531  if ([CPPlatform isBrowser])
1532  {
1533  // Then also allow the browser to capture the copied text into the system clipboard.
1534  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1535  }
1536 }
1537 
1538 - (void)cut:(id)sender
1539 {
1540  if (![self isEnabled])
1541  return;
1542 
1543  [self copy:sender];
1544 
1545  if (![self isEditable])
1546  return;
1547 
1548  if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
1549  {
1550  [self deleteBackward:sender];
1551  }
1552  else
1553  {
1554  // Allow the browser's standard cut handling. This should also result in the deleteBackward: happening.
1555  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1556 
1557  // 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".
1560  }
1561 }
1562 
1563 - (void)paste:(id)sender
1564 {
1565  if (!([self isEnabled] && [self isEditable]))
1566  return;
1567 
1568  if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste])
1569  {
1570  var pasteboard = [CPPasteboard generalPasteboard];
1571 
1572  if (![[pasteboard types] containsObject:CPStringPboardType])
1573  return;
1574 
1575  [self deleteBackward:sender];
1576 
1577  var selectedRange = [self selectedRange],
1578  pasteString = [pasteboard stringForType:CPStringPboardType],
1579  newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
1580 
1581  [self setStringValue:newValue];
1582  [self _didEdit];
1583  [self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
1584  }
1585  // 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".
1586  else
1587  {
1588  // Allow the browser's standard paste handling.
1589  [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
1590 
1593  }
1594 }
1595 
1596 - (CPRange)selectedRange
1597 {
1598  // TODO Need a way to figure out the selected range if we're not using an input. Need
1599  // to get whole document selection and somehow see which part is inside of this text field.
1600  if ([[self window] firstResponder] !== self)
1601  return CPMakeRange(0, 0);
1602 
1603 #if PLATFORM(DOM)
1604 
1605  // we wrap this in try catch because firefox will throw an exception in certain instances
1606  try
1607  {
1608  var inputElement = [self _inputElement],
1609  selectionStart = inputElement.selectionStart,
1610  selectionEnd = inputElement.selectionEnd;
1611 
1612  if ([selectionStart isKindOfClass:CPNumber])
1613  return CPMakeRange(selectionStart, selectionEnd - selectionStart);
1614 
1615  // browsers which don't support selectionStart/selectionEnd (aka IE).
1616  var theDocument = inputElement.ownerDocument || inputElement.document,
1617  selectionRange = theDocument.selection.createRange(),
1618  range = inputElement.createTextRange();
1619 
1620  if (range.inRange(selectionRange))
1621  {
1622  range.setEndPoint('EndToStart', selectionRange);
1623  return CPMakeRange(range.text.length, selectionRange.text.length);
1624  }
1625  }
1626  catch (e)
1627  {
1628  // fall through to the return
1629  }
1630 
1631 #endif
1632 
1633  return CPMakeRange(0, 0);
1634 }
1635 
1636 - (void)setSelectedRange:(CPRange)aRange
1637 {
1638  if (![[self window] firstResponder] === self)
1639  return;
1640 
1641 #if PLATFORM(DOM)
1642 
1643  if (![self isEditable])
1644  {
1645  // No input element - selectable text field only.
1646  var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
1647  positioned:CPWindowAbove
1648  relativeToEphemeralSubviewNamed:@"bezel-view"];
1649 
1650  if (contentView)
1651  [contentView setSelectedRange:aRange];
1652  }
1653  else
1654  {
1655  // Input element
1656  var inputElement = [self _inputElement];
1657 
1658  try
1659  {
1660  if ([inputElement.selectionStart isKindOfClass:CPNumber])
1661  {
1662  inputElement.selectionStart = aRange.location;
1663  inputElement.selectionEnd = CPMaxRange(aRange);
1664  }
1665  else
1666  {
1667  // browsers which don't support selectionStart/selectionEnd (aka IE).
1668  var theDocument = inputElement.ownerDocument || inputElement.document,
1669  existingRange = theDocument.selection.createRange(),
1670  range = inputElement.createTextRange();
1671 
1672  if (range.inRange(existingRange))
1673  {
1674  range.collapse(true);
1675  range.move('character', aRange.location);
1676  range.moveEnd('character', aRange.length);
1677  range.select();
1678  }
1679  }
1680  }
1681  catch (e)
1682  {
1683  }
1684  }
1685 #endif
1686 }
1687 
1688 - (void)selectAll:(id)sender
1689 {
1690  [self selectText:sender];
1691 }
1692 
1693 - (void)deleteBackward:(id)sender
1694 {
1695  if (!([self isEnabled] && [self isEditable]))
1696  return;
1697 
1698  var selectedRange = [self selectedRange];
1699 
1700  if (selectedRange.length === 0)
1701  {
1702  if (selectedRange.location < 1)
1703  return;
1704 
1705  // Delete a single element backward from the insertion point if there's no selection.
1706  selectedRange.location -= 1;
1707  selectedRange.length += 1;
1708  }
1709 
1710  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1711 }
1712 
1713 - (void)delete:(id)sender
1714 {
1715  if (!([self isEnabled] && [self isEditable]))
1716  return;
1717 
1718  // delete: only works when there's a selection (as opposed to deleteForward: and deleteBackward:).
1719  var selectedRange = [self selectedRange];
1720 
1721  if (selectedRange.length < 1)
1722  return;
1723 
1724  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1725 }
1726 
1727 - (void)deleteForward:(id)sender
1728 {
1729  if (!([self isEnabled] && [self isEditable]))
1730  return;
1731 
1732  var selectedRange = [self selectedRange];
1733 
1734  if (selectedRange.length === 0)
1735  {
1736  if (selectedRange.location >= _stringValue.length)
1737  return;
1738 
1739  // Delete a single element forward from the insertion point if there's no selection.
1740  selectedRange.length += 1;
1741  }
1742 
1743  [self _replaceCharactersInRange:selectedRange withCharacters:@""];
1744 }
1745 
1746 - (void)_replaceCharactersInRange:(CPRange)range withCharacters:(CPString)characters
1747 {
1748  var newValue = [_stringValue stringByReplacingCharactersInRange:range withString:characters];
1749 
1750  if (_invokedByUserEvent)
1751  {
1752  [self _setStringValue:newValue];
1753  }
1754  else
1755  {
1756  [self _setObjectValue:newValue useFormatter:NO];
1757  [self setSelectedRange:CPMakeRange(range.location, 0)];
1758 
1759 #if PLATFORM(DOM)
1760  // Since we just performed the deletion manually, we don't need the browser to do anything else.
1761  [[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
1762 #endif
1763  }
1764 
1765  [self _didEdit];
1766 }
1767 
1768 #pragma mark Setting the Delegate
1769 
1770 - (void)setDelegate:(id <CPTextFieldDelegate>)aDelegate
1771 {
1772  if (_delegate === aDelegate)
1773  return;
1774 
1775  _delegate = aDelegate;
1776  _implementedDelegateMethods = 0;
1777 
1778  if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
1780 
1781  if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
1782  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
1783 
1784  if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
1785  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidChange_;
1786 
1787  if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
1788  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidEndEditing_;
1789 
1790  if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)])
1791  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidFocus_;
1792 
1793  if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)])
1794  _implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBlur_;
1795 }
1796 
1798 {
1799  return _delegate;
1800 }
1801 
1802 - (CGRect)contentRectForBounds:(CGRect)bounds
1803 {
1804  var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
1805 
1806  return CGRectInsetByInset(bounds, contentInset);
1807 }
1808 
1809 - (CGRect)bezelRectForBounds:(CGRect)bounds
1810 {
1811  var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
1812 
1813  return CGRectInsetByInset(bounds, bezelInset);
1814 }
1815 
1816 - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
1817 {
1818  if (aName === "bezel-view")
1819  return [self bezelRectForBounds:[self bounds]];
1820 
1821  else if (aName === "content-view")
1822  return [self contentRectForBounds:[self bounds]];
1823 
1824  return [super rectForEphemeralSubviewNamed:aName];
1825 }
1826 
1827 - (CPView)createEphemeralSubviewNamed:(CPString)aName
1828 {
1829  if (aName === "bezel-view")
1830  {
1831  var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
1832 
1833  [view setHitTests:NO];
1834 
1835  return view;
1836  }
1837  else
1838  {
1839  var view = [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
1840 
1841  [view setHitTests:NO];
1842 
1843  return view;
1844  }
1845 
1846  return [super createEphemeralSubviewNamed:aName];
1847 }
1848 
1849 - (void)layoutSubviews
1850 {
1851  var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
1852  positioned:CPWindowBelow
1853  relativeToEphemeralSubviewNamed:@"content-view"];
1854 
1855  if (bezelView)
1856  [bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
1857 
1858  var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
1859  positioned:CPWindowAbove
1860  relativeToEphemeralSubviewNamed:@"bezel-view"];
1861 
1862  if (contentView)
1863  {
1864  [contentView setHidden:(_stringValue && _stringValue.length > 0) && [self hasThemeState:CPThemeStateEditing]];
1865 
1866  var string = "";
1867 
1868  if ([self hasThemeState:CPTextFieldStatePlaceholder])
1869  string = [self placeholderString];
1870  else
1871  {
1872  string = _stringValue;
1873 
1874  if ([self isSecure])
1875  string = secureStringForString(string);
1876  }
1877 
1878  [contentView setText:string];
1879 
1880  [contentView setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
1881  [contentView setFont:[self currentValueForThemeAttribute:@"font"]];
1882  [contentView setAlignment:[self currentValueForThemeAttribute:@"alignment"]];
1883  [contentView setVerticalAlignment:[self currentValueForThemeAttribute:@"vertical-alignment"]];
1884  [contentView setLineBreakMode:[self currentValueForThemeAttribute:@"line-break-mode"]];
1885  [contentView setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
1886  [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
1887  }
1888 
1889  if (_isEditing)
1890  [self _setCSSStyleForInputElement];
1891 }
1892 
1893 - (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
1894 {
1895  var count = objects.length,
1896  value = [objects[0] valueForKeyPath:aKeyPath];
1897 
1898  [self setStringValue:value];
1899  [self setPlaceholderString:@""];
1900 
1901  while (count-- > 1)
1902  if (value !== [objects[count] valueForKeyPath:aKeyPath])
1903  {
1904  [self setPlaceholderString:@"Multiple Values"];
1905  [self setStringValue:@""];
1906  }
1907 }
1908 
1909 #pragma mark Overrides
1910 
1916 - (void)setTextColor:(CPColor)aColor
1917 {
1918  // We don't want to change the text-color of the placeHolder of the textField
1919  var placeholderColor = [self valueForThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
1920 
1921  [super setTextColor:aColor];
1922  [self setValue:placeholderColor forThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
1923 }
1924 
1925 - (void)viewDidHide
1926 {
1927  [super viewDidHide];
1928 
1929  if ([[self window] firstResponder] === self)
1930  [self _resignFirstKeyResponder];
1931 }
1932 
1933 - (void)viewDidUnhide
1934 {
1935  [super viewDidUnhide];
1936 
1937  if ([self isEditable] && [[self window] firstResponder] === self)
1938  [self _becomeFirstKeyResponder];
1939 }
1940 
1941 - (BOOL)validateUserInterfaceItem:(id /*<CPValidatedUserInterfaceItem>*/)anItem
1942 {
1943  var theAction = [anItem action];
1944 
1945  if (![self isEditable] && (theAction == @selector(cut:) || theAction == @selector(paste:) || theAction == @selector(delete:)))
1946  return NO;
1947 
1948  // FIXME - [self selectedRange] is always empty if we're not an editable field, so we must assume yes here.
1949  if (![self isEditable])
1950  return YES;
1951 
1952  if (theAction == @selector(copy:) || theAction == @selector(cut:) || theAction == @selector(delete:))
1953  return [self selectedRange].length;
1954 
1955  return YES;
1956 }
1957 
1958 #pragma mark Private
1959 
1960 - (BOOL)_isWithinUsablePlatformRect
1961 {
1962  // Make sure the text field is completely within the platform window
1963  // so the browser will not scroll it into view.
1964 
1965  var wind = [self window];
1966 
1967  // If the field is not yet within a window, it can't be first responder
1968  if (!wind)
1969  return NO;
1970 
1971  var scrollView = [self enclosingScrollView],
1972  previousContentViewBoundsOrigin;
1973 
1974  // Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
1975  var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
1976 
1977  var frame = [self convertRectToBase:[self contentRectForBounds:[self bounds]]],
1978  usableRect = [[wind platformWindow] usableContentFrame];
1979 
1980  frame.origin = [wind convertBaseToGlobal:frame.origin];
1981 
1982  // Here we restore the previous scrolling posiition
1983  [self _restorePreviousScrollingOrigin:previousScrollingOrigin];
1984 
1985  return (CGRectGetMinX(frame) >= CGRectGetMinX(usableRect) &&
1986  CGRectGetMaxX(frame) <= CGRectGetMaxX(usableRect) &&
1987  CGRectGetMinY(frame) >= CGRectGetMinY(usableRect) &&
1988  CGRectGetMaxY(frame) <= CGRectGetMaxY(usableRect));
1989 }
1990 
1994 - (CGPoint)_scrollToVisibleRectAndReturnPreviousOrigin
1995 {
1996  var scrollView = [self enclosingScrollView],
1997  previousContentViewBoundsOrigin;
1998 
1999  // Here we scroll to the textField, otherwise the textField could not be in the usable platformRect
2000  if ([scrollView isKindOfClass:[CPScrollView class]])
2001  {
2002  previousContentViewBoundsOrigin = CGPointMakeCopy([[scrollView contentView] boundsOrigin]);
2003 
2004  if (![[self superview] scrollRectToVisible:[self frame]])
2005  previousContentViewBoundsOrigin = nil;
2006  }
2007 
2008  return previousContentViewBoundsOrigin;
2009 }
2010 
2014 - (void)_restorePreviousScrollingOrigin:(CGPoint)scrollingOrigin
2015 {
2016  if (scrollingOrigin)
2017  [[[self enclosingScrollView] contentView] setBoundsOrigin:scrollingOrigin];
2018 }
2019 
2020 @end
2021 
2022 var secureStringForString = function(aString)
2023 {
2024  // This is true for when aString === "" and null/undefined.
2025  if (!aString)
2026  return "";
2027 
2028  return Array(aString.length + 1).join(CPSecureTextFieldCharacter);
2029 };
2030 
2031 
2032 var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
2033  CPTextFieldIsSelectableKey = "CPTextFieldIsSelectableKey",
2034  CPTextFieldIsBorderedKey = "CPTextFieldIsBorderedKey",
2035  CPTextFieldIsBezeledKey = "CPTextFieldIsBezeledKey",
2036  CPTextFieldBezelStyleKey = "CPTextFieldBezelStyleKey",
2037  CPTextFieldDrawsBackgroundKey = "CPTextFieldDrawsBackgroundKey",
2038  CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
2039  CPTextFieldAlignmentKey = "CPTextFieldAlignmentKey",
2040  CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
2041  CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey",
2042  CPTextFieldUsesSingleLineMode = "CPTextFieldUsesSingleLineMode",
2043  CPTextFieldWraps = "CPTextFieldWraps",
2044  CPTextFieldScrolls = "CPTextFieldScrolls";
2045 
2046 
2047 @implementation CPTextField (CPCoding)
2048 
2054 - (id)initWithCoder:(CPCoder)aCoder
2055 {
2056  self = [super initWithCoder:aCoder];
2057 
2058  if (self)
2059  {
2060  [self setEditable:[aCoder decodeBoolForKey:CPTextFieldIsEditableKey]];
2061  [self setSelectable:[aCoder decodeBoolForKey:CPTextFieldIsSelectableKey]];
2062 
2063  [self setDrawsBackground:[aCoder decodeBoolForKey:CPTextFieldDrawsBackgroundKey]];
2064 
2065  [self setTextFieldBackgroundColor:[aCoder decodeObjectForKey:CPTextFieldBackgroundColorKey]];
2066 
2067  [self setLineBreakMode:[aCoder decodeIntForKey:CPTextFieldLineBreakModeKey]];
2068  [self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
2069 
2070  [self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
2071 
2072  [self _setUsesSingleLineMode:[aCoder decodeBoolForKey:CPTextFieldUsesSingleLineMode]];
2073  [self _setWraps:[aCoder decodeBoolForKey:CPTextFieldWraps]];
2074  [self _setScrolls:[aCoder decodeBoolForKey:CPTextFieldScrolls]];
2075  }
2076 
2077  return self;
2078 }
2079 
2084 - (void)encodeWithCoder:(CPCoder)aCoder
2085 {
2086  [super encodeWithCoder:aCoder];
2087 
2088  [aCoder encodeBool:_isEditable forKey:CPTextFieldIsEditableKey];
2089  [aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey];
2090 
2091  [aCoder encodeBool:_drawsBackground forKey:CPTextFieldDrawsBackgroundKey];
2092 
2093  [aCoder encodeObject:_textFieldBackgroundColor forKey:CPTextFieldBackgroundColorKey];
2094 
2095  [aCoder encodeInt:[self lineBreakMode] forKey:CPTextFieldLineBreakModeKey];
2096  [aCoder encodeInt:[self alignment] forKey:CPTextFieldAlignmentKey];
2097 
2098  [aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
2099 
2100  [aCoder encodeBool:_usesSingleLineMode forKey:CPTextFieldUsesSingleLineMode];
2101  [aCoder encodeBool:_wraps forKey:CPTextFieldWraps];
2102  [aCoder encodeBool:_scrolls forKey:CPTextFieldScrolls];
2103 }
2104 
2105 @end
2106 @implementation _CPTextFieldValueBinder : CPBinder
2107 {
2108  id __doxygen__;
2109 }
2110 
2111 - (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding
2112 {
2113  [super _updatePlaceholdersWithOptions:options];
2114 
2115  [self _setPlaceholder:@"Multiple Values" forMarker:CPMultipleValuesMarker isDefault:YES];
2116  [self _setPlaceholder:@"No Selection" forMarker:CPNoSelectionMarker isDefault:YES];
2117  [self _setPlaceholder:@"Not Applicable" forMarker:CPNotApplicableMarker isDefault:YES];
2118  [self _setPlaceholder:@"" forMarker:CPNullMarker isDefault:YES];
2119 }
2120 
2121 - (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
2122 {
2123  [_source setPlaceholderString:aValue];
2124  [_source setObjectValue:nil];
2125 }
2126 
2127 - (void)setValue:(id)aValue forBinding:(CPString)aBinding
2128 {
2129  if (!aValue || (aValue.isa && [aValue isMemberOfClass:CPNull]))
2130  [_source setPlaceholderString:[self _placeholderForMarker:CPNullMarker]];
2131 
2132  [_source setObjectValue:aValue];
2133 }
2134 
2135 - (void)reverseSetValueFor:(CPString)aBinding
2136 {
2137  var destination = [_info objectForKey:CPObservedObjectKey],
2138  keyPath = [_info objectForKey:CPObservedKeyPathKey],
2139  options = [_info objectForKey:CPOptionsKey],
2140  newValue = [self valueForBinding:aBinding],
2141  value = [destination valueForKeyPath:keyPath];
2142 
2143  if (CPIsControllerMarker(value) && newValue === nil)
2144  return;
2145 
2146  newValue = [self reverseTransformValue:newValue withOptions:options];
2147 
2148  [self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
2149  [destination setValue:newValue forKeyPath:keyPath];
2150  [self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
2151 }
2152 
2153 @end
2154 @implementation _CPTextFieldPatternValueBinder : CPValueWithPatternBinding
2155 {
2156  id __doxygen__;
2157 }
2158 
2159 - (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
2160 {
2161  [_source setPlaceholderString:aValue];
2162  [_source setObjectValue:nil];
2163 }
2164 
2165 - (void)setValue:(id)aValue forBinding:(CPString)aBinding
2166 {
2167  if (!aValue || (aValue.isa && [aValue isMemberOfClass:CPNull]))
2168  [_source setPlaceholderString:[self _placeholderForMarker:CPNullMarker]];
2169 
2170  [_source setObjectValue:aValue];
2171 }
2172 
2173 @end
2174 
2176 
2177 - (void)updateTrackingAreas
2178 {
2179  [self removeAllTrackingAreas];
2180 
2181  if ([self isEnabled] && (_isEditable || _isSelectable))
2182  {
2183  var myBounds = CGRectMakeCopy([self bounds]),
2184  contentInset = [self currentValueForThemeAttribute:@"content-inset"];
2185 
2186  [self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectInsetByInset(myBounds, contentInset)
2187  options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
2188  owner:self
2189  userInfo:nil]];
2190  }
2191 }
2192 
2193 - (void)cursorUpdate:(CPEvent)anEvent
2194 {
2195  [[CPCursor IBeamCursor] set];
2196 }
2197 
2198 @end
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:1617
void setDrawsBackground:(BOOL shouldDrawBackground)
Definition: CPTextField.j:529
var CPTextFieldDOMStandardInputElement
Definition: CPTextField.j:50
CGRect convertRectToBase:(CGRect aRect)
Definition: CPView.j:2322
void postNotification:(CPNotification aNotification)
var CPTextFieldIsBorderedKey
Definition: CPTextField.j:2034
var CPTextFieldIsBezeledKey
Definition: CPTextField.j:2035
float defaultLineHeightForFont()
Definition: CPFont.j:362
var CPTextFieldAlignmentKey
Definition: CPTextField.j:2039
BOOL isEnabled()
Definition: CPControl.j:970
void textDidChange:(CPNotification note)
Definition: CPTextField.j:1212
BOOL setThemeState:(ThemeState aState)
Definition: CPView.j:3214
CGRect frame
var CPTextFieldTextDidChangeValue
Definition: CPTextField.j:53
void selectText:(id sender)
Definition: CPTextField.j:1462
void setValue:forThemeAttribute:inState:(id aValue, [forThemeAttribute] CPString aName, [inState] ThemeState aState)
Definition: CPView.j:3330
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:1636
var CPTextFieldDelegate_controlTextDidBeginEditing_
Definition: CPTextField.j:34
The main run loop for the application.
Definition: CPRunLoop.h:2
CPRightTextAlignment
Definition: CPText.j:74
id generalPasteboard()
Definition: CPPasteboard.j:82
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:1642
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
CPFont font()
Definition: CPControl.j:899
void viewDidHide()
Definition: CPView.j:1781
CPInputOnInputEventFeature
void selectAll:(id sender)
Definition: CPTextField.j:1688
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
CPIsControllerMarker
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:1302
CPTextFieldDidBlurNotification
Definition: CPTextField.j:46
void deleteBackward:(id sender)
Definition: CPTextField.j:1693
void copy:(id sender)
Definition: CPTextField.j:1503
void setControlSize:(CPControlSize aControlSize)
Definition: CPControl.j:211
void setEnabled:(BOOL isEnabled)
Definition: CPControl.j:959
CPFormatter formatter()
Definition: CPControl.j:1216
CPKeyUpMask
void setValue:forThemeAttribute:(id aValue, [forThemeAttribute] CPString aName)
Definition: CPView.j:3343
CPTextFieldBezelStyle CPTextFieldSquareBezel
Definition: CPTextField.j:42
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
CPScrollView enclosingScrollView()
Definition: CPView.j:2928
void rightMouseDown:(CPEvent anEvent)
Definition: CPView.j:1902
var CPTextFieldIsSelectableKey
Definition: CPTextField.j:2033
CPRunLoop currentRunLoop()
Definition: CPRunLoop.j:232
var CPTextFieldWraps
Definition: CPTextField.j:2043
void setEditable:(BOOL shouldBeEditable)
Definition: CPTextField.j:373
void textDidBlur:(CPNotification note)
Definition: CPTextField.j:1188
CGRect bounds()
Definition: CALayer.j:203
CPWindow window()
Definition: CPView.j:503
CGSize frameSize()
Definition: CPView.j:1032
CPRange selectedRange()
Definition: CPTextField.j:1596
CGPoint convertPointFromBase:(CGPoint aPoint)
Definition: CPView.j:2221
CPEditableBinding
var CPTextFieldCachedDragFunction
Definition: CPTextField.j:58
CPView createEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3356
CPNaturalTextAlignment
Definition: CPText.j:77
id initWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
void setPlaceholderString:(CPString aStringValue)
Definition: CPTextField.j:1360
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
CPClipView contentView()
Definition: CPScrollView.j:377
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:1085
var CPTextFieldBezelStyleKey
Definition: CPTextField.j:2036
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 textDidBeginEditing:(CPNotification note)
Definition: CPTextField.j:1225
void setTextColor:(CPColor aColor)
Definition: CPControl.j:841
var CPTextFieldDOMPasswordInputElement
Definition: CPTextField.j:51
CGRect contentRectForBounds:(CGRect bounds)
Definition: CPTextField.j:1802
BOOL isEditable()
Definition: CPTextField.j:403
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2556
var CPTextFieldPlaceholderStringKey
Definition: CPTextField.j:2041
void setObjectValue:(id anObject)
Definition: CPControl.j:534
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:1809
CPWindow window()
Definition: CPEvent.j:341
int length()
Definition: CPString.j:186
CPVerticalTextAlignment CPTopVerticalTextAlignment
Definition: CPControl.j:53
var secureStringForString
Definition: CPTextField.j:2022
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:2032
CPTheme defaultTheme()
Definition: CPTheme.j:44
void setNeedsLayout()
Definition: CPView.j:2707
id target()
Definition: CPControl.j:308
CPString stringValue()
Definition: CPControl.j:613
CPBottomVerticalTextAlignment
Definition: CPControl.j:55
var CPTextFieldDOMCurrentElement
Definition: CPTextField.j:48
BOOL isKeyWindow()
Definition: CPWindow.j:2051
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
void setBoundsOrigin:(CGPoint aPoint)
Definition: CPClipView.j:81
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
BOOL isSelectable()
Definition: CPTextField.j:437
CPString cssString()
Definition: CPFont.j:383
void setAlignment:(CPTextAlignment alignment)
Definition: CPControl.j:776
BOOL unsetThemeState:(ThemeState aState)
Definition: CPView.j:3227
Sends messages (CPNotification) between objects.
CPNotification notificationWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
CPString placeholderString()
Definition: CPTextField.j:1378
void addTrackingArea:(CPTrackingArea trackingArea)
Definition: CPView.j:3500
Definition: CPTheme.h:2
void setSelectable:(BOOL aFlag)
Definition: CPTextField.j:427
CPNewlineCharacter
Definition: CPText.j:49
CPLineBreakMode lineBreakMode()
Definition: CPControl.j:831
CPTimeInterval currentTimestamp()
Definition: CPEvent.j:84
var CPTextFieldDelegate_controlTextDidFocus_
Definition: CPTextField.j:37
var CPTextFieldLineBreakModeKey
Definition: CPTextField.j:2038
var CPTextFieldBlurHandler
Definition: CPTextField.j:59
void textDidEndEditing:(CPNotification note)
Definition: CPTextField.j:1237
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:1100
var CPTextFieldUsesSingleLineMode
Definition: CPTextField.j:2042
var CPTextFieldDOMTextAreaElement
Definition: CPTextField.j:49
CPDisplayPatternValueBinding
void updateTrackingAreas()
Definition: CPTextField.j:2177
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:122
var CPTextFieldDrawsBackgroundKey
Definition: CPTextField.j:2037
Definition: CPEvent.h:2
void setTextFieldBackgroundColor:(CPColor aColor)
Definition: CPTextField.j:552
var CPTextFieldBackgroundColorKey
Definition: CPTextField.j:2040
CPKeyDownMask
CPTrackingArea initWithRect:options:owner:userInfo:(CGRect aRect, [options] CPTrackingAreaOptions options, [owner] id owner, [userInfo] CPDictionary userInfo)
CPCenterTextAlignment
Definition: CPText.j:75
CPPlatformWindow platformWindow()
Definition: CPWindow.j:384
void removeAllTrackingAreas()
Definition: CPView.j:3564
CPTextFieldDidFocusNotification
Definition: CPTextField.j:45
CPValueBinding
var CPTextFieldInputResigning
Definition: CPTextField.j:54
A bridged object to native Javascript numbers.
Definition: CPNumber.h:2
void viewDidUnhide()
Definition: CPView.j:1795
void encodeWithCoder:(CPCoder aCoder)
Definition: CPControl.j:1114
void textDidFocus:(CPNotification note)
Definition: CPTextField.j:1200
var CPTextFieldScrolls
Definition: CPTextField.j:2044
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:202
CPNullMarker
CPView layoutEphemeralSubviewNamed:positioned:relativeToEphemeralSubviewNamed:(CPString aViewName, [positioned] CPWindowOrderingMode anOrderingMode, [relativeToEphemeralSubviewNamed] CPString relativeToViewName)
Definition: CPView.j:3366
CPCenterVerticalTextAlignment
Definition: CPControl.j:54
id alloc()
Definition: CPObject.j:130
CGRect rectForEphemeralSubviewNamed:(CPString aViewName)
Definition: CPView.j:3361
Definition: CPView.j:136
CPInput1PxLeftPadding