@@ -0,0 +1,2618 @@
+// Copyright 2012 The Apache Software Foundation%0A//%0A// Licensed under the Apache License, Version 2.0 (the %22License%22);%0A// you may not use this file except in compliance with the License.%0A// You may obtain a copy of the License at%0A//%0A// http://www.apache.org/licenses/LICENSE-2.0%0A//%0A// Unless required by applicable law or agreed to in writing, software%0A// distributed under the License is distributed on an %22AS IS%22 BASIS,%0A// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.%0A// See the License for the specific language governing permissions and%0A// limitations under the License.%0A%0Apackage org.apache.tapestry5.corelib.base;%0A%0Aimport org.apache.tapestry5.ClientElement;%0Aimport org.apache.tapestry5.ComponentResources;%0Aimport org.apache.tapestry5.annotations.Environmental;%0Aimport org.apache.tapestry5.dom.Element;%0Aimport org.apache.tapestry5.ioc.annotations.Inject;%0Aimport org.apache.tapestry5.services.javascript.JavaScriptSupport;%0A%0A/**%0A * Provides support for elements that will optionally render a unique %7B@code id%7D attribute, but only if it is%0A * requested. Subclasses should invoke %7B@link #storeElement(org.apache.tapestry5.dom.Element)%7D%0A * when they begin an element that requires an id.%0A *%0A * @since 5.4%0A */%0Apublic abstract class BaseClientElement implements ClientElement%0A%7B%0A    private Element element;%0A%0A    private String clientId;%0A%0A    @Inject%0A    protected ComponentResources resources;%0A%0A    @Environmental%0A    protected JavaScriptSupport javaScriptSupport;%0A%0A    /**%0A     * Invoked (usually from a %7B@link org.apache.tapestry5.annotations.BeginRender%7D phase method) to assigned%0A     * the element, and clear the clientId (only relevant for components that render in a loop).%0A     */%0A    protected void storeElement(Element element)%0A    %7B%0A        assert element != null;%0A%0A        this.element = element;%0A        clientId = null; // Until asked.%0A    %7D%0A%0A    /**%0A     * When invoked the first time (per request), a unique id is assigned and and id attribute added to the %7B@linkplain #element element%7D for%0A     * the component.%0A     */%0A    @Override%0A    public String getClientId()%0A    %7B%0A%0A        if (clientId == null)%0A        %7B%0A            if (element == null)%0A            %7B%0A                throw new IllegalStateException(String.format(%22Component %25s has not yet rendered; it is not possible to request its client id until after it has begun rendering.%22,%0A                        resources.getCompleteId()));%0A            %7D%0A%0A            clientId = javaScriptSupport.allocateClientId(resources);%0A%0A            element.forceAttributes(%22id%22, clientId);%0A        %7D%0A%0A        return clientId;%0A    %7D%0A%7D%0A

Introduce a base class for elements that want to include a "lazy" clientId property