001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 package org.apache.tapestry.dojo.html; 015 016 import org.apache.hivemind.ApplicationRuntimeException; 017 import org.apache.tapestry.*; 018 import org.apache.tapestry.dojo.AbstractWidget; 019 import org.apache.tapestry.engine.DirectServiceParameter; 020 import org.apache.tapestry.engine.IEngineService; 021 import org.apache.tapestry.json.JSONObject; 022 import org.apache.tapestry.link.DirectLink; 023 import org.apache.tapestry.listener.ListenerInvoker; 024 025 import java.util.Collections; 026 import java.util.HashMap; 027 import java.util.List; 028 import java.util.Map; 029 030 031 /** 032 * Wraps a dojo InlineEditBox widget. 033 * 034 * <p> 035 * Manages a single string value that when hovered over can be edited "inline" in the document 036 * wherever it is referenced. Supports various modes of operation (ie disable/enabled), as well as 037 * textarea or single line style edits. 038 * </p> 039 * 040 * 041 * <p> 042 * Some of the commonly used widget functions to listen to are:<br/> 043 * <ul> 044 * <li><b>onSave - </b>When the save button is clicked. Default function listened to when updating 045 * server side managed value. 046 * </li> 047 * <li><b>onUndo - </b>When cancel button is clicked.</li> 048 * <li><b>onMouseOver - </b>Mouse moved over editable region.</li> 049 * <li><b>onMouseOut - </b>Mouse moved away from editable region.</li> 050 * </ul> 051 * </p> 052 * 053 */ 054 public abstract class InlineEditBox extends AbstractWidget implements IDirect 055 { 056 /** 057 * Default single line editing text mode. Use as one of two possible 058 * parameters to the <code>mode</code> parameter. 059 */ 060 public static final String TEXT_MODE = "text"; 061 062 /** 063 * Multi line editing text mode. Use as one of two possible 064 * parameters to the <code>mode</code> parameter. 065 */ 066 public static final String TEXT_AREA_MODE = "textarea"; 067 068 public abstract String getValue(); 069 public abstract void setValue(String value); 070 071 public abstract String getMode(); 072 073 public abstract int getMinWidth(); 074 075 public abstract int getMinHeight(); 076 077 public abstract boolean getDoFade(); 078 079 public abstract boolean isDisabled(); 080 081 public abstract IActionListener getListener(); 082 083 public abstract Object getParameters(); 084 085 public abstract void setStateful(boolean value); 086 087 /** 088 * {@inheritDoc} 089 */ 090 public void renderWidget(IMarkupWriter writer, IRequestCycle cycle) 091 { 092 if (!cycle.isRewinding()) 093 { 094 writer.begin(getTemplateTagName()); // use whatever template tag they specified 095 renderInformalParameters(writer, cycle); 096 renderIdAttribute(writer, cycle); 097 } 098 099 renderBody(writer, cycle); 100 101 if (!cycle.isRewinding()) 102 { 103 writer.end(); 104 } 105 106 if(getMode() == null || (!TEXT_MODE.equals(getMode()) && !TEXT_AREA_MODE.equals(getMode()))) 107 throw new ApplicationRuntimeException(WidgetMessages.invalidTextMode(getMode())); 108 109 if (cycle.isRewinding()) 110 return; 111 112 JSONObject prop = new JSONObject(); 113 prop.put("widgetId", getClientId()); 114 prop.put("value", getValue()); 115 prop.put("mode", getMode()); 116 prop.put("minWidth", getMinWidth()); 117 prop.put("minHeight", getMinHeight()); 118 prop.put("doFade", getDoFade()); 119 120 Map parms = new HashMap(); 121 parms.put("component", this); 122 parms.put("props", prop.toString()); 123 124 PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, this); 125 getScript().execute(this, cycle, prs, parms); 126 } 127 128 /** 129 * Callback url used by client side widget to update server component. 130 * 131 * @return The url string to be used by the client side js function to notify 132 * this component that an update has been made. 133 */ 134 public String getUpdateUrl() 135 { 136 Object[] parameters = DirectLink.constructServiceParameters(getParameters()); 137 138 DirectServiceParameter dsp = new DirectServiceParameter(this, parameters); 139 140 return getEngine().getLink(isStateful(), dsp).getURL(); 141 } 142 143 /** 144 * {@inheritDoc} 145 */ 146 public List getUpdateComponents() 147 { 148 return Collections.EMPTY_LIST; 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 public boolean isAsync() 155 { 156 return true; 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 public boolean isJson() 163 { 164 return false; 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 public void trigger(IRequestCycle cycle) 171 { 172 String newValue = cycle.getParameter(getClientId()); 173 174 setValue(newValue); 175 176 if (getListener() != null) 177 { 178 getListenerInvoker().invokeListener(getListener(), this, cycle); 179 } 180 } 181 182 /** Injected. */ 183 public abstract IEngineService getEngine(); 184 185 /** Injected. */ 186 public abstract IScript getScript(); 187 188 /** Injected. */ 189 public abstract ListenerInvoker getListenerInvoker(); 190 }