Displaying several images (BLOBs) at once in a WAM

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
Joop
Posts: 26
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Displaying several images (BLOBs) at once in a WAM

Post by Joop »

Hi,

I want to create a WAM that displays serveral images (stored in BLOB fields) on one page. So far (with the help of the documentation) I can produce a list of links (anchor). When you click on a link the image is opened in a new tab of the browser. This method uses the webroutine with the Reponse parameter:

RDMLX:

Code: Select all

* -----------------------------------------------------------------------------
* Show photo in new browser tab
* -----------------------------------------------------------------------------
Webroutine Name(uShowFoto) Response(#HTTPR) Desc('Show photo')
Web_Map For(*Input) Fields(#PRIFILRRN)
Fetch Fields(#KVFFOT) From_File(ZNPKVF) Io_Error(*Next) Val_Error(*Next) With_Rrn(#PRIFILRRN)
#HTTPR.ContentFile := #KVFFOT.FileName
Endroutine /* uShowFoto */
XSL:

Code: Select all

<td class="KVFVLG">
<xsl:attribute name="__cellvalue">
    <xsl:value-of select="$KVFVLG" />
</xsl:attribute>
<xsl:call-template name="std_anchor">
    <xsl:with-param name="show_in_new_window"  select="true()" />
    <xsl:with-param name="on_click_wrname" select="'uShowFoto'" />
    <xsl:with-param name="currentrownumval"  select="$PRIFILRRN" />
    <xsl:with-param name="currentrowhfield"  select="'PRIFILRRN'" />
    <xsl:with-param name="name" select="$KVFVLG/@id" />
    <xsl:with-param name="value" select="$KVFVLG" />
</xsl:call-template>
</td>
But I wanted to show all the images together on one page instead of a list of links. Wonder if anyone out there has done something like this?
--
Regards,
Joop Roseboom
User avatar
Dino
Posts: 472
Joined: Fri Jul 19, 2019 7:49 am
Location: Robbinsville, NC
Contact:

Re: Displaying several images (BLOBs) at once in a WAM

Post by Dino »

Hi,

This is one idea, as always when programming, there are several ways to do the same:

Basically in this example, i show some blobs from the web, and some blobs from a table. Notice that the blobs from the web already have a published web address, so showing them in a list is simple. but the local ones, needed a bit more of effort, to recover the temporary path and moving (or copying) them to a published web folder.
The only change I did in the XSL was this:

Code: Select all

                        <img>
                           <xsl:attribute name="src">
                              <xsl:value-of select="$STD_STRNG" />
                           </xsl:attribute>
                        </img>

basically, i added and img line and the vvalue for src, is the value in the STD_STRNG in the list.

This is the WAM CODE:
WAM RDMLX Code
WAM RDMLX Code
wamblob1.png (68.58 KiB) Viewed 10667 times

Code: Select all

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_WAM)
Def_List Name(#imagelst) Fields(#std_strng) Type(*WORKING) Entrys(*MAX)
Webroutine Name(ShowImages)
Web_Map For(*BOTH) Fields(#imagelst)

Define Field(#wcommand) Type(*CHAR) Length(255)

* fill a few blobs in the list, note this blobs are in the published web already
#std_blob := 'https://www.google.com/logos/doodles/2020/december-holidays-days-2-30-6753651837108830.5-s.png'
#std_strng := #std_blob.FileName
Add_Entry To_List(#imagelst)

#std_blob := 'https://media3.giphy.com/media/LW5vBvAb48Oe9OoEKT/200.gif'
#std_strng := #std_blob.FileName
Add_Entry To_List(#imagelst)

* but the next blobs are not, they are local in my database
#std_count := 0
Select Fields(#xEmployeeImage) From_File(xEmployeeImages)
* just reading the first 10
Leave If(#std_count > 10)
#std_count += 1

#STD_STRNG := #xEmployeeImage
* std_strng will have a value like: C:\SWLANSA\LANSA\tmp\lobwam\5c395301-3f73-41b8-b7ef-51e09c3bba32\xempimage\xempimg\female-1.png which we cant use in the web.
* one idea, i could copy this file to a published web location

If (*CPUTYPE = AS400)
* * AS400
#wcommand := 'CPY OBJ(' + #quote + #std_strng + #quote + ') TODIR(' + #quote + '/LANSA_dcxpgmlib/webserver/images' + #quote + ')'
Exec_Os400 Command(#wcommand) If_Error(*NEXT)
#STD_STRNG := 'http://as400instalation:8080/images/temp/' + #STD_STRNG.Substring( (#STD_STRNG.LastPositionOf( '/' ) + 1), 255 )
Else
* Windows
#wcommand := 'cmd/c "' + "copy /Y" + #std_strng + ' C:\SWLANSA\LANSA\WebServer\Images\temp"'
Use Builtin(SYSTEM_COMMAND) With_Args(S #wcommand) To_Get(#std_num)
#STD_STRNG := 'http://localhost:8080/images/temp/' + #STD_STRNG.Substring( (#STD_STRNG.LastPositionOf( '\' ) + 1), 255 )
Endif

Add_Entry To_List(#imagelst)
Endselect
Endroutine
End_Com
and this is the full XSL (only change was adding that img section):
XSL
XSL
wamblob2.png (59.63 KiB) Viewed 10667 times

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!-- WAM       : testw12 - test wam
     Webroutine: ShowImages - 
     Timestamp : 2020-12-02T11:28:52-05:00 -->
<xsl:transform version="1.0" exclude-result-prefixes="lxml wd"
               xmlns:lxml="http://www.lansa.com/2002/XML/Runtime-Data"
               xmlns:wd="http://www.lansa.com/2002/XSL/Weblet-Design"
               xmlns="http://www.w3.org/1999/xhtml"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:import href="std_keys.xsl" />
   <xsl:import href="std_variables.xsl" />
   <xsl:import href="std_hidden.xsl" />
   <xsl:import href="testw12_layout.xsl" />
   <xsl:import href="std_image.xsl" />
   <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8"
               indent="no" />

   <xsl:template match="/">
      <xsl:call-template name="layout" />
   </xsl:template>

   <xsl:template match="/lxml:data">
      <xsl:apply-templates select="/lxml:data/lxml:lists/lxml:list[@name='IMAGELST']"
                           wd:listname="IMAGELST">
         <xsl:with-param name="allowSort" select="true()" />
         <xsl:with-param name="allowColResize" select="true()" />
         <xsl:with-param name="rowHoverEffect" select="false()" />
         <xsl:with-param name="selectableRows" select="false()" />
         <xsl:with-param name="hide_header_if_empty" select="true()" />
         <xsl:with-param name="resizeOnLoad" select="true()" />
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="/lxml:data/lxml:lists/lxml:list[@name='IMAGELST']">
      <xsl:param name="allowSort" select="true()" wd:type="std:boolean"
                 wd:tip_id="" />
      <xsl:param name="allowColResize" select="true()" wd:type="std:boolean"
                 wd:tip_id="" />
      <xsl:param name="rowHoverEffect" select="false()" wd:type="std:boolean"
                 wd:tip_id="" />
      <xsl:param name="selectableRows" select="false()" wd:type="std:boolean"
                 wd:tip_id="" />
      <xsl:param name="hide_header_if_empty" select="true()"
                 wd:type="std:boolean" wd:tip_id="" />
      <xsl:param name="resizeOnLoad" select="true()" wd:type="std:boolean"
                 wd:tip_id="" />
      <xsl:variable name="thelist"
                    select="/lxml:data/lxml:lists/lxml:list[@name='IMAGELST']" />
      <input type="hidden" name="IMAGELST.."
             value="{count(lxml:list-entries/lxml:entry[1])}" />
      <div id="IMAGELST_wrap" class="std_grid_wrapper">
         <xsl:if test="$lweb_design_mode">
            <xsl:attribute name="class">std_grid_wrapper_designtime</xsl:attribute>
         </xsl:if>
         <table id="IMAGELST" class="std_grid ui-widget">
            <xsl:if test="not($hide_header_if_empty) or ($thelist/@row-count != 0)">
               <thead>
                  <tr class="list-h ui-widget-header">
                     <th class="utext STD_STRNG std_grid_sort_indicator"
                         __decimalseparator="" __formattype="varchar"
                         __mode="input" __allowsort="true">
                        <xsl:for-each select="$thelist/lxml:list-header/lxml:header[1]/*[.//text()[normalize-space(.)!='']]"
                                      wd:edit-as-list="false">
                           <xsl:value-of select="." />
                           <xsl:if test="not(position() = last())">
                              <br />
                           </xsl:if>
                        </xsl:for-each>
                        <div class="std_grid_cell_sizer">
                           <xsl:if test="boolean(/lxml:data/lxml:context[@design])">
                              <xsl:attribute name="class">hidden__</xsl:attribute>
                           </xsl:if>
                           <xsl:comment>.</xsl:comment>
                        </div>
                     </th>
                  </tr>
               </thead>
            </xsl:if>
            <tbody class="ui-widget-content">
               <xsl:for-each select="$thelist/lxml:list-entries/lxml:entry">
                  <xsl:variable name="STD_STRNG" select="lxml:column[1]" />
                  <tr __oddrc="list-o" __evenrc="list-e">
                     <xsl:attribute name="class">
                        <xsl:choose>
                           <xsl:when test="position() mod 2">list-o</xsl:when>
                           <xsl:otherwise>list-e</xsl:otherwise>
                        </xsl:choose>
                     </xsl:attribute>
                     <td class="STD_STRNG">
                        <xsl:attribute name="__cellvalue">
                           <xsl:value-of select="$STD_STRNG" />
                        </xsl:attribute>
                        <img>
                           <xsl:attribute name="src">
                              <xsl:value-of select="$STD_STRNG" />
                           </xsl:attribute>
                        </img>
                     </td>
                  </tr>
               </xsl:for-each>
            </tbody>
         </table>
      </div>
      <script type="text/javascript">
         <xsl:call-template name="apply-csp-nonce.private" />
         <xsl:text disable-output-escaping="yes">//&lt;![CDATA[</xsl:text>
register_std_grid('IMAGELST',{
 columns: 1,
 allowSort: <xsl:value-of select="$allowSort" />,
 allowColResize: <xsl:value-of select="$allowColResize" />,
 hoverEffect: <xsl:value-of select="$rowHoverEffect" />,
 selectableRows: <xsl:value-of select="$selectableRows" />,
 resizeOnLoad: <xsl:value-of select="$resizeOnLoad" />
});
<xsl:text disable-output-escaping="yes">//]]&gt;</xsl:text>
      </script>
   </xsl:template>

   <xsl:template match="/lxml:data" mode="content.hidden">
      <xsl:apply-imports />
   </xsl:template>
</xsl:transform>
and this is the run:
Run
Run
wamblob3.png (167.94 KiB) Viewed 10667 times
Joop
Posts: 26
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Re: Displaying several images (BLOBs) at once in a WAM

Post by Joop »

Hi Dino,

Thanks for your reply and time to make this example. I've tried it on our system and it works like a charm!
I'm very happy :D
--
Regards,
Joop Roseboom
User avatar
Dino
Posts: 472
Joined: Fri Jul 19, 2019 7:49 am
Location: Robbinsville, NC
Contact:

Re: Displaying several images (BLOBs) at once in a WAM

Post by Dino »

Just a heads up if you using the copy from temporary blob location folder to published web, the temporary blob location is an individual unique named folder, while the published location in this example is not. so if two users try to copy the same name of the image, you may run in a problem of one replacing each other. depending in what you are doing that could be ok, or not.

Adding replace(*Yes) could be all needed sometimes, or you may want want to rename the files before moving there, etc. I did solve the issue in another case, taking the unique folder name and joining it to the name of the file in a rename operation, to conserve the uniqueness.
Joop
Posts: 26
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Re: Displaying several images (BLOBs) at once in a WAM

Post by Joop »

Hi Dino,

I did indeed put the REPLACE(*YES) in the copy statement but that's okay the way we are using it. But thanks for the heads up!
Thanks again for your reply.
--
Regards,
Joop Roseboom
Post Reply