001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.behavior; 018 019import java.io.Serializable; 020 021import org.apache.wicket.AttributeModifier; 022import org.apache.wicket.model.IModel; 023import org.apache.wicket.util.string.Strings; 024 025/** 026 * AttributeModifier that appends the given value, rather than replace it. This is especially useful 027 * for adding CSS classes to markup elements, or adding JavaScript snippets to existing element 028 * handlers. 029 * 030 * <pre> 031 * <a href="#" wicket:id="foo" class="link" onmouseover="doSomething()"> 032 * </pre> 033 * 034 * can be modified with these AttributeAppenders: 035 * 036 * <pre> 037 * link.add(new AttributeAppender("class", Model.of("hot"))); 038 * link.add(new AttributeAppender("onmouseover", Model.of("foo();return false;")).setSeparator(";")); 039 * </pre> 040 * 041 * this will result in the following markup: 042 * 043 * <pre> 044 * <a href="#" wicket:id="foo" class="link hot" onmouseover="doSomething();foo();return false;"> 045 * </pre> 046 * 047 * @see AttributeModifier#append(String, IModel) 048 * @see AttributeModifier#append(String, Serializable) 049 * @see AttributeModifier#prepend(String, IModel) 050 * @see AttributeModifier#prepend(String, Serializable) 051 * 052 * @author Martijn Dashorst 053 */ 054public class AttributeAppender extends AttributeModifier 055{ 056 private static final long serialVersionUID = 1L; 057 058 /** 059 * Separator between the current value and the concatenated value, typically a space ' ' or 060 * colon ';'. 061 */ 062 private String separator; 063 064 /** 065 * Creates an attribute modifier that concatenates the {@code replaceModel} to the attribute's 066 * current value, optionally separated by the {@link #getSeparator() separator}. 067 * 068 * @param attribute 069 * @param replaceModel 070 */ 071 public AttributeAppender(String attribute, IModel<?> replaceModel) 072 { 073 super(attribute, replaceModel); 074 } 075 076 /** 077 * Creates an attribute modifier that appends the {@code value} to the attribute's current 078 * value, optionally separated by the {@link #getSeparator() separator}. 079 * 080 * @param attribute 081 * @param value 082 */ 083 public AttributeAppender(String attribute, Serializable value) 084 { 085 super(attribute, value); 086 } 087 088 /** 089 * Creates an AttributeModifier that appends the value to the current value of the 090 * attribute, and will add the attribute when it is not there already. 091 * 092 * @param attribute 093 * the attribute to append the appendModels value to 094 * @param value 095 * the value to append 096 * @param separator 097 * the separator string, comes between the original value and the append value 098 */ 099 public AttributeAppender(String attribute, Serializable value, String separator) 100 { 101 super(attribute, value); 102 setSeparator(separator); 103 } 104 105 /** 106 * Creates an AttributeModifier that appends the appendModel's value to the current value of the 107 * attribute, and will add the attribute when it is not there already. 108 * 109 * @param attribute 110 * the attribute to append the appendModels value to 111 * @param appendModel 112 * the model supplying the value to append 113 * @param separator 114 * the separator string, comes between the original value and the append value 115 */ 116 public AttributeAppender(String attribute, IModel<?> appendModel, String separator) 117 { 118 super(attribute, appendModel); 119 setSeparator(separator); 120 } 121 122 /** 123 * Gets the separator used by attribute appenders and prependers. 124 * 125 * @return the separator used by attribute appenders and prependers. 126 */ 127 public String getSeparator() 128 { 129 return separator; 130 } 131 132 /** 133 * Sets the separator used by attribute appenders and prependers. 134 * 135 * @param separator 136 * a space, semicolon or other character used to separate the current value and the 137 * appended/prepended value. 138 * @return this 139 */ 140 public AttributeAppender setSeparator(String separator) 141 { 142 this.separator = separator; 143 return this; 144 } 145 146 @Override 147 protected Serializable newValue(String currentValue, String appendValue) 148 { 149 // Short circuit when one of the values is empty: return the other value. 150 if (Strings.isEmpty(currentValue)) 151 { 152 return appendValue; 153 } 154 else if (Strings.isEmpty(appendValue)) 155 { 156 return currentValue; 157 } 158 StringBuilder sb = new StringBuilder(currentValue); 159 sb.append((getSeparator() == null ? "" : getSeparator())); 160 sb.append(appendValue); 161 return sb.toString(); 162 } 163 164 @Override 165 public String toString() 166 { 167 String attributeModifier = super.toString(); 168 attributeModifier = attributeModifier.substring(0, attributeModifier.length() - 2) + 169 ", separator=" + separator + "]"; 170 return attributeModifier; 171 } 172}