/* * Copyright 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.user.client.ui; import com.google.gwt.dom.builder.shared.HtmlElementBuilderBase; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; /** * Used by {@link IsRenderable} to mark their root element in such a way that * they can be later retrieved. This class abstracts the exact details of how * the element is marked and retrieved, so that we can always use the best * method avaialable without having to change all implementations of * {@link IsRenderable}. * <p> * The expected flow is for the {@link IsRenderable} object to use one of the * {@link #stamp} methods below to mark their HTML. At a later point, its parent * widget will use the {@link #findStampedElement} to retrieve the right element. */ public class RenderableStamper { // The token used to stamp IsRenderable objects. private final String token; /** * Creates a stamper that will be use the given token, which is assumed * to be unique and will be escaped before being used. */ public RenderableStamper(String token) { this.token = SafeHtmlUtils.htmlEscape(token); } /** * Finds the element that was previously stamped in the DOM. * For this to work properly the element must be attached to the document. */ public Element findStampedElement() { // TODO(rdcastro): Add a DEV-only check to make sure the element is attached. return Document.get().getElementById(token); } /** * Stamps an HTML element in such a way that it can be later found in the DOM tree. * To be used by {@link IsRenderable} objects built using {@link SafeHtml} directly, this assumes * the element to be stamped is the first found in the given {@link SafeHtml}. * Returns safeHtml untouched if it does not being with a tag. */ public SafeHtml stamp(SafeHtml safeHtml) { String html = safeHtml.asString().trim(); if (!html.startsWith("<")) { return safeHtml; } int endOfFirstTag = html.indexOf('>'); // TODO(rdcastro): Maybe add a DEV-only check to make sure endOfFirstTag != -1 if (html.charAt(endOfFirstTag - 1) == '/') { endOfFirstTag--; } StringBuilder htmlBuilder = new StringBuilder() .append(html.substring(0, endOfFirstTag)) .append(" id ='") .append(token) .append("'") .append(html.substring(endOfFirstTag)); return SafeHtmlUtils.fromTrustedString(htmlBuilder.toString()); } /** * Stamps an HTML element in such a way that it can be later found in the DOM tree. * To be used by {@link IsRenderable} objects built using ElementBuilder, this assumes * the given elementBuilder is for the root element that should later be claimed. */ public <T extends HtmlElementBuilderBase<?>> T stamp(T elementBuilder) { elementBuilder.id(token); return elementBuilder; } }