001 /**
002 * Copyright 2005-2012 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 */
016 package org.kuali.rice.krad.uif.component;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
020 import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBeanBase;
021 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
022 import org.kuali.rice.krad.datadictionary.validator.Validator;
023 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
024 import org.kuali.rice.krad.uif.CssConstants;
025 import org.kuali.rice.krad.uif.control.ControlBase;
026 import org.kuali.rice.krad.uif.modifier.ComponentModifier;
027 import org.kuali.rice.krad.uif.service.ExpressionEvaluatorService;
028 import org.kuali.rice.krad.uif.util.ExpressionUtils;
029 import org.kuali.rice.krad.uif.util.ScriptUtils;
030 import org.kuali.rice.krad.uif.view.View;
031 import org.kuali.rice.krad.uif.widget.Tooltip;
032 import org.kuali.rice.krad.util.ObjectUtils;
033
034 import java.util.ArrayList;
035 import java.util.HashMap;
036 import java.util.List;
037 import java.util.Map;
038
039 /**
040 * Base implementation of <code>Component</code> which other component
041 * implementations should extend
042 *
043 * <p>
044 * Provides base component properties such as id and template. Also provides
045 * default implementation for the <code>ScriptEventSupport</code> and
046 * <code>Ordered</code> interfaces. By default no script events except the
047 * onDocumentReady are supported.
048 * </p>
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052 public abstract class ComponentBase extends UifDictionaryBeanBase implements Component {
053 private static final long serialVersionUID = -4449335748129894350L;
054
055 private String id;
056 private String baseId;
057 private String template;
058 private String templateName;
059
060 private String title;
061
062 private boolean render;
063
064 @KeepExpression
065 private String progressiveRender;
066 private boolean progressiveRenderViaAJAX;
067 private boolean progressiveRenderAndRefresh;
068 private List<String> progressiveDisclosureControlNames;
069 private String progressiveDisclosureConditionJs;
070
071 @KeepExpression
072 private String conditionalRefresh;
073 private String conditionalRefreshConditionJs;
074 private List<String> conditionalRefreshControlNames;
075
076 private List<String> refreshWhenChangedPropertyNames;
077 private List<String> additionalComponentsToRefresh;
078 private String additionalComponentsToRefreshJs;
079 private boolean refreshedByAction;
080 private boolean disclosedByAction;
081
082 private int refreshTimer;
083
084 private boolean resetDataOnRefresh;
085 private String methodToCallOnRefresh;
086
087 private boolean hidden;
088 private boolean readOnly;
089 private Boolean required;
090
091 private String align;
092 private String valign;
093 private String width;
094
095 //optional table-backed layout options
096 private int colSpan;
097 private int rowSpan;
098 private List<String> cellCssClasses;
099
100 private String style;
101 private List<String> cssClasses;
102
103 private Tooltip toolTip;
104
105 private int order;
106
107 private boolean skipInTabOrder;
108
109 private String finalizeMethodToCall;
110 private List<Object> finalizeMethodAdditionalArguments;
111 private MethodInvokerConfig finalizeMethodInvoker;
112
113 private boolean selfRendered;
114 private String renderedHtmlOutput;
115
116 private boolean disableSessionPersistence;
117 private boolean forceSessionPersistence;
118
119 private ComponentSecurity componentSecurity;
120
121 private String onLoadScript;
122 private String onUnloadScript;
123 private String onCloseScript;
124 private String onBlurScript;
125 private String onChangeScript;
126 private String onClickScript;
127 private String onDblClickScript;
128 private String onFocusScript;
129 private String onSubmitScript;
130 private String onKeyPressScript;
131 private String onKeyUpScript;
132 private String onKeyDownScript;
133 private String onMouseOverScript;
134 private String onMouseOutScript;
135 private String onMouseUpScript;
136 private String onMouseDownScript;
137 private String onMouseMoveScript;
138 private String onDocumentReadyScript;
139
140 private List<ComponentModifier> componentModifiers;
141
142 private Map<String, String> templateOptions;
143 private String templateOptionsJSString;
144
145 @ReferenceCopy(newCollectionInstance = true)
146 private transient Map<String, Object> context;
147
148 private List<PropertyReplacer> propertyReplacers;
149
150 private Map<String, String> dataAttributes;
151
152 public ComponentBase() {
153 super();
154
155 order = 0;
156 colSpan = 1;
157 rowSpan = 1;
158
159 render = true;
160 selfRendered = false;
161 progressiveRenderViaAJAX = false;
162 progressiveRenderAndRefresh = false;
163 refreshedByAction = false;
164 resetDataOnRefresh = false;
165 disableSessionPersistence = false;
166 forceSessionPersistence = false;
167
168 componentSecurity = ObjectUtils.newInstance(getComponentSecurityClass());
169
170 refreshWhenChangedPropertyNames = new ArrayList<String>();
171 additionalComponentsToRefresh = new ArrayList<String>();
172 finalizeMethodAdditionalArguments = new ArrayList<Object>();
173 cssClasses = new ArrayList<String>();
174 componentModifiers = new ArrayList<ComponentModifier>();
175 templateOptions = new HashMap<String, String>();
176 context = new HashMap<String, Object>();
177 propertyReplacers = new ArrayList<PropertyReplacer>();
178 dataAttributes = new HashMap<String, String>();
179 }
180
181 /**
182 * The following updates are done here:
183 *
184 * <ul>
185 * <li></li>
186 * </ul>
187 *
188 * @see Component#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object)
189 */
190 public void performInitialization(View view, Object model) {
191
192 }
193
194 /**
195 * The following updates are done here:
196 *
197 * <ul>
198 * <li>Evaluate the progressive render condition (if set) and combine with the current render status to set the
199 * render status</li>
200 * </ul>
201 *
202 * @see Component#performApplyModel(org.kuali.rice.krad.uif.view.View, java.lang.Object,
203 * org.kuali.rice.krad.uif.component.Component)
204 */
205 public void performApplyModel(View view, Object model, Component parent) {
206 if (this.render && StringUtils.isNotEmpty(progressiveRender)) {
207 // progressive anded with render, will not render at least one of the two are false
208 ExpressionEvaluatorService expressionEvaluatorService =
209 KRADServiceLocatorWeb.getExpressionEvaluatorService();
210 String adjustedProgressiveRender = expressionEvaluatorService.replaceBindingPrefixes(view, this,
211 progressiveRender);
212 Boolean progRenderEval = (Boolean) expressionEvaluatorService.evaluateExpression(model, context,
213 adjustedProgressiveRender);
214
215 this.setRender(progRenderEval);
216 }
217 }
218
219 /**
220 * The following finalization is done here:
221 *
222 * <ul>
223 * <li>progressiveRender and conditionalRefresh variables are processed if set</li>
224 * <li>If any of the style properties were given, sets the style string on
225 * the style property</li>
226 * <li>Set the skipInTabOrder flag for nested components</li>
227 * </ul>
228 *
229 * @see Component#performFinalize(org.kuali.rice.krad.uif.view.View, java.lang.Object,
230 * org.kuali.rice.krad.uif.component.Component)
231 */
232 public void performFinalize(View view, Object model, Component parent) {
233 if (StringUtils.isNotEmpty(progressiveRender)) {
234 progressiveRender = KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view, this,
235 progressiveRender);
236 progressiveDisclosureControlNames = new ArrayList<String>();
237 progressiveDisclosureConditionJs = ExpressionUtils.parseExpression(progressiveRender,
238 progressiveDisclosureControlNames);
239 }
240
241 if (StringUtils.isNotEmpty(conditionalRefresh)) {
242 conditionalRefresh = KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view,
243 this, conditionalRefresh);
244 conditionalRefreshControlNames = new ArrayList<String>();
245 conditionalRefreshConditionJs = ExpressionUtils.parseExpression(conditionalRefresh,
246 conditionalRefreshControlNames);
247 }
248
249 List<String> adjustedRefreshPropertyNames = new ArrayList<String>();
250 for (String refreshPropertyName : refreshWhenChangedPropertyNames) {
251 adjustedRefreshPropertyNames.add(
252 KRADServiceLocatorWeb.getExpressionEvaluatorService().replaceBindingPrefixes(view, this,
253 refreshPropertyName));
254 }
255 refreshWhenChangedPropertyNames = adjustedRefreshPropertyNames;
256
257 // add the align, valign, and width settings to style
258 if (StringUtils.isNotBlank(getAlign()) && !StringUtils.contains(getStyle(), CssConstants.TEXT_ALIGN)) {
259 appendToStyle(CssConstants.TEXT_ALIGN + getAlign() + ";");
260 }
261
262 if (StringUtils.isNotBlank(getValign()) && !StringUtils.contains(getStyle(), CssConstants.VERTICAL_ALIGN)) {
263 appendToStyle(CssConstants.VERTICAL_ALIGN + getValign() + ";");
264 }
265
266 if (StringUtils.isNotBlank(getWidth()) && !StringUtils.contains(getStyle(), CssConstants.WIDTH)) {
267 appendToStyle(CssConstants.WIDTH + getWidth() + ";");
268 }
269
270 // Set the skipInTabOrder flag on all nested components
271 // Set the tabIndex on controls to -1 in order to be skipped on tabbing
272 for (Component component : getComponentsForLifecycle()) {
273 if (component != null && component instanceof ComponentBase && skipInTabOrder) {
274 ((ComponentBase) component).setSkipInTabOrder(skipInTabOrder);
275 if (component instanceof ControlBase) {
276 ((ControlBase) component).setTabIndex(-1);
277 }
278 }
279 }
280
281 // if this is not rendering and it is not rendering via an ajax call, but still has a progressive render
282 // condition we still want to render the component, but hide it (in ajax cases, template creates a placeholder)
283 boolean hide = false;
284 if (!this.render && !this.progressiveRenderViaAJAX && !this.progressiveRenderAndRefresh && StringUtils
285 .isNotBlank(progressiveRender)) {
286 hide = true;
287 } else if (this.isHidden()) {
288 hide = true;
289 }
290
291 if (hide) {
292 if (StringUtils.isNotBlank(this.getStyle())) {
293 if (this.getStyle().endsWith(";")) {
294 this.setStyle(this.getStyle() + " display: none;");
295 } else {
296 this.setStyle(this.getStyle() + "; display: none;");
297 }
298 } else {
299 this.setStyle("display: none;");
300 }
301 }
302 }
303
304 /**
305 * @see org.kuali.rice.krad.uif.component.Component#getComponentsForLifecycle()
306 */
307 public List<Component> getComponentsForLifecycle() {
308 List<Component> components = new ArrayList<Component>();
309
310 components.add(toolTip);
311
312 return components;
313 }
314
315 /**
316 * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes()
317 */
318 public List<Component> getComponentPrototypes() {
319 List<Component> components = new ArrayList<Component>();
320
321 for (ComponentModifier modifier : componentModifiers) {
322 components.addAll(modifier.getComponentPrototypes());
323 }
324
325 components.addAll(getPropertyReplacerComponents());
326
327 return components;
328 }
329
330 /**
331 * Returns list of components that are being held in property replacers configured for this component
332 *
333 * @return List<Component>
334 */
335 public List<Component> getPropertyReplacerComponents() {
336 List<Component> components = new ArrayList<Component>();
337 for (Object replacer : propertyReplacers) {
338 components.addAll(((PropertyReplacer) replacer).getNestedComponents());
339 }
340
341 return components;
342 }
343
344 /**
345 * @see org.kuali.rice.krad.uif.component.Component#getId()
346 */
347 @BeanTagAttribute(name = "id")
348 public String getId() {
349 return this.id;
350 }
351
352 /**
353 * @see org.kuali.rice.krad.uif.component.Component#setId(java.lang.String)
354 */
355 public void setId(String id) {
356 this.id = id;
357 }
358
359 /**
360 * @see org.kuali.rice.krad.uif.component.Component#getBaseId()
361 */
362 public String getBaseId() {
363 return this.baseId;
364 }
365
366 /**
367 * @see org.kuali.rice.krad.uif.component.Component#setBaseId(java.lang.String)
368 */
369 public void setBaseId(String baseId) {
370 this.baseId = baseId;
371 }
372
373 /**
374 * @see org.kuali.rice.krad.uif.component.Component#getTemplate()
375 */
376 @BeanTagAttribute(name = "template")
377 public String getTemplate() {
378 return this.template;
379 }
380
381 /**
382 * @see org.kuali.rice.krad.uif.component.Component#setTemplate(java.lang.String)
383 */
384 public void setTemplate(String template) {
385 this.template = template;
386 }
387
388 @BeanTagAttribute(name = "templateName")
389 public String getTemplateName() {
390 return templateName;
391 }
392
393 public void setTemplateName(String templateName) {
394 this.templateName = templateName;
395 }
396
397 /**
398 * @see org.kuali.rice.krad.uif.component.Component#getTitle()
399 */
400 @BeanTagAttribute(name = "title")
401 public String getTitle() {
402 return this.title;
403 }
404
405 /**
406 * @see org.kuali.rice.krad.uif.component.Component#setTitle(java.lang.String)
407 */
408 public void setTitle(String title) {
409 this.title = title;
410 }
411
412 /**
413 * @see org.kuali.rice.krad.uif.component.Component#isHidden()
414 */
415 @BeanTagAttribute(name = "hidden")
416 public boolean isHidden() {
417 return this.hidden;
418 }
419
420 /**
421 * @see org.kuali.rice.krad.uif.component.Component#setHidden(boolean)
422 */
423 public void setHidden(boolean hidden) {
424 this.hidden = hidden;
425 }
426
427 /**
428 * @see org.kuali.rice.krad.uif.component.Component#isReadOnly()
429 */
430 @BeanTagAttribute(name = "readOnly")
431 public boolean isReadOnly() {
432 return this.readOnly;
433 }
434
435 /**
436 * @see org.kuali.rice.krad.uif.component.Component#setReadOnly(boolean)
437 */
438 public void setReadOnly(boolean readOnly) {
439 this.readOnly = readOnly;
440 }
441
442 /**
443 * @see org.kuali.rice.krad.uif.component.Component#getRequired()
444 */
445 @BeanTagAttribute(name = "required")
446 public Boolean getRequired() {
447 return this.required;
448 }
449
450 /**
451 * @see org.kuali.rice.krad.uif.component.Component#setRequired(java.lang.Boolean)
452 */
453 public void setRequired(Boolean required) {
454 this.required = required;
455 }
456
457 /**
458 * @see org.kuali.rice.krad.uif.component.Component#isRender()
459 */
460 @BeanTagAttribute(name = "render")
461 public boolean isRender() {
462 return this.render;
463 }
464
465 /**
466 * @see org.kuali.rice.krad.uif.component.Component#setRender(boolean)
467 */
468 public void setRender(boolean render) {
469 this.render = render;
470 }
471
472 /**
473 * @see org.kuali.rice.krad.uif.component.Component#getColSpan()
474 */
475 @BeanTagAttribute(name = "ColSpan")
476 public int getColSpan() {
477 return this.colSpan;
478 }
479
480 /**
481 * @see org.kuali.rice.krad.uif.component.Component#setColSpan(int)
482 */
483 public void setColSpan(int colSpan) {
484 this.colSpan = colSpan;
485 }
486
487 /**
488 * @see org.kuali.rice.krad.uif.component.Component#getRowSpan()
489 */
490 @BeanTagAttribute(name = "rowSpan")
491 public int getRowSpan() {
492 return this.rowSpan;
493 }
494
495 /**
496 * @see org.kuali.rice.krad.uif.component.Component#setRowSpan(int)
497 */
498 public void setRowSpan(int rowSpan) {
499 this.rowSpan = rowSpan;
500 }
501
502 /**
503 * @see org.kuali.rice.krad.uif.component.Component#getCellCssClasses()
504 */
505 public List<String> getCellCssClasses() {
506 return cellCssClasses;
507 }
508
509 /**
510 * @see Component#setCellCssClasses(java.util.List)
511 */
512 public void setCellCssClasses(List<String> cellCssClasses) {
513 this.cellCssClasses = cellCssClasses;
514 }
515
516 /**
517 * @see Component#addCellCssClass(String)
518 */
519 public void addCellCssClass(String cssClass) {
520 if (this.cellCssClasses == null){
521 this.cellCssClasses = new ArrayList<String>();
522 }
523
524 if(cssClass != null){
525 this.cellCssClasses.add(cssClass);
526 }
527 }
528
529 /**
530 * Builds the HTML class attribute string by combining the cellStyleClasses list
531 * with a space delimiter
532 *
533 * @return String class attribute string
534 */
535 public String getCellStyleClassesAsString() {
536 if (cellCssClasses != null) {
537 return StringUtils.join(cellCssClasses, " ");
538 }
539
540 return "";
541 }
542
543 /**
544 * Horizontal alignment of the component within its container
545 * <p>
546 * All components belong to a <code>Container</code> and are placed using a
547 * <code>LayoutManager</code>. This property specifies how the component
548 * should be aligned horizontally within the container. During the finalize
549 * phase the CSS text-align style will be created for the align setting.
550 * </p>
551 *
552 * @return String horizontal align
553 * @see org.kuali.rice.krad.uif.CssConstants.TextAligns
554 */
555 @BeanTagAttribute(name = "align")
556 public String getAlign() {
557 return this.align;
558 }
559
560 /**
561 * Sets the components horizontal alignment
562 *
563 * @param align
564 */
565 public void setAlign(String align) {
566 this.align = align;
567 }
568
569 /**
570 * Vertical alignment of the component within its container
571 *
572 * <p>
573 * All components belong to a <code>Container</code> and are placed using a
574 * <code>LayoutManager</code>. This property specifies how the component
575 * should be aligned vertically within the container. During the finalize
576 * phase the CSS vertical-align style will be created for the valign
577 * setting.
578 * </p>
579 *
580 * @return String vertical align
581 * @see org.kuali.rice.krad.uif.CssConstants.VerticalAligns
582 */
583 @BeanTagAttribute(name = "valign")
584 public String getValign() {
585 return this.valign;
586 }
587
588 /**
589 * Setter for the component's vertical align
590 *
591 * @param valign
592 */
593 public void setValign(String valign) {
594 this.valign = valign;
595 }
596
597 /**
598 * Width the component should take up in the container
599 * <p>
600 * All components belong to a <code>Container</code> and are placed using a
601 * <code>LayoutManager</code>. This property specifies a width the component
602 * should take up in the Container. This is not applicable for all layout
603 * managers. During the finalize phase the CSS width style will be created
604 * for the width setting.
605 * </p>
606 * <p>
607 * e.g. '30%', '55px'
608 * </p>
609 *
610 * @return String width string
611 */
612 @BeanTagAttribute(name = "width")
613 public String getWidth() {
614 return this.width;
615 }
616
617 /**
618 * Setter for the components width
619 *
620 * @param width
621 */
622 public void setWidth(String width) {
623 this.width = width;
624 }
625
626 /**
627 * @see org.kuali.rice.krad.uif.component.Component#getStyle()
628 */
629 @BeanTagAttribute(name = "style")
630 public String getStyle() {
631 return this.style;
632 }
633
634 /**
635 * @see org.kuali.rice.krad.uif.component.Component#setStyle(java.lang.String)
636 */
637 public void setStyle(String style) {
638 this.style = style;
639 }
640
641 /**
642 * @see org.kuali.rice.krad.uif.component.Component#getCssClasses()
643 */
644 @BeanTagAttribute(name = "cssClasses", type = BeanTagAttribute.AttributeType.LISTVALUE)
645 public List<String> getCssClasses() {
646 return this.cssClasses;
647 }
648
649 /**
650 * @see org.kuali.rice.krad.uif.component.Component#setCssClasses(java.util.List)
651 */
652 public void setCssClasses(List<String> cssClasses) {
653 this.cssClasses = cssClasses;
654 }
655
656 /**
657 * Builds the HTML class attribute string by combining the styleClasses list
658 * with a space delimiter
659 *
660 * @return String class attribute string
661 */
662 public String getStyleClassesAsString() {
663 if (cssClasses != null) {
664 return StringUtils.join(cssClasses, " ");
665 }
666
667 return "";
668 }
669
670 /**
671 * @see org.kuali.rice.krad.uif.component.Component#addStyleClass(java.lang.String)
672 */
673 public void addStyleClass(String styleClass) {
674 if (!cssClasses.contains(styleClass)) {
675 cssClasses.add(styleClass);
676 }
677 }
678
679 /**
680 * @see org.kuali.rice.krad.uif.component.Component#appendToStyle(java.lang.String)
681 */
682 public void appendToStyle(String styleRules) {
683 if (style == null) {
684 style = "";
685 }
686 style = style + styleRules;
687 }
688
689 /**
690 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodToCall()
691 */
692 @BeanTagAttribute(name = "finalizeMethodToCall")
693 public String getFinalizeMethodToCall() {
694 return this.finalizeMethodToCall;
695 }
696
697 /**
698 * Setter for the finalize method
699 *
700 * @param finalizeMethodToCall
701 */
702 public void setFinalizeMethodToCall(String finalizeMethodToCall) {
703 this.finalizeMethodToCall = finalizeMethodToCall;
704 }
705
706 /**
707 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodAdditionalArguments()
708 */
709 @BeanTagAttribute(name = "finalizeMethodAdditionalArguments", type = BeanTagAttribute.AttributeType.LISTBEAN)
710 public List<Object> getFinalizeMethodAdditionalArguments() {
711 return finalizeMethodAdditionalArguments;
712 }
713
714 /**
715 * Setter for the finalize additional arguments list
716 *
717 * @param finalizeMethodAdditionalArguments
718 */
719 public void setFinalizeMethodAdditionalArguments(List<Object> finalizeMethodAdditionalArguments) {
720 this.finalizeMethodAdditionalArguments = finalizeMethodAdditionalArguments;
721 }
722
723 /**
724 * @see org.kuali.rice.krad.uif.component.Component#getFinalizeMethodInvoker()
725 */
726 @BeanTagAttribute(name = "finalizeMethodInvoker", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
727 public MethodInvokerConfig getFinalizeMethodInvoker() {
728 return this.finalizeMethodInvoker;
729 }
730
731 /**
732 * Setter for the method invoker instance
733 *
734 * @param finalizeMethodInvoker
735 */
736 public void setFinalizeMethodInvoker(MethodInvokerConfig finalizeMethodInvoker) {
737 this.finalizeMethodInvoker = finalizeMethodInvoker;
738 }
739
740 /**
741 * @see org.kuali.rice.krad.uif.component.Component#isSelfRendered()
742 */
743 @BeanTagAttribute(name = "selfRendered")
744 public boolean isSelfRendered() {
745 return this.selfRendered;
746 }
747
748 /**
749 * @see org.kuali.rice.krad.uif.component.Component#setSelfRendered(boolean)
750 */
751 public void setSelfRendered(boolean selfRendered) {
752 this.selfRendered = selfRendered;
753 }
754
755 /**
756 * @see org.kuali.rice.krad.uif.component.Component#getRenderedHtmlOutput()
757 */
758 @BeanTagAttribute(name = "renderedHtmlOutput")
759 public String getRenderedHtmlOutput() {
760 return this.renderedHtmlOutput;
761 }
762
763 /**
764 * @see org.kuali.rice.krad.uif.component.Component#setRenderedHtmlOutput(java.lang.String)
765 */
766 public void setRenderedHtmlOutput(String renderedHtmlOutput) {
767 this.renderedHtmlOutput = renderedHtmlOutput;
768 }
769
770 /**
771 * @see Component#isDisableSessionPersistence()
772 */
773 @BeanTagAttribute(name = "disableSessionPersistence")
774 public boolean isDisableSessionPersistence() {
775 return disableSessionPersistence;
776 }
777
778 /**
779 * @see Component#setDisableSessionPersistence(boolean)
780 */
781 public void setDisableSessionPersistence(boolean disableSessionPersistence) {
782 this.disableSessionPersistence = disableSessionPersistence;
783 }
784
785 /**
786 * @see Component#isForceSessionPersistence()
787 */
788 @BeanTagAttribute(name = "forceSessionPersistence")
789 public boolean isForceSessionPersistence() {
790 return forceSessionPersistence;
791 }
792
793 /**
794 * @see Component#setForceSessionPersistence(boolean)
795 */
796 public void setForceSessionPersistence(boolean forceSessionPersistence) {
797 this.forceSessionPersistence = forceSessionPersistence;
798 }
799
800 /**
801 * @see Component#getComponentSecurity()
802 */
803 @BeanTagAttribute(name = "componentSecurity", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
804 public ComponentSecurity getComponentSecurity() {
805 return componentSecurity;
806 }
807
808 /**
809 * @see Component#setComponentSecurity(org.kuali.rice.krad.uif.component.ComponentSecurity)
810 */
811 public void setComponentSecurity(ComponentSecurity componentSecurity) {
812 this.componentSecurity = componentSecurity;
813 }
814
815 /**
816 * Returns the security class that is associated with the component (used for initialization and validation)
817 *
818 * @return Class<? extends ComponentSecurity>
819 */
820 protected Class<? extends ComponentSecurity> getComponentSecurityClass() {
821 return ComponentSecurity.class;
822 }
823
824 /**
825 * @see org.kuali.rice.krad.uif.component.Component#getComponentModifiers()
826 */
827 @BeanTagAttribute(name = "componentModifiers", type = BeanTagAttribute.AttributeType.LISTBEAN)
828 public List<ComponentModifier> getComponentModifiers() {
829 return this.componentModifiers;
830 }
831
832 /**
833 * @see org.kuali.rice.krad.uif.component.Component#setComponentModifiers(java.util.List)
834 */
835 public void setComponentModifiers(List<ComponentModifier> componentModifiers) {
836 this.componentModifiers = componentModifiers;
837 }
838
839 /**
840 * @see org.kuali.rice.krad.uif.component.Component#getContext()
841 */
842 @BeanTagAttribute(name = "context", type = BeanTagAttribute.AttributeType.MAPBEAN)
843 public Map<String, Object> getContext() {
844 return this.context;
845 }
846
847 /**
848 * @see org.kuali.rice.krad.uif.component.Component#setContext(java.util.Map)
849 */
850 public void setContext(Map<String, Object> context) {
851 this.context = context;
852 }
853
854 /**
855 * @see org.kuali.rice.krad.uif.component.Component#pushObjectToContext(java.lang.String,
856 * java.lang.Object)
857 */
858 public void pushObjectToContext(String objectName, Object object) {
859 if (this.context == null) {
860 this.context = new HashMap<String, Object>();
861 }
862 pushToPropertyReplacerContext(objectName, object);
863 this.context.put(objectName, object);
864 }
865
866 /*
867 * Adds the object to the context of the components in the
868 * PropertyReplacer object. Only checks for a list, map or component.
869 */
870 protected void pushToPropertyReplacerContext(String objectName, Object object) {
871 for (Component replacerComponent : getPropertyReplacerComponents()) {
872 replacerComponent.pushObjectToContext(objectName, object);
873 }
874 }
875
876 /**
877 * @see org.kuali.rice.krad.uif.component.ComponentBase#pushAllToContext
878 */
879 public void pushAllToContext(Map<String, Object> objects) {
880 if (objects != null) {
881 for (Map.Entry<String, Object> objectEntry : objects.entrySet()) {
882 pushObjectToContext(objectEntry.getKey(), objectEntry.getValue());
883 }
884 }
885 }
886
887 /**
888 * @see org.kuali.rice.krad.uif.component.Component#getPropertyReplacers()
889 */
890 @BeanTagAttribute(name = "propertyReplacers", type = BeanTagAttribute.AttributeType.LISTBEAN)
891 public List<PropertyReplacer> getPropertyReplacers() {
892 return this.propertyReplacers;
893 }
894
895 /**
896 * @see org.kuali.rice.krad.uif.component.Component#setPropertyReplacers(java.util.List)
897 */
898 public void setPropertyReplacers(List<PropertyReplacer> propertyReplacers) {
899 this.propertyReplacers = propertyReplacers;
900 }
901
902 /**
903 * @see org.springframework.core.Ordered#getOrder()
904 */
905 @BeanTagAttribute(name = "order")
906 public int getOrder() {
907 return this.order;
908 }
909
910 /**
911 * Setter for the component's order
912 *
913 * @param order
914 */
915 public void setOrder(int order) {
916 this.order = order;
917 }
918
919 /**
920 * @see org.kuali.rice.krad.uif.component.Component#getToolTip()
921 */
922 @BeanTagAttribute(name = "toolTip", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
923 public Tooltip getToolTip() {
924 return toolTip;
925 }
926
927 /**
928 * @see org.kuali.rice.krad.uif.component.Component#setToolTip(Tooltip)
929 */
930 public void setToolTip(Tooltip toolTip) {
931 this.toolTip = toolTip;
932 }
933
934 /**
935 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnLoadScript()
936 */
937 @BeanTagAttribute(name = "onLoadScript")
938 public String getOnLoadScript() {
939 return onLoadScript;
940 }
941
942 /**
943 * Setter for the components onLoad script
944 *
945 * @param onLoadScript
946 */
947 public void setOnLoadScript(String onLoadScript) {
948 this.onLoadScript = onLoadScript;
949 }
950
951 /**
952 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDocumentReadyScript()
953 */
954 @BeanTagAttribute(name = "onDocumentReadyScript")
955 public String getOnDocumentReadyScript() {
956 String onDocScript = this.onDocumentReadyScript;
957 // if the refreshTimer property has been set then pre-append the call to refreshComponetUsingTimer to the onDocumentReadyScript.
958 // if the refreshTimer property is set then the methodToCallOnRefresh should also be set.
959 if (refreshTimer > 0) {
960 onDocScript = (null == onDocScript) ? "" : onDocScript;
961 onDocScript = "refreshComponentUsingTimer('"
962 + this.id
963 + "','"
964 + this.methodToCallOnRefresh
965 + "',"
966 + refreshTimer
967 + ");"
968 + onDocScript;
969 }
970 return onDocScript;
971 }
972
973 /**
974 * Setter for the components onDocumentReady script
975 *
976 * @param onDocumentReadyScript
977 */
978 public void setOnDocumentReadyScript(String onDocumentReadyScript) {
979 this.onDocumentReadyScript = onDocumentReadyScript;
980 }
981
982 /**
983 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnUnloadScript()
984 */
985 @BeanTagAttribute(name = "onUnloadScript")
986 public String getOnUnloadScript() {
987 return onUnloadScript;
988 }
989
990 /**
991 * Setter for the components onUnload script
992 *
993 * @param onUnloadScript
994 */
995 public void setOnUnloadScript(String onUnloadScript) {
996 this.onUnloadScript = onUnloadScript;
997 }
998
999 /**
1000 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnCloseScript()
1001 */
1002 @BeanTagAttribute(name = "onCloseScript")
1003 public String getOnCloseScript() {
1004 return onCloseScript;
1005 }
1006
1007 /**
1008 * Setter for the components onClose script
1009 *
1010 * @param onCloseScript
1011 */
1012 public void setOnCloseScript(String onCloseScript) {
1013 this.onCloseScript = onCloseScript;
1014 }
1015
1016 /**
1017 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnBlurScript()
1018 */
1019 @BeanTagAttribute(name = "onBlurScript")
1020 public String getOnBlurScript() {
1021 return onBlurScript;
1022 }
1023
1024 /**
1025 * Setter for the components onBlur script
1026 *
1027 * @param onBlurScript
1028 */
1029 public void setOnBlurScript(String onBlurScript) {
1030 this.onBlurScript = onBlurScript;
1031 }
1032
1033 /**
1034 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnChangeScript()
1035 */
1036 @BeanTagAttribute(name = "onChangeScript")
1037 public String getOnChangeScript() {
1038 return onChangeScript;
1039 }
1040
1041 /**
1042 * Setter for the components onChange script
1043 *
1044 * @param onChangeScript
1045 */
1046 public void setOnChangeScript(String onChangeScript) {
1047 this.onChangeScript = onChangeScript;
1048 }
1049
1050 /**
1051 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnClickScript()
1052 */
1053 @BeanTagAttribute(name = "onClickScript")
1054 public String getOnClickScript() {
1055 return onClickScript;
1056 }
1057
1058 /**
1059 * Setter for the components onClick script
1060 *
1061 * @param onClickScript
1062 */
1063 public void setOnClickScript(String onClickScript) {
1064 this.onClickScript = onClickScript;
1065 }
1066
1067 /**
1068 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnDblClickScript()
1069 */
1070 @BeanTagAttribute(name = "onDblClickScript")
1071 public String getOnDblClickScript() {
1072 return onDblClickScript;
1073 }
1074
1075 /**
1076 * Setter for the components onDblClick script
1077 *
1078 * @param onDblClickScript
1079 */
1080 public void setOnDblClickScript(String onDblClickScript) {
1081 this.onDblClickScript = onDblClickScript;
1082 }
1083
1084 /**
1085 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnFocusScript()
1086 */
1087 @BeanTagAttribute(name = "onFocusScript")
1088 public String getOnFocusScript() {
1089 return onFocusScript;
1090 }
1091
1092 /**
1093 * Setter for the components onFocus script
1094 *
1095 * @param onFocusScript
1096 */
1097 public void setOnFocusScript(String onFocusScript) {
1098 this.onFocusScript = onFocusScript;
1099 }
1100
1101 /**
1102 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnSubmitScript()
1103 */
1104 @BeanTagAttribute(name = "onSubmitScript")
1105 public String getOnSubmitScript() {
1106 return onSubmitScript;
1107 }
1108
1109 /**
1110 * Setter for the components onSubmit script
1111 *
1112 * @param onSubmitScript
1113 */
1114 public void setOnSubmitScript(String onSubmitScript) {
1115 this.onSubmitScript = onSubmitScript;
1116 }
1117
1118 /**
1119 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyPressScript()
1120 */
1121 @BeanTagAttribute(name = "onKeyPressScript")
1122 public String getOnKeyPressScript() {
1123 return onKeyPressScript;
1124 }
1125
1126 /**
1127 * Setter for the components onKeyPress script
1128 *
1129 * @param onKeyPressScript
1130 */
1131 public void setOnKeyPressScript(String onKeyPressScript) {
1132 this.onKeyPressScript = onKeyPressScript;
1133 }
1134
1135 /**
1136 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyUpScript()
1137 */
1138 @BeanTagAttribute(name = "onKeyUpScript")
1139 public String getOnKeyUpScript() {
1140 return onKeyUpScript;
1141 }
1142
1143 /**
1144 * Setter for the components onKeyUp script
1145 *
1146 * @param onKeyUpScript
1147 */
1148 public void setOnKeyUpScript(String onKeyUpScript) {
1149 this.onKeyUpScript = onKeyUpScript;
1150 }
1151
1152 /**
1153 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnKeyDownScript()
1154 */
1155 @BeanTagAttribute(name = "onKeyDownScript")
1156 public String getOnKeyDownScript() {
1157 return onKeyDownScript;
1158 }
1159
1160 /**
1161 * Setter for the components onKeyDown script
1162 *
1163 * @param onKeyDownScript
1164 */
1165 public void setOnKeyDownScript(String onKeyDownScript) {
1166 this.onKeyDownScript = onKeyDownScript;
1167 }
1168
1169 /**
1170 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOverScript()
1171 */
1172 @BeanTagAttribute(name = "onMouseOverScript")
1173 public String getOnMouseOverScript() {
1174 return onMouseOverScript;
1175 }
1176
1177 /**
1178 * Setter for the components onMouseOver script
1179 *
1180 * @param onMouseOverScript
1181 */
1182 public void setOnMouseOverScript(String onMouseOverScript) {
1183 this.onMouseOverScript = onMouseOverScript;
1184 }
1185
1186 /**
1187 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseOutScript()
1188 */
1189 @BeanTagAttribute(name = "onMouseOutScript")
1190 public String getOnMouseOutScript() {
1191 return onMouseOutScript;
1192 }
1193
1194 /**
1195 * Setter for the components onMouseOut script
1196 *
1197 * @param onMouseOutScript
1198 */
1199 public void setOnMouseOutScript(String onMouseOutScript) {
1200 this.onMouseOutScript = onMouseOutScript;
1201 }
1202
1203 /**
1204 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseUpScript()
1205 */
1206 @BeanTagAttribute(name = "onMouseUpScript")
1207 public String getOnMouseUpScript() {
1208 return onMouseUpScript;
1209 }
1210
1211 /**
1212 * Setter for the components onMouseUp script
1213 *
1214 * @param onMouseUpScript
1215 */
1216 public void setOnMouseUpScript(String onMouseUpScript) {
1217 this.onMouseUpScript = onMouseUpScript;
1218 }
1219
1220 /**
1221 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseDownScript()
1222 */
1223 @BeanTagAttribute(name = "onMouseDownScript")
1224 public String getOnMouseDownScript() {
1225 return onMouseDownScript;
1226 }
1227
1228 /**
1229 * Setter for the components onMouseDown script
1230 *
1231 * @param onMouseDownScript
1232 */
1233 public void setOnMouseDownScript(String onMouseDownScript) {
1234 this.onMouseDownScript = onMouseDownScript;
1235 }
1236
1237 /**
1238 * @see org.kuali.rice.krad.uif.component.ScriptEventSupport#getOnMouseMoveScript()
1239 */
1240 @BeanTagAttribute(name = "onMouseMoveScript")
1241 public String getOnMouseMoveScript() {
1242 return onMouseMoveScript;
1243 }
1244
1245 /**
1246 * Setter for the components onMouseMove script
1247 *
1248 * @param onMouseMoveScript
1249 */
1250 public void setOnMouseMoveScript(String onMouseMoveScript) {
1251 this.onMouseMoveScript = onMouseMoveScript;
1252 }
1253
1254 /**
1255 * @see org.kuali.rice.krad.uif.component.Component#getTemplateOptions()
1256 */
1257 @BeanTagAttribute(name = "templateOptions", type = BeanTagAttribute.AttributeType.MAPVALUE)
1258 public Map<String, String> getTemplateOptions() {
1259 if (templateOptions == null) {
1260 templateOptions = new HashMap<String, String>();
1261 }
1262 return this.templateOptions;
1263 }
1264
1265 /**
1266 * @see Component#setTemplateOptions(java.util.Map)
1267 */
1268 public void setTemplateOptions(Map<String, String> templateOptions) {
1269 this.templateOptions = templateOptions;
1270 }
1271
1272 /**
1273 * Builds a string from the underlying <code>Map</code> of template options
1274 * that will export that options as a JavaScript Map for use in js and
1275 * jQuery plugins
1276 *
1277 * @return String of widget options formatted as JS Map
1278 */
1279 @Override
1280 @BeanTagAttribute(name = "templateOptionsJSString")
1281 public String getTemplateOptionsJSString() {
1282 if (templateOptionsJSString != null) {
1283 return templateOptionsJSString;
1284 }
1285
1286 if (templateOptions == null) {
1287 templateOptions = new HashMap<String, String>();
1288 }
1289 StringBuilder sb = new StringBuilder();
1290
1291 sb.append("{");
1292
1293 for (String optionKey : templateOptions.keySet()) {
1294 String optionValue = templateOptions.get(optionKey);
1295
1296 if (sb.length() > 1) {
1297 sb.append(",");
1298 }
1299
1300 sb.append(optionKey);
1301 sb.append(":");
1302
1303 sb.append(ScriptUtils.convertToJsValue(optionValue));
1304 }
1305
1306 sb.append("}");
1307
1308 return sb.toString();
1309 }
1310
1311 @Override
1312 public void setTemplateOptionsJSString(String templateOptionsJSString) {
1313 this.templateOptionsJSString = templateOptionsJSString;
1314 }
1315
1316 /**
1317 * When set if the condition is satisfied, the component will be displayed. The component MUST BE a
1318 * container or field type. progressiveRender is defined in a limited Spring EL syntax. Only valid
1319 * form property names, and, or, logical comparison operators (non-arithmetic), and the matches
1320 * clause are allowed. String and regex values must use single quotes ('), booleans must be either true or false,
1321 * numbers must be a valid double, either negative or positive.
1322 *
1323 * <p>
1324 * DO NOT use progressiveRender and a conditional refresh statement on the same component
1325 * unless it is known that the component will always be visible in all cases when a conditional refresh happens
1326 * (ie conditional refresh has progressiveRender's condition anded with its own condition).
1327 * </p>
1328 *
1329 * <p>
1330 * <b>If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh option
1331 * with this property instead.</b>
1332 * </p>
1333 *
1334 * @return String progressiveRender expression
1335 */
1336 @BeanTagAttribute(name = "progressiveRender")
1337 public String getProgressiveRender() {
1338 return this.progressiveRender;
1339 }
1340
1341 /**
1342 * @param progressiveRender the progressiveRender to set
1343 */
1344 public void setProgressiveRender(String progressiveRender) {
1345 this.progressiveRender = progressiveRender;
1346 }
1347
1348 /**
1349 * When set if the condition is satisfied, the component will be refreshed.
1350 *
1351 * <p>The component MUST BE a container or field type. conditionalRefresh is
1352 * defined in a limited Spring EL syntax. Only valid form property names,
1353 * and, or, logical comparison operators (non-arithmetic), and the matches
1354 * clause are allowed. String and regex values must use single quotes ('),
1355 * booleans must be either true or false, numbers must be a valid double
1356 * either negative or positive.
1357 *
1358 * <p>DO NOT use progressiveRender and conditionalRefresh on the same component
1359 * unless it is known that the component will always be visible in all cases
1360 * when a conditionalRefresh happens (ie conditionalRefresh has
1361 * progressiveRender's condition anded with its own condition). <b>If a
1362 * component should be refreshed every time it is shown, use the
1363 * progressiveRenderAndRefresh option with this property instead.</b></p>
1364 *
1365 * @return the conditionalRefresh
1366 */
1367 @BeanTagAttribute(name = "conditionalRefresh")
1368 public String getConditionalRefresh() {
1369 return this.conditionalRefresh;
1370 }
1371
1372 /**
1373 * Set the conditional refresh condition
1374 *
1375 * @param conditionalRefresh the conditionalRefresh to set
1376 */
1377 public void setConditionalRefresh(String conditionalRefresh) {
1378 this.conditionalRefresh = conditionalRefresh;
1379 }
1380
1381 /**
1382 * Control names used to control progressive disclosure, set internally
1383 * cannot be set.
1384 *
1385 * @return the progressiveDisclosureControlNames
1386 */
1387 public List<String> getProgressiveDisclosureControlNames() {
1388 return this.progressiveDisclosureControlNames;
1389 }
1390
1391 /**
1392 * The condition to show this component progressively converted to a js
1393 * expression, set internally cannot be set.
1394 *
1395 * @return the progressiveDisclosureConditionJs
1396 */
1397 public String getProgressiveDisclosureConditionJs() {
1398 return this.progressiveDisclosureConditionJs;
1399 }
1400
1401 /**
1402 * The condition to refresh this component converted to a js expression, set
1403 * internally cannot be set.
1404 *
1405 * @return the conditionalRefreshConditionJs
1406 */
1407 public String getConditionalRefreshConditionJs() {
1408 return this.conditionalRefreshConditionJs;
1409 }
1410
1411 /**
1412 * Control names used to control conditional refresh, set internally cannot
1413 * be set.
1414 *
1415 * @return the conditionalRefreshControlNames
1416 */
1417 public List<String> getConditionalRefreshControlNames() {
1418 return this.conditionalRefreshControlNames;
1419 }
1420
1421 /**
1422 * When progressiveRenderViaAJAX is true, this component will be retrieved
1423 * from the server when it first satisfies its progressive render condition.
1424 *
1425 * <p>After the first retrieval, it is hidden/shown in the html by the js when
1426 * its progressive condition result changes. <b>By default, this is false,
1427 * so components with progressive render capabilities will always be already
1428 * within the client html and toggled to be hidden or visible.</b></p>
1429 *
1430 * @return the progressiveRenderViaAJAX
1431 */
1432 @BeanTagAttribute(name = "progressiveRenderViaAJAX")
1433 public boolean isProgressiveRenderViaAJAX() {
1434 return this.progressiveRenderViaAJAX;
1435 }
1436
1437 /**
1438 * @param progressiveRenderViaAJAX the progressiveRenderViaAJAX to set
1439 */
1440 public void setProgressiveRenderViaAJAX(boolean progressiveRenderViaAJAX) {
1441 this.progressiveRenderViaAJAX = progressiveRenderViaAJAX;
1442 }
1443
1444 /**
1445 * If true, when the progressiveRender condition is satisfied, the component
1446 * will always be retrieved from the server and shown(as opposed to being
1447 * stored on the client, but hidden, after the first retrieval as is the
1448 * case with the progressiveRenderViaAJAX option).
1449 *
1450 * <p><b>By default, this is
1451 * false, so components with progressive render capabilities will always be
1452 * already within the client html and toggled to be hidden or visible.</b></p>
1453 *
1454 * @return the progressiveRenderAndRefresh
1455 */
1456 @BeanTagAttribute(name = "progressiveRenderAndRefresh")
1457 public boolean isProgressiveRenderAndRefresh() {
1458 return this.progressiveRenderAndRefresh;
1459 }
1460
1461 /**
1462 * Set the progressive render and refresh option.
1463 *
1464 * @param progressiveRenderAndRefresh the progressiveRenderAndRefresh to set
1465 */
1466 public void setProgressiveRenderAndRefresh(boolean progressiveRenderAndRefresh) {
1467 this.progressiveRenderAndRefresh = progressiveRenderAndRefresh;
1468 }
1469
1470 /**
1471 * @see Component#getRefreshWhenChangedPropertyNames()
1472 */
1473 @BeanTagAttribute(name = "refreshWhenChangedPropertyNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
1474 public List<String> getRefreshWhenChangedPropertyNames() {
1475 return this.refreshWhenChangedPropertyNames;
1476 }
1477
1478 /**
1479 * @see Component#setRefreshWhenChangedPropertyNames(java.util.List<java.lang.String>)
1480 */
1481 public void setRefreshWhenChangedPropertyNames(List<String> refreshWhenChangedPropertyNames) {
1482 this.refreshWhenChangedPropertyNames = refreshWhenChangedPropertyNames;
1483 }
1484
1485 /**
1486 * @see Component#getAdditionalComponentsToRefresh()
1487 */
1488 @BeanTagAttribute(name = "additionalComponentsToRefresh", type = BeanTagAttribute.AttributeType.LISTVALUE)
1489 public List<String> getAdditionalComponentsToRefresh() {
1490 return additionalComponentsToRefresh;
1491 }
1492
1493 /**
1494 * @see Component#setAdditionalComponentsToRefresh(java.util.List<java.lang.String>)
1495 */
1496 public void setAdditionalComponentsToRefresh(List<String> additionalComponentsToRefresh) {
1497 this.additionalComponentsToRefresh = additionalComponentsToRefresh;
1498 }
1499
1500 /**
1501 * @see Component#isRefreshedByAction()
1502 */
1503 public boolean isRefreshedByAction() {
1504 return refreshedByAction;
1505 }
1506
1507 /**
1508 * @see Component#setRefreshedByAction(boolean)
1509 */
1510 public void setRefreshedByAction(boolean refreshedByAction) {
1511 this.refreshedByAction = refreshedByAction;
1512 }
1513
1514 /**
1515 * @see org.kuali.rice.krad.uif.component.Component#isDisclosedByAction()
1516 */
1517 public boolean isDisclosedByAction() {
1518 return disclosedByAction;
1519 }
1520
1521 /**
1522 * @see Component#setDisclosedByAction(boolean)
1523 */
1524 public void setDisclosedByAction(boolean disclosedByAction) {
1525 this.disclosedByAction = disclosedByAction;
1526 }
1527
1528 /**
1529 * Time in seconds that the component will be automatically refreshed
1530 *
1531 * <p>
1532 * This will invoke the refresh process just like the conditionalRefresh and refreshWhenChangedPropertyNames.
1533 * When using this property methodToCallOnRefresh and id should also be specified
1534 * </p>
1535 *
1536 * @return refreshTimer
1537 */
1538 @BeanTagAttribute(name = "refreshTimer")
1539 public int getRefreshTimer() {
1540 return refreshTimer;
1541 }
1542
1543 /**
1544 * Setter for refreshTimer
1545 *
1546 * @param refreshTimer
1547 */
1548 public void setRefreshTimer(int refreshTimer) {
1549 this.refreshTimer = refreshTimer;
1550 }
1551
1552 /**
1553 * @see Component#isResetDataOnRefresh()
1554 */
1555 @BeanTagAttribute(name = "resetDataOnRefresh")
1556 public boolean isResetDataOnRefresh() {
1557 return resetDataOnRefresh;
1558 }
1559
1560 /**
1561 * @see Component#setResetDataOnRefresh(boolean)
1562 */
1563 public void setResetDataOnRefresh(boolean resetDataOnRefresh) {
1564 this.resetDataOnRefresh = resetDataOnRefresh;
1565 }
1566
1567 /**
1568 * Name of a method on the controller that should be invoked as part of the component refresh and disclosure
1569 * process
1570 *
1571 * <p>
1572 * During the component refresh or disclosure process it might be necessary to perform other operations, such as
1573 * preparing data or executing a business process. This allows the configuration of a method on the underlying
1574 * controller that should be called for the component refresh action. In this method, the necessary logic can be
1575 * performed and then the base component update method invoked to carry out the component refresh.
1576 * </p>
1577 *
1578 * <p>
1579 * Controller method to invoke must accept the form, binding result, request, and response arguments
1580 * </p>
1581 *
1582 * @return String valid controller method name
1583 */
1584 @BeanTagAttribute(name = "methodToCallOnRefresh")
1585 public String getMethodToCallOnRefresh() {
1586 return methodToCallOnRefresh;
1587 }
1588
1589 /**
1590 * Setter for the controller method to call for a refresh or disclosure action on this component
1591 *
1592 * @param methodToCallOnRefresh
1593 */
1594 public void setMethodToCallOnRefresh(String methodToCallOnRefresh) {
1595 this.methodToCallOnRefresh = methodToCallOnRefresh;
1596 }
1597
1598 /**
1599 * @param skipInTabOrder flag
1600 */
1601 public void setSkipInTabOrder(boolean skipInTabOrder) {
1602 this.skipInTabOrder = skipInTabOrder;
1603 }
1604
1605 /**
1606 * Flag indicating that this component and its nested components must be
1607 * skipped when keyboard tabbing.
1608 *
1609 * @return the skipInTabOrder flag
1610 */
1611 @BeanTagAttribute(name = "skipInTabOrder")
1612 public boolean isSkipInTabOrder() {
1613 return skipInTabOrder;
1614 }
1615
1616 /**
1617 * Get the dataAttributes setup for this component - to be written to the html/jQuery data
1618 *
1619 * <p>The attributes that are complex objects (contain {}) they will be written through script.
1620 * The attritubes that are simple (contain no objects) will be written directly to the html of the
1621 * component using standard data-.
1622 * Either way they can be access through .data() call in jQuery</p>
1623 *
1624 * @return map of dataAttributes
1625 */
1626 @BeanTagAttribute(name = "dataAttributes", type = BeanTagAttribute.AttributeType.MAPVALUE)
1627 public Map<String, String> getDataAttributes() {
1628 return dataAttributes;
1629 }
1630
1631 /**
1632 * DataAttributes that will be written to the html and/or through script to be consumed by jQuery.
1633 *
1634 * @param dataAttributes the data attributes to set for this component
1635 */
1636 public void setDataAttributes(Map<String, String> dataAttributes) {
1637 this.dataAttributes = dataAttributes;
1638 }
1639
1640 /**
1641 * Add a data attribute to the dataAttributes map - to be written to the html/jQuery data.
1642 *
1643 * @param key key of the data attribute
1644 * @param value value of the data attribute
1645 */
1646 public void addDataAttribute(String key, String value) {
1647 dataAttributes.put(key, value);
1648 }
1649
1650 /**
1651 * Add a data attribute to the dataAttributes map if the given value is non null
1652 * or the empty string
1653 *
1654 * @param key - key for the data attribute entry
1655 * @param value - value for the data attribute
1656 */
1657 public void addDataAttributeIfNonEmpty(String key, String value) {
1658 if (StringUtils.isNotBlank(value)) {
1659 addDataAttribute(key, value);
1660 }
1661 }
1662
1663 /**
1664 * Returns js that will add data to this component by the element which matches its id.
1665 * This will return script for only the complex data elements (containing {});
1666 *
1667 * @return jQuery data script for adding complex data attributes
1668 */
1669 public String getComplexDataAttributesJs() {
1670 String js = "";
1671 if (getDataAttributes() == null) {
1672 return js;
1673 } else {
1674 for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1675 if (data != null && data.getValue() != null &&
1676 data.getValue().trim().startsWith("{") && data.getValue().trim().endsWith("}")) {
1677 js = js + "jQuery('#" + this.getId() + "').data('" + data.getKey() + "', " + data.getValue() + ");";
1678 }
1679 }
1680 return js;
1681 }
1682 }
1683
1684 /**
1685 * Returns a string that can be put into a the tag of a component to add data attributes inline.
1686 * This does not include the complex attributes which contain {}
1687 *
1688 * @return html string for data attributes for the simple attributes
1689 */
1690 public String getSimpleDataAttributes() {
1691 String attributes = "";
1692 if (getDataAttributes() == null) {
1693 return attributes;
1694 } else {
1695 for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1696 if (data != null && data.getValue() != null && !data.getValue().trim().startsWith("{")) {
1697 attributes = attributes + " " + "data-" + data.getKey() + "=\"" + data.getValue() + "\"";
1698 }
1699 }
1700 return attributes;
1701 }
1702 }
1703
1704 /**
1705 * @see org.kuali.rice.krad.uif.component.Component#getAllDataAttributesJs()
1706 */
1707 @Override
1708 public String getAllDataAttributesJs() {
1709 String js = "";
1710 if (getDataAttributes() == null) {
1711 return js;
1712 } else {
1713 for (Map.Entry<String, String> data : getDataAttributes().entrySet()) {
1714 js = js + "jQuery('#" + this.getId() + "').data('" + data.getKey() + "', " + ScriptUtils
1715 .convertToJsValue(data.getValue()) + ");";
1716 }
1717 return js;
1718 }
1719 }
1720
1721 /**
1722 * @see org.kuali.rice.krad.uif.component.Component#getAdditionalComponentsToRefreshJs
1723 */
1724 public String getAdditionalComponentsToRefreshJs() {
1725 if (!(this.getAdditionalComponentsToRefresh().isEmpty())) {
1726 additionalComponentsToRefreshJs = ScriptUtils.convertStringListToJsArray(
1727 this.getAdditionalComponentsToRefresh());
1728 }
1729 return additionalComponentsToRefreshJs;
1730 }
1731
1732 /**
1733 * @see org.kuali.rice.krad.uif.component.Component#completeValidation
1734 */
1735 public void completeValidation(ValidationTrace tracer) {
1736 tracer.addBean(this);
1737
1738 // Check for invalid characters in the components id
1739 if (getId() != null) {
1740 if (getId().contains("'")
1741 || getId().contains("\"")
1742 || getId().contains("[]")
1743 || getId().contains(".")
1744 || getId().contains("#")) {
1745 String currentValues[] = {"id = " + getId()};
1746 tracer.createError("Id contains invalid characters", currentValues);
1747 }
1748 }
1749
1750 if (tracer.getValidationStage() == ValidationTrace.BUILD) {
1751 // Check for a render presence if the component is set to render
1752 if ((isProgressiveRenderViaAJAX() || isProgressiveRenderAndRefresh()) && (getProgressiveRender() == null)) {
1753 String currentValues[] = {"progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
1754 "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
1755 "progressiveRender = " + getProgressiveRender()};
1756 tracer.createError(
1757 "ProgressiveRender must be set if progressiveRenderViaAJAX or progressiveRenderAndRefresh are true",
1758 currentValues);
1759 }
1760 }
1761
1762 // Check for rendered html if the component is set to self render
1763 if (isSelfRendered() && getRenderedHtmlOutput() == null) {
1764 String currentValues[] =
1765 {"selfRendered = " + isSelfRendered(), "renderedHtmlOutput = " + getRenderedHtmlOutput()};
1766 tracer.createError("RenderedHtmlOutput must be set if selfRendered is true", currentValues);
1767 }
1768
1769 // Check to prevent over writing of session persistence status
1770 if (isDisableSessionPersistence() && isForceSessionPersistence()) {
1771 String currentValues[] = {"disableSessionPersistence = " + isDisableSessionPersistence(),
1772 "forceSessionPersistence = " + isForceSessionPersistence()};
1773 tracer.createWarning("DisableSessionPersistence and forceSessionPersistence cannot be both true",
1774 currentValues);
1775 }
1776
1777 // Check for un-executable data resets when no refresh option is set
1778 if (getMethodToCallOnRefresh() != null || isResetDataOnRefresh()) {
1779 if (!isProgressiveRenderAndRefresh()
1780 && !isRefreshedByAction()
1781 && !isProgressiveRenderViaAJAX()
1782 && !StringUtils.isNotEmpty(conditionalRefresh)
1783 && !(refreshTimer > 0)) {
1784 String currentValues[] = {"methodToCallONRefresh = " + getMethodToCallOnRefresh(),
1785 "resetDataONRefresh = " + isResetDataOnRefresh(),
1786 "progressiveRenderAndRefresh = " + isProgressiveRenderAndRefresh(),
1787 "refreshedByAction = " + isRefreshedByAction(),
1788 "progressiveRenderViaAJAX = " + isProgressiveRenderViaAJAX(),
1789 "conditionalRefresh = " + getConditionalRefresh(), "refreshTimer = " + getRefreshTimer()};
1790 tracer.createWarning(
1791 "MethodToCallONRefresh and resetDataONRefresh should only be set when a trigger event is set",
1792 currentValues);
1793 }
1794 }
1795
1796 // Check to prevent complications with rendering and refreshing a component that is not always shown
1797 if (StringUtils.isNotEmpty(getProgressiveRender()) && StringUtils.isNotEmpty(conditionalRefresh)) {
1798 String currentValues[] = {"progressiveRender = " + getProgressiveRender(),
1799 "conditionalRefresh = " + getConditionalRefresh()};
1800 tracer.createWarning("DO NOT use progressiveRender and conditionalRefresh on the same component unless "
1801 + "it is known that the component will always be visible in all cases when a conditionalRefresh "
1802 + "happens (ie conditionalRefresh has progressiveRender's condition and with its own condition). "
1803 + "If a component should be refreshed every time it is shown, use the progressiveRenderAndRefresh "
1804 + "option with this property instead.", currentValues);
1805 }
1806
1807 // Check for valid Spring EL format for progressiveRender
1808 if (!Validator.validateSpringEL(getProgressiveRender())) {
1809 String currentValues[] = {"progressiveRender =" + getProgressiveRender()};
1810 tracer.createError("ProgressiveRender must follow the Spring EL @{} format", currentValues);
1811 }
1812
1813 // Check for valid Spring EL format for conditionalRefresh
1814 if (!Validator.validateSpringEL(getConditionalRefresh())) {
1815 String currentValues[] = {"conditionalRefresh =" + getConditionalRefresh()};
1816 tracer.createError("conditionalRefresh must follow the Spring EL @{} format", currentValues);
1817 ;
1818 }
1819 }
1820
1821 }