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 assign 045 * the element, and clear the clientId (only relevant for components that render in a loop). 046 * @param element the element to store 047 */ 048 protected void storeElement(Element element) 049 { 050 assert element != null; 051 052 this.element = element; 053 clientId = null; // Until asked. 054 } 055 056 /** 057 * When invoked the first time (per request), a unique id is assigned and and id attribute added to the {@linkplain #element element} for 058 * the component. 059 */ 060 public String getClientId() 061 { 062 063 if (clientId == null) 064 { 065 if (element == null) 066 { 067 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.", 068 resources.getCompleteId())); 069 } 070 071 clientId = javaScriptSupport.allocateClientId(resources); 072 073 element.forceAttributes("id", clientId); 074 } 075 076 return clientId; 077 } 078}