1 16 17 package org.apache.cocoon.forms.flow.javascript.v3; 18 import java.math.BigDecimal ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.LinkedList ; 22 import java.util.List ; 23 import java.util.Map ; 24 25 import org.apache.cocoon.forms.datatype.Datatype; 26 import org.apache.cocoon.forms.datatype.SelectionList; 27 import org.apache.cocoon.forms.event.ActionEvent; 28 import org.apache.cocoon.forms.event.ActionListener; 29 import org.apache.cocoon.forms.event.ActionListenerEnabled; 30 import org.apache.cocoon.forms.event.ValueChangedEvent; 31 import org.apache.cocoon.forms.event.ValueChangedListener; 32 import org.apache.cocoon.forms.event.ValueChangedListenerEnabled; 33 import org.apache.cocoon.forms.formmodel.Action; 34 import org.apache.cocoon.forms.formmodel.AggregateField; 35 import org.apache.cocoon.forms.formmodel.BooleanField; 36 import org.apache.cocoon.forms.formmodel.ContainerWidget; 37 import org.apache.cocoon.forms.formmodel.DataWidget; 38 import org.apache.cocoon.forms.formmodel.Field; 39 import org.apache.cocoon.forms.formmodel.Form; 40 import org.apache.cocoon.forms.formmodel.MultiValueField; 41 import org.apache.cocoon.forms.formmodel.Output; 42 import org.apache.cocoon.forms.formmodel.Repeater; 43 import org.apache.cocoon.forms.formmodel.SelectableWidget; 44 import org.apache.cocoon.forms.formmodel.Submit; 45 import org.apache.cocoon.forms.formmodel.Upload; 46 import org.apache.cocoon.forms.formmodel.Widget; 47 import org.apache.cocoon.forms.formmodel.WidgetState; 48 import org.apache.cocoon.forms.validation.ValidationError; 49 import org.apache.cocoon.forms.validation.ValidationErrorAware; 50 import org.apache.cocoon.forms.validation.WidgetValidator; 51 import org.apache.commons.lang.BooleanUtils; 52 import org.mozilla.javascript.Context; 53 import org.mozilla.javascript.Function; 54 import org.mozilla.javascript.JavaScriptException; 55 import org.mozilla.javascript.NativeArray; 56 import org.mozilla.javascript.Scriptable; 57 import org.mozilla.javascript.ScriptableObject; 58 import org.mozilla.javascript.Undefined; 59 import org.mozilla.javascript.Wrapper; 60 61 65 public class ScriptableWidget extends ScriptableObject implements ValueChangedListener, ActionListener, WidgetValidator { 66 67 final static String WIDGETS_PROPERTY = "__widgets__"; 68 69 Widget delegate; 70 ScriptableWidget formWidget; 71 private Function onChange; 72 private Function onActivate; 73 private Function validator; 74 75 public String getClassName() { 76 return "Widget"; 77 } 78 79 public ScriptableWidget() { 80 } 81 82 public ScriptableWidget(Object widget) { 83 this.delegate = (Widget)unwrap(widget); 84 if (delegate instanceof Form) { 85 formWidget = this; 86 Map widgetMap = new HashMap (); 87 widgetMap.put(delegate, this); 88 defineProperty(WIDGETS_PROPERTY, widgetMap, DONTENUM|PERMANENT); 89 } 90 } 91 92 static private Object unwrap(Object obj) { 93 if (obj == Undefined.instance) { 94 return null; 95 } 96 if (obj instanceof Wrapper) { 97 return ((Wrapper)obj).unwrap(); 98 } 99 return obj; 100 } 101 102 private void deleteWrapper(Widget w) { 103 if (delegate instanceof Form) { 104 Map widgetMap = (Map )super.get(WIDGETS_PROPERTY, this); 105 widgetMap.remove(w); 106 } 107 } 108 109 private ScriptableWidget wrap(Widget w) { 110 if (w == null) return null; 111 if (delegate instanceof Form) { 112 Map widgetMap = (Map )super.get(WIDGETS_PROPERTY, this); 113 ScriptableWidget result = null; 114 result = (ScriptableWidget)widgetMap.get(w); 115 if (result == null) { 116 result = new ScriptableWidget(w); 117 result.formWidget = this; 118 result.setPrototype(getClassPrototype(this, getClassName())); 119 result.setParentScope(getParentScope()); 120 widgetMap.put(w, result); 121 } 122 return result; 123 } else { 124 return formWidget.wrap(w); 125 } 126 } 127 128 public boolean has(String id, Scriptable start) { 129 if (delegate != null && delegate instanceof ContainerWidget) { 130 Widget sub = ((ContainerWidget)delegate).getChild(id); 131 if (sub != null) { 132 return true; 133 } 134 } 135 return super.has(id, start); 136 } 137 138 public boolean has(int index, Scriptable start) { 139 if (super.has(index, start)) { 140 return true; 141 } 142 if (delegate instanceof Repeater) { 143 Repeater repeater = (Repeater)delegate; 144 return index >= 0 && index < repeater.getSize(); 145 } 146 if (delegate instanceof MultiValueField) { 147 Object [] values = (Object [])delegate.getValue(); 148 return index >= 0 && index < values.length; 149 } 150 return false; 151 } 152 153 public Object get(String id, Scriptable start) { 154 Object result = super.get(id, start); 155 if (result != NOT_FOUND) { 156 return result; 157 } 158 if (delegate != null && delegate instanceof ContainerWidget) { 159 Widget sub = ((ContainerWidget)delegate).getChild(id); 160 if (sub != null) { 161 return wrap(sub); 162 } 163 } 164 return NOT_FOUND; 165 } 166 167 public Object get(int index, Scriptable start) { 168 Object result = super.get(index, start); 169 if (result != NOT_FOUND) { 170 return result; 171 } 172 if (delegate instanceof Repeater) { 173 Repeater repeater = (Repeater)delegate; 174 if (index >= 0) { 175 int count = index + 1 - repeater.getSize(); 176 if (count > 0) { 177 ScriptableWidget[] rows = new ScriptableWidget[count]; 178 for (int i = 0; i < count; i++) { 179 rows[i] = wrap(repeater.addRow()); 180 } 181 for (int i = 0; i < count; i++) { 182 rows[i].notifyAddRow(); 183 } 184 } 185 return wrap(repeater.getRow(index)); 186 } 187 } else if (delegate instanceof MultiValueField) { 188 Object [] values = (Object [])delegate.getValue(); 189 if (index >= 0 && index < values.length) { 190 return values[index]; 191 } 192 } 193 return NOT_FOUND; 194 } 195 196 public Object [] getAllIds() { 197 Object [] result = super.getAllIds(); 198 return addWidgetIds(result); 199 } 200 201 public Object [] getIds() { 202 Object [] result = super.getIds(); 203 return addWidgetIds(result); 204 } 205 206 private Object [] addWidgetIds(Object [] result) { 207 if (delegate instanceof ContainerWidget) { 208 Iterator iter = ((ContainerWidget)delegate).getChildren(); 209 List list = new LinkedList (); 210 for (int i = 0; i < result.length; i++) { 211 list.add(result[i]); 212 } 213 while (iter.hasNext()) { 214 Widget widget = (Widget)iter.next(); 215 list.add(widget.getId()); 216 } 217 result = list.toArray(); 218 } 219 return result; 220 } 221 222 private void deleteRow(Repeater repeater, int index) { 223 Widget row = repeater.getRow(index); 224 ScriptableWidget s = wrap(row); 225 s.notifyRemoveRow(); 226 formWidget.deleteWrapper(row); 227 repeater.removeRow(index); 228 } 229 230 private void notifyAddRow() { 231 ScriptableWidget repeater = wrap(delegate.getParent()); 232 Object prop = getProperty(repeater, "onAddRow"); 233 if (prop instanceof Function) { 234 try { 235 Function fun = (Function)prop; 236 Object [] args = new Object [1]; 237 Scriptable scope = getTopLevelScope(this); 238 Scriptable thisObj = scope; 239 Context cx = Context.getCurrentContext(); 240 args[0] = this; 241 fun.call(cx, scope, thisObj, args); 242 } catch (Exception exc) { 243 throw Context.reportRuntimeError(exc.getMessage()); 244 } 245 } 246 } 247 248 private void notifyRemoveRow() { 249 ScriptableWidget repeater = wrap(delegate.getParent()); 250 Object prop = getProperty(repeater, "onRemoveRow"); 251 if (prop instanceof Function) { 252 try { 253 Function fun = (Function)prop; 254 Object [] args = new Object [1]; 255 Scriptable scope = getTopLevelScope(this); 256 Scriptable thisObj = scope; 257 Context cx = Context.getCurrentContext(); 258 args[0] = this; 259 fun.call(cx, scope, thisObj, args); 260 } catch (Exception exc) { 261 throw Context.reportRuntimeError(exc.getMessage()); 262 } 263 } 264 } 265 266 public void delete(int index) { 267 if (delegate instanceof Repeater) { 268 Repeater repeater = (Repeater)delegate; 269 if (index >= 0 && index < repeater.getSize()) { 270 deleteRow(repeater, index); 271 return; 272 } 273 } else if (delegate instanceof MultiValueField) { 274 MultiValueField field = (MultiValueField)delegate; 275 Object [] values = (Object [])field.getValue(); 276 if (values != null && values.length > index) { 277 Object [] newValues = new Object [values.length-1]; 278 int i; 279 for (i = 0; i < index; i++) { 280 newValues[i] = values[i]; 281 } 282 i++; 283 for (;i < values.length; i++) { 284 newValues[i-1] = values[i]; 285 } 286 field.setValues(newValues); 287 } 288 return; 289 } 290 super.delete(index); 291 } 292 293 public Object jsGet_value() { 294 return delegate.getValue(); 295 } 296 297 public Object jsFunction_getValue() { 298 return jsGet_value(); 299 } 300 301 public void jsFunction_setValue(Object value) throws JavaScriptException { 302 jsSet_value(value); 303 } 304 305 public void jsSet_length(int len) { 306 if (delegate instanceof Repeater) { 307 Repeater repeater = (Repeater)delegate; 308 int size = repeater.getSize(); 309 if (size > len) { 310 while (repeater.getSize() > len) { 311 deleteRow(repeater, repeater.getSize() - 1); 312 } 313 } else { 314 for (int i = size; i < len; ++i) { 315 wrap(repeater.addRow()).notifyAddRow(); 316 } 317 } 318 } 319 } 320 321 public Object jsGet_length() { 322 if (delegate instanceof Repeater) { 323 Repeater repeater = (Repeater)delegate; 324 return new Integer (repeater.getSize()); 325 } 326 return Undefined.instance; 327 } 328 329 public void jsSet_value(Object value) throws JavaScriptException { 330 if (delegate instanceof AggregateField) { 331 AggregateField aggregateField = (AggregateField)delegate; 332 if (value instanceof Scriptable) { 333 Scriptable obj = (Scriptable)value; 334 Object [] ids = obj.getIds(); 335 for (int i = 0; i < ids.length; i++) { 336 String id = String.valueOf(ids[i]); 337 Object val = getProperty(obj, id); 338 ScriptableWidget wid = wrap(aggregateField.getChild(id)); 339 if (wid == null) { 340 throw new JavaScriptException("No field \"" + id + "\" in widget \"" + aggregateField.getId() + "\""); 341 } 342 if (wid.delegate instanceof Field || 343 wid.delegate instanceof BooleanField || 344 wid.delegate instanceof Output) { 345 if (val instanceof Scriptable) { 346 Scriptable s = (Scriptable)val; 347 if (s.has("value", s)) { 348 wid.jsSet_value(s.get("value", s)); 349 } 350 } 351 } else { 352 wid.jsSet_value(val); 353 } 354 } 355 aggregateField.combineFields(); 356 return; 357 } 358 } 360 if (delegate instanceof DataWidget) { 361 value = unwrap(value); 362 if (value != null) { 363 Datatype datatype = ((DataWidget)delegate).getDatatype(); 365 Class typeClass = datatype.getTypeClass(); 366 if (typeClass == String .class) { 367 value = Context.toString(value); 368 } else if (typeClass == boolean.class || 369 typeClass == Boolean .class) { 370 value = Context.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE; 371 } else { 372 if (value instanceof Double ) { 373 if (typeClass == long.class || typeClass == Long .class) { 375 value = new Long (((Number )value).longValue()); 376 } else if (typeClass == int.class || 377 typeClass == Integer .class) { 378 value = new Integer (((Number )value).intValue()); 379 } else if (typeClass == float.class || 380 typeClass == Float .class) { 381 value = new Float (((Number )value).floatValue()); 382 } else if (typeClass == short.class || 383 typeClass == Short .class) { 384 value = new Short (((Number )value).shortValue()); 385 } else if (typeClass == BigDecimal .class) { 386 value = new BigDecimal (((Number )value).doubleValue()); 387 } 388 } 389 } 390 } 391 delegate.setValue(value); 392 } else if (delegate instanceof BooleanField) { 393 BooleanField field = (BooleanField)delegate; 394 field.setValue(BooleanUtils.toBooleanObject(Context.toBoolean(value))); 395 } else if (delegate instanceof Repeater) { 396 Repeater repeater = (Repeater)delegate; 397 if (value instanceof NativeArray) { 398 NativeArray arr = (NativeArray)value; 399 Object length = getProperty(arr, "length"); 400 int len = ((Number )length).intValue(); 401 for (int i = repeater.getSize(); i >= len; --i) { 402 deleteRow(repeater, i); 403 } 404 for (int i = 0; i < len; i++) { 405 Object elemValue = getProperty(arr, i); 406 ScriptableWidget wid = wrap(repeater.getRow(i)); 407 wid.jsSet_value(elemValue); 408 } 409 } 410 } else if (delegate instanceof Repeater.RepeaterRow) { 411 Repeater.RepeaterRow row = (Repeater.RepeaterRow)delegate; 412 if (value instanceof Scriptable) { 413 Scriptable obj = (Scriptable)value; 414 Object [] ids = obj.getIds(); 415 for (int i = 0; i < ids.length; i++) { 416 String id = String.valueOf(ids[i]); 417 Object val = getProperty(obj, id); 418 ScriptableWidget wid = wrap(row.getChild(id)); 419 if (wid == null) { 420 throw new JavaScriptException("No field \"" + id + "\" in row " + i + " of repeater \"" + row.getParent().getId() + "\""); 421 } 422 if (wid.delegate instanceof Field || 423 wid.delegate instanceof BooleanField || 424 wid.delegate instanceof Output) { 425 if (val instanceof Scriptable) { 426 Scriptable s = (Scriptable)val; 427 if (s.has("value", s)) { 428 wid.jsSet_value(s.get("value", s)); 429 } 430 } 431 } else { 432 wid.jsSet_value(val); 433 } 434 } 435 } else { 436 throw new JavaScriptException("Expected an object instead of: " + Context.toString(value)); 437 } 438 } else if (delegate instanceof MultiValueField) { 439 MultiValueField field = (MultiValueField)delegate; 440 Object [] values = null; 441 if (value instanceof NativeArray) { 442 NativeArray arr = (NativeArray)value; 443 Object length = getProperty(arr, "length"); 444 int len = ((Number )length).intValue(); 445 values = new Object [len]; 446 for (int i = 0; i < len; i++) { 447 Object elemValue = getProperty(arr, i); 448 values[i] = unwrap(elemValue); 449 } 450 } else if (value instanceof Object []) { 451 values = (Object [])value; 452 } 453 field.setValues(values); 454 } else { 455 delegate.setValue(value); 456 } 457 } 458 459 public String jsFunction_getId() { 460 return delegate.getId(); 461 } 462 463 public WidgetState jsGet_state() { 464 return delegate.getState(); 465 } 466 467 public void jsSet_state(Object stateObj) { 468 Object obj = unwrap(stateObj); 469 WidgetState state = null; 470 471 if (obj instanceof String ) { 472 state = WidgetState.stateForName((String )obj); 473 } else if (obj instanceof WidgetState) { 474 state = (WidgetState)obj; 475 } 476 477 if (state == null) { 478 throw new IllegalArgumentException ("Invalid value for widgetState " + stateObj); 479 } 480 481 delegate.setState(state); 482 } 483 484 public ScriptableWidget jsFunction_getSubmitWidget() { 485 return wrap(delegate.getForm().getSubmitWidget()); 486 } 487 488 public String jsFunction_getRequestParameterName() { 489 return delegate.getRequestParameterName(); 490 } 491 492 496 public Object jsFunction_getParent() { 497 if (delegate != null) { 498 return wrap(delegate.getParent()); 499 } 500 return Undefined.instance; 501 } 502 503 public boolean jsFunction_isRequired() { 504 return delegate.isRequired(); 505 } 506 507 public ScriptableWidget jsFunction_getForm() { 508 return formWidget; 509 } 510 511 public boolean jsFunction_equals(Object other) { 512 if (other instanceof ScriptableWidget) { 513 ScriptableWidget otherWidget = (ScriptableWidget)other; 514 return delegate.equals(otherWidget.delegate); 515 } 516 return false; 517 } 518 519 public ScriptableWidget jsFunction_lookupWidget(String id) { 520 Widget sub = null; 521 sub = delegate.lookupWidget(id); 522 return wrap(sub); 523 } 524 525 public void jsFunction_setValidationError(Object message , 526 Object parameters) { 527 if (delegate instanceof ValidationErrorAware) { 528 String [] parms = null; 529 if (parameters != null && parameters != Undefined.instance) { 530 Scriptable obj = Context.toObject(parameters, this); 531 int len = (int) 532 Context.toNumber(getProperty(obj, "length")); 533 parms = new String [len]; 534 for (int i = 0; i < len; i++) { 535 parms[i] = Context.toString(getProperty(obj, i)); 536 } 537 } 538 ValidationError validationError = null; 539 if (message != null) { 540 if (parms != null && parms.length > 0) { 541 validationError = 542 new ValidationError(Context.toString(message), parms); 543 } else { 544 validationError = 545 new ValidationError(Context.toString(message), parms != null); 546 } 547 } 548 ((ValidationErrorAware)delegate).setValidationError(validationError); 549 } 550 } 551 552 public void jsFunction_setAttribute(String name, Object value) { 553 delegate.setAttribute(name, value); 554 } 555 556 public Object jsFunction_getAttribute(String jsname) { 557 return delegate.getAttribute(jsname); 558 } 559 560 public void jsFunction_removeAttribute(String name) { 561 delegate.removeAttribute(name); 562 } 563 564 public Widget jsFunction_unwrap() { 565 return delegate; 566 } 567 568 public ScriptableWidget jsFunction_addRow() { 569 ScriptableWidget result = null; 570 if (delegate instanceof Repeater) { 571 result = wrap(((Repeater)delegate).addRow()); 572 result.notifyAddRow(); 573 } 574 return result; 575 } 576 577 public ScriptableObject jsFunction_getRow(int index) { 578 if (delegate instanceof Repeater) { 579 return wrap(((Repeater)delegate).getRow(index)); 580 } 581 return null; 582 } 583 584 public void jsFunction_removeRow(Object obj) throws JavaScriptException { 585 if (delegate instanceof Repeater) { 586 Repeater repeater = (Repeater)delegate; 587 if (obj instanceof Function) { 588 Function fun = (Function)obj; 589 int len = repeater.getSize(); 590 boolean[] index = new boolean[len]; 591 Object [] args = new Object [1]; 592 Scriptable scope = getTopLevelScope(this); 593 Scriptable thisObj = scope; 594 Context cx = Context.getCurrentContext(); 595 for (int i = 0; i < len; i++) { 596 ScriptableWidget row = wrap(repeater.getRow(i)); 597 args[0] = row; 598 Object result = fun.call(cx, scope, thisObj, args); 599 index[i] = Context.toBoolean(result); 600 } 601 for (int i = len-1; i >= 0; --i) { 602 if (index[i]) { 603 deleteRow(repeater, i); 604 } 605 } 606 } else { 607 int index = (int)Context.toNumber(obj); 608 if (index >= 0 && index < repeater.getSize()) { 609 deleteRow(repeater, index); 610 } 611 } 612 } 613 } 614 615 public Object jsGet_onChange() { 616 if (onChange != null) 617 return onChange; 618 else 619 return Undefined.instance; 620 } 621 622 public Object jsGet_onActivate() { 623 if (onActivate != null) 624 return onActivate; 625 else 626 return Undefined.instance; 627 } 628 629 public void jsSet_onChange(Object value) { 630 value = unwrap(value); 631 if (value == null) { 632 this.onChange = null; 633 if (delegate instanceof ValueChangedListenerEnabled) { 634 ((ValueChangedListenerEnabled)delegate).removeValueChangedListener(this); 635 } 636 return; 637 } 638 639 if (value instanceof Function) { 640 if (delegate instanceof ValueChangedListenerEnabled) { 641 if (this.onChange == null) 642 ((ValueChangedListenerEnabled)delegate).addValueChangedListener(this); 643 this.onChange = (Function)value; 644 } 645 } 646 647 } 648 649 public void jsSet_onActivate(Object value) { 650 value = unwrap(value); 651 if (value == null) { 652 this.onActivate = null; 653 if (delegate instanceof ActionListenerEnabled) { 654 ((ActionListenerEnabled)delegate).removeActionListener(this); 655 } 656 return; 657 } 658 659 if (value instanceof Function) { 660 if (delegate instanceof ActionListenerEnabled) { 661 if (this.onActivate == null) 662 ((ActionListenerEnabled)delegate).addActionListener(this); 663 this.onActivate = (Function)value; 664 } 665 } 666 } 667 668 public void valueChanged(ValueChangedEvent event) { 669 if (onChange != null) { 670 try { 671 Object [] args = new Object [2]; 672 Scriptable scope = getTopLevelScope(this); 673 Scriptable thisObj = scope; 674 Context cx = Context.getCurrentContext(); 675 args[0] = event.getOldValue(); 676 args[1] = event.getNewValue(); 677 onChange.call(cx, scope, thisObj, args); 678 } catch (Exception exc) { 679 throw Context.reportRuntimeError(exc.getMessage()); 680 } 681 } 682 } 683 684 public void actionPerformed(ActionEvent event) { 685 if (onActivate != null) { 686 try { 687 Object [] args = new Object [1]; 688 Scriptable scope = getTopLevelScope(this); 689 Scriptable thisObj = scope; 690 Context cx = Context.getCurrentContext(); 691 args[0] = event.getActionCommand(); 692 onActivate.call(cx, scope, thisObj, args); 693 } catch (Exception exc) { 694 throw Context.reportRuntimeError(exc.getMessage()); 695 } 696 } 697 } 698 699 public Object jsGet_validator() { 700 if (validator != null) 701 return validator; 702 else 703 return Undefined.instance; 704 } 705 706 public void jsSet_validator(Object value) { 707 value = unwrap(value); 708 if (value == null) { 709 this.validator = null; 710 delegate.removeValidator(this); 711 return; 712 } 713 714 if (value instanceof Function) { 715 if (this.validator == null) 716 delegate.addValidator(this); 717 this.validator = (Function)value; 718 } 719 720 } 721 722 public boolean validate(Widget widget) { 723 try { 724 Object [] args = new Object [1]; 725 Scriptable scope = getTopLevelScope(this); 726 Scriptable thisObj = scope; 727 Context cx = Context.getCurrentContext(); 728 args[0] = this; 729 Object result = validator.call(cx, scope, thisObj, args); 730 return Context.toBoolean(result); 731 } catch (Exception exc) { 732 throw Context.reportRuntimeError(exc.getMessage()); 733 } 734 } 735 736 public void jsFunction_setSelectionList(Object arg, 737 Object valuePathArg, 738 Object labelPathArg) 739 throws Exception { 740 if (delegate instanceof SelectableWidget) { 741 arg = unwrap(arg); 742 if (valuePathArg != Undefined.instance && labelPathArg != Undefined.instance) { 743 String valuePath = Context.toString(valuePathArg); 744 String labelPath = Context.toString(labelPathArg); 745 ((SelectableWidget)delegate).setSelectionList(arg, valuePath, labelPath); 746 } else { 747 if (arg instanceof SelectionList) { 748 SelectionList selectionList = (SelectionList)arg; 749 ((SelectableWidget)delegate).setSelectionList(selectionList); 750 } else { 751 String str = Context.toString(arg); 752 ((SelectableWidget)delegate).setSelectionList(str); 753 } 754 } 755 } 756 } 757 758 static final Object [] WIDGET_CLASS_MAP = { 759 Form.class, "Form", 760 Field.class, "Field", 761 Action.class, "Action", 762 Repeater.class, "Repeater", 763 Repeater.RepeaterRow.class, "RepeaterRow", 764 AggregateField.class, "AggregateField", 765 BooleanField.class, "BooleanField", 766 MultiValueField.class, "MultiValueField", 767 Output.class, "Output", 768 Submit.class, "Submit", 769 Upload.class, "Upload" 770 }; 771 772 public String jsFunction_getWidgetClass() { 773 for (int i = 0; i < WIDGET_CLASS_MAP.length; i += 2) { 774 Class c = (Class )WIDGET_CLASS_MAP[i]; 775 if (c.isAssignableFrom(delegate.getClass())) { 776 return (String )WIDGET_CLASS_MAP[i + 1]; 777 } 778 } 779 return "<unknown>"; 780 } 781 782 public String jsFunction_toString() { 783 return "[object Widget (" + jsFunction_getWidgetClass() + ")]"; 784 } 785 786 } 787 | Popular Tags |