Dynamically Resizing Graphics
This note demonstrates a method for implementing clickable in-place resizing of graphics in WebWorks Help. You could use this method to implement thumbnails that toggle to full size and back again on the HTML page; the example here employs it to allow users to temporarily enlarge screenshots for improved legibility.
Why Have dynamically resizable graphics?
In using FrameMaker to author software user guides and help, we display most screen shots at a somewhat reduced size (125 DPI to 250 DPI, depending on the size of the graphic), to better fit a standard page (in PDF output) and to minimize required scrolling in a typically small help window (in HTML output). In FrameMaker, we use Object Properties to specify the desired DPI for display.
The reduced shots are usually perfectly legible in PDF, on screen and in printouts. In HTML, the layout of reduced shots is clear, but text and button labels (if not large and bold) are not. Whether we let ePublisher Pro process the full-size screenshot or whether we create a pre-shrunk version in a graphic tool and then import it full-size into HTML, browsers cannot display the reduced text legibly.
The technique described here allows the user to click on any screenshot to display it at its full size, in-place on the help page. A second click restores the image to its original inserted size. You can implement this capability by modifying the XSL transform that ePublisher uses to generate image tags in its WebWorks Help output.
What the Output Looks like
Click here for an example. The referenced HTML file and image are attached to this article. Note that there is hover text (tool-tip text) that informs the user that the image can be resized.
What the Generated Display Code Looks Like
In default WebWorks Help 5, an image imported into a FrameMaker document, anchored to its own paragraph and explicitly sized, is converted to HTML similar to the following (carriage returns added for readability):
<div id="727345" class="Anchor"> <img id="727363" class="Default" src="images/login_screen.png" width="349" height="139" style="display: block; float: none; left: 0.0; text-align: center; top: 0.0;" /> </div>
In our version of WebWorks Help modified to support resizing, the same imported image would result in the following HTML (carriage returns added for readability):
<div class="Anchor"><a name="727869"> <img id="727867" class="Default" src="images/login_screen.png" width="349" height="139" style="display: block; float: none; left: 0.0; text-align: center; top: 0.0;" alt="Click to enlarge" title="Click to enlarge" onclick="javascript:document.getElementById('727867').style.display='none'; document.getElementById('727867a').style.display='block';" /> <img id="727867a" class="Default" src="images/login_screen.png" style="display: none; float: none; left: 0.0; text-align: center; top: 0.0;" alt="Click to reduce" title="Click to reduce" onclick="javascript:document.getElementById('727867').style.display='block';document.getElementById('727867a').style.display='none';" /></a></div>
In this code, the first img element displays the graphic at reduced size, but includes a JavaScript onclick attribute that uses the document object's getElementByID method to hide the reduced graphic and display the full-size one. The second img element is active only when the enlarged graphic is being displayed; its onclick hides the full-size graphic and displays the reduced one.
To implement the Display Code
To generate this more complex code, you need to alter only the file content.xsl. In WebWorks Help 5, the file is located at WebWorks\ePublisher Pro\Formats\WebWorks Help 5.0. (You should of course use format overrides or create a custom format so that you are not altering the original WebWorks Help 5.0 format.)
In content.xsl, locate the section that generates the IMG tag and its attributes. It is in the Frame-FullSize XSL template, near the end of the file:
<xsl:template name="Frame-FullSize"> ... <!-- Tag --> ... <!-- Graphic element --> ... <!-- Generate D Links --> ... </xsl:template>
Within the Frame-FullSize template, you will change parts of the Graphic element section--the stretch from just after the Tag section to just before the Generate D Links section.
The altered code is displayed below. Changed or added code sections are bolded. Note that this altered section is essentially two consecutive versions the of the original Graphic element section, each customized slightly so that together they generate the two img elements shown above. The principal changes are these:
Alteration of the alt attribute, and addition of a title attribute, to generate "Click to enlarge" and "Click to reduce" tool-tips for IE and Firefox, respectively.
Generation of a unique ID for the expanded version of the graphic. The code for the second img tag adds the letter a to the end of the ID generated by ePublisher for the original (reduced) version of the graphic. (That unique ID is used in the getElementByID method.)
Use of string manipulation to modify the Style attribute section in the second img tag. It changes " display: block " to " display: none ". This change is needed to prevent the reduced graphic from re-displaying when the expanded graphic is displayed.
Addition of a JavaScript onclick attribute to each img tag, to hide the graphic in its current state and redraw it in its new state.
<!-- First Graphic element (unexpanded) -->
<!-- --> <xsl:element name="{$VarTag}" namespace="{$GlobalDefaultNamespace}"> <!-- ID attribute --> <!-- --> <xsl:attribute name="id"> <xsl:value-of select="$ParamFrame/@id" /> </xsl:attribute> <!-- Class attribute --> <!-- --> <xsl:attribute name="class"> <xsl:value-of select="wwstring:CSSClassName($ParamFrame/@stylename)" /> </xsl:attribute> <!-- Src attribute --> <!-- --> <xsl:attribute name="src"> <xsl:value-of select="$VarSrc" /> </xsl:attribute> <!-- Width attribute --> <!-- --> <xsl:if test="$VarWidth > 0"> <xsl:attribute name="width"> <xsl:value-of select="$VarWidth"/> </xsl:attribute> </xsl:if> <!-- Height attribute --> <!-- --> <xsl:if test="$VarHeight > 0"> <xsl:attribute name="height"> <xsl:value-of select="$VarHeight"/> </xsl:attribute> </xsl:if> <!-- Style attribute --> <!-- --> <xsl:if test="string-length($VarInlineCSSProperties) > 0"> <xsl:attribute name="style"> <xsl:value-of select="$VarInlineCSSProperties" /> </xsl:attribute> </xsl:if>
<!-- Alt attribute -->
<!-- -->
<xsl:choose>
<xsl:when test="string-length($VarAltText) > 0">
<xsl:attribute name="alt">
<xsl:value-of select="$VarAltText" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="alt">
<xsl:value-of select="'Click to enlarge'" />
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Title attribute -->
<!-- -->
<xsl:attribute name="title">
<xsl:value-of select="'Click to enlarge'" />
</xsl:attribute>
<!-- onclick Javascript attribute -->
<!-- -->
<xsl:attribute name="onclick">
<xsl:value-of select="'javascript:document.getElementById('" />'<xsl:value-of select='$ParamFrame/@id' />').style.display='none';document.getElementById('<xsl:value-of select='$ParamFrame/@id' />a').style.display='block';</xsl:attribute>
<!-- Longdesc attribute --> <!-- --> <xsl:if test="string-length($VarLongDescription) > 0"> <xsl:attribute name="longdesc"> <xsl:value-of select="$VarLongDescription" /> </xsl:attribute> </xsl:if> <!-- Usemap attribute --> <!-- --> <xsl:if test="string-length($VarUseMap) > 0"> <xsl:attribute name="usemap"> <xsl:value-of select="$VarUseMap" /> </xsl:attribute> <xsl:attribute name="border"> <xsl:value-of select="'0'" /> </xsl:attribute> </xsl:if> </xsl:element>
<!-- Second Graphic element (expanded) -->
<!-- --> <xsl:element name="{$VarTag}" namespace="{$GlobalDefaultNamespace}"> <!-- ID attribute --> <!-- --> <xsl:attribute name="id">
<xsl:value-of select="$ParamFrame/@id" />a</xsl:attribute>
<!-- Class attribute --> <!-- --> <xsl:attribute name="class"> <xsl:value-of select="wwstring:CSSClassName($ParamFrame/@stylename)" /> </xsl:attribute> <!-- Src attribute --> <!-- --> <xsl:attribute name="src"> <xsl:value-of select="$VarSrc" /> </xsl:attribute>
<!-- Style attribute: same as before except don't display it (assumes default display style is "block") -->
<!-- -->
<xsl:if test="string-length($VarInlineCSSProperties) > 0">
<xsl:variable name="VarPrefix" select="substring-before($VarInlineCSSProperties, 'block')" />
<xsl:variable name="VarSuffix" select="substring-after($VarInlineCSSProperties, 'block')" />
<xsl:attribute name="style">
<xsl:value-of select="concat($VarPrefix,'none',$VarSuffix)" />
</xsl:attribute>
</xsl:if>
<!-- Alt attribute -->
<!-- -->
<xsl:choose>
<xsl:when test="string-length($VarAltText) > 0">
<xsl:attribute name="alt">
<xsl:value-of select="$VarAltText" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="alt">
<xsl:value-of select="'Click to reduce'" />
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Title attribute -->
<!-- -->
<xsl:attribute name="title">
<xsl:value-of select="'Click to reduce'" />
</xsl:attribute>
<!-- onclick Javascript attribute -->
<!-- -->
<xsl:attribute name="onclick">
<xsl:value-of select="'javascript:document.getElementById('" />'<xsl:value-of select='$ParamFrame/@id' />').style.display='block';document.getElementById('<xsl:value-of select='$ParamFrame/@id' />a').style.display='none';</xsl:attribute>
<!-- Longdesc attribute --> <!-- --> <xsl:if test="string-length($VarLongDescription) > 0"> <xsl:attribute name="longdesc"> <xsl:value-of select="$VarLongDescription" /> </xsl:attribute> </xsl:if> <!-- Usemap attribute --> <!-- --> <xsl:if test="string-length($VarUseMap) > 0"> <xsl:attribute name="usemap"> <xsl:value-of select="$VarUseMap" /> </xsl:attribute> <xsl:attribute name="border"> <xsl:value-of select="'0'" /> </xsl:attribute> </xsl:if> </xsl:element>
Making Only Certain Graphics Resizable
Because it may not make sense to have all graphics resizable (some graphics may be at full size already, and high-resolution images or line drawings may be too large if displayed at full size), you can add logic to content.xsl to ensure that only graphics of a given class (Default in the example shown here) will be made resizable, all others getting the normal handling of the unchanged content.xsl. (As explained in the WebWorks documentation, you can specify a graphic element's class in FrameMaker by embedding a text frame with a particular GraphicStyle marker in the imported graphic's frame.)
The example below shows the XSL logic added to content.xsl to allow this discrimination based on graphic class. (Non-bold portions are the unchanged default content.xsl code before and after the changed sections; bolded portions are the added logic code.)
... <!-- Tag --> <!-- --> <xsl:variable name="VarTagProperty" select="$VarContextRule/wwproject:Properties/wwproject:Property[@Name = 'tag']/@Value" /> <xsl:variable name="VarTag"> <xsl:choose> <xsl:when test="string-length($VarTagProperty) > 0"> <xsl:value-of select="$VarTagProperty" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="'img'" /> </xsl:otherwise> </xsl:choose> </xsl:variable>
<!-- Generate the IMG tag or tags -->
<!-- If class = "Default", use two tags to toggle image between reduced and full size -->
<!-- Otherwise use standard WWH 5.0 processing (fixed size) -->
<xsl:choose>
<xsl:when test="(wwstring:CSSClassName($ParamFrame/@stylename) = 'Default')">
***In here goes the altered graphic-element section that was presented above***
<xsl:otherwise>
***In here goes the original unchanged graphic-element section from content.xsl ***
</xsl:otherwise>
</xsl:choose>
An altered version of content.xsl, containing the changes noted here, is atached to this note (content.xsl). To customize it for your purposes, you might want to change the graphics class that it specifies as resizable, and you might want to change the alt or title text.
Acknowledgments
Originally contributed by DaveBice. Thanks to Carla Ahlstrom of RSA Security for providing the original Dynamic HTML replacement code.