001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.uif.component; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 020import org.kuali.rice.krad.uif.CssConstants; 021import org.kuali.rice.krad.uif.UifConstants.ViewStatus; 022import org.kuali.rice.krad.uif.control.ControlBase; 023import org.kuali.rice.krad.uif.modifier.ComponentModifier; 024import org.kuali.rice.krad.uif.util.ExpressionUtils; 025import org.kuali.rice.krad.uif.view.View; 026import org.kuali.rice.krad.util.ObjectUtils; 027 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033/** 034 * Base implementation of <code>Component</code> which other component 035 * implementations should extend 036 * 037 * <p> 038 * Provides base component properties such as id and template. Also provides 039 * default implementation for the <code>ScriptEventSupport</code> and 040 * <code>Ordered</code> interfaces. By default no script events except the 041 * onDocumentReady are supported. 042 * </p> 043 * 044 * @author Kuali Rice Team (rice.collab@kuali.org) 045 */ 046public abstract class ComponentBase extends ConfigurableBase implements Component { 047 private static final long serialVersionUID = -4449335748129894350L; 048 049 private String id; 050 private String factoryId; 051 private String template; 052 private String title; 053 054 private boolean render; 055 private boolean refresh; 056 057 @KeepExpression 058 private String progressiveRender; 059 private boolean progressiveRenderViaAJAX; 060 private boolean progressiveRenderAndRefresh; 061 private List<String> progressiveDisclosureControlNames; 062 private String progressiveDisclosureConditionJs; 063 064 @KeepExpression 065 private String conditionalRefresh; 066 private String conditionalRefreshConditionJs; 067 private List<String> conditionalRefreshControlNames; 068 069 private String refreshWhenChanged; 070 private List<String> refreshWhenChangedControlNames; 071 private boolean refreshedByAction; 072 073 private boolean resetDataOnRefresh; 074 private String refreshDiscloseMethodToCall; 075 076 private boolean hidden; 077 private boolean readOnly; 078 private Boolean required; 079 080 private String align; 081 private String valign; 082 private String width; 083 084 private int colSpan; 085 private int rowSpan; 086 087 private String style; 088 private List<String> styleClasses; 089 090 private int order; 091 092 private boolean skipInTabOrder; 093 094 private String finalizeMethodToCall; 095 private List<Object> finalizeMethodAdditionalArguments; 096 private MethodInvokerConfig finalizeMethodInvoker; 097 private boolean selfRendered; 098 private String renderOutput; 099 100 private boolean persistInSession; 101 102 private ComponentSecurity componentSecurity; 103 104 private String onLoadScript; 105 private String onUnloadScript; 106 private String onCloseScript; 107 private String onBlurScript; 108 private String onChangeScript; 109 private String onClickScript; 110 private String onDblClickScript; 111 private String onFocusScript; 112 private String onSubmitScript; 113 private String onKeyPressScript; 114 private String onKeyUpScript; 115 private String onKeyDownScript; 116 private String onMouseOverScript; 117 private String onMouseOutScript; 118 private String onMouseUpScript; 119 private String onMouseDownScript; 120 private String onMouseMoveScript; 121 private String onDocumentReadyScript; 122 123 private List<ComponentModifier> componentModifiers; 124 125 private Map<String, String> componentOptions; 126 private String componentOptionsJSString; 127 128 @ReferenceCopy(newCollectionInstance = true) 129 private transient Map<String, Object> context; 130 131 private List<PropertyReplacer> propertyReplacers; 132 133 public ComponentBase() { 134 super(); 135 136 order = 0; 137 colSpan = 1; 138 rowSpan = 1; 139 140 render = true; 141 selfRendered = false; 142 progressiveRenderViaAJAX = false; 143 progressiveRenderAndRefresh = false; 144 refreshedByAction = false; 145 resetDataOnRefresh = false; 146 persistInSession = false; 147 148 componentSecurity = ObjectUtils.newInstance(getComponentSecurityClass()); 149 150 finalizeMethodAdditionalArguments = new ArrayList<Object>(); 151 styleClasses = new ArrayList<String>(); 152 componentModifiers = new ArrayList<ComponentModifier>(); 153 componentOptions = new HashMap<String, String>(); 154 context = new HashMap<String, Object>(); 155 propertyReplacers = new ArrayList<PropertyReplacer>(); 156 } 157 158 /** 159 * The following updates are done here: 160 * 161 * <ul> 162 * <li></li> 163 * </ul> 164 * 165 * @see Component#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object) 166 */ 167 public void performInitialization(View view, Object model) { 168 169 } 170 171 /** 172 * The following updates are done here: 173 * 174 * <ul> 175 * <li>Evaluate the progressive render condition (if set) and combine with the current render status to set the 176 * render status</li> 177 * </ul> 178 * 179 * @see Component#performApplyModel(org.kuali.rice.krad.uif.view.View, java.lang.Object, org.kuali.rice.krad.uif.component.Component) 180 */ 181 public void performApplyModel(View view, Object model, Component parent) { 182 if (StringUtils.isNotEmpty(progressiveRender)) { 183 // progressive anded with conditional render, will not render at least one of the two are false 184 Boolean progRenderEval = (Boolean) KRADServiceLocatorWeb.getExpressionEvaluatorService().evaluateExpression( 185 model, context, progressiveRender); 186 187 this.setRender(progRenderEval && this.render); 188 } 189 } 190 191 /** 192 * The following finalization is done here: 193 * 194 * <ul> 195 * <li>progressiveRender and conditionalRefresh variables are processed if set</li> 196 * <li>If any of the style properties were given, sets the style string on 197 * the style property</li> 198 * <li>Set the skipInTabOrder flag for nested components</li> 199 * </ul> 200 * 201 * @see Component#performFinalize(org.kuali.rice.krad.uif.view.View, java.lang.Object, org.kuali.rice.krad.uif.component.Component) 202 */ 203 public void performFinalize(View view, Object model, Component parent) { 204 if (StringUtils.isNotEmpty(progressiveRender)) { 205 progressiveRender = ExpressionUtils.replaceBindingPrefixes(view, this, progressiveRender); 206 progressiveDisclosureControlNames = new ArrayList<String>(); 207 progressiveDisclosureConditionJs = ExpressionUtils.parseExpression(progressiveRender, 208 progressiveDisclosureControlNames); 209 } 210 211 if (StringUtils.isNotEmpty(conditionalRefresh)) { 212 conditionalRefresh = ExpressionUtils.replaceBindingPrefixes(view, this, conditionalRefresh); 213 conditionalRefreshControlNames = new ArrayList<String>(); 214 conditionalRefreshConditionJs = ExpressionUtils.parseExpression(conditionalRefresh, 215 conditionalRefreshControlNames); 216 } 217 218 if (StringUtils.isNotEmpty(refreshWhenChanged)) { 219 refreshWhenChanged = ExpressionUtils.replaceBindingPrefixes(view, this, refreshWhenChanged); 220 refreshWhenChangedControlNames = new ArrayList<String>(); 221 String[] names = StringUtils.split(refreshWhenChanged, ","); 222 for (String name : names) { 223 refreshWhenChangedControlNames.add(name.trim()); 224 } 225 } 226 227 // TODO: does this check on final status need to be here? 228 if (!ViewStatus.FINAL.equals(view.getViewStatus())) { 229 // add the align, valign, and width settings to style 230 if (StringUtils.isNotBlank(getAlign()) && !StringUtils.contains(getStyle(), CssConstants.TEXT_ALIGN)) { 231 appendToStyle(CssConstants.TEXT_ALIGN + getAlign() + ";"); 232 } 233 234 if (StringUtils.isNotBlank(getValign()) && !StringUtils.contains(getStyle(), CssConstants.VERTICAL_ALIGN)) { 235 appendToStyle(CssConstants.VERTICAL_ALIGN + getValign() + ";"); 236 } 237 238 if (StringUtils.isNotBlank(getWidth()) && !StringUtils.contains(getStyle(), CssConstants.WIDTH)) { 239 appendToStyle(CssConstants.WIDTH + getWidth() + ";"); 240 } 241 } 242 243 // Set the skipInTabOrder flag on all nested components 244 // Set the tabIndex on controls to -1 in order to be skipped on tabbing 245 for (Component component : getComponentsForLifecycle()) { 246 if (component != null && component instanceof ComponentBase && skipInTabOrder) { 247 ((ComponentBase) component).setSkipInTabOrder(skipInTabOrder); 248 if (component instanceof ControlBase) { 249 ((ControlBase) component).setTabIndex(-1); 250 } 251 } 252 } 253 } 254 255 /** 256 * @see org.kuali.rice.krad.uif.component.Component#getComponentsForLifecycle() 257 */ 258 public List<Component> getComponentsForLifecycle() { 259 List<Component> components = new ArrayList<Component>(); 260 261 return components; 262 } 263 264 /** 265 * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes() 266 */ 267 public List<Component> getComponentPrototypes() { 268 List<Component> components = new ArrayList<Component>(); 269 270 for (ComponentModifier modifier : componentModifiers) { 271 components.addAll(modifier.getComponentPrototypes()); 272 } 273 274 components.addAll(getPropertyReplacerComponents()); 275 276 return components; 277 } 278 279 /** 280 * Returns list of components that are being held in property replacers configured for this component 281 * 282 * @return List<Component> 283 */ 284 public List<Component> getPropertyReplacerComponents() { 285 List<Component> components = new ArrayList<Component>(); 286 for (Object replacer : propertyReplacers) { 287 components.addAll(((PropertyReplacer) replacer).getNestedComponents()); 288 } 289 290 return components; 291 } 292 293 /** 294 * @see org.kuali.rice.krad.uif.component.Component#getId() 295 */ 296 public String getId() { 297 return this.id; 298 } 299 300 /** 301 * @see org.kuali.rice.krad.uif.component.Component#setId(java.lang.String) 302 */ 303 public void setId(String id) { 304 this.id = id; 305 } 306 307 /** 308 * @see org.kuali.rice.krad.uif.component.Component#getFactoryId() 309 */ 310 public String getFactoryId() { 311 return this.factoryId; 312 } 313 314 /** 315 * @see org.kuali.rice.krad.uif.component.Component#setFactoryId(java.lang.String) 316 */ 317 public void setFactoryId(String factoryId) { 318 this.factoryId = factoryId; 319 } 320 321 /** 322 * @see org.kuali.rice.krad.uif.component.Component#getTemplate() 323 */ 324 public String getTemplate() { 325 return this.template; 326 } 327 328 /** 329 * @see org.kuali.rice.krad.uif.component.Component#setTemplate(java.lang.String) 330 */ 331 public void setTemplate(String template) { 332 this.template = template; 333 } 334 335 /** 336 * @see org.kuali.rice.krad.uif.component.Component#getTitle() 337 */ 338 public String getTitle() { 339 return this.title; 340 } 341 342 /** 343 * @see org.kuali.rice.krad.uif.component.Component#setTitle(java.lang.String) 344 */ 345 public void setTitle(String title) { 346 this.title = title; 347 } 348 349 /** 350 * @see org.kuali.rice.krad.uif.component.Component#isHidden() 351 */ 352 public boolean isHidden() { 353 return this.hidden; 354 } 355 356 /** 357 * @see org.kuali.rice.krad.uif.component.Component#setHidden(boolean) 358 */ 359 public void setHidden(boolean hidden) { 360 this.hidden = hidden; 361 } 362 363 /** 364 * @see org.kuali.rice.krad.uif.component.Component#isReadOnly() 365 */ 366 public boolean isReadOnly() { 367 return this.readOnly; 368 } 369 370 /** 371 * @see org.kuali.rice.krad.uif.component.Component#setReadOnly(boolean) 372 */ 373 public void setReadOnly(boolean readOnly) { 374 this.readOnly = readOnly; 375 } 376 377 /** 378 * @see org.kuali.rice.krad.uif.component.Component#getRequired() 379 */ 380 public Boolean getRequired() { 381 return this.required; 382 } 383 384 /** 385 * @see org.kuali.rice.krad.uif.component.Component#setRequired(java.lang.Boolean) 386 */ 387 public void setRequired(Boolean required) { 388 this.required = required; 389 } 390 391 /** 392 * @see org.kuali.rice.krad.uif.component.Component#isRender() 393 */ 394 public boolean isRender() { 395 return this.render; 396 } 397 398 /** 399 * @see org.kuali.rice.krad.uif.component.Component#setRender(boolean) 400 */ 401 public void setRender(boolean render) { 402 this.render = render; 403 } 404 405 /** 406 * @see org.kuali.rice.krad.uif.component.Component#getColSpan() 407 */ 408 public int getColSpan() { 409 return this.colSpan; 410 } 411 412 /** 413 * @see org.kuali.rice.krad.uif.component.Component#setColSpan(int) 414 */ 415 public void setColSpan(int colSpan) { 416 this.colSpan = colSpan; 417 } 418 419 /** 420 * @see org.kuali.rice.krad.uif.component.Component#getRowSpan() 421 */ 422 public int getRowSpan() { 423 return this.rowSpan; 424 } 425 426 /** 427 * @see org.kuali.rice.krad.uif.component.Component#setRowSpan(int) 428 */ 429 public void setRowSpan(int rowSpan) { 430 this.rowSpan = rowSpan; 431 } 432 433 /** 434 * Horizontal alignment of the component within its container 435 * <p> 436 * All components belong to a <code>Container</code> and are placed using a 437 * <code>LayoutManager</code>. This property specifies how the component 438 * should be aligned horizontally within the container. During the finalize 439 * phase the CSS text-align style will be created for the align setting. 440 * </p> 441 * 442 * @return String horizontal align 443 * @see org.kuali.rice.krad.uif.CssConstants.TextAligns 444 */ 445 public String getAlign() { 446 return this.align; 447 } 448 449 /** 450 * Sets the components horizontal alignment 451 * 452 * @param align 453 */ 454 public void setAlign(String align) { 455 this.align = align; 456 } 457 458 /** 459 * Vertical alignment of the component within its container 460 * <p> 461 * All components belong to a <code>Container</code> and are placed using a 462 * <code>LayoutManager</code>. This property specifies how the component 463 * should be aligned vertically within the container. During the finalize 464 * phase the CSS vertical-align style will be created for the valign 465 * setting. 466 * </p> 467 * 468 * @return String vertical align 469 * @see org.kuali.rice.krad.uif.CssConstants.VerticalAligns 470 */ 471 public String getValign() { 472 return this.valign; 473 } 474 475 /** 476 * Setter for the component's vertical align 477 * 478 * @param valign 479 */ 480 public void setValign(String valign) { 481 this.valign = valign; 482 } 483 484 /** 485 * Width the component should take up in the container 486 * <p> 487 * All components belong to a <code>Container</code> and are placed using a 488 * <code>LayoutManager</code>. This property specifies a width the component 489 * should take up in the Container. This is not applicable for all layout 490 * managers. During the finalize phase the CSS width style will be created 491 * for the width setting. 492 * </p> 493 * <p> 494 * e.g. '30%', '55px' 495 * </p> 496 * 497 * @return String width string 498 */ 499 public String getWidth() { 500 return this.width; 501 } 502 503 /** 504 * Setter for the components width 505 * 506 * @param width 507 */ 508 public void setWidth(String width) { 509 this.width = width; 510 } 511 512 /** 513 * @see org.kuali.rice.krad.uif.component.Component#getStyle() 514 */ 515 public String getStyle() { 516 return this.style; 517 } 518 519 /** 520 * @see org.kuali.rice.krad.uif.component.Component#setStyle(java.lang.String) 521 */ 522 public void setStyle(String style) { 523 this.style = style; 524 } 525 526 /** 527 * @see org.kuali.rice.krad.uif.component.Component#getStyleClasses() 528 */ 529 public List<String> getStyleClasses() { 530 return this.styleClasses; 531 } 532 533 /** 534 * @see org.kuali.rice.krad.uif.component.Component#setStyleClasses(java.util.List) 535 */ 536 public void setStyleClasses(List<String> styleClasses) { 537 this.styleClasses = styleClasses; 538 } 539 540 /** 541 * Builds the HTML class attribute string by combining the styleClasses list 542 * with a space delimiter 543 * 544 * @return String class attribute string 545 */ 546 public String getStyleClassesAsString() { 547 if (styleClasses != null) { 548 return StringUtils.join(styleClasses, " "); 549 } 550 551 return ""; 552 } 553 554 /** 555 * @see org.kuali.rice.krad.uif.component.Component#addStyleClass(java.lang.String) 556 */ 557 public void addStyleClass(String styleClass) { 558 if (!styleClasses.contains(styleClass)) { 559 styleClasses.add(styleClass); 560 } 561 } 562 563 /** 564 * @see org.kuali.rice.krad.uif.component.Component#appendToStyle(java.lang.String) 565 */ 566 public void appendToStyle(String styleRules) { 567 if (style == null) { 568 style = ""; 569 } 570 style = style + styleRules; 571 } 572 573 /** 574 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodToCall() 575 */ 576 public String getFinalizeMethodToCall() { 577 return this.finalizeMethodToCall; 578 } 579 580 /** 581 * Setter for the finalize method 582 * 583 * @param finalizeMethodToCall 584 */ 585 public void setFinalizeMethodToCall(String finalizeMethodToCall) { 586 this.finalizeMethodToCall = finalizeMethodToCall; 587 } 588 589 /** 590 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodAdditionalArguments() 591 */ 592 public List<Object> getFinalizeMethodAdditionalArguments() { 593 return finalizeMethodAdditionalArguments; 594 } 595 596 /** 597 * Setter for the finalize additional arguments list 598 * 599 * @param finalizeMethodAdditionalArguments 600 */ 601 public void setFinalizeMethodAdditionalArguments(List<Object> finalizeMethodAdditionalArguments) { 602 this.finalizeMethodAdditionalArguments = finalizeMethodAdditionalArguments; 603 } 604 605 /** 606 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodInvoker() 607 */ 608 public MethodInvokerConfig getFinalizeMethodInvoker() { 609 return this.finalizeMethodInvoker; 610 } 611 612 /** 613 * Setter for the method invoker instance 614 * 615 * @param finalizeMethodInvoker 616 */ 617 public void setFinalizeMethodInvoker(MethodInvokerConfig finalizeMethodInvoker) { 618 this.finalizeMethodInvoker = finalizeMethodInvoker; 619 } 620 621 /** 622 * @see org.kuali.rice.krad.uif.component.Component#isSelfRendered() 623 */ 624 public boolean isSelfRendered() { 625 return this.selfRendered; 626 } 627 628 /** 629 * @see org.kuali.rice.krad.uif.component.Component#setSelfRendered(boolean) 630 */ 631 public void setSelfRendered(boolean selfRendered) { 632 this.selfRendered = selfRendered; 633 } 634 635 /** 636 * @see org.kuali.rice.krad.uif.component.Component#getRenderOutput() 637 */ 638 public String getRenderOutput() { 639 return this.renderOutput; 640 } 641 642 /** 643 * @see org.kuali.rice.krad.uif.component.Component#setRenderOutput(java.lang.String) 644 */ 645 public void setRenderOutput(String renderOutput) { 646 this.renderOutput = renderOutput; 647 } 648 649 /** 650 * @see Component#isPersistInSession() 651 */ 652 public boolean isPersistInSession() { 653 return persistInSession; 654 } 655 656 /** 657 * @see Component#setPersistInSession(boolean) 658 */ 659 public void setPersistInSession(boolean persistInSession) { 660 this.persistInSession = persistInSession; 661 } 662 663 /** 664 * @see Component#getComponentSecurity() 665 */ 666 public ComponentSecurity getComponentSecurity() { 667 return componentSecurity; 668 } 669 670 /** 671 * @see Component#setComponentSecurity(org.kuali.rice.krad.uif.component.ComponentSecurity) 672 */ 673 public void setComponentSecurity(ComponentSecurity componentSecurity) { 674 this.componentSecurity = componentSecurity; 675 } 676 677 /** 678 * Returns the security class that is associated with the component (used for initialization and validation) 679 * 680 * @return Class<? extends ComponentSecurity> 681 */ 682 protected Class<? extends ComponentSecurity> getComponentSecurityClass() { 683 return ComponentSecurity.class; 684 } 685 686 /** 687 * @see org.kuali.rice.krad.uif.component.Component#getComponentModifiers() 688 */ 689 public List<ComponentModifier> getComponentModifiers() { 690 return this.componentModifiers; 691 } 692 693 /** 694 * @see org.kuali.rice.krad.uif.component.Component#setComponentModifiers(java.util.List) 695 */ 696 public void setComponentModifiers(List<ComponentModifier> componentModifiers) { 697 this.componentModifiers = componentModifiers; 698 } 699 700 /** 701 * @see org.kuali.rice.krad.uif.component.Component#getContext() 702 */ 703 public Map<String, Object> getContext() { 704 return this.context; 705 } 706 707 /** 708 * @see org.kuali.rice.krad.uif.component.Component#setContext(java.util.Map) 709 */ 710 public void setContext(Map<String, Object> context) { 711 this.context = context; 712 } 713 714 /** 715 * @see org.kuali.rice.krad.uif.component.Component#pushObjectToContext(java.lang.String, 716 * java.lang.Object) 717 */ 718 public void pushObjectToContext(String objectName, Object object) { 719 if (this.context == null) { 720 this.context = new HashMap<String, Object>(); 721 } 722 pushToPropertyReplacerContext(objectName, object); 723 this.context.put(objectName, object); 724 } 725 726 /* 727 * Adds the object to the context of the components in the 728 * PropertyReplacer object. Only checks for a list, map or component. 729 */ 730 protected void pushToPropertyReplacerContext(String objectName, Object object) { 731 for (Component replacerComponent : getPropertyReplacerComponents()) { 732 replacerComponent.pushObjectToContext(objectName, object); 733 } 734 } 735 736 /** 737 * @see org.kuali.rice.krad.uif.component.ComponentBase#pushAllToContext 738 */ 739 public void pushAllToContext(Map<String, Object> objects) { 740 if (objects != null) { 741 for (Map.Entry<String, Object> objectEntry : objects.entrySet()) { 742 pushObjectToContext(objectEntry.getKey(), objectEntry.getValue()); 743 } 744 } 745 } 746 747 /** 748 * @see org.kuali.rice.krad.uif.component.Component#getPropertyReplacers() 749 */ 750 public List<PropertyReplacer> getPropertyReplacers() { 751 return this.propertyReplacers; 752 } 753 754 /** 755 * @see org.kuali.rice.krad.uif.component.Component#setPropertyReplacers(java.util.List) 756 */ 757 public void setPropertyReplacers(List<PropertyReplacer> propertyReplacers) { 758 this.propertyReplacers = propertyReplacers; 759 } 760 761 /** 762 * @see org.springframework.core.Ordered#getOrder() 763 */ 764 public int getOrder() { 765 return this.order; 766 } 767 768 /** 769 * Setter for the component's order 770 * 771 * @param order 772 */ 773 public void setOrder(int order) { 774 this.order = order; 775 } 776 777 /** 778 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnLoad() 779 */ 780 public boolean getSupportsOnLoad() { 781 return false; 782 } 783 784 /** 785 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnLoadScript() 786 */ 787 public String getOnLoadScript() { 788 return onLoadScript; 789 } 790 791 /** 792 * Setter for the components onLoad script 793 * 794 * @param onLoadScript 795 */ 796 public void setOnLoadScript(String onLoadScript) { 797 this.onLoadScript = onLoadScript; 798 } 799 800 /** 801 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnDocumentReady() 802 */ 803 public boolean getSupportsOnDocumentReady() { 804 return true; 805 } 806 807 /** 808 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDocumentReadyScript() 809 */ 810 public String getOnDocumentReadyScript() { 811 return onDocumentReadyScript; 812 } 813 814 /** 815 * Setter for the components onDocumentReady script 816 * 817 * @param onDocumentReadyScript 818 */ 819 public void setOnDocumentReadyScript(String onDocumentReadyScript) { 820 this.onDocumentReadyScript = onDocumentReadyScript; 821 } 822 823 /** 824 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnUnload() 825 */ 826 public boolean getSupportsOnUnload() { 827 return false; 828 } 829 830 /** 831 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnUnloadScript() 832 */ 833 public String getOnUnloadScript() { 834 return onUnloadScript; 835 } 836 837 /** 838 * Setter for the components onUnload script 839 * 840 * @param onUnloadScript 841 */ 842 public void setOnUnloadScript(String onUnloadScript) { 843 this.onUnloadScript = onUnloadScript; 844 } 845 846 /** 847 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnClose() 848 */ 849 public boolean getSupportsOnClose() { 850 return false; 851 } 852 853 /** 854 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnCloseScript() 855 */ 856 public String getOnCloseScript() { 857 return onCloseScript; 858 } 859 860 /** 861 * Setter for the components onClose script 862 * 863 * @param onCloseScript 864 */ 865 public void setOnCloseScript(String onCloseScript) { 866 this.onCloseScript = onCloseScript; 867 } 868 869 /** 870 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnBlur() 871 */ 872 public boolean getSupportsOnBlur() { 873 return false; 874 } 875 876 /** 877 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnBlurScript() 878 */ 879 public String getOnBlurScript() { 880 return onBlurScript; 881 } 882 883 /** 884 * Setter for the components onBlur script 885 * 886 * @param onBlurScript 887 */ 888 public void setOnBlurScript(String onBlurScript) { 889 this.onBlurScript = onBlurScript; 890 } 891 892 /** 893 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnChange() 894 */ 895 public boolean getSupportsOnChange() { 896 return false; 897 } 898 899 /** 900 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnChangeScript() 901 */ 902 public String getOnChangeScript() { 903 return onChangeScript; 904 } 905 906 /** 907 * Setter for the components onChange script 908 * 909 * @param onChangeScript 910 */ 911 public void setOnChangeScript(String onChangeScript) { 912 this.onChangeScript = onChangeScript; 913 } 914 915 /** 916 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnClick() 917 */ 918 public boolean getSupportsOnClick() { 919 return false; 920 } 921 922 /** 923 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnClickScript() 924 */ 925 public String getOnClickScript() { 926 return onClickScript; 927 } 928 929 /** 930 * Setter for the components onClick script 931 * 932 * @param onClickScript 933 */ 934 public void setOnClickScript(String onClickScript) { 935 this.onClickScript = onClickScript; 936 } 937 938 /** 939 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnDblClick() 940 */ 941 public boolean getSupportsOnDblClick() { 942 return false; 943 } 944 945 /** 946 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDblClickScript() 947 */ 948 public String getOnDblClickScript() { 949 return onDblClickScript; 950 } 951 952 /** 953 * Setter for the components onDblClick script 954 * 955 * @param onDblClickScript 956 */ 957 public void setOnDblClickScript(String onDblClickScript) { 958 this.onDblClickScript = onDblClickScript; 959 } 960 961 /** 962 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnFocus() 963 */ 964 public boolean getSupportsOnFocus() { 965 return false; 966 } 967 968 /** 969 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnFocusScript() 970 */ 971 public String getOnFocusScript() { 972 return onFocusScript; 973 } 974 975 /** 976 * Setter for the components onFocus script 977 * 978 * @param onFocusScript 979 */ 980 public void setOnFocusScript(String onFocusScript) { 981 this.onFocusScript = onFocusScript; 982 } 983 984 /** 985 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnSubmit() 986 */ 987 public boolean getSupportsOnSubmit() { 988 return false; 989 } 990 991 /** 992 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnSubmitScript() 993 */ 994 public String getOnSubmitScript() { 995 return onSubmitScript; 996 } 997 998 /** 999 * Setter for the components onSubmit script 1000 * 1001 * @param onSubmitScript 1002 */ 1003 public void setOnSubmitScript(String onSubmitScript) { 1004 this.onSubmitScript = onSubmitScript; 1005 } 1006 1007 /** 1008 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnKeyPress() 1009 */ 1010 public boolean getSupportsOnKeyPress() { 1011 return false; 1012 } 1013 1014 /** 1015 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyPressScript() 1016 */ 1017 public String getOnKeyPressScript() { 1018 return onKeyPressScript; 1019 } 1020 1021 /** 1022 * Setter for the components onKeyPress script 1023 * 1024 * @param onKeyPressScript 1025 */ 1026 public void setOnKeyPressScript(String onKeyPressScript) { 1027 this.onKeyPressScript = onKeyPressScript; 1028 } 1029 1030 /** 1031 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnKeyUp() 1032 */ 1033 public boolean getSupportsOnKeyUp() { 1034 return false; 1035 } 1036 1037 /** 1038 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyUpScript() 1039 */ 1040 public String getOnKeyUpScript() { 1041 return onKeyUpScript; 1042 } 1043 1044 /** 1045 * Setter for the components onKeyUp script 1046 * 1047 * @param onKeyUpScript 1048 */ 1049 public void setOnKeyUpScript(String onKeyUpScript) { 1050 this.onKeyUpScript = onKeyUpScript; 1051 } 1052 1053 /** 1054 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnKeyDown() 1055 */ 1056 public boolean getSupportsOnKeyDown() { 1057 return false; 1058 } 1059 1060 /** 1061 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyDownScript() 1062 */ 1063 public String getOnKeyDownScript() { 1064 return onKeyDownScript; 1065 } 1066 1067 /** 1068 * Setter for the components onKeyDown script 1069 * 1070 * @param onKeyDownScript 1071 */ 1072 public void setOnKeyDownScript(String onKeyDownScript) { 1073 this.onKeyDownScript = onKeyDownScript; 1074 } 1075 1076 /** 1077 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnMouseOver() 1078 */ 1079 public boolean getSupportsOnMouseOver() { 1080 return false; 1081 } 1082 1083 /** 1084 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOverScript() 1085 */ 1086 public String getOnMouseOverScript() { 1087 return onMouseOverScript; 1088 } 1089 1090 /** 1091 * Setter for the components onMouseOver script 1092 * 1093 * @param onMouseOverScript 1094 */ 1095 public void setOnMouseOverScript(String onMouseOverScript) { 1096 this.onMouseOverScript = onMouseOverScript; 1097 } 1098 1099 /** 1100 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnMouseOut() 1101 */ 1102 public boolean getSupportsOnMouseOut() { 1103 return false; 1104 } 1105 1106 /** 1107 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOutScript() 1108 */ 1109 public String getOnMouseOutScript() { 1110 return onMouseOutScript; 1111 } 1112 1113 /** 1114 * Setter for the components onMouseOut script 1115 * 1116 * @param onMouseOutScript 1117 */ 1118 public void setOnMouseOutScript(String onMouseOutScript) { 1119 this.onMouseOutScript = onMouseOutScript; 1120 } 1121 1122 /** 1123 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnMouseUp() 1124 */ 1125 public boolean getSupportsOnMouseUp() { 1126 return false; 1127 } 1128 1129 /** 1130 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseUpScript() 1131 */ 1132 public String getOnMouseUpScript() { 1133 return onMouseUpScript; 1134 } 1135 1136 /** 1137 * Setter for the components onMouseUp script 1138 * 1139 * @param onMouseUpScript 1140 */ 1141 public void setOnMouseUpScript(String onMouseUpScript) { 1142 this.onMouseUpScript = onMouseUpScript; 1143 } 1144 1145 /** 1146 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnMouseDown() 1147 */ 1148 public boolean getSupportsOnMouseDown() { 1149 return false; 1150 } 1151 1152 /** 1153 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseDownScript() 1154 */ 1155 public String getOnMouseDownScript() { 1156 return onMouseDownScript; 1157 } 1158 1159 /** 1160 * Setter for the components onMouseDown script 1161 * 1162 * @param onMouseDownScript 1163 */ 1164 public void setOnMouseDownScript(String onMouseDownScript) { 1165 this.onMouseDownScript = onMouseDownScript; 1166 } 1167 1168 /** 1169 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getSupportsOnMouseMove() 1170 */ 1171 public boolean getSupportsOnMouseMove() { 1172 return false; 1173 } 1174 1175 /** 1176 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseMoveScript() 1177 */ 1178 public String getOnMouseMoveScript() { 1179 return onMouseMoveScript; 1180 } 1181 1182 /** 1183 * Setter for the components onMouseMove script 1184 * 1185 * @param onMouseMoveScript 1186 */ 1187 public void setOnMouseMoveScript(String onMouseMoveScript) { 1188 this.onMouseMoveScript = onMouseMoveScript; 1189 } 1190 1191 public Map<String, String> getComponentOptions() { 1192 if (componentOptions == null) { 1193 componentOptions = new HashMap<String, String>(); 1194 } 1195 return this.componentOptions; 1196 } 1197 1198 public void setComponentOptions(Map<String, String> componentOptions) { 1199 this.componentOptions = componentOptions; 1200 } 1201 1202 /** 1203 * Builds a string from the underlying <code>Map</code> of component options 1204 * that will export that options as a JavaScript Map for use in js and 1205 * jQuery plugins 1206 * 1207 * @return String of widget options formatted as JS Map 1208 */ 1209 @Override 1210 public String getComponentOptionsJSString() { 1211 if (componentOptionsJSString != null) { 1212 return componentOptionsJSString; 1213 } 1214 1215 if (componentOptions == null) { 1216 componentOptions = new HashMap<String, String>(); 1217 } 1218 StringBuilder sb = new StringBuilder(); 1219 1220 sb.append("{"); 1221 1222 for (String optionKey : componentOptions.keySet()) { 1223 String optionValue = componentOptions.get(optionKey); 1224 1225 if (sb.length() > 1) { 1226 sb.append(","); 1227 } 1228 1229 sb.append(optionKey); 1230 sb.append(":"); 1231 1232 boolean isNumber = false; 1233 if (StringUtils.isNotBlank(optionValue) && (StringUtils.isNumeric(optionValue.trim().substring(0, 1)) 1234 || optionValue.trim().substring(0, 1).equals("-"))) { 1235 try { 1236 Double.parseDouble(optionValue.trim()); 1237 isNumber = true; 1238 } catch (NumberFormatException e) { 1239 isNumber = false; 1240 } 1241 } 1242 // If an option value starts with { or [, it would be a nested value 1243 // and it should not use quotes around it 1244 if (StringUtils.startsWith(optionValue, "{") || StringUtils.startsWith(optionValue, "[")) { 1245 sb.append(optionValue); 1246 } 1247 // need to be the base boolean value "false" is true in js - a non 1248 // empty string 1249 else if (optionValue.equalsIgnoreCase("false") || optionValue.equalsIgnoreCase("true")) { 1250 sb.append(optionValue); 1251 } 1252 // if it is a call back function, do not add the quotes 1253 else if (StringUtils.startsWith(optionValue, "function") && StringUtils.endsWith(optionValue, "}")) { 1254 sb.append(optionValue); 1255 } 1256 // for numerics 1257 else if (isNumber) { 1258 sb.append(optionValue); 1259 } else { 1260 sb.append("\"" + optionValue + "\""); 1261 } 1262 } 1263 1264 sb.append("}"); 1265 1266 return sb.toString(); 1267 } 1268 1269 @Override 1270 public void setComponentOptionsJSString(String componentOptionsJSString) { 1271 this.componentOptionsJSString = componentOptionsJSString; 1272 } 1273 1274 public String getEventCode() { 1275 String eventCode = ""; 1276 1277 return eventCode; 1278 } 1279 1280 /** 1281 * When set if the condition is satisfied, the component will be displayed. The component MUST BE a 1282 * container or field type. progressiveRender is defined in a limited Spring EL syntax. Only valid 1283 * form property names, and, or, logical comparison operators (non-arithmetic), and the matches 1284 * clause are allowed. String and regex values must use single quotes ('), booleans must be either true or false, 1285 * numbers must be a valid double, either negative or positive. 1286 * 1287 * <p> 1288 * DO NOT use progressiveRender and a conditional refresh statement on the same component 1289 * unless it is known that the component will always be visible in all cases when a conditional refresh happens 1290 * (ie conditional refresh has progressiveRender's condition anded with its own condition). 1291 * </p> 1292 * 1293 * <p> 1294 * <b>If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh option 1295 * with this property instead.</b> 1296 * </p> 1297 * 1298 * @return String progressiveRender expression 1299 */ 1300 public String getProgressiveRender() { 1301 return this.progressiveRender; 1302 } 1303 1304 /** 1305 * @param progressiveRender the progressiveRender to set 1306 */ 1307 public void setProgressiveRender(String progressiveRender) { 1308 this.progressiveRender = progressiveRender; 1309 } 1310 1311 /** 1312 * When set if the condition is satisfied, the component will be refreshed. 1313 * The component MUST BE a container or field type. conditionalRefresh is 1314 * defined in a limited Spring EL syntax. Only valid form property names, 1315 * and, or, logical comparison operators (non-arithmetic), and the matches 1316 * clause are allowed. String and regex values must use single quotes ('), 1317 * booleans must be either true or false, numbers must be a valid double 1318 * either negative or positive. <br> 1319 * DO NOT use progressiveRender and conditionalRefresh on the same component 1320 * unless it is known that the component will always be visible in all cases 1321 * when a conditionalRefresh happens (ie conditionalRefresh has 1322 * progressiveRender's condition anded with its own condition). <b>If a 1323 * component should be refreshed every time it is shown, use the 1324 * progressiveRenderAndRefresh option with this property instead.</b> 1325 * 1326 * @return the conditionalRefresh 1327 */ 1328 public String getConditionalRefresh() { 1329 return this.conditionalRefresh; 1330 } 1331 1332 /** 1333 * @param conditionalRefresh the conditionalRefresh to set 1334 */ 1335 public void setConditionalRefresh(String conditionalRefresh) { 1336 this.conditionalRefresh = conditionalRefresh; 1337 } 1338 1339 /** 1340 * Control names used to control progressive disclosure, set internally 1341 * cannot be set. 1342 * 1343 * @return the progressiveDisclosureControlNames 1344 */ 1345 public List<String> getProgressiveDisclosureControlNames() { 1346 return this.progressiveDisclosureControlNames; 1347 } 1348 1349 /** 1350 * The condition to show this component progressively converted to a js 1351 * expression, set internally cannot be set. 1352 * 1353 * @return the progressiveDisclosureConditionJs 1354 */ 1355 public String getProgressiveDisclosureConditionJs() { 1356 return this.progressiveDisclosureConditionJs; 1357 } 1358 1359 /** 1360 * The condition to refresh this component converted to a js expression, set 1361 * internally cannot be set. 1362 * 1363 * @return the conditionalRefreshConditionJs 1364 */ 1365 public String getConditionalRefreshConditionJs() { 1366 return this.conditionalRefreshConditionJs; 1367 } 1368 1369 /** 1370 * Control names used to control conditional refresh, set internally cannot 1371 * be set. 1372 * 1373 * @return the conditionalRefreshControlNames 1374 */ 1375 public List<String> getConditionalRefreshControlNames() { 1376 return this.conditionalRefreshControlNames; 1377 } 1378 1379 /** 1380 * When progressiveRenderViaAJAX is true, this component will be retrieved 1381 * from the server when it first satisfies its progressive render condition. 1382 * After the first retrieval, it is hidden/shown in the html by the js when 1383 * its progressive condition result changes. <b>By default, this is false, 1384 * so components with progressive render capabilities will always be already 1385 * within the client html and toggled to be hidden or visible.</b> 1386 * 1387 * @return the progressiveRenderViaAJAX 1388 */ 1389 public boolean isProgressiveRenderViaAJAX() { 1390 return this.progressiveRenderViaAJAX; 1391 } 1392 1393 /** 1394 * @param progressiveRenderViaAJAX the progressiveRenderViaAJAX to set 1395 */ 1396 public void setProgressiveRenderViaAJAX(boolean progressiveRenderViaAJAX) { 1397 this.progressiveRenderViaAJAX = progressiveRenderViaAJAX; 1398 } 1399 1400 /** 1401 * If true, when the progressiveRender condition is satisfied, the component 1402 * will always be retrieved from the server and shown(as opposed to being 1403 * stored on the client, but hidden, after the first retrieval as is the 1404 * case with the progressiveRenderViaAJAX option). <b>By default, this is 1405 * false, so components with progressive render capabilities will always be 1406 * already within the client html and toggled to be hidden or visible.</b> 1407 * 1408 * @return the progressiveRenderAndRefresh 1409 */ 1410 public boolean isProgressiveRenderAndRefresh() { 1411 return this.progressiveRenderAndRefresh; 1412 } 1413 1414 /** 1415 * @param progressiveRenderAndRefresh the progressiveRenderAndRefresh to set 1416 */ 1417 public void setProgressiveRenderAndRefresh(boolean progressiveRenderAndRefresh) { 1418 this.progressiveRenderAndRefresh = progressiveRenderAndRefresh; 1419 } 1420 1421 /** 1422 * Specifies a property by name that when it value changes will 1423 * automatically perform a refresh on this component. This can be a comma 1424 * separated list of multiple properties that require this component to be 1425 * refreshed when any of them change. <Br>DO NOT use with progressiveRender 1426 * unless it is know that progressiveRender condition will always be 1427 * satisfied before one of these fields can be changed. 1428 * 1429 * @return the refreshWhenChanged 1430 */ 1431 public String getRefreshWhenChanged() { 1432 return this.refreshWhenChanged; 1433 } 1434 1435 /** 1436 * @param refreshWhenChanged the refreshWhenChanged to set 1437 */ 1438 public void setRefreshWhenChanged(String refreshWhenChanged) { 1439 this.refreshWhenChanged = refreshWhenChanged; 1440 } 1441 1442 /** 1443 * Control names which will refresh this component when they are changed, added 1444 * internally 1445 * 1446 * @return the refreshWhenChangedControlNames 1447 */ 1448 public List<String> getRefreshWhenChangedControlNames() { 1449 return this.refreshWhenChangedControlNames; 1450 } 1451 1452 /** 1453 * @see Component#isRefreshedByAction() 1454 */ 1455 public boolean isRefreshedByAction() { 1456 return refreshedByAction; 1457 } 1458 1459 /** 1460 * @see Component#setRefreshedByAction(boolean) 1461 */ 1462 public void setRefreshedByAction(boolean refreshedByAction) { 1463 this.refreshedByAction = refreshedByAction; 1464 } 1465 1466 /** 1467 * @see Component#isResetDataOnRefresh() 1468 */ 1469 public boolean isResetDataOnRefresh() { 1470 return resetDataOnRefresh; 1471 } 1472 1473 /** 1474 * @see Component#setResetDataOnRefresh(boolean) 1475 */ 1476 public void setResetDataOnRefresh(boolean resetDataOnRefresh) { 1477 this.resetDataOnRefresh = resetDataOnRefresh; 1478 } 1479 1480 /** 1481 * @return the refresh 1482 */ 1483 public boolean isRefresh() { 1484 return this.refresh; 1485 } 1486 1487 /** 1488 * @param refresh the refresh to set 1489 */ 1490 public void setRefresh(boolean refresh) { 1491 this.refresh = refresh; 1492 } 1493 1494 /** 1495 * Name of a method on the controller that should be invoked as part of the component refresh and disclosure process 1496 * 1497 * <p> 1498 * During the component refresh or disclosure process it might be necessary to perform other operations, such as 1499 * preparing data or executing a business process. This allows the configuration of a method on the underlying 1500 * controller that should be called for the component refresh action. In this method, the necessary logic can be 1501 * performed and then the base component update method invoked to carry out the component refresh. 1502 * </p> 1503 * 1504 * <p> 1505 * Controller method to invoke must accept the form, binding result, request, and response arguments 1506 * </p> 1507 * 1508 * @return String valid controller method name 1509 */ 1510 public String getRefreshDiscloseMethodToCall() { 1511 return refreshDiscloseMethodToCall; 1512 } 1513 1514 /** 1515 * Setter for the controller method to call for a refresh or disclosure action on this component 1516 * 1517 * @param refreshDiscloseMethodToCall 1518 */ 1519 public void setRefreshDiscloseMethodToCall(String refreshDiscloseMethodToCall) { 1520 this.refreshDiscloseMethodToCall = refreshDiscloseMethodToCall; 1521 } 1522 1523 /** 1524 * @param skipInTabOrder flag 1525 */ 1526 public void setSkipInTabOrder(boolean skipInTabOrder) { 1527 this.skipInTabOrder = skipInTabOrder; 1528 } 1529 1530 /** 1531 * Flag indicating that this component and its nested components must be 1532 * skipped when keyboard tabbing. 1533 * 1534 * @return the skipInTabOrder flag 1535 */ 1536 public boolean isSkipInTabOrder() { 1537 return skipInTabOrder; 1538 } 1539 1540}