001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.head;
018
019import java.util.Collections;
020import java.util.List;
021import java.util.Objects;
022
023import org.apache.wicket.Application;
024import org.apache.wicket.core.util.string.JavaScriptUtils;
025import org.apache.wicket.request.Response;
026import org.apache.wicket.request.resource.ResourceReference;
027import org.apache.wicket.settings.JavaScriptLibrarySettings;
028import org.apache.wicket.util.string.Strings;
029import org.apache.wicket.util.value.AttributeMap;
030
031/**
032 * {@link HeaderItem} for scripts that need to be executed directly after the DOM has been built,
033 * but before external resources, such as images, are loaded.
034 *
035 * @author papegaaij
036 */
037public class OnDomReadyHeaderItem extends AbstractCspHeaderItem
038{
039        private static final long serialVersionUID = 1L;
040
041        /**
042         * Creates a {@link OnDomReadyHeaderItem} for the script.
043         *
044         * @param javaScript
045         *            The script to execute on the DOM ready event.
046         *
047         * @return A newly created {@link OnDomReadyHeaderItem}.
048         */
049        public static OnDomReadyHeaderItem forScript(CharSequence javaScript)
050        {
051                return new OnDomReadyHeaderItem(javaScript);
052        }
053
054        private final CharSequence javaScript;
055
056        /**
057         * Constructor.
058         *
059         * The JavaScript should be provided by overloaded #getJavaScript
060         */
061        public OnDomReadyHeaderItem()
062        {
063                this(null);
064        }
065
066        /**
067         * Construct.
068         *
069         * @param javaScript
070         */
071        public OnDomReadyHeaderItem(CharSequence javaScript)
072        {
073                this.javaScript = javaScript;
074        }
075
076        /**
077         * @return the script that gets executed on the DOM ready event.
078         */
079        public CharSequence getJavaScript()
080        {
081                return javaScript;
082        }
083
084        @Override
085        public void render(Response response)
086        {
087                CharSequence js = getJavaScript();
088                if (Strings.isEmpty(js) == false)
089                {
090                        AttributeMap attributes = new AttributeMap();
091                        attributes.putAttribute(JavaScriptUtils.ATTR_TYPE, "text/javascript");
092                        attributes.putAttribute(JavaScriptUtils.ATTR_CSP_NONCE, getNonce());
093                        JavaScriptUtils.writeInlineScript(response, "Wicket.Event.add(window, \"domready\", " +
094                                        "function(event) { " + js + ";});", attributes);
095                }
096        }
097
098        @Override
099        public Iterable<?> getRenderTokens()
100        {
101                return Collections.singletonList("javascript-domready-" + getJavaScript());
102        }
103
104        @Override
105        public String toString()
106        {
107                return "OnDomReadyHeaderItem('" + getJavaScript() + "')";
108        }
109
110        @Override
111        public int hashCode()
112        {
113                return Objects.hash(javaScript);
114        }
115
116        @Override
117        public boolean equals(Object o)
118        {
119                if (this == o) return true;
120                if (o == null || getClass() != o.getClass()) return false;
121                OnDomReadyHeaderItem that = (OnDomReadyHeaderItem) o;
122                return Objects.equals(javaScript, that.javaScript);
123        }
124
125        @Override
126        public List<HeaderItem> getDependencies()
127        {
128                JavaScriptLibrarySettings ajaxSettings = Application.get().getJavaScriptLibrarySettings();
129                ResourceReference wicketAjaxReference = ajaxSettings.getWicketAjaxReference();
130                List<HeaderItem> dependencies = super.getDependencies();
131                dependencies.add(JavaScriptHeaderItem.forReference(wicketAjaxReference));
132                return dependencies;
133        }
134}