001 // Copyright 2008, 2010, 2011 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 015 package org.apache.tapestry5.corelib.components; 016 017 import org.apache.tapestry5.*; 018 import org.apache.tapestry5.annotations.Parameter; 019 import org.apache.tapestry5.annotations.SupportsInformalParameters; 020 import org.apache.tapestry5.dom.Element; 021 import org.apache.tapestry5.ioc.annotations.Inject; 022 import org.apache.tapestry5.services.javascript.JavaScriptSupport; 023 024 /** 025 * Renders an arbitrary element including informal parameters. 026 * 027 * @tapestrydoc 028 */ 029 @SupportsInformalParameters 030 public class Any implements ClientElement 031 { 032 @Parameter(defaultPrefix = BindingConstants.LITERAL) 033 private String element; 034 035 /** 036 * The desired client id, which defaults to the components id. 037 */ 038 @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL) 039 private String clientId; 040 041 private Element anyElement; 042 043 private String uniqueId; 044 045 @Inject 046 private ComponentResources resources; 047 048 @Inject 049 private JavaScriptSupport javascriptSupport; 050 051 String defaultElement() 052 { 053 return resources.getElementName("div"); 054 } 055 056 void beginRender(MarkupWriter writer) 057 { 058 anyElement = writer.element(element); 059 060 uniqueId = null; 061 062 resources.renderInformalParameters(writer); 063 } 064 065 /** 066 * Returns the client id. This has side effects: this first time this is called (after the Any component renders 067 * its start tag), a unique id is allocated (based on, and typically the same as, the clientId parameter, which 068 * defaults to the component's id). The rendered element is updated, with its id attribute set to the unique client 069 * id, which is then returned. 070 * 071 * @return unique client id for this component 072 */ 073 public String getClientId() 074 { 075 if (anyElement == null) 076 throw new IllegalStateException(String.format( 077 "Unable to provide client id for component %s as it has not yet rendered.", resources 078 .getCompleteId())); 079 080 if (uniqueId == null) 081 { 082 uniqueId = javascriptSupport.allocateClientId(clientId); 083 anyElement.forceAttributes("id", uniqueId); 084 } 085 086 return uniqueId; 087 } 088 089 void afterRender(MarkupWriter writer) 090 { 091 writer.end(); // the element 092 } 093 094 void inject(JavaScriptSupport javascriptSupport, ComponentResources resources, String element, String clientId) 095 { 096 this.javascriptSupport = javascriptSupport; 097 this.resources = resources; 098 this.element = element; 099 this.clientId = clientId; 100 } 101 }