001: /*
002: * GWT-Ext Widget Library
003: * Copyright(c) 2007-2008, GWT-Ext.
004: * licensing@gwt-ext.com
005: *
006: * http://www.gwt-ext.com/license
007: */
008:
009: package com.gwtext.client.widgets.form;
010:
011: import com.google.gwt.core.client.JavaScriptObject;
012: import com.google.gwt.user.client.DOM;
013: import com.google.gwt.user.client.Element;
014: import com.gwtext.client.core.DomConfig;
015: import com.gwtext.client.widgets.BoxComponent;
016: import com.gwtext.client.widgets.form.event.FieldListener;
017:
018: /**
019: * Base class for form fields that provides default event handling, sizing, value handling and other functionality.
020: */
021: public abstract class Field extends BoxComponent {
022:
023: public Field() {
024: }
025:
026: public Field(String fieldLabel) {
027: setFieldLabel(fieldLabel);
028: }
029:
030: public Field(String fieldLabel, String name) {
031: setFieldLabel(fieldLabel);
032: setName(name);
033: }
034:
035: public Field(String fieldLabel, String name, int width) {
036: setFieldLabel(fieldLabel);
037: setName(name);
038: setWidth(width);
039: }
040:
041: public Field(JavaScriptObject jsObj) {
042: super (jsObj);
043: }
044:
045: /**
046: * Set the location of the error message target globally.
047: *
048: * @param msgTarget supported values are 'qtip' (default) and 'side'
049: */
050: public static native void setMsgTarget(String msgTarget) /*-{
051: $wnd.Ext.form.Field.prototype.msgTarget = msgTarget;
052: }-*/;
053:
054: protected abstract JavaScriptObject create(JavaScriptObject config);
055:
056: /**
057: * Apply the behaviors of this component to an existing element. This is used instead of render().
058: *
059: * @param id the ID of the node
060: */
061: public void applyTo(String id) {
062: Element el = DOM.getElementById(id);
063: if (el == null) {
064: throw new IllegalArgumentException("Element with id : "
065: + id + " not found.");
066: //RootPanel.get().add(new HTML("<div id='" + id + "'></div"));
067: }
068: applyTo(getOrCreateJsObj(), id);
069: }
070:
071: /**
072: * Apply the behaviors of this component to an existing element. This is used instead of render().
073: *
074: * @param element the element
075: */
076: public native void applyTo(Element element) /*-{
077: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
078: field.applyTo(element);
079: }-*/;
080:
081: private native void applyTo(JavaScriptObject field, String id) /*-{
082: field.applyTo(id);
083: }-*/;
084:
085: /**
086: * Clear any invalid styles/messages for this field.
087: */
088: public native void clearInvalid() /*-{
089: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
090: field.clearInvalid();
091: }-*/;
092:
093: /**
094: * Returns the name attribute of the field if available.
095: *
096: * @return the name attribute of the Field
097: */
098: public String getName() {
099: return getAttribute("name");
100: }
101:
102: /**
103: * Returns the raw data value which may or may not be a valid, defined value.
104: *
105: * @return the raw field value
106: */
107: public native String getRawValue() /*-{
108: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
109: return field.getRawValue();
110: }-*/;
111:
112: /**
113: * Return the value of the field as a String.
114: *
115: * @return value as String
116: */
117: public native String getValueAsString() /*-{
118: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
119: var value = field.getValue();
120: return (value == null || value === undefined ) ? '' : value.toString();
121: }-*/;
122:
123: /**
124: * Returns true if this field has been changed since it was originally loaded and is not disabled.
125: *
126: * @return true if field changed
127: */
128: public native boolean isDirty() /*-{
129: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
130: return field.isDirty();
131: }-*/;
132:
133: /**
134: * Returns whether or not the field value is currently valid.
135: *
136: * @return true if valid
137: */
138: public native boolean isValid() /*-{
139: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
140: return field.isValid();
141: }-*/;
142:
143: /**
144: * Returns whether or not the field value is currently valid.
145: *
146: * @param preventMark true to disable marking the field invalid
147: * @return true if valid
148: */
149: public native boolean isValid(boolean preventMark) /*-{
150: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
151: return field.isValid(preventMark);
152: }-*/;
153:
154: /**
155: * Mark this field as invalid.
156: *
157: * @param message the validation message
158: */
159: public native void markInvalid(String message) /*-{
160: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
161: field.markInvalid(message);
162: }-*/;
163:
164: /**
165: * Resets the current field value to the originally loaded value and clears any validation messages.
166: */
167: public native void reset() /*-{
168: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
169: field.reset();
170: }-*/;
171:
172: /**
173: * Sets the underlying DOM field's value directly, bypassing validation. To set the value with validation use {@link #setValue(String)}.
174: *
175: * @param value field value
176: */
177: public native void setRawValue(String value) /*-{
178: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
179: field.setRawValue(value);
180: }-*/;
181:
182: /**
183: * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue(String)}.
184: *
185: * @param value the field value
186: */
187: private native void setValueRendered(String value) /*-{
188: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
189: field.setValue(value);
190: }-*/;
191:
192: public native boolean validate() /*-{
193: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
194: return field.validate();
195: }-*/;
196:
197: /**
198: * Add a Field Listener.
199: *
200: * @param listener the listener
201: */
202: public native void addListener(FieldListener listener) /*-{
203: this.@com.gwtext.client.widgets.BoxComponent::addListener(Lcom/gwtext/client/widgets/event/BoxComponentListener;)(listener);
204: var fieldJ = this;
205:
206: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('blur',
207: function(fld) {
208: listener.@com.gwtext.client.widgets.form.event.FieldListener::onBlur(Lcom/gwtext/client/widgets/form/Field;)(fieldJ);
209: }
210: );
211:
212: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('change',
213: function(fld, newVal, oldVal) {
214: var newValJ = (newVal == null || newVal === undefined || newVal == '') ? null : $wnd.GwtExt.convertToJavaType(newVal);
215: var oldValJ = (oldVal == null || oldVal === undefined || oldVal == '' ) ? null : $wnd.GwtExt.convertToJavaType(oldVal);
216: listener.@com.gwtext.client.widgets.form.event.FieldListener::onChange(Lcom/gwtext/client/widgets/form/Field;Ljava/lang/Object;Ljava/lang/Object;)(fieldJ, newValJ, oldValJ);
217: }
218: );
219:
220: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('focus',
221: function(fld) {
222: listener.@com.gwtext.client.widgets.form.event.FieldListener::onFocus(Lcom/gwtext/client/widgets/form/Field;)(fieldJ);
223: }
224: );
225:
226: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('invalid',
227: function(fld, msg) {
228: if(msg === undefined) msg = null;
229: listener.@com.gwtext.client.widgets.form.event.FieldListener::onInvalid(Lcom/gwtext/client/widgets/form/Field;Ljava/lang/String;)(fieldJ, msg);
230: }
231: );
232:
233: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('specialkey',
234: function(fld, event) {
235: var e = @com.gwtext.client.core.EventObject::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(event);
236: listener.@com.gwtext.client.widgets.form.event.FieldListener::onSpecialKey(Lcom/gwtext/client/widgets/form/Field;Lcom/gwtext/client/core/EventObject;)(fieldJ, e);
237: }
238: );
239:
240: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('valid',
241: function(fld) {
242: listener.@com.gwtext.client.widgets.form.event.FieldListener::onValid(Lcom/gwtext/client/widgets/form/Field;)(fieldJ);
243: }
244: );
245:
246: }-*/;
247:
248: // --- config properties ---
249:
250: public String getXType() {
251: return "field";
252: }
253:
254: /**
255: * Set to true for a default element spec (defaults to {tag: "input", type: "text", size: "20", autocomplete: "off"})
256: *
257: * @param autoCreate true for a default element spec
258: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
259: */
260: public void setAutoCreate(boolean autoCreate)
261: throws IllegalStateException {
262: setAttribute("autoCreate", autoCreate, true);
263: }
264:
265: public boolean isAutoCreate() {
266: return getAttributeAsBoolean("autoCreate");
267: }
268:
269: /**
270: * A DomHelper config spec to use for field creation.
271: *
272: * @param domConfig a DomHelper config spec to use for field creation
273: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
274: */
275: public void setAutoCreate(DomConfig domConfig)
276: throws IllegalStateException {
277: setAttribute("autoCreate", domConfig.getJsObject(), true);
278: }
279:
280: /**
281: * The CSS class used to provide field clearing (defaults to 'x-form-clear-left')
282: *
283: * @param clearCls the CSS class used to provide the clearing
284: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
285: */
286: public void setClearCls(String clearCls)
287: throws IllegalStateException {
288: setAttribute("clearCls", clearCls, true);
289: }
290:
291: /**
292: * The CSS class used to provide field clearing (defaults to 'x-form-clear-left')
293: *
294: * @return the clear Class
295: */
296: public String getClearCls() {
297: return getAttribute("clearCls");
298: }
299:
300: /**
301: * A CSS class to apply to the field's underlying element.
302: *
303: * @param cls the CSS class
304: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
305: */
306: public void setCls(String cls) throws IllegalStateException {
307: super .setCls(cls);
308: }
309:
310: /**
311: * CSS class to apply to the field's underlying element
312: *
313: * @return the CSS class
314: */
315: public String getCls() {
316: return getAttribute("cls");
317: }
318:
319: /**
320: * True to disable the field (defaults to false).
321: *
322: * @param disabled true to disable
323: */
324: public void setDisabled(boolean disabled) {
325: setAttribute("disabled", disabled, true, true);
326: }
327:
328: /**
329: * The default CSS class for the field (defaults to "x-form-field").
330: *
331: * @param fieldClass the fields class
332: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
333: */
334: public void setFieldClass(String fieldClass)
335: throws IllegalStateException {
336: setAttribute("fieldClass", fieldClass, true);
337: }
338:
339: /**
340: * The CSS class to use when the field receives focus (defaults to "x-form-focus").
341: *
342: * @param focusClass CSS class on focus
343: */
344: public void setFocusClass(String focusClass) {
345: setAttribute("focusClass", focusClass, true, true);
346: }
347:
348: /**
349: * The CSS class to use when the field receives focus (defaults to "x-form-focus").
350: *
351: * @return the focus class
352: */
353: public String getFocusClass() {
354: return getAttribute("focusClass");
355: }
356:
357: /**
358: * Set the fields label. Alias for {@link #setFieldLabel(String)}
359: *
360: * @param fieldLabel the field label
361: */
362: public void setLabel(String fieldLabel) {
363: setFieldLabel(fieldLabel);
364: }
365:
366: /**
367: * Set the fields label.
368: *
369: * @param fieldLabel the field label
370: */
371: public void setFieldLabel(String fieldLabel) {
372: setAttribute("fieldLabel", fieldLabel, true, true);
373: if (isRendered()) {
374: setFieldLabelRendered(fieldLabel, getId());
375: }
376: }
377:
378: private native boolean setFieldLabelRendered(String fieldLabel,
379: String fieldId) /*-{
380: var field = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
381: var label = $wnd.Ext.DomQuery.select($wnd.String.format('label[for="{0}"]', fieldId));
382: if (label){
383: //todo preserve user specified labelSeparator and only update the label text.
384: //var separator = typeof field.container.labelSeparator == 'undefined' ? field.labelSeparator : field.container.labelSeparator;
385: label[0].childNodes[0].nodeValue = fieldLabel;
386: }
387: }-*/;
388:
389: /**
390: * True to completely hide the label element (defaults to false).
391: *
392: * @param hideLabel true to completely hide the label element (defaults to false)
393: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
394: */
395: public void setHideLabel(boolean hideLabel)
396: throws IllegalStateException {
397: setAttribute("hideLabel", hideLabel, true);
398: }
399:
400: public boolean isHideLabel() {
401: return getAttributeAsBoolean("hideLabel");
402: }
403:
404: /**
405: * The type attribute for input fields -- e.g. radio, text, password (defaults to "text").
406: *
407: * @param inputType the input type
408: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
409: */
410: public void setInputType(String inputType)
411: throws IllegalStateException {
412: setAttribute("inputType", inputType, true);
413: }
414:
415: /**
416: * The type attribute for input fields -- e.g. radio, text, password (defaults to "text").
417: *
418: * @return the input type
419: */
420: public String getInputType() {
421: if (isRendered()) {
422: return DOM.getElementProperty(getElement(), "type");
423: } else {
424: String inputType = getAttribute("inputType");
425: if (inputType == null)
426: inputType = "text";
427: return inputType;
428: }
429: }
430:
431: /**
432: * The CSS class to use when marking a field invalid (defaults to "x-form-invalid").
433: *
434: * @param invalidClass CSS class when field is invalid
435: */
436: public void setInvalidClass(String invalidClass) {
437: setAttribute("invalidClass", invalidClass, true, true);
438: }
439:
440: /**
441: * The CSS class to use when marking a field invalid (defaults to "x-form-invalid").
442: *
443: * @return the invalid CSS class
444: */
445: public String getInvalidClass() {
446: return getAttribute("invalidClass");
447: }
448:
449: /**
450: * The error text to use when marking a field invalid and no message is provided (defaults to "The value in this field is invalid").
451: * This error message is displayed when the used specified validator returns false.
452: *
453: * @param invalidText invalid text on error
454: * @see TextField#setValidator(Validator)
455: */
456: public void setInvalidText(String invalidText) {
457: setAttribute("invalidText", invalidText, true, true);
458: }
459:
460: /**
461: * The error text to use when marking a field invalid and no message is provided (defaults to "The value in this field is invalid").
462: * This error message is displayed when the used specified validator returns false.
463: *
464: * @return the invalid text
465: */
466: public String getInvalidText() {
467: return getAttribute("invalidText");
468: }
469:
470: /**
471: * Set the CSS style of the fields label. For example 'display:none'.
472: *
473: * @param labelStyle the CSS style for the fields label
474: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
475: */
476: public void setLabelStyle(String labelStyle)
477: throws IllegalStateException {
478: setAttribute("labelStyle", labelStyle, true);
479: }
480:
481: /**
482: * The CSS style of the fields label.
483: *
484: * @return the label style
485: */
486: public String getLabelStyle() {
487: return getAttribute("labelStyle");
488: }
489:
490: /**
491: * The seprator between the fields label and the field. Can use ' ' or '&nbsp;'
492: *
493: * @param labelSeparator the label separator
494: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
495: */
496: public void setLabelSeparator(String labelSeparator)
497: throws IllegalStateException {
498: setAttribute("labelSeparator", labelSeparator, true);
499: }
500:
501: /**
502: * The seprator between the fields label and the field.
503: *
504: * @return the label separator
505: */
506: public String getLabelSeparator() {
507: return getAttribute("labelSeparator");
508: }
509:
510: //todo enum
511: /**
512: * The effect used when displaying a validation message under the field (defaults to 'normal').
513: * Other possible values are "slide" and "slideRight"
514: *
515: * @param msgFx validation message style
516: */
517: public void setMsgFx(String msgFx) {
518: setAttribute("msgFx", msgFx, true, true);
519: }
520:
521: /**
522: * The location where error text should display. Should be one of the following values (defaults to 'qtip') :
523: *
524: * <pre>
525: * Value Description
526: * ----------- ----------------------------------------------------------------------
527: * qtip Display a quick tip when the user hovers over the field
528: * title Display a default browser title attribute popup
529: * under Add a block div beneath the field containing the error text
530: * side Add an error icon to the right of the field with a popup on hover
531: * [element id] Add the error text directly to the innerHTML of the specified element</pre>
532: *
533: * @param msgTarget the error message target
534: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
535: */
536: public void setFieldMsgTarget(String msgTarget)
537: throws IllegalStateException {
538: setAttribute("msgTarget", msgTarget, true);
539: }
540:
541: /**
542: * Set the field's HTML name attribute.
543: *
544: * @param name the fields name
545: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
546: */
547: public void setName(String name) throws IllegalStateException {
548: setAttribute("name", name, true);
549: }
550:
551: /**
552: * True to mark the field as readOnly in HTML (defaults to false) -- Note: this only sets the element's readOnly DOM attribute.
553: *
554: * @param readOnly true to mark field read only
555: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
556: */
557: public void setReadOnly(boolean readOnly)
558: throws IllegalStateException {
559: setAttribute("readOnly", readOnly, true);
560: }
561:
562: public boolean isReadOnly() {
563: return getAttributeAsBoolean("readOnly");
564: }
565:
566: /**
567: * The tabIndex for this field. Note this only applies to fields that are rendered, not those which are built via applyTo.
568: *
569: * @param tabIndex the fields tab index
570: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
571: */
572: public void setTabIndex(int tabIndex) throws IllegalStateException {
573: setAttribute("tabIndex", tabIndex, true);
574: }
575:
576: /**
577: * The tabIndex for this field.
578: *
579: * @return the tab index
580: */
581: public int getTabindex() {
582: return getAttributeAsInt("tabindex");
583: }
584:
585: /**
586: * Whether the field should validate when it loses focus (defaults to true).
587: *
588: * @param validateOnBlur true to validate on blur
589: */
590: public void setValidateOnBlur(boolean validateOnBlur) {
591: setAttribute("validateOnBlur", validateOnBlur, true, true);
592: }
593:
594: /**
595: * Whether the field should validate when it loses focus (defaults to true).
596: *
597: * @return true if validate on blur
598: */
599: public boolean isValidateOnBlur() {
600: return getAttributeAsBoolean("validateOnBlur");
601: }
602:
603: /**
604: * The length of time in milliseconds after user input begins until validation is initiated (defaults to 250).
605: *
606: * @param validationDelay the validation delay in milliseconds
607: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
608: */
609: public void setValidationDelay(int validationDelay)
610: throws IllegalStateException {
611: setAttribute("validationDelay", validationDelay, true);
612: }
613:
614: /**
615: * The length of time in milliseconds after user input begins until validation is initiated (defaults to 250).
616: *
617: * @return the validation delay
618: */
619: public int getValidationDelay() {
620: return getAttributeAsInt("validationDelay");
621: }
622:
623: /**
624: * Set to false to disable automatic validation.
625: *
626: * @param validationEvent false to disable automatic validation
627: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
628: */
629: public void setValidationEvent(boolean validationEvent)
630: throws IllegalStateException {
631: setAttribute("validationEvent", validationEvent, true);
632: }
633:
634: /**
635: * The event that should initiate field validation. (defaults to "keyup")..
636: *
637: * @param validationEvent event to initiate validation
638: */
639: public void setValidationEvent(String validationEvent) {
640: setAttribute("validationEvent", validationEvent, true, true);
641: }
642:
643: /**
644: * A value to initialize this field with.
645: *
646: * @param value the field value
647: */
648: public void setValue(String value) {
649: if (!isRendered()) {
650: setAttribute("value", value, true);
651: } else {
652: setValueRendered(value);
653: }
654: }
655:
656: /**
657: * Set the width of the field.
658: *
659: * @param width the field width
660: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
661: */
662: public void setWidth(int width) throws IllegalStateException {
663: setAttribute("width", width, true);
664: }
665:
666: /**
667: * Set the width of the field.
668: *
669: * @param width the field width
670: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
671: */
672: public void setWidth(String width) throws IllegalStateException {
673: setAttribute("width", width, true);
674: }
675: }
|