blob: f22a72e80d0fc4695f280810daae41170d067233 [file] [log] [blame]
/*
* 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;
}
}