001package com.hfg.javascript;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.HashMap;
006import java.util.List;
007import java.util.Map;
008
009import com.hfg.html.HTML;
010import com.hfg.html.HTMLTag;
011import com.hfg.html.Link;
012import com.hfg.html.attribute.HTMLColor;
013import com.hfg.util.StringBuilderPlus;
014import com.hfg.util.StringUtil;
015import com.hfg.xml.XMLUtil;
016
017//------------------------------------------------------------------------------
018/**
019 Widget for creating a popup menu that can be used in an href attribute (a link
020 or an Area object) or an onclick() handler.
021 <p>
022 See <a href='doc-files/PopupMenuJSTest.html' target='_parent'>this page</a> for examples.
023 </p>
024 <pre>
025 HTMLDoc doc = new HTMLDoc();
026 doc.setDoctype(Doctype.XHTML_1_0_TRANSITIONAL);
027 HTML html = new HTML("PopupMenuJS Test");
028 doc.setRootTag(html);
029
030 Body body = html.getBody();
031
032 body.br(3);
033
034 // Add the CSS classes needed
035 html.getHead().addStyle(PopupMenuJS.generateCommonCSS());
036 // Add the javascript needed
037 html.getHead().addJavascript(PopupMenuJS.generateCommonJavascript());
038
039 PopupMenuJS menu3 = new PopupMenuJS();
040 menu3.setMenuTitle("Test Menu #2");
041 menu3.addLink(new Link("http://localhost.com/URL7", "Nifty Site"));
042 menu3.addLink(new Link("URL8", "Click Me!"));
043 menu3.addLink(new Link());
044 menu3.addLink(new Link("javascript:alert('Hello World!');", "Hello World!"));
045 // Add the menu definition to the page's javascript
046 html.getHead().addJavascript(menu3.generateMenuJavascript());
047 // Attach the menu to the desired tag
048 menu3.attachToTag(body.addLink("javascript:void(0)", "Link Example"));
049
050 </pre>
051 @author J. Alex Taylor, hairyfatguy.com
052 */
053//------------------------------------------------------------------------------
054// com.hfg XML/HTML Coding Library
055//
056// This library is free software; you can redistribute it and/or
057// modify it under the terms of the GNU Lesser General Public
058// License as published by the Free Software Foundation; either
059// version 2.1 of the License, or (at your option) any later version.
060//
061// This library is distributed in the hope that it will be useful,
062// but WITHOUT ANY WARRANTY; without even the implied warranty of
063// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
064// Lesser General Public License for more details.
065//
066// You should have received a copy of the GNU Lesser General Public
067// License along with this library; if not, write to the Free Software
068// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
069//
070// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
071// [email protected]
072//------------------------------------------------------------------------------
073
074public class PopupMenuJS
075{
076   private String     mMenuId;
077   private List<Link> mLinks;
078   private String     mTitle;
079   private boolean    mPin;
080
081   private static String    sFont        = "Arial,sans-serif";
082   private static String    sFontSize    = ".8em";
083   private static boolean   sDefaultPin  = false;
084   private static HTMLColor sMenuColor   = new HTMLColor(Color.decode("#99ffff"));
085   private static HTMLColor sHeaderColor = new HTMLColor(Color.decode("#000066"));
086   private static String    sCachedJs;
087   private static String    sCachedCss;
088
089   private static int sIndex = 1;
090
091   //##########################################################################
092   // CONSTRUCTORS
093   //##########################################################################
094
095   //--------------------------------------------------------------------------
096   public PopupMenuJS()
097   {
098      super();
099      mMenuId = "_HfgPopup" + sIndex++;
100      setPin(sDefaultPin);
101   }
102
103   //##########################################################################
104   // PUBLIC METHODS
105   //##########################################################################
106
107   //--------------------------------------------------------------------------
108   public static void setFont(String inValue)
109   {
110      sFont = inValue;
111      sCachedCss = null;
112   }
113
114   //--------------------------------------------------------------------------
115   public static void setFontSize(String inValue)
116   {
117      sFont = inValue;
118      sCachedCss = null;
119   }
120
121   //--------------------------------------------------------------------------
122   public static void setDefaultPin(boolean inValue)
123   {
124      sDefaultPin = inValue;
125   }
126
127   //--------------------------------------------------------------------------
128   /**
129    Specify whether or not to 'pin' the menu once it is opened.
130    */
131   public PopupMenuJS setPin(boolean inValue)
132   {
133      mPin = inValue;
134      return this;
135   }
136
137   //--------------------------------------------------------------------------
138   public static void setDefaultMenuColor(Color inValue)
139   {
140      sMenuColor = new HTMLColor(inValue);
141      sCachedCss = null;
142   }
143
144   //--------------------------------------------------------------------------
145   public static void setDefaultHeaderColor(Color inValue)
146   {
147      sHeaderColor = new HTMLColor(inValue);
148      sCachedCss = null;
149   }
150
151   //--------------------------------------------------------------------------
152   public static String generateCommonCSS()
153   {
154      if (null == sCachedCss)
155      {
156         Map<String, String> tokenSubstitutionMap = new HashMap<String, String>();
157         tokenSubstitutionMap.put("FONT", sFont);
158         tokenSubstitutionMap.put("FONT_SIZE", sFontSize);
159         tokenSubstitutionMap.put("HEADER_COLOR", sHeaderColor.toString());
160         tokenSubstitutionMap.put("MENU_COLOR", sMenuColor.toString());
161
162         sCachedCss = JsUtil.getJSResourceAsString("popupMenu.css", tokenSubstitutionMap);
163      }
164
165      return sCachedCss;
166   }
167
168   //--------------------------------------------------------------------------
169   /**
170    Generates the generic javascript methods for creating a popup menu.
171    */
172   public static synchronized String generateCommonJavascript()
173   {
174      if (null == sCachedJs)
175      {
176         Map<String, String> tokenSubstitutionMap = new HashMap<String, String>();
177
178         sCachedJs = JsUtil.getJSResourceAsString("popupMenu.js", tokenSubstitutionMap);
179      }
180
181      return sCachedJs;
182   }
183
184   //--------------------------------------------------------------------------
185   public String getDisplayMenuJavascript()
186   {
187      return "javascript:hfg.js.PopupMenu.display(event, " + mMenuId + ");";
188   }
189   //--------------------------------------------------------------------------
190   /**
191    * Popup menus can be added to any tag which supports onmouseover and onmouseout.
192    * You will also need to add generateJS() to the javascript in the page's &lt;head&gt; tag.
193    * @param inTag the tag to which the onclick() or onmouseover() attribute will
194    *              be set to display a menu.
195    */
196   public void attachToTag(HTMLTag inTag)
197   {
198      String currentValue = inTag.getAttributeValue(HTML.ONCLICK);
199      inTag.setAttribute(HTML.ONCLICK,
200                         (currentValue != null ? currentValue + ";" : "") + "hfg.js.PopupMenu.display(event, " + mMenuId + ")");
201
202//      currentValue = inTag.getAttributeValue(HTML.CLASS);
203//      inTag.setAttribute(HTML.CLASS, (currentValue != null ? currentValue + " " : "") + "hoverboard");
204   }
205
206   //--------------------------------------------------------------------------
207   public PopupMenuJS setMenuTitle(String inValue)
208   {
209      mTitle = inValue;
210      return this;
211   }
212
213   //--------------------------------------------------------------------------
214   /**
215    Add a link to the popup menu.
216    */
217   public PopupMenuJS addLink(Link inLink)
218   {
219      if (inLink != null)
220      {
221         if (null == mLinks) mLinks = new ArrayList<Link>();
222         mLinks.add(inLink);
223      }
224      return this;
225   }
226
227   //--------------------------------------------------------------------------
228   /**
229    Add a divider to the popup menu.
230    */
231   public PopupMenuJS addDivider()
232   {
233      if (null == mLinks) mLinks = new ArrayList<Link>();
234      mLinks.add(new Link());
235
236      return this;
237   }
238
239   //--------------------------------------------------------------------------
240   /**
241    Add a divider to the popup menu.
242    */
243   public PopupMenuJS addDivider(String inTitle)
244   {
245      if (null == mLinks) mLinks = new ArrayList<Link>();
246      mLinks.add(new Link("", inTitle));
247
248      return this;
249   }
250
251   //---------------------------------------------------------------------------
252   public String generateMenuJavascript()
253   {
254      StringBuilderPlus buffer = new StringBuilderPlus();
255/*
256      buffer.appendln("var " + mMenuId + " = [");
257
258      if (mTitle != null)
259      {
260         buffer.appendln("['title', " + StringUtil.singleQuote(XMLUtil.escapeApos(mTitle)) + "],");
261      }
262
263      buffer.appendln("['pin', " + (mPin ? "1" : "0") + "],");
264
265      if (mLinks != null)
266      {
267         for (int i = 0; i < mLinks.size(); i++)
268         {
269            Link link = mLinks.get(i);
270            if (StringUtil.isSet(link.getURL()))
271            {
272               buffer.append("['link', '" + link.getContent() + "', '" + link.getURL() + "']");
273            }
274            else
275            {
276               buffer.append("['divider'" + (StringUtil.isSet(link.getContent()) ? ", '" + link.getContent() + "'" : "") + "]");
277            }
278
279            buffer.appendln((i < mLinks.size() - 1 ? "," : ""));
280         }
281      }
282
283      buffer.appendln("]");
284*/
285
286      buffer.append("var " + mMenuId + " = { 'config': {");
287      buffer.append("'pin': " + StringUtil.singleQuote(mPin ? "1" : "0"));
288      if (StringUtil.isSet(mTitle))
289      {
290         buffer.append(", 'title': " + StringUtil.singleQuote(XMLUtil.escapeApos(mTitle)));
291      }
292
293      buffer.appendln("}, 'content': [");
294
295      if (mLinks != null)
296      {
297         for (int i = 0; i < mLinks.size(); i++)
298         {
299            Link link = mLinks.get(i);
300            if (StringUtil.isSet(link.getURL()))
301            {
302//               buffer.append("['link', '" + link.getContent() + "', '" + link.getURL() + "']");
303               link = (Link) link.clone();
304               link.setContent("&#8226; " + link.getContent());
305               link.addClass("hfgmenu");
306               buffer.append("['link', '" + StringUtil.replaceAll(link.toHTML(), "'", "\\'") + "']");
307            }
308            else
309            {
310               buffer.append("['divider'" + (StringUtil.isSet(link.getContent()) ? ", '" + link.getContent() + "'" : "") + "]");
311            }
312
313            buffer.appendln((i < mLinks.size() - 1 ? "," : ""));
314         }
315      }
316
317      buffer.appendln("]}");
318
319      return buffer.toString();
320   }
321}