Friday, December 28, 2018

Preview Image before save





This post is about how to preview image before save. Our customers wants to see what image was uploaded and next to save it so we read below instruction and we able to how implement this feature.


Before start it it' better to read this post about Setter & Getter API in Oracle APEX because I've used that.


Demo application: OAC

Download files and sample application via APEX-PreviewImageBeforeSave












Adding JS Files

We need to upload js files via APEX-PreviewImageBeforeSave




Now we should do something step by step

This sample has two pages [5] for Manipulating data ,[6] for adding image.

First of all, we add two buttons in front of item that we need to upload image in terms of subject at Page 5 according below images.

The item in this page is P5_PRODUCT_NAME



So add codes in Post text of Item.

<a aria-label="Uploda image" class="a-Button a-Button--popupLOV" 
href="&P5_TEMP_IMAGE." id="upload-img-pro" style="background-color: &P5_BUTTON_COLOR.;"
title="upload image">
<span aria-hidden="true" class="fa fa-file-image-o  fa-anim-flash 
fam-25-percent fam-is-danger" style="color: red; font-size: 1.4rem; 
vertical-align: top;"></span></a>
<a aria-label="Clear" class="a-Button a-Button--popupLOV 
image-remove" href="javascript:void(0);" title="Delete image">
<span class="fa fa-close"></span></a>         



Create Upload Url when we click on upload image on page 5

BEGIN
   :P5_TEMP_IMAGE := apex_util.prepare_url (p_url => 'f?p='
                                             || :APP_ALIAS
                                             || ':6:'
                                             || :SESSION
                                             ||'::NO::P6_ID,P6_SEQ:'||:P5_PRODUCT_ID||',1',
                                      p_triggering_element => '$(''body'')'
                                     );           
END;




As I mentioned the first of blog we used some packages for manipulation of image file. Now we create a process for remove parameter the content of image when page loads.

Purge Parameters:

--remove parameters
APEX_PKG_PARAMS.purgeparams; 







Add a new parameter of blob. the default sequences of array is 1 and we could setting several of values.


APEX_PKG_PARAMS.setparamblob(p_param => empty_blob(),                                                           p_count_seq => 1);






This process is for checking image file in order to change the color of upload button.


declare
    l_filesize number;
begin
    If :P5_PRODUCT_ID Is Not Null Then
        select nvl(dbms_lob.getlength(PRODUCT_IMAGE),0)
        into   l_filesize
        from   TDEMO_BLOB
        where  product_id = :P5_PRODUCT_ID;
        
        if l_filesize > 0 then
               :P5_BUTTON_COLOR := '#19e30c';
        else
               :P5_BUTTON_COLOR := '#f8f8f8';
        end if; 
    End If;                                   
end;






Now, we add two Dynamic Action on page 5 {Delete Image & Close Dialog). 

Step by Step we add some true Actions.(Below Images are clear and we don't need to explain about each image)

Delete Image:



Close Dialog:









Create true Actions below of Delete Image:
Confirm





Create true Actions below of Delete Image:
Execute PL/SQL CODE


Update TDEMO_BLOB set PRODUCT_IMAGE = empty_blob()
where  PRODUCT_ID = :P5_PRODUCT_ID;
APEX_PKG_PARAMS.setparamblob(p_param => empty_blob(),
                             p_count_seq => 1);





Create true Actions below of Delete Image:
Set Style






Create true Actions below of Close Dialog:
Execute PL/SQL CODE


:P5_TEMP_SIZE:= nvl(dbms_lob.getlength(APEX_PKG_PARAMS.getparamblob(p_seq => 1)),0);






Create true Actions below of Close Dialog:
Execute Javascript CODE


if (apex.item( "P5_TEMP_SIZE" ). getValue() > 0) 
   $("#upload-img-pro").css("background-color", "#19e30c");
else
   $("#upload-img-pro").css("background-color", "#f8f8f8");







How to save image file?
we need to create a new process for saving upload file.

Update TDEMO_BLOB set PRODUCT_IMAGE = APEX_PKG_PARAMS.getparamblob(p_seq => 1)
where  PRODUCT_ID = :P5_PRODUCT_ID;





Next major step on Page 6


we add below URL and JavaScript codes on page level

#APP_IMAGES#js.cookie.js





/******************************************************* */

/*https://www.jqueryscript.net/zoom/

*/

/*!

 * jQuery Page Zoom Plugin v1.1

 *

 * Description:

 * Allow the user to zoom in or out on the page using links or buttons (anything that will accept an onClick event).

 *

 */

!function(o) {

    o.page_zoom = function(e) {

        var m = {

            max_zoom: 2,

            min_zoom: .5,

            zoom_increment: .1,

            current_zoom: 1,

            selectors: {

                zoom_in: ".zoom_in",

                zoom_out: ".zoom_out",

                zoom_reset: ".zoom_reset"

            }

        }

          , t = !1

          , n = {

            init: function(e) {

                "object" == o.type(e) && (m = o.extend(m, e)),

                "undefined" != typeof Cookies && (t = !0),

                t && null == Cookies.get("page_zoom") ? Cookies.set("page_zoom", 1) : (t ? m.current_zoom = parseFloat(Cookies.get("page_zoom")) : m.current_zoom = 1,

                1 != m.current_zoom && n.set_zoom(m.current_zoom)),

                o(m.selectors.zoom_in).bind("click", n.zoom_in),

                o(m.selectors.zoom_out).bind("click", n.zoom_out),

                o(m.selectors.zoom_reset).bind("click", n.zoom_reset)

            },

            set_zoom: function(e) {

                o(".image-zoom").css({ //class name of P6_IMAGE

                    zoom: e,

                    "-moz-transform": "scale(" + e + ")",

                    "-moz-transform-origin": "0 0"

                }),

                m.current_zoom = e,

                t && Cookies.set("page_zoom", e)

            },

            zoom_in: function() {

                var o = parseFloat(m.current_zoom + m.zoom_increment);

                o < m.max_zoom ? n.set_zoom(o) : n.set_zoom(m.max_zoom)

            },

            zoom_out: function() {

                var o = parseFloat(m.current_zoom - m.zoom_increment);

                o > m.min_zoom ? n.set_zoom(o) : n.set_zoom(m.min_zoom)

            },

            zoom_reset: function() {

                n.set_zoom(1)

            }

        };

        n.init(e)

    }

}(apex.jQuery);


/******************************************************* */

$(document).ready(function() {

 $.page_zoom();

});



Css codes:

/*hide scroll on modal dialog*/

.t-Dialog-bodyWrapperIn {

    overflow: hidden !important;

} 



.center-div

{

  margin: auto;

    z-index: 800;

  top: 0;

  right: 0;

  bottom: 0;

  left: 0;

  overflow: auto; 

  width:360px; 

  height:250px; 

  text-align: center;

  display: block;

}



span.b-zoom {

    font-size: 1.4rem; 

    vertical-align: top;

}



for prevent error ajax set this property to "Always"






Add a new region with six items and set properties like images






P6_UPLOAD_FILE









<a class="a-Button a-Button--popupLOV zoom_in" id="zoom_in" aria-label="zoom in" title="zoom in" href="javascript:void(0);"><span aria-hidden="true" class="fa fa-plus-square b-zoom"></span>
</a>
<a class="a-Button a-Button--popupLOV zoom_out" id="zoom_out" aria-label="zoom out" title="zoom out" href="javascript:void(0);"><span aria-hidden="true" class="fa fa-minus-square b-zoom"></span>
</a>
<a class="a-Button a-Button--popupLOV zoom_reset" id="zoom_reset" aria-label="zoom reset" title="zoom reset" href="javascript:void(0);"><span aria-hidden="true" class="fa fa-refresh  b-zoom"></span>
</a>




This item uses for display image file

P6_IMAGE

select APEX_PKG_PARAMS.getparamblob(p_seq => :P6_SEQ)
from dual









if nvl(dbms_lob.getlength(APEX_PKG_PARAMS.getparamblob(p_seq => :P6_SEQ)),0) > 0 then
return true;
else
return false;
end if;








DELETE Button







if nvl(dbms_lob.getlength(APEX_PKG_PARAMS.getparamblob(p_seq => :P6_SEQ)),0) > 0 then
return true;
else
return false;
end if;







Now, we add three Dynamic Action on page 6 {Extension checker / Submit / Delete Image). 

Step by Step we add some true Actions.(Below Images are clear and we don't need to explain about each image)



Extension Checker:





Submit:




Delete Image:






Create true Actions below of Extension Checker:
Execute JavaScript Code


//control extension file

var filename = apex.item("P6_UPLOAD_FILE").getValue();

var validExts = new Array(".jpg", ".gif", ".png");

var fileExt = filename;

fileExt = fileExt.substring(fileExt.lastIndexOf('.'));

if (validExts.indexOf(fileExt) < 0) {

  /*apex.item("P6_UPLOAD_FILE").setValue('');*/

    alert("فايل شما نامعتبر مي باشد، از فايل ها معتبر استفاده كنيد " +

           validExts.toString());

  

  return false;

}

else return true;







Create true Actions below of Submit:
Execute JavaScript Code


//reset image size

$('.zoom_reset').trigger('click');





Create true Actions below of Submit:
Submit Page






Create true Actions below of Delete Image:
Execute PL/SQL Code


APEX_PKG_PARAMS.setparamblob(p_param => empty_blob(),
                             p_seq  => :P6_SEQ);
:P6_ID := null;






Create true Actions below of Delete Image:
Execute JavaScript Code


$("#P6_IMAGE").remove();

$(".image-div").remove();

$("#deleteimg").remove();








we need to create a new process for setting image file temporary and parameter.

declare
    l_filecontent BLOB;
    l_filename VARCHAR2(400);
begin

    If :P6_UPLOAD_FILE Is Not Null Then
        Select FILENAME, BLOB_CONTENT
        Into   l_filename, l_filecontent
        From   apex_application_temp_files
        Where  NAME = :P6_UPLOAD_FILE;

        APEX_PKG_PARAMS.setparamblob(p_param => l_filecontent,
                                     p_seq  => :P6_SEQ);
    :P6_ID := null;
    End If;                                   
end;










Now we able to run and enjoy it!






3 comments :

  1. Replies
    1. Hi mustafa,

      The sample app is working also in this blog you able to implement step by step.

      Delete
  2. May i have full export of OAC application?

    ReplyDelete