aboutsummaryrefslogtreecommitdiffstats
path: root/test/data/iframeTest.js
blob: 4db56833c5faee5079b8336cb4dc3f915afda97a (plain)
1
2
3
4
5
6
7
window.startIframeTest = function() {
	var args = Array.prototype.slice.call( arguments );

	// Note: jQuery may be undefined if page did not load it
	args.unshift( window.jQuery, window, document );
	window.parent.iframeCallback.apply( null, args );
};
id='n105' href='#n105'>105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
/*
 * Copyright 2000-2016 Vaadin Ltd.
 *
 * 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.vaadin.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.jsoup.nodes.Element;

import com.vaadin.server.JsonPaintTarget;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.ui.customlayout.CustomLayoutState;
import com.vaadin.ui.declarative.DesignContext;

/**
 * <p>
 * A container component with freely designed layout and style. The layout
 * consists of items with textually represented locations. Each item contains
 * one sub-component, which can be any Vaadin component, such as a layout. The
 * adapter and theme are responsible for rendering the layout with a given style
 * by placing the items in the defined locations.
 * </p>
 *
 * <p>
 * The placement of the locations is not fixed - different themes can define the
 * locations in a way that is suitable for them. One typical example would be to
 * create visual design for a web site as a custom layout: the visual design
 * would define locations for "menu", "body", and "title", for example. The
 * layout would then be implemented as an HTML template for each theme.
 * </p>
 *
 * <p>
 * The default theme handles the styles that are not defined by drawing the
 * subcomponents just as in OrderedLayout.
 * </p>
 *
 * @author Vaadin Ltd.
 * @since 3.0
 */
@SuppressWarnings("serial")
public class CustomLayout extends AbstractLayout implements LegacyComponent {

    private static final int BUFFER_SIZE = 10000;

    /**
     * Custom layout slots containing the components.
     */
    private final HashMap<String, Component> slots = new HashMap<>();

    /**
     * Default constructor only used by subclasses. Subclasses are responsible
     * for setting the appropriate fields. Either
     * {@link #setTemplateName(String)}, that makes layout fetch the template
     * from theme, or {@link #setTemplateContents(String)}.
     *
     * @since 7.5.0
     */
    public CustomLayout() {
        setWidth(100, Unit.PERCENTAGE);
    }

    /**
     * Constructs a custom layout with the template given in the stream.
     *
     * @param templateStream
     *            Stream containing template data. Must be using UTF-8 encoding.
     *            To use a String as a template use for instance new
     *            ByteArrayInputStream("&lt;template&gt;".getBytes()).
     * @param streamLength
     *            Length of the templateStream
     * @throws IOException
     */
    public CustomLayout(InputStream templateStream) throws IOException {
        this();
        initTemplateContentsFromInputStream(templateStream);
    }

    /**
     * Constructor for custom layout with given template name. Template file is
     * fetched from "&lt;theme&gt;/layout/&lt;templateName&gt;".
     */
    public CustomLayout(String template) {
        this();
        setTemplateName(template);
    }

    protected void initTemplateContentsFromInputStream(
            InputStream templateStream) throws IOException {
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(templateStream, "UTF-8"));
        StringBuilder builder = new StringBuilder(BUFFER_SIZE);
        try {
            char[] cbuf = new char[BUFFER_SIZE];
            int nRead;
            while ((nRead = reader.read(cbuf, 0, BUFFER_SIZE)) > 0) {
                builder.append(cbuf, 0, nRead);
            }
        } finally {
            reader.close();
        }

        setTemplateContents(builder.toString());
    }

    @Override
    protected CustomLayoutState getState() {
        return (CustomLayoutState) super.getState();
    }

    @Override
    protected CustomLayoutState getState(boolean markAsDirty) {
        return (CustomLayoutState) super.getState(markAsDirty);
    }

    /**
     * Adds the component into this container to given location. If the location
     * is already populated, the old component is removed.
     *
     * @param c
     *            the component to be added.
     * @param location
     *            the location of the component.
     */
    public void addComponent(Component c, String location) {
        final Component old = slots.get(location);
        if (old != null) {
            removeComponent(old);
        }
        slots.put(location, c);
        getState().childLocations.put(c, location);

        super.addComponent(c);
    }

    /**
     * Adds the component into this container. The component is added without
     * specifying the location (empty string is then used as location). Only one
     * component can be added to the default "" location and adding more
     * components into that location overwrites the old components.
     *
     * @param c
     *            the component to be added.
     */
    @Override
    public void addComponent(Component c) {
        this.addComponent(c, "");
    }

    /**
     * Removes the component from this container.
     *
     * @param c
     *            the component to be removed.
     */
    @Override
    public void removeComponent(Component c) {
        if (c == null) {
            return;
        }
        slots.values().remove(c);
        getState().childLocations.remove(c);
        super.removeComponent(c);
    }

    /**
     * Removes the component from this container from given location.
     *
     * @param location
     *            the Location identifier of the component.
     */
    public void removeComponent(String location) {
        this.removeComponent(slots.get(location));
    }

    /**
     * Gets the component container iterator for going trough all the components
     * in the container.
     *
     * @return the Iterator of the components inside the container.
     */
    @Override
    public Iterator<Component> iterator() {
        return slots.values().iterator();
    }

    /**
     * Gets the number of contained components. Consistent with the iterator
     * returned by {@link #getComponentIterator()}.
     *
     * @return the number of contained components
     */
    @Override
    public int getComponentCount() {
        return slots.values().size();
    }

    /**
     * Gets the child-component by its location.
     *
     * @param location
     *            the name of the location where the requested component
     *            resides.
     * @return the Component in the given location or null if not found.
     */
    public Component getComponent(String location) {
        return slots.get(location);
    }

    /* Documented in superclass */
    @Override
    public void replaceComponent(Component oldComponent,
            Component newComponent) {

        // Gets the locations
        String oldLocation = null;
        String newLocation = null;
        for (final String location : slots.keySet()) {
            final Component component = slots.get(location);
            if (component == oldComponent) {
                oldLocation = location;
            }
            if (component == newComponent) {
                newLocation = location;
            }
        }

        if (oldLocation == null) {
            addComponent(newComponent);
        } else if (newLocation == null) {
            removeComponent(oldLocation);
            addComponent(newComponent, oldLocation);
        } else {
            slots.put(newLocation, oldComponent);
            slots.put(oldLocation, newComponent);
            getState().childLocations.put(newComponent, oldLocation);
            getState().childLocations.put(oldComponent, newLocation);
        }
    }

    /** Get the name of the template */
    public String getTemplateName() {
        return getState(false).templateName;
    }

    /** Get the contents of the template */
    public String getTemplateContents() {
        return getState(false).templateContents;
    }

    /**
     * Set the name of the template used to draw custom layout.
     *
     * With GWT-adapter, the template with name 'templatename' is loaded from
     * VAADIN/themes/themename/layouts/templatename.html. If the theme has not
     * been set (with Application.setTheme()), themename is 'default'.
     *
     * @param templateName
     */
    public void setTemplateName(String templateName) {
        getState().templateName = templateName;
        getState().templateContents = null;
    }

    /**
     * Set the contents of the template used to draw the custom layout.
     *
     * @param templateContents
     */
    public void setTemplateContents(String templateContents) {
        getState().templateContents = templateContents;
        getState().templateName = null;
    }

    @Override
    public void changeVariables(Object source, Map<String, Object> variables) {
        // Nothing to see here
    }

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        // Workaround to make the CommunicationManager read the template file
        // and send it to the client
        String templateName = getState(false).templateName;
        if (templateName != null && templateName.length() != 0) {
            Set<Object> usedResources = ((JsonPaintTarget) target)
                    .getUsedResources();
            String resourceName = "layouts/" + templateName + ".html";
            usedResources.add(resourceName);
        }
    }

    @Override
    public void readDesign(Element design, DesignContext designContext) {
        super.readDesign(design, designContext);

        for (Element child : design.children()) {

            Component childComponent = designContext.readDesign(child);

            if (child.hasAttr(":location")) {
                addComponent(childComponent, child.attr(":location"));
            } else {
                addComponent(childComponent);
            }
        }
    }

    @Override
    public void writeDesign(Element design, DesignContext designContext) {
        super.writeDesign(design, designContext);

        for (Entry<String, Component> slot : slots.entrySet()) {
            Element child = designContext.createElement(slot.getValue());
            if (slots.size() > 1 || !"".equals(slot.getKey())) {
                child.attr(":location", slot.getKey());
            }
            design.appendChild(child);
        }
    }
}