001/* Interface for parameters that provide web export content.
002
003 Copyright (c) 2011-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028
029package ptolemy.vergil.basic.export.web;
030
031import java.util.List;
032
033import ptolemy.kernel.util.IllegalActionException;
034import ptolemy.kernel.util.NameDuplicationException;
035import ptolemy.kernel.util.NamedObj;
036import ptolemy.kernel.util.Settable;
037import ptolemy.util.StringUtilities;
038
039///////////////////////////////////////////////////////////////////
040//// ParameterDisplayIconScript
041/**
042 * A parameter specifying default JavaScript actions to associate
043 * with icons in model. Putting this into a model causes an action
044 * to be associated with each icon (as specified by the <i>include</i>
045 * and <i>instancesOf</i> parameters) that, on moving the mouse over
046 * the icon, displays in a table the parameters of the corresponding
047 * Ptolemy II object. The table is displayed in a tooltip.
048 * <p>
049 * This parameter is designed to be included in a Configuration file
050 * to specify global default behavior for export to Web. Just put
051 * it in the top level of the Configuration, and this behavior
052 * will be provided by default.
053 *
054 * @author Edward A. Lee
055 * @version $Id$
056 * @since Ptolemy II 10.0
057 * @Pt.ProposedRating Red (cxh)
058 * @Pt.AcceptedRating Red (cxh)
059 */
060public class ParameterDisplayIconScript extends DefaultIconScript {
061
062    /** Create an instance of this parameter.
063     *  @param container The container.
064     *  @param name The name.
065     *  @exception IllegalActionException If the superclass throws it.
066     *  @exception NameDuplicationException If the superclass throws it.
067     */
068    public ParameterDisplayIconScript(NamedObj container, String name)
069            throws IllegalActionException, NameDuplicationException {
070        super(container, name);
071    }
072
073    ///////////////////////////////////////////////////////////////////
074    ////                         public methods                    ////
075
076    /** Override base class since content here should only be added if
077     * it does not exist already.
078     *
079     * @return False, since default content should only be added if no content
080     * already exists
081     */
082    @Override
083    public boolean isOverwriteable() {
084        return false;
085    }
086
087    /** Get an HTML table describing the parameters of the object.
088     *  @param object The Ptolemy object to return a table for.
089     *  @return An HTML table displaying the parameter values for the
090     *   specified object, or the string "Has no parameters" if the
091     *   object has no parameters.
092     */
093    public static String getParameterTable(NamedObj object) {
094        StringBuffer table = new StringBuffer();
095        List<Settable> parameters = object.attributeList(Settable.class);
096        boolean hasParameter = false;
097        for (Settable parameter : parameters) {
098            if (parameter.getVisibility().equals(Settable.FULL)) {
099                hasParameter = true;
100                table.append("<tr><td>");
101                table.append(parameter.getName());
102                table.append("</td><td>");
103                String expression = parameter.getExpression();
104                expression = StringUtilities.escapeForXML(expression);
105                expression = expression.replaceAll("'", "\\\\'");
106                // Bizarrely, escaping all characters except newlines work.
107                // Newlines need to be converted to \n.
108                // No idea why so many backslashes are required below.
109                expression = expression.replaceAll("&#10;", "\\\\\\n");
110
111                if (expression.length() == 0) {
112                    expression = "&nbsp;";
113                }
114                table.append(expression);
115                table.append("</td><td>");
116                String value = parameter.getValueAsString();
117                value = StringUtilities.escapeForXML(value);
118                value = value.replaceAll("'", "\\\\'");
119                // Bizarrely, escaping all characters except newlines work.
120                // Newlines need to be converted to \n.
121                // No idea why so many backslashes are required below.
122                value = value.replaceAll("&#10;", "\\\\\\n");
123
124                if (value.length() == 0) {
125                    value = "&nbsp;";
126                }
127                table.append(value);
128                table.append("</td></tr>");
129            }
130        }
131        if (hasParameter) {
132            table.insert(0,
133                    "<table border=\"1\">" + "<tr><td><b>Parameter</b></td>"
134                            + "<td><b>Expression</b></td>"
135                            + "<td><b>Value</b></td></tr>");
136            table.append("</table>");
137        } else {
138            table.append("Has no parameters.");
139        }
140        return table.toString();
141    }
142
143    ///////////////////////////////////////////////////////////////////
144    ////                         protected methods                 ////
145
146    /** Override the base class to provide the parameter table
147     *  for the specified object.
148     *  Provide default content to the specified web exporter to be
149     *  included in a web page for the container of this object for
150     *  objects that do not override onmouseover.
151     *  This class provides an area attribute of type
152     *  "onmouseover" that displays the parameter values
153     *  of the object and one of type "onmouseout" that
154     *  clears that display.
155     *
156     *  @param exporter The exporter to which to provide the content.
157     *  @param object The object which provides the content.
158     *  @exception IllegalActionException If there is a problem creating the content
159     * or if there is a name duplication with the created attributes
160     */
161    @Override
162    protected void _provideDefaultAttributes(NamedObj object,
163            WebExporter exporter) throws IllegalActionException {
164
165        WebAttribute webAttribute;
166
167        String command = "<h2>" + object.getName() + "</h2>"
168                + getParameterTable(object);
169
170        // Create WebAttribute for the class "tooltip".
171        webAttribute = WebAttribute.appendToWebAttribute(object,
172                "classWebAttribute", "class", "tooltip");
173        exporter.defineAttribute(webAttribute, true);
174
175        // Content of the tooltip.
176        webAttribute = WebAttribute.createWebAttribute(object,
177                "titleWebAttribute", "title");
178        webAttribute.setExpression(command);
179        exporter.defineAttribute(webAttribute, true);
180    }
181
182    /** Provide default content to the specified web exporter to be
183     *  included in a web page for the container of this object for
184     *  objects that do not override onmouseover.  This class provides
185     *  an HTML table containing parameter names and values, plus a
186     *  placeholder &lt;div&gt; tag which the script writes
187     *  information in upon onmouseover().
188     *
189     *  @param exporter The exporter to which to provide the content.
190     *  @exception IllegalActionException If evaluating the value
191     *   of this parameter fails.
192     */
193    @Override
194    protected void _provideElements(WebExporter exporter)
195            throws IllegalActionException {
196        // FIXME:  How to do this, from old comments?
197        //*  If the <i>eventType</i> parameter is "default", then
198        //*  remove all previously defined defaults and use the global
199        //*  defaults.
200
201        WebElement webElement;
202
203        // Add content from IconScript (DefaultIconScript does not override
204        // _provideElements)
205        super._provideElements(exporter);
206
207        // Define the JavaScript command writeText.  Script with this name
208        // should only be included once (onceOnly -> true)
209        /* Replaced by tooltipster
210        webElement = WebElement.createWebElement(getContainer(),
211                "writeTextScriptWebElement", "writeTextScript");
212        webElement.setParent(WebElement.HEAD);
213        webElement
214                .setExpression("<script type=\"text/javascript\">\n"
215                        + "function writeText(text) {\n"
216                        + "   document.getElementById(\"afterImage\").innerHTML = text;\n"
217                        + "};\n" + "</script>");
218        exporter.defineElement(webElement, true);
219         */
220
221        // Define the JavaScript command to initialize tooltipster,
222        // the JQuery library being used to display parameters.  Script with this name
223        // should only be included once (onceOnly -> true)
224        webElement = WebElement.createWebElement(getContainer(),
225                "tooltipsterScriptWebElement", "tooltipster");
226        webElement.setParent(WebElement.HEAD);
227        webElement.setExpression("<script type=\"text/javascript\">\n"
228                + "$(document).ready(function() {\n"
229                + "  $('.tooltip').tooltipster({\n"
230                + "    contentAsHTML: true\n" + "  });\n" + "});\n"
231                + "</script>");
232        exporter.defineElement(webElement, true);
233
234        // Put a destination paragraph in the end section of the HTML.
235        webElement = WebElement.createWebElement(getContainer(),
236                "afterImageWebElement", "afterImage");
237        webElement.setParent(WebElement.END);
238        webElement.setExpression("<div id=\"afterImage\">\n"
239                + "  <script type=\"text/javascript\">\n"
240                + "     writeText('Mouse over the icons to see their parameters. "
241                + "Click on composites and plotters to reveal their contents (if provided).');\n"
242                + "  </script>\n" + "  <noscript>\n"
243                + "     Your browser does not support JavaScript so moving the mouse\n"
244                + "     over the actors will not display their parameters. To enable\n"
245                + "     JavaScript, consult the security preferences of your browser.\n"
246                + "     <br/>See <a href=\"http://support.microsoft.com/gp/howtoscript\"><code>http://support.microsoft.com/gp/howtoscript</code></a> for details.\n"
247                + "  </noscript>\n" + "</div>");
248        exporter.defineElement(webElement, true);
249    }
250}