001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest.widget;
014
015import java.io.*;
016
017import org.apache.juneau.html.*;
018import org.apache.juneau.internal.*;
019import org.apache.juneau.rest.*;
020import org.apache.juneau.serializer.*;
021
022/**
023 * A subclass of widgets for rendering menu items with drop-down windows.
024 * 
025 * <p>
026 * Defines some simple CSS and Javascript for enabling drop-down menus in the nav section of the page (although
027 * nothing keeps you from using it in an arbitrary location in the page).
028 * 
029 * <p>
030 * The script specifies a <js>"menuClick(element)"</js> function that toggles the visibility of the next sibling of the
031 * element.
032 * 
033 * <p>
034 * Subclasses should implement the following two methods:
035 * <ul>
036 *    <li class='jm'>{@link #getLabel(RestRequest)} - The menu item label.
037 *    <li class='jm'>{@link #getContent(RestRequest)} - The menu item content.
038 * </ul>
039 * 
040 * <p>
041 * For example, to render a link that brings up a simple dialog in a div tag:
042 * <p class='bcode'>
043 *    <ja>@Override</ja>
044 *    <jk>public</jk> String getLabel() {
045 *       <jk>return</jk> <js>"my-menu-item"</js>;
046 *    };
047 * 
048 *    <ja>@Override</ja>
049 *    <jk>public</jk> Div getLabel() {
050 *       <jk>return</jk> Html5Builder.<jsm>div</jsm>(<js>"Surprise!"</js>).style(<js>"color:red"</js>);
051 *    };
052 * </p>
053 * 
054 * <p>
055 * The HTML content returned by the {@link #getHtml(RestRequest)} method is added where the <js>"$W{...}"</js> is
056 * referenced in the page.
057 * 
058 * <h5 class='section'>See Also:</h5>
059 * <ul>
060 *    <li class='link'><a class="doclink" href="../../../../../overview-summary.html#juneau-rest-server.Widgets">Overview &gt; juneau-rest-server &gt; Widgets</a>
061 * </ul>
062 */
063public abstract class MenuItemWidget extends Widget {
064
065   /**
066    * Returns the Javascript needed for the show and hide actions of the menu item.
067    */
068   @Override /* Widget */
069   public String getScript(RestRequest req) throws Exception {
070      return loadScript("MenuItemWidget.js");
071   }
072
073   /**
074    * Defines a <js>"menu-item"</js> class that needs to be used on the outer element of the HTML returned by the
075    * {@link #getHtml(RestRequest)} method.
076    */
077   @Override /* Widget */
078   public String getStyle(RestRequest req) throws Exception {
079      return loadStyle("MenuItemWidget.css");
080   }
081
082   @Override /* Widget */
083   public String getHtml(RestRequest req) throws Exception {
084      StringBuilder sb = new StringBuilder();
085      sb.append(""
086         + "<div class='menu-item'>"
087         + "\n\t<a class='link' onclick='menuClick(this)'>"+getLabel(req)+"</a>"
088         + "\n\t<div class='popup-content'>\n"
089      );
090      Object o = getContent(req);
091      if (o instanceof Reader) {
092         try (Reader r = (Reader)o; Writer w = new StringBuilderWriter(sb)) {
093            IOUtils.pipe(r, w);
094         }
095      } else if (o instanceof CharSequence) {
096         sb.append((CharSequence)o);
097      } else {
098         SerializerSessionArgs args = new SerializerSessionArgs(req.getProperties(), null, req.getLocale(), null, null, req.getUriContext());
099         WriterSerializerSession session = HtmlSerializer.DEFAULT.createSession(args);
100         session.indent = 2;
101         session.serialize(o, sb);
102      }
103      sb.append(""
104         + "\n\t</div>"
105         + "\n</div>"
106      );
107      return sb.toString();
108   }
109
110   /**
111    * The label for the menu item as it's rendered in the menu bar.
112    * 
113    * @param req The HTTP request object.
114    * @return The menu item label.
115    * @throws Exception
116    */
117   public abstract String getLabel(RestRequest req) throws Exception;
118
119   /**
120    * The content of the popup.
121    * 
122    * @param req The HTTP request object.
123    * @return
124    *    The content of the popup.
125    *    <br>Can be any of the following types:
126    *    <ul>
127    *       <li>{@link Reader} - Serialized directly to the output.
128    *       <li>{@link CharSequence} - Serialized directly to the output.
129    *       <li>Other - Serialized as HTML using {@link HtmlSerializer#DEFAULT}.
130    *          <br>Note that this includes any of the {@link org.apache.juneau.dto.html5} beans.
131    *    </ul>
132    * @throws Exception
133    */
134   public abstract Object getContent(RestRequest req) throws Exception;
135}