Skip to Content

I’ve seen a few discussions like “Where’s my Image file when I publish my dashboard?” or similar.  It might be related to someone having put the image in a Favorites folder in the BO Platform or forgetting to migrate it up in whatever folder it’s in, or likewise in the SE80 MIME Repo on the NetWeaver side.

What a pain, I say.  Images should be a simple thing to deal with.  I lamented about this in a recent document with a workaround of Base-64 encoding the URI of the Image.

How to embed images inside of a Design Studio App without uploading to server.

This works, still, but I wanted to make it easier without leaving Design Studio to go off and Base-64 encode an Image and then copy and paste it back into Design Studio.  So I made (gasp) an SDK Component to do it for us.  I called it ‘SuperImage’ but in hindsight, maybe ‘SimpleImage’ is more accurate, as this is the smallest snippet of SDK code that was needed.  I decided to again use the SAPUI5 handler to get this done.  Here’s the component.js in its entirety.  You can see that it’s more comments than code.


sap.ui.commons.Image.extend("com.sample.superimage.SuperImage", {
  renderer : {},
  metadata : { // Not to be confused with the Data Source metadata property
  properties : {
  onclick : "string" // While 'onclick' is technically a DS Event, it does pass some information, so let's take it.
  }
  },
  initDesignStudio : function() {
  // Called by sap.designstudio.sdkui5.Handler  (sdkui5_handler.js)
  },
  // Override onclick setter to then attach/detach Design Studio event raising.
  setOnclick : function(s){
  /*
  * Geeking out for a moment:
  *
  * Conjecture, but the string that is passed appears to be a supporting JS command string.
  *
  * Example:
  * sap.zen.request.zenSendCommandArrayWoEventWZenPVT([['GUID','1',0],['BI_COMMAND_TYPE','ABSTRACT',0]]);
  *
  * This Command Array is ultimately passed to object 'sapbi_page' to so some server-side processing with.
  * The actual 'sap.zen.request.zenSendCommandArrayWoEventWZenPVT' should only be actually evaluated when the event is raised (on click).
  *
  * Those who enjoy picking through code can find this function call also on line 74 of 'sdkui5_handler.js' as well as other places
  * It also looks like it supports some sort of undocumented or yet-unimplemented SDK funclet thing...
  * The function itself is defined in 'bi_command_util.js' which is contained in 'com.sap.ip.bi.zen.rt.framework_12.0.2.201311041742.jar'
  *
  * Long story short, let's not eval it in the setter, and leave it alone.  But, let's see if there's any value so we can
  * attach or detach an event listener (so we get a proper mouse cursor)
  *
  * PS. Anyone having BEx WAD 7.0 flashbacks with references to 'sapbi_page' references? ;)
  *
  */
  if(s && s != ""){ // If there's onclick BIAL, then add an event listener (and get a hand cursor).
  this.attachPress(this.clickHandler);
  }else{ // If not, remove the event listener (which will get rid of the hand cursor, too)
  this.detachPress(this.clickHandler);
  }
  },
  clickHandler : function(){
  this.fireDesignStudioEvent("onclick");
  }
});

(Most people won’t care about the onclick commentary, but I found it interesting).  Moving on, the real magic happens in the additional_properties_sheet.js.  Using no server upload, I do all this within the JavaScript layer by using the FileReader API (FileReader – Web API Interfaces | MDN).


sap.designstudio.sdk.PropertyPage.subclass("com.sample.superimage.SuperImagePropertyPage",  function() {
  var that = this;
  this._src = "";
  this.init = function() {
  var that = this;
  $("#imageFile").change(function(e) {
  var input = e.target;
  if ( input.files && input.files[0] ) {
        var FR= new FileReader();
        FR.onload = function(e) {
            that._src = e.target.result;
            that.updateImage();
            that.firePropertiesChanged(["src"]);
        };    
        FR.readAsDataURL( input.files[0] );
    }else{
      alert("A problem occured reading the file.");
    }
  });
  if (window.File && window.FileReader) { /* Good to go... */ } else { // Display warning for pre-IE10 versions.
  alert('File APIs are not supported in this browser.  You probably need to be at IE10 or higher.');
  }
  };
  this.updateImage = function(){
    // Compute dimensions for image description snippet.
    var i = new Image();
        i.onload = function(){
        var w = i.width;
        var h = i.height;
        var imgDesc = w + " x" + h + " ("+i.src.length+" bytes)";
        $('#imgInfo').text(imgDesc);
        $('#base64').text(i.src);
        };
        i.src = that._src;
        $('#img').attr( "src", that._src );
  };
  this.src = function(value){
  if( value === undefined){
  return this._src;
  }else{
  this._src = value;
  this.updateImage();
  return this;
  }
  };
});

So what does the component do at runtime?  Let’s start and see:

Start by dragging in the component, and be greeted with a placeholder image:

/wp-content/uploads/2014/02/si1_379781.png

Let’s change the image by clicking on the Browse button and then selecting a local file:

/wp-content/uploads/2014/02/si2_379782.png

We can see that the image instantly changes (and has auto width and height, as a bonus).  You can then resize the image just like any other component, if you wish.

But what about reuse?  Hosted Image URLs can be referenced multiple times at no additional size costs.  If we were to copy this image over and over, yes the image data is copied.  For small iconography, who cares, but for larger backgrounds such as the one above, this could be a performance hit.  How to overcome?  One option would be to yes, host the dang image file, or….. use the scripting layer to copy image sources between images.  Provided with the source code is a full example, but for now, a snippet of the BIAL along with a short animation of the end-result:

/wp-content/uploads/2014/02/si3_379783.png

Example at run-time showing image data re-use (Click image not animating):

/wp-content/uploads/2014/02/si_example_379790.gif

Full source and example app is in the attached .zip (remove the .txt after downloading)

To report this post you need to login first.

6 Comments

You must be Logged on to comment or reply to a post.

  1. Mike Howles Post author

    I don’t see how this has to do with this blog post.  I’d suggest posting it as a new discussion so that it gets better attention.

    (0) 
  2. vivek kumar

    Hi Mike,

    I am new in DS SDK.

    can we use this code with handler type=”div” also?

    if no can you please help me to convert the code so that it will be compatible with div handler type also.

    (0) 

Leave a Reply