001// Copyright 2012 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 015package org.apache.tapestry5.corelib.base; 016 017import org.apache.tapestry5.ClientElement; 018import org.apache.tapestry5.ComponentResources; 019import org.apache.tapestry5.annotations.Environmental; 020import org.apache.tapestry5.dom.Element; 021import org.apache.tapestry5.ioc.annotations.Inject; 022import org.apache.tapestry5.services.javascript.JavaScriptSupport; 023 024/** 025 * Provides support for elements that will optionally render a unique {@code id} attribute, but only if it is 026 * requested. Subclasses should invoke {@link #storeElement(org.apache.tapestry5.dom.Element)} 027 * when they begin an element that requires an id. 028 * 029 * @since 5.4 030 */ 031public abstract class BaseClientElement implements ClientElement 032{ 033 private Element element; 034 035 private String clientId; 036 037 @Inject 038 protected ComponentResources resources; 039 040 @Environmental 041 protected JavaScriptSupport javaScriptSupport; 042 043 /** 044 * Invoked (usually from a {@link org.apache.tapestry5.annotations.BeginRender} phase method) to assigned 045 * the element, and clear the clientId (only relevant for components that render in a loop). 046 */ 047 protected void storeElement(Element element) 048 { 049 assert element != null; 050 051 this.element = element; 052 clientId = null; // Until asked. 053 } 054 055 /** 056 * When invoked the first time (per request), a unique id is assigned and and id attribute added to the {@linkplain #element element} for 057 * the component. 058 */ 059 public String getClientId() 060 { 061 062 if (clientId == null) 063 { 064 if (element == null) 065 { 066 throw new IllegalStateException(String.format("Component %s has not yet rendered; it is not possible to request its client id until after it has begun rendering.", 067 resources.getCompleteId())); 068 } 069 070 clientId = javaScriptSupport.allocateClientId(resources); 071 072 element.forceAttributes("id", clientId); 073 } 074 075 return clientId; 076 } 077}