Quantcast
Channel: SAPUI5 Developer Center
Viewing all 789 articles
Browse latest View live

Google Maps library for UI5

0
0

There are a number of map providers available to use with UI5, none of them seemed to me to be as simple to use as Google Maps, so I wrote a library.

map1.png

 

Getting Started

Goto OpenUI5 Googlemaps Library Github page, download and install the library


Include the library


sap.ui.getCore().loadLibrary("openui5.googlemaps", "../openui5/googlemaps/");

 

Add a openui5.googlemaps control to your page

 

 

<?xml version="1.0" encoding="UTF-8" ?><mvc:View xmlns:mvc="sap.ui.core.mvc"    xmlns:gmaps="openui5.googlemaps"    controllerName="sampleController">    <gmaps:Map height="250px" zoom="12" lat="-33.895" lng="151.275">        <gmaps:markers>            <gmaps:Marker lat="-33.895" lng="151.275" info="Bondi Beach" />        </gmaps:markers>    </gmaps:Map></mvc:View>

 

Its as simple as that.

 

The openui5.googlemaps library supports Maps, Markers, Polylines and Polygons.

It also has Location detection and the ability to add an API key.

 

Along with the library there are also a number of sample applications to help get you started.

map2.png

The library if FOSS, contributions welcome, any issues please report through sapui5  - Stack Overflow

 

Enjoy


Consuming Web service in SAPUI5

0
0

This is a useful blog for beginners in ui5. This shows an example to consume the webservice in ui5 application. There are different ways in which this can be achieved. I have shown 2 methods in this blog. In both the methods, the input xml to the webservice is posted and the response is taken.

 

  • Parsing the xml response received from the webservice

var textArea = new sap.ui.commons.TextArea({

                     id : "textArea1"

});

var request = "<Your input xml to the webservice>”;

                    var response = "";

          $.ajax({

                 url : "Your webservice wsdl url",

                 type : "POST",

                 data : request,

                 dataType : "text",

                 contentType : "text/xml; charset=\"utf-8\"",

                 success : function(data, textStatus, jqXHR) {

                        response = data;

                 },

                 error: function(xhr, status)

                 {

                        console.log("ERROR");     

                 },

                 complete : function(xhr,status) {

                        uicontrols();

                 }

          });

                           function uicontrols(){

                     parser=new DOMParser();

                     xmlDoc=parser.parseFromString(response,"text/xml");

                                         var returnVal = xmlDoc.getElementsByTagName("The tag from response xml which you want")              [0].childNodes[0].nodeValue;

                     textArea.setValue(returnVal); //set the value to textArea

          }

 

  • Using XML model 

var request = "<Your input xml to the webservice>”;

                            var response = "";

              $.ajax({

                     url : "Your webservice wsdl url",

                     type : "POST",

                     data : request,

                     dataType : "text",

                     contentType : "text/xml; charset=\"utf-8\"",

                     success : function(data, textStatus, jqXHR) {

                           response = data;

                     },

                     error: function(xhr, status)

                     {

                           console.log("ERROR");     

                     },

                     complete : function(xhr,status) {

                           uicontrols();

                     }

              });

var oModel = new sap.ui.model.xml.XMLModel(); 

                           function uicontrols(){

                     oModel.setXML(response);

}

var oTable = new sap.ui.table.Table({

                     id: "table1"

});

             oTable.addColumn( 

                                          new sap.ui.table.Column({       

                                  label: new sap.ui.commons.Label({text: "Label1"}),       

template: new sap.ui.commons.TextField().bindProperty("value", "Tag1/text()"

})

              );

              oTable.addColumn( 

                                          new sap.ui.table.Column({       

                                  label: new sap.ui.commons.Label({text: "Label2"}),       

template: new sap.ui.commons.TextField().bindProperty("value", "Tag2/text()"

})

);

             oTable.setModel(oModel);  

             oTable.bindRows({path: "/the main XML tag under which Tag1 and Tag2 are present/"});


Thank you,

Navya

Online and Offline capability in HTML5

0
0

Hi,

 

Here we comes to know how to store data into HTML5 local database. HTML5 introduced Local storage concepts. The Main use for this concept was offline capabilities and local persisted storage features, you can deliver the same rich user experiences online and offline that were previously available only in proprietary desktop application development frameworks.HTML5 localStorage is synchronous and is currently the only database storage mechanism that is supported cross-platform and cross-browser.

 

 

 

How to use?

 

Step1 :

 

SetItems to Local DB:

 

Window.localStorage.setItem(“giveKeyValues”, “YourArrayItems”);

 

For ex :

Var serNumArr = [];//Create Array put your rec into this array

var notiNumRcvdString =    JSON.stringify(serNumArr);

              window.localStorage.setItem("NewSerialNumbersMob26",notiNumRcvdString);

 

Capture.JPG

 

 

 

 

GetItems from DB:

 

 

Window.localStorage.getItem(“giveKeyValues”);




newScanArray = window.localStorage.getItem("NewSerialNumbersMob26"); // It will return your rec

 

var getSerNumInArray = new Array();

              getSerNumInArray  = JSON.parse(newScanArray);// Convert your Db rec to Below format

 

 

                     Internal function of JSON.parse(newScanArray):

 

                     getSerNumInArray [0] = 124567

 

getSerNumInArray [1] = 1245789 ...

 

 

 

Remove Items:

  Window.localStorage.removeItems(“giveKeyValues”);


It will remove Items based on your KeyValue

 

 


Thanks,

Karthik A

Inherit Third Party Library into SAPUI5

0
0

Hi,

 

Here i will explain about how to insert third party library to SAPUI5 and how to use that library file.

 

Tables in SAPUI5 : sap.ui.table.Table [ Here we cant able to use nested tables ]

 

Nested Tables Ex:  

 

Capture3.JPG

 

 

Insert Third Party Lib:

 

Capture1.JPG

 

 

define nested table in HTML tags:

 

 

<table id="example" class="display" cellspacing="0" width="100%">

        <thead>

            <tr>

                <th>Name</th>

                <th>Position</th>

                <th>Office</th>

                <th>Age</th>

                <th>Start date</th>

                <th>Salary</th>

            </tr>

        </thead>

 

        <tfoot>

            <tr>

                <th>Name</th>

                <th>Position</th>

                <th>Office</th>

                <th>Age</th>

                <th>Start date</th>

                <th>Salary</th>

            </tr>

        </tfoot>

 

 

 

Ref Link:

 

http://www.datatables.net/

 

 

Thanks,

Karthik A

Create Component-preload.js using Gulp

0
0

Before I begin with the topic I would like to give a brief introduction about Gulp.

Gulp.js is a open source JavaScript Task Runner. You can easily automate task like

minification, compilation, unit testing, linting, etc

 

Use the -g options to install Gulp globally on your machine.

npm install -g gulp

 

Component-preload.js is a step taken by SAP Fiori to improve performance.

This file is automatically called by the framework on the time of loading.

The below given code is used by me in a project to construct Component-preload.js .

// Include gulp

var gulp = require('gulp');

 

// Include Our Plugins

 

var jshint = require('gulp-jshint');

var concat = require('gulp-concat');

var rename = require('gulp-rename');

var uglify = require('gulp-uglify');

var minifyHTML = require('gulp-minify-html');

var tap = require('gulp-tap');

var writeFile = require('writefile');

var path = require('path');

 

 

  var sMyAppName = "testapp";

  var sFilename = 'Component-preload';

  var fPath;

  var sFileTmp;

  var sFileNameQ;

console.log(sMyAppName);

   var oComp = {

   name: sMyAppName  + "/" + sFilename , //testapp.component-preload

   version: "2.0",

   modules:{}

}

 

 

gulp.task('scripts', function() {

 

 

  return gulp.src(['testapp/WebContent/*.js','testapp/WebContent/view/*.js'])

  .pipe(uglify())

  .pipe(tap(function(file) {

            fPath =  sMyAppName + '/' + path.basename(file.path);

            oComp.modules[fPath] = file.contents.toString();

  }));

  });

 

 

gulp.task('scripts_1', function() {

 

 

  return gulp.src(['testapp/WebContent/view/*.xml'])

  .pipe(minifyHTML({comments:true}))

  .pipe(tap(function(file) {

            fPath =  sMyAppName + '/' + path.basename(file.path);

            oComp.modules[fPath] = file.contents.toString();

  }));

  });

 

 

  console.log(oComp);

  setTimeout(function(){

 

  sFileTmp = 'jQuery.sap.registerPreloadedModules(' + JSON.stringify(oComp) + ')';

  sFileNameQ = sFilename + '.js';    //Component-preload.js

 

     writeFile( sFileNameQ , sFileTmp, function(err) {

                if (err) throw err;

                console.log('It\'s saved!');

            });

  },1000);

 

  gulp.task('default', ['scripts','scripts_1']);

 

I am also looking into another ways to optimize Fiori Performance.

Please let me know of you guys have some suggestions.

Using Camera as Barcode scanner on your mobile device in SAPUI5 app

0
0

One question that I get very often form my customers is: "How can I use all this mobile device functions like camera, GPS and all the other stuff in a Web Application?".

 

As you might know the browser runs the Webpage in a sandbox for safety reasons. Direct access to devices like camera is not possible. Because of that reason we need to run the webpages in a native app.

 

This is exactly was Apache Cordova does. You can run your Webpages in a native app and access all devices via JavaScript. One other big advantage is, that all pages are on your device, so the performance is higher than in a browser.

 

For a prove of concept I choose the SAP Fiori like App from this great tutorial:

Building SAP Fiori-like UIs with SAPUI5 in 10 Exercises

 

The Idea

After finishing this Exercises I have a nice Fiori like app that is running in a browser. What I want to do is to use the camera of my iPad as a Barcode scanner. This are two tasks in one step. First we have to use the camera to scan the barcode an second the barcode must be translated from a picture to a value. That seems to be a good testcase.

 

I was surprised how easy it was to build this function. I will show the steps and the needed code.

 

At the end the application will look like this:

 

Barcode2.jpg

After pressing the Camera next to the Search Field, the Camera will be started and you can start to scan the Barcode. The result will be written into the Search Field and filter the list.

 

Barcode3.jpg

 

The Environment

Some information of my environment. I run Eclipse on a Mac. We bring the App on an iPad and using the camera of the iPad. To do this you need to install Xcode on you Mac and you need a membership of the Apple Developer Program, what costs 80 Euro for one year.

 

This app won't run in the simulator of Xcode, because you can't use the camera in the simulator.

 

I expect that the shown solution also runs on android or other devices, but I didn't test it. I would be happy for every feedback.

 

Create a Cordova Project from our SAP Fiori like App

We start at the point when you finishing the development of the SAP Fiori liked App. The next step is to install Apache Cordova. How to do this and how to create a Cordova Project is described on the following page:

Installing and running the command line interface of Apache Cordova

 

The next steps are very easy and straight forward. Copy all files of the "WebContent" folder of your Eclipse project into the "WWW" Folder of your Cordova project. Furthermore we need the resource files of SAPUI5. What I have done is to download the OPENUI5 runtime from OPENUI5 on GITHub.This project is able to run with OPENUI5, what is even more cooler.

 

Copy the recource Folder of OPENUI5 into the "WWW" Folder of the Cordova project. There are probably better solutions than to copy the folder in every project, but for this proof we use this very easy solution.

 

We are already at the point, where you can run out Fiori like app as a native app on your device. With the following command Cordova will build an iOS Xcode project:

 

$ cordova platform add ios

 

Open the new Xcode project that is created in the folder "platforms" of your Cordova project and run it. You can run it direct on your iPad or in the simulator. At this point we can run it in the simulator, because we don't use the Camera so far.

 

If you want to build a native app on other platforms you can create it in the same way.

 

If you added the platform once, you should never change the source in the platform folder. After changing the source in the "WWW" folder of your Cordova project, you can update the platform depended code with:

 

$ cordova build ios

 

The Barcode scanner

Now we can start to develop the Barcode scanner. Actually we don't develop it by our own, we use a Cordova plugin. First of all you have to add the Plugin into your Cordova project. The following page is a good starting page, if you need a Barcode scanning example that is running on its own:

 

GitHub Barcode Example

 

As described on this page, we add the needed Plugin to our Cordova project with the following command line

 

$ cordova plugins add https://github.com/wildabeast/BarcodeScanner.git

 

Now we are at the most interesting part. We want that our SAP Fiori like App and the Barcode Scanner are playing together.

 

First we have to change the index.html. We have to add the Cordova Script

 

Barcode_indexhtml.jpg

The next step is to add the Button next to the Search field. We do this in the Master.View.xml

 

Barcode_MasterViewXML.jpg

 

The last but important changes are in Master.Controller.js.

- We build a handle for the Camera button

- We separate the filter in an own function, that it can be called after the scan

- We use sap.m.message.toast to output messages

 

Here are the changes of Master.Controller.js form the top

 

First we add the sap.m.MessageToast library

Barcode_MasterController1.jpg

Second we change the handleSearch, that it calls our new function doFilter. The app should run without this change, but I love clean code:

 

Barcode_MasterController2.jpg

 

Next we build the new handleCamera, that is called after pressing the Camera button. Here you can see that most of the work is done by the Plugin.

 

Barcode_MasterController3.jpg

 

And last we build our new function doFilter that is called by handleSearch and handleCamera

 

Barcode_MasterController4.jpg

That's it!

 

Copy all that changes into your Cordova project, build the platform depended code again as describe, start Xcode and run this project on your iPad.

 

Have fun!

 

Upload Image to SAP Gateway and Display Image in UI5 - Using New Fileuploader with SAP Gateway

0
0

I have prepared oData service that can handle uploading and downloading files using SAP gateway in blog post Uploading Files to SAP GW, Downloading Files from SAP GW - New Techniques. Based on this oData service, I created ui5 application that is described in this blog post.

 

Issues with Fileuploader and SAP gateway

There are few reasons why sap.ui.commons.fileuploader was not able to work with SAP gateway properly:

  • SAP Gateway could not receive multipart/form-data mime type as pointed out byJibin Joy in Re: File Attachment using gateway
  • Fileuploader could not send form data as AJAX call to send the form with different mimetype. Extending of Fileuploader was necessary to solve this issue as shown by John Patterson in Re: FileUploader and X-CSRF-Token?
  • When sending the post request to oData service, we also need to supply CSRF token to Gateway, what was not possible without extending Fileuploader.

 

Good news, bad news

As of openUI 1.21, sap.ui.commons.Fileuploader is deprecated and we should use sap.ui.unified.Fileuploader. Please refer to OpenUI5 SDK - Demo Kit. Good news are that there are built-in methods that can send file as AJAX call and also allows us to set header fields. Bad news are that it will still not work with IE8/9.

 

Implementing critical part in OpenUI5

I have prepared basic UI5 service that can manage (add, edit, delete) users. More details for this prerequisite is written in my blog post. Further, I will show how to extend this application with new options to upload Image for user and show the file in user's card.

http://www.abap-developers.com/wp-content/uploads/2014/07/ui1.jpg

Uploading image via Fileuploader

  • We need to refresh CSRF token(line 5) and use it as a header parameter (line 14).
  • Set sendXHR parameter(line 11), which will make fileuploader send data as AJAX call
  • Set useMultipart(line 12) to false, mimetype of uploaded file will be send.
  • Set slug header parameter and fill it with filename so we can read it in Gateway (line 29)

 

    /*****   Upload dialog  *****/    function openUploadDialog(user){         var oUploadDialog = new sap.ui.commons.Dialog();        oUploadDialog.setTitle("Upload photo");        sap.ui.getCore().getModel().refreshSecurityToken();        // prepare the FileUploader control        var oFileUploader = new sap.ui.unified.FileUploader({            uploadUrl : "your_service/UserSet('"+ user[0].getValue() +"')/Photo",            name: "simpleUploader",             uploadOnChange: false,            sendXHR: true,            useMultipart: false,            headerParameters: [                new sap.ui.unified.FileUploaderParameter({name: "x-csrf-token", value: sap.ui.getCore().getModel().getHeaders()['x-csrf-token'] }),                ],            uploadComplete: function (oEvent) {                var sResponse = oEvent.getParameter("response");                if (sResponse) {                    oUploadDialog.close();                    sap.ui.commons.MessageBox.show("Return Code: " + sResponse, "Response", "Response");                }            }                            });        // create a button to trigger the upload        var oTriggerButton = new sap.ui.commons.Button({             text:'Upload',             press:function() {                 // call the upload method                 oFileUploader.insertHeaderParameter(new sap.ui.unified.FileUploaderParameter({name: "slug", value: oFileUploader.getValue() }));                 oFileUploader.upload();              }         });        oUploadDialog.addContent(oFileUploader);        oUploadDialog.addContent()        oUploadDialog.addContent(oTriggerButton);        oUploadDialog.open();   }

Displaying image in UI5

I have used Image element for displaying image. Just point source of the file to your Gateway are that's it.

     var oImage = new sap.ui.commons.Image({width: "200px"});     oImage.setSrc("your_service/UserPhotoSet('"+ user[0].getValue() +"')/$value");

Implemented application

You can find whole source code of my application in github - Upload Image in UI5. Backend part source codes are in document Code snippets for Uploading Files to SAP GW, Downloading Files from SAP GW - New Techniques.

 

When you select line with user and click on upload's user photo button, you can send image to Gateway.

ui5-app1.JPG

 

When you select line with user and show his user card, you will see his photo:

ui5app-2.JPG

 

Open issue and conclusion

I did not proposed any workaround for IE8/9. But when I was implementing the application I noticed that in higher SP of SAP Gateway I could read the multipart/form-data mimetype in CREATE_STREAM method, request body was in value of media resource. Maybe it is possible to read and parse those data, we would no need even AJAX call for fileuploader. But this solution would need more research. I hope you enjoy this blog.

SAPUI5: Numbers only textfield & Currency Textfields

0
0

Introduction

 

     In many cases when we develop web pages for business purposes, we may need to limit the text field numeric only(age,phone numbers etc). Same way, customers need the currency to be entered separated by comma,instead of seeing it as plain numbers. Here I am adding the code snippets to make the SAPUI5 text field to cater both the cases.

 

Create a Plain SAPUI5 TextField(sap.ui.commons.TextField)

 

var textbox = new sap.ui.commons.TextField("data",{  textDirection : sap.ui.core.TextDirection.RTL  });

Making the TextField to accept only numbers :

 

     For this, we need to register browser event "keypress" for the textbox, so that the corresponding event handler would handle the pressed key, and check if it is a number or not.

 

textbox.attachBrowserEvent("keypress",function(e){  var key_codes = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 8];            if (!($.inArray(e.which, key_codes) >= 0)) {              e.preventDefault();            }        });

where , [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 8] is the array of ASCII values ranging from 0 to 9. It makes sure that the hit key is in this range.

Now the text box is numbers only.

 

Making theTextField  as a Currency field

    

     All we need is to define a JavaScript function to put the comma between the digits properly, and handle the decimal places. Here, for this example, I consider INR so that the comma separation will be 3,2,2.. pattern and is having 2 decimal places.

          Instead of keypress , we will be using keyup event to capture the data.

 

textbox.attachBrowserEvent("keyup",function(e){  var Number1 = e.srcElement.value; // source element pointer with data     var CommaSeperaterList = '3,2,2,2,2,2,2,2,2';     var Number = Number1.replace(/\,/g, '');     var myArray = CommaSeperaterList.split(',');     var newNum = "";     var newNum2 = "";     var end;     var count = 0;     if (Number.indexOf('.') != -1) {                 places = Number.length - Number.indexOf('.') - 1;         if (places >= 3) {              num = parseFloat(Number);             Number = num.toFixed(2);         }         var a = Number.split(".");         Number = a[0];            end = '.' + a[1];     }     else { var end = ""; }     var q = 0;     for (var k = Number.length - 1; k >= 0; k--) {         ar = myArray[q];         var oneChar = Number.charAt(k);         if (count == ar) {             newNum += ",";             newNum += oneChar;             count = 1;             q++;             continue;         }         else {             newNum += oneChar;             count++;         }     }     for (var k = newNum.length - 1; k >= 0; k--) {         var oneChar = newNum.charAt(k);         newNum2 += oneChar;     }     e.srcElement.value = newNum2 + end;        });

where, '3,2,2,2,2,2,2,2,2' is being the comma places. Based on the currency type, we can change it and adapt new comma separation system.

Number = num.toFixed(2); statement fixes the decimal places to 2.

 

snip.JPG

 

Regards,

Sreehari.


Integrate OpenUI5 and Google App Engine on Python runtime

0
0

I am playing a little bit with Google App Engine (GAE) and as first thing I tried to integrate OpenUI5 in a demo app.

 

My app is just showing a list of projects and let the user to create a new project.

Here a screen:

Screen Shot 2014-08-01 at 12.54.25.png

 

Detailed info for Google App Engine SDK installation can be found in the official documentation:

 

Download the Google App Engine SDK - Google App Engine &amp;mdash; Google Developers

 

I also used PyDev eclipse plugin as IDE.

 

For OpenUI5 SDK, you can download it from here (I used version 1.22.4):

 

OpenUI5 - Download

 

On App Engine side, my application is built on three main python modules:

 

models/project.py --> it is the model; it creates one Datastore entity - Projects - with two characteristics: project_id and project_description and it implements three functions:

  1. get_projects: returns all created projects
  2. get_project: returns one single project
  3. put_project: creates a new project

 

from google.appengine.ext import db
class Projects(db.Model):    project_id = db.StringProperty(required=True, )    project_description = db.StringProperty(required=True)
def get_projects():    list_of_projects = []    q = db.GqlQuery("SELECT * FROM Projects")    for p in q.run():        current_project = { 'project_id' : p.project_id, 'project_description' : p.project_description}        list_of_projects.append(current_project)    return list_of_projects
def get_project(project_id=None):    if not project_id:        return None    key = db.Key.from_path('Projects', project_id)    project = db.get(key)    if not project:        return None    return project
def put_project(project_id, project_description):    query = Projects.all(keys_only=True).filter('project_id', project_id)    entity = query.get()    if entity:        raise Exception('unique_property must have a unique value!')    project = Projects(project_id=project_id, project_description=project_description)    project.put()

main.py --> Is the main request handler for the GAE application (MainPage class is the handler)

 

import datetime
import jinja2
import os
import webapp2
from google.appengine.api import users
template_env = jinja2.Environment(  loader=jinja2.FileSystemLoader(os.getcwd()))
class MainPage(webapp2.RequestHandler):    def get(self):        current_time = datetime.datetime.now()        current_user = users.get_current_user()        login_url = users.create_login_url(self.request.path)        logout_url = users.create_logout_url(self.request.path)        template = template_env.get_template('templates/index.html')        context = {                  'current_time' : current_time,                  'current_user' : current_user,                  'login_url' : login_url,                  'logout_url' : logout_url,                  }        self.response.out.write(template.render(context))
application = webapp2.WSGIApplication([('/', MainPage)],                                      debug=True)

projects_handler.py --> is the handler for a POST request to create a new project and a GET request to get all projects in a JSON format (I haven't found a good solution to espose the data via odata in python, some comments here would be really appreciated)

 

import webapp2
import json
from models import projects
class PostProject(webapp2.RequestHandler):    def post(self):        try:            project_id = self.request.get('project_id')            project_description = self.request.get('project_description')            projects.put_project(project_id, project_description)        except:            self.response.set_status(500)            return        self.response.set_status(200)    
class GetProjects(webapp2.RequestHandler):    def get(self):        self.response.headers['Content-Type'] = 'application/json'        obj = projects.get_projects()        self.response.out.write(json.dumps(obj))
application = webapp2.WSGIApplication([('/post_project', PostProject)],                                      debug=True)
application_get_projects = webapp2.WSGIApplication([('/get_projects', GetProjects)],                                      debug=True)

app.yaml is the GAE configuration file in python, I defined 4 static handlers for directories and three script handlers for the http requests (one for main page GET, one for GET the list of projects as Json file, one for POST a new project):

 

application: com-oloconsulting-damien
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /css  static_dir: css
- url: /js  static_dir: js
- url: /openui5  static_dir: openui5-runtime-1.22.4
- url: /ui  static_dir: ui
- url: /post_project  script: projects_handler.application
- url: /get_projects  script: projects_handler.application_get_projects
- url: .*  script: main.application
libraries:
- name: webapp2  version: "2.5.1"
- name: jinja2  version: latest
- name: markupsafe  version: latest

Basically the app is working in this way: first page is managed by main.py, POST and GET requests on Projects model are managed by module projects_handler.py.

 

From OpenUI5 side, I created two views and put them in the same page:

 

ProjectList view (it implements a table for the list of projects):

 

sap.ui.jsview('ui.ProjectList', {  getControllerName : function() {  return 'ui.ProjectList';  },  createContent : function(oController) {  var oTable = new sap.ui.table.Table({editable:false});  var oControl = new sap.ui.commons.TextView({text: '{project_id}'});  oTable.addColumn(new sap.ui.table.Column({  label: new sap.ui.commons.Label({text: oBundle.getText('ProjectId')}),  template: oControl, sortProperty: 'project_id',  filterProperty: 'project_id', width: '50px'}));  var oControl = new sap.ui.commons.TextView({text: '{project_description}'});  oTable.addColumn(new sap.ui.table.Column({  label: new sap.ui.commons.Label({text: oBundle.getText('ProjectDescription')}),  template: oControl, sortProperty: 'project_description',  filterProperty: 'project_description', width: '200px'}));  var aData = oController.getProjects();  var oModel = new sap.ui.model.json.JSONModel();  oModel.setData({modelData: aData});  oTable.setModel(oModel);  oTable.bindRows('/modelData');  oTable.sort(oTable.getColumns()[0]);  return oTable;  }
});

The controller is implementing only one function to get the list of the projects (it is called in the view to fill the model data: var aData = oController.getProjects();)

 

getProjects: function() {  var aUrl = '/get_projects';  var aData = [];  jQuery.ajax({  url: aUrl,  async: false,  type: 'GET',  success: function(data, textStatus, jqXHR) {  //alert('success to post');  aData = data;  },  error: function(jqXHR, textStatus, errorThrown) {  alert('fail to post');  }  });  return aData;  }

ProjectCreation view (it defines a form with a couple of textFields and a button):

 

sap.ui.jsview('ui.ProjectCreation', {  getControllerName : function() {  return 'ui.ProjectCreation';  },  createContent : function(oController) {  var oLayout = new sap.ui.layout.form.GridLayout('ProjectCreationFormLayout');  var oForm = new sap.ui.layout.form.Form('ProjectCreationForm',{  title: new sap.ui.core.Title({  text: oBundle.getText('CreateProject')  }),  width: '50%',  layout: oLayout,  formContainers: [                  new sap.ui.layout.form.FormContainer('ProjectCreationFC', {                  formElements: [                                  new sap.ui.layout.form.FormElement({                                  fields: [                                          new sap.ui.commons.Label('lblProjectId', {                                          text: oBundle.getText('ProjectId')                                          }),                                          new sap.ui.commons.TextField('txtProjectId')                                          ]                                  }),                                  new sap.ui.layout.form.FormElement({                                  fields: [                                          new sap.ui.commons.Label('lblProjectDescription', {                                          text: oBundle.getText('ProjectDescription')                                          }),                                          new sap.ui.commons.TextField('txtProjectDescription')                                          ]                                  }),                                  new sap.ui.layout.form.FormElement({                                  fields: [                                          new sap.ui.commons.Button('ProjectCreationButton', {                                          text: 'Insert',                                          tooltip: oBundle.getText('CreateProject'),                                          press: function(oEvent){                                                oController.onCreateButtonPress(oEvent,oController);                                                }                                          })                                          ]                                  })                                ]                  })                  ]  });  return oForm;  }
});

The controller is implementing the function for inserting a new project:

 

onCreateButtonPress: function(oEvent, oController) {  var oProjectId = sap.ui.getCore().byId('txtProjectId');  var oProjectDescription = sap.ui.getCore().byId('txtProjectDescription');  var aUrl = '/post_project';  var formData = {      project_id: oProjectId.getValue(),      project_description: oProjectDescription.getValue()  };  jQuery.ajax({      url: aUrl,      type: 'POST',      data: formData,      success: function(data, textStatus, jqXHR) {            alert(oBundle.getText('ProjectCreationOk'));            location.reload();      },      error: function(jqXHR, textStatus, errorThrown) {            alert(oBundle.getText('ProjectCreationError'));      }  });
}

You can test the application at this link:

 

http://com-oloconsulting-damien.appspot.com/

 

here it is a snapshot of the GAE datastore after a couple of projects creation:

Screen Shot 2014-08-01 at 12.50.20.png

Video: Create a responsive UI5 Order Search application in 40 minutes with Neptune

0
0

Recently we (Neptune) held a getting started webinar on how to create a fully functional Sales Order Search application based on UI5 using the Neptune Application Designer.

 

The coding (minus the backend ABAP coding which was only walked through) took our CEO Ole-André Haugen 40 minutes to complete

 

The video shows a lot of tips and tricks that will make your Neptune programming faster. Therefore, even if you are an experienced user of our tool, I think it might be worth to view.

 

Also at the end of the session, we showed some of the new cool features we released in SP3.

 

That includes features such as a new AppCache configuration, upgrade of the Select component using a dictionary table or domain value range without any coding and the introduction of the newest version of OpenUI5.

 

Well here is the video, and I will shortly post the second video in these series that covers the superb Neptune offline solution.

 

Offline First - the new paradigm in web development done Neptune style

0
0

There is a lot of talk these days about a new trend in web development called “Offline First”. We are just getting comfortable with redesigning our enterprise application screens according to the “Mobile First” design pattern, and it is now time to design and build our applications offline-first.

 

I have in the last few years discouraged customers from offline scenarios and claimed that offline should only be implemented where absolutely necessary and often as an emergency backup solution. Much in the same way as you would see at a point of sales in a store – you manage basic operations such as backup credit card handling to be able to sell your merchandise in the event of connectivity loss.    

 

We used to think that the connectivity issue would be solved quickly and that the world would soon have global online coverage. Unfortunately that was wishful thinking and it looks like we will have to live with unreliable networking for some time still.

 

This new paradigm will help create applications that are always usable with a new way to design your applications.

 

We at Neptune have created a new easy to use offline functionality for SAPUI5 to meet this new challenge and you can watch this recorded webinar where Ole-André Haugen creates an offline sales order application in just 40 minutes


 

Also you can read about the technical solution in this blog.

 

No more data roaming for your traveling expense app!

What can grunt do for your UI5 project?

0
0

In case you want to know if grunt can add value to SAPUI5/OpenUI5 projects, this blog may be of interest to you. To understand what grunt can do for your UI5 project, let`s take the POS app from the open UI5 demokit as an example. This app is located in the folder demokit/pos and uses XML views. This is more or less how you would normally develop your own open UI5 app.

 

When coding a UI5 app, you want to ensure that the code is valid and: without syntax errors and standard compliant. One way to achieve this is to load the page in a browser and see if the page works, although this is not productive. Tools like jshint check the syntax of a JS file. Speeding up the process of syntax checking a lot. As grunt is a task runner it is possible to run a set of configured tasks against your project. This way, the verification process is further automated.

 

After setting up grunt it`s time to install the plugins. For now, checking the code for errors is more than enough. The plugins for doing so for the POS demo app used by me are:

  • jshint: checks Javascript files. These are the controllers and helper files.
  • htmlhint: checks the HTML file. Normally this is the index.html which loads the UI5 library.
  • xml-validator: UI5 app can use of XML files to define the views. In such case you only will see any XML syntax errors when the view is loaded by UI5.


Lets see how the sample app performs against the grunt plugins. [The configuration of the tasks can be found in the GitHub repository. (will post the link here later)]


JSHINT

 

Command:grunt jshint:scn

grunt1.jpg

Perfect! Jshint did not find any errors in the sample application.

 

XML_VALIDATOR


Command:grunt xml_validator:scn

grunt2.jpg

Again: nothing wrong with the files.

 

HTMLHINT

 

Command: grunt htmlhint:scn

grunt3.jpg

2 Errors were found! These are related to how tags should be written. Let`s fix these.

  • 1st Error. Solution: close tag: <meta charset="UTF-8" />
  • 2nd error. Solution: close tag: <link rel="stylesheet" type="text/css" href="css/style.css"/>

 

Optimize size

 

Grunt already helped to create a better HTML5 app. The code is now error free, but not optimized in size. Fortunately, there are grunt plugins for that task:

  • uglify
  • xmlmin
  • imagemin
  • htmlmin


Note: When creating minimized files it is a good idea to rename them (adding min) or create them in a new folder like target, build, etc.


Javascript

grunt4.jpg

Result: This decreased the Javascript files size from 23.4KB to 13.6KB.

 

XML

Command: grunt xmlmin:scn

Result: XML files are minimized to 8.84KB, compared to 9.74KB

 

HTML

Command:grunt htmlmin:scn

Result: From 1.04KB to 1.02KB

grunt5.jpg

Images

Command:grunt imagemin:scn

Result: Saved 10.31 KB in space

grunt6.jpg

Result

After running these grunt plugins in order, the UI5 app contains no syntax errors and is minimized. But does it still work?

grunt7.jpg

Looks good!

 

Including the model, css and i18n files the project size is now 141 KB, compared to 166 KB. This is a saving of 25KB. Of course, this is not much, but the POS sample app is also nothing really big. The 25 KB saving scales: if you have 10.000 users that access all the resources at least once, it is a saving of 244 MB. Of course if GZIP is configured on the server, the file size shrinks further. But here we also face another problem: normally a web server is not compressing all files, only some (HTML) or only when they are larger than a specific size (NW). In case your web server is only compressing HTML files, the above demonstrated grunt plugins will help you in creating HTML5 apps consuming less space.

 

To not have to execute the steps manually, I recommend using the watch plugin to execute the tasks automatically.

 

Verdict

Using grunt to optimize a UI5 app makes sense. Not only will it help you to produce cleaner, more standardized and smaller code, but to establish a development process.

Design Thinking - My Learning from SAP DT Workshop

0
0

Couple of weeks back  I got a chance to attend SAP workshop on Design thinking(DT) in Bangalore, India. I was floored by the DT  mindset  and the power it brings along for Innovation , providing customer delight not to forget it saves training costs!.“Design thinking” as a mindset has been there in IT Industry for quite some time now, it has become new buzzword @SAP recently.Simply put it means redefining the user experience(UX) by keeping the User (human) at the center of application design and keeping the UI  as simple as possible.SAP Fiori which is gaining huge popularity for enhanced user experience is based on DT principals.I have put my learning in this blog.Hope you will find it useful and DT mindset will help you innovate better!.


Design thinking is a human-centered approach to innovation that draws from the designer's toolkit to integrate the needs of people, the possibilities of technology, and the requirements for business success.” —Tim Brown, president and CEO IDEO


(Photo source :Ideo_ted1_Tim)

Picture1.png

Traditionally, design has been treated as a downstream step in the development process—the point where designers, who have played no earlier role in the actual work of innovation, come along and put a beautiful wrapper around the idea. Increased competition, high training cost and so called wicked problems has led to increased practice of Design Thinking mindset.(photo source :https://experience.sap.com/)

Innnovation.png

Until recently ‘active’ user role was majorly required at the time of UAT (User Assisted Testing).But by this time the development phase was already completed and lot of rework was required because of misunderstood problems, to fix the design issues. In the DT methodology more effort and time is spent on clearly “defining and understanding” the problem in multiple iterations (as seen in below diagram), directly with the end user rather than to solve the problem.

Picture3.jpg

Now I will explain each of the "Design Thinking" steps in detail:


Understand : Get an initial understanding of the problem

Understand with a sense of Empathy to the User

Place yourself in user shoes

Talk Less , Listen more


Observe : View users and their behaviors from their context

Watch what a typical user day looks like

Repeating behavior pattern ,Interactions

Take Pictures, Collect artifacts

Write down your observations

Goal is to get to know your user more than they know of themselves

 

Story telling :Story is created with user being at the center .This helps us to improve the connection and identify with the subject. Synthesize the ideas from different user researchers


Persona : Create the profile of the user which includes his goal, Job responsibility, Role, Pain points, Competencies, Age, Marital status, Ethnicity, Interaction points

Picture10.png



Ideate: This mode transitions from problem space to solution space

With needs identified generate as many solution ideas as possible

Step beyond obvious solutions

Do not judge ideas

Uncover unexpected areas for exploration

During brainstorming, have one conversation at a time

Log your brainstorming session

Encourage wild Ideas

Support and build on others Ideas

Stay focused on goal


Prototype :To create “concrete” embodiment of a solution concept  that can be used to test. Follows the principal of “Fail early fail often”. Build to think and not vice versa.

Generally of following types:

  Role Playing

  Simple HTML application

  Post-it notes

  Objects/Physical prototype

Story boarding


Test :Used to "refine” our solutions and make them better ,typically done with the user . Iterate the process based on learnings and findings.


SAP Fiori: Made to improve the SAP UX by keeping things simple (photo source :https://experience.sap.com)

Picture12.png


SAP Fiori : Each tile represents separate App which can be grouped as per user need (photo source :https://experience.sap.com)

Picture7.png

Everyone, you agree or not is a service provider (photo source :https://experience.sap.com).

 

Good UX is the key differentiator in this competitive market

Reduces support costs, greater customer satisfaction and loyalty

 

Picture8.png


Please visit the below Ted talk to understand the Impact of DT  in the real world :https://www.youtube.com/watch?v=IwidCkCmWg4


Just 1 way of developing UI5 apps with localhost against Gateway services (& more)

0
0

Decisions, decisions...

If you're starting out in SAP Enterprise UI5/Gateway development, you are going to find there are more than a thousand different ways of achieving the outcome. There's editors, there's repositories, there's web content hosting, different types of views, binding techniques, etc; but in just a very quick post, I thought I would highlight just a couple of techniques that I think work well, and this is coming from one of the few Web UI developers still working on a Windows laptop in this space it seems - who would have thought (For reference, I also note IE is the most buggy browser for UI5 releases now days which is a shift for SAP)

Web Server

If you are developing UI5, and not sitting next to a big HANA data centre hosting the SDK; or are regularly on planes without WiFi (like we do in Australia), you'll want to deploy Apache Tomcat or similar on your workstation.  You can deploy OpenUI5 libraries against an IIS instance but you don't get everything working if you do this, so I suggest a local install of Tomcat, and hosting your UI5 there. But I actually don't recommend Tomcat for testing your initial development. Why? Well speed of hitting f5 to refresh your app and test actually.

See for me, unless you are a JavaScript legend who has a JS interpreter in their head running continuously over your code understanding all the intricacies of the libraries you've included; making lots of changes in JavaScript within UI5 before doing a test leads to - "it's broken, now what the hell did I do?". Trust me, "Check for 'file not found' or parse errors." will be the most annoying error message you come across when doing UI5 development.  And that's when you need to go over every last change you did in the last 15 minutes to see where you broke the code. Performing more agile techniques of developing a small piece of functionality, then testing it; leads to a more sane development experience; and the ability to wrap up for the day on a win rather than not even wanting to check it in to GitHub as a stable version/backup (since I'm told you shouldn't check-in to Github unless it's a tested working change).

So the fastest way of testing I've come across on Windows, is just to point a virtual directory on IIS at my GitHub cloned repository, make change - test.  IIS instantly feeds up the new content without any delays. There's some cool features in the UI5 Grunt server implementation you'll read about on SCN (quickly typing this post so haven't looked it up sorry) but I found the automatic 1 or 2 second delay in refresh was enough to annoy me, but this may work better for many.

One aspect to consider is setting up cache control appropriately for your source code and libraries. e.g. You want to make sure your ui5 libraries are cached in your browser, but also want to make sure that your code is not cached. You can turn off caching in developer tools, but that slows you down a lot also.

Testing against Gateway using Localhost

I'd love to be able to tell you to leverage the new mock framework in UI5 rather than be dependent on the Gateway server, but until someone posts a guide on how to do this for a production like Gateway service model that may not exist in development yet and responds with a level of logic - I'm forced to tell you how I leverage Gateway. So...

Quick and easy way to run UI5 on localhost and call Gateway (without CORS issues due to localhost and your Gateway hostname being different and Gateway not configured to say it's fine to consume its services on localhost) is to run Chrome in unsafe mode (find your Chrome.exe file and add --disable-web-security ensuring Chrome is not running anywhere) - But that's kind of annoying since I use Chrome for email and everything else and don't trust the web to run in unsafe mode; so rather than do that, let's create a reverse proxy so that everything from /localhost/sap/* goes to our Gateway server for processing. 

This can be a little confusing, but if you follow this post about it, it's not too hard:

http://www.iis.net/learn/extensions/url-rewrite-module/reverse-proxy-with-url-rewrite-v2-and-application-request-routing

Try to not overthink it like I did, checking boxes I shouldn't have, and it should be straight forward. You may need to play around with header variables and the like if someone has tuned your Gateway and you are using full paths contained with the Gateway responses (in other words, you may need to rewrite the contents of your Gateway calls to point at "localhost/sap" but for typical UI5 deployments, simply getting localhost/sap pointing at Gateway should do the trick.

e.g. If you modify your web.config file in c:\inetpub\wwwroot with the following; after install ARR and activating the proxy; you should be up and running:

<?xml version="1.0" encoding="UTF-8"?><configuration>    <system.webServer>        <rewrite>                 <rules>                                <rule name="Reverse Proxy to Gateway" stopProcessing="true">                                                <match url="^sap/(.*)" />                                                <action type="Rewrite" url="http://<GatewayServer>:<Port>/sap/{R:1}" />                                </rule>                </rules>        </rewrite>    </system.webServer></configuration>

Editor

Sublime seems to be the editor of choice for UI5 (at least on Windows since Atom runs atrociously slow on Windows but may catch up soon) and hopefully you'll find the information from John Patterson and Tobias Hoffman already to get you set-up correctly. I kind of wondered why everyone loved it since it was a great text editor (fast, easy on the eyes, lots of cool editor options like "find all" followed by editing all found locations at once simply by typing, but not a great development tool; but after looking into JS Linters that run while you type on Sublime Text 3, and Prettify to make all my XML, HTML and JS look fantastic (Thanks John and Tobias for highlighting this); I absolutely can recommend Sublime Text 3. Hopefully some of us are paying licenses for this as the developer(s) deserve making a lot from this editor (it's kind of free but with an annoying prompt if you don't buy it).  Note - Anyone come across a good real-time XML linter for ST3?

If you're wondering what Linter is all about - well just wikipedia it, but in short it's effectively looking for compilation or proper usage errors in your code.

Eclipse - Meh...

The HANA RDE for UI5 has hope, especially offering XML View intellisense, but was just too slow for me in Australia to be usable.

GitHub - Code Repository

I run GitHub Windows on my desktop as I'm not a power "Command line Git user" just yet and haven't figured out what Sublime is capable of doing here, but it's very cool for submitting the changes, and seeing the differences in your code.  To get a private repository for enterprise development is only US$7 a month; but if you don't feel like paying that for privacy, make sure you accidentally let us in on your GitHub account so we can all learn from each other...

Now something I probably do incorrectly, but whatever, is I tend to backup versions of my code regularly while refactoring my code. The reasoning behind this is that GitHub makes it so easy to look at what you changed, and can help debug refactoring regression issues.  Plus, if I had a developer who only checked in once a week, I'd be worried they weren't backing up their code anywhere. Supposedly working off branches is discouraged now days, but for me, the team is working on independent developments, so it isn't an issue for now.


Deployment

John and Tobias start to get into this in Tobias's Grunt blog and looks like John has a good #saptd session coming up about this that I plan to attend; but all I can say is; when it comes to deploying in production; standard development code can be significantly improved for performance.  Maybe on your initial release, deploy as is to allow debugging of problems; but effort (not insignificant) is required to get everything caching, minimalised, grouped, etc.


That's all folks!

That's it for now as I'm just quickly getting my thoughts down plus wondering how much more I don't know that some of the readers may be able to help us with. For those new to UI5 development, I hope this is of help and gives you ideas, especially if you're stuck (happily) on Windows.

Simple Notifications for UI5

0
0

 

Enhance your Control-Lib!

 

Intro

 

Today i want to show you a new custom control for UI5-applications. I let myself inspired by codrops once again (see Notification Styles Inspiration).

 

The idea is to create a simple and responsive notification, which can be used on different devices. Besides, it should be possible to have different types of notifications (error, warning, information and success). Although UI5-developers can already use the NotificationBar to show messages and notifications, i want to offer an additional control, which has its focus on simplicity and a responsive design.

 

To get a better impression, please check out the following links.

 

View Demo

 

Get Source Code

 

Usage

 

It's pretty simple to add a new notification in your app. Just write the following code to create a new instance of the control and to show it immediately.

 

new neko.control.Notification({       message : "Your message",       type : "success",      durability : 3000,       close : function(){              // do something great             },       open : function(){              // do something great            }       }).show();

 

When you have a look at the control implementation, that you can see further properties like "layout" and "effect". These properties can be used, to apply different CSS to your notification. On this way, you can influence the behavior and layout of your control over additional CSS-classes. And this is really cool, because you can enhance your notifications just with CSS. There is no need to modify the underlying JavaScript implementation. If you need some suggestions for this, just a look at the mentioned codrops-article above.

 

Regards

 

Michael


UI5 Components and Extensibility Starters

0
0

While working on Fiori application I was very impressed with the extensibility provided by the standard application

  1. View Extensions
  2. View Replacements
  3. View Modifications
  4. Control Extensions

 

I tried to go through the demokit documentation and did not find a well document example set for these concepts. So thought of writing this blog for giving a simple starting point in this concept. Hope it helps.

 

Ok, so let us first understand the very basis of extension. Extensions using UI5 components and some of the core apis can be done in premise of application space where custom application and original application resources are accessible to each other. Also very important thing to note that this extension approach is not an object oriented extension model but rather javascript code merging approach.

 

So, for instance in deployed on same server.

 

Now with this is in context, let us first create an application, original application and see what it takes to bring in the above four extension points in application.

 

So I create a new mobile application, say NEWUI5RND

and in index.html create componentContainer

<script>

  new sap.m.Shell("Shell",{

                                      title:"You Can Extend Me",

                                      appWidthLimited:false,

                                      app: new sap.ui.core.ComponentContainer({

                                                                                                    name : 'com.rnd'

                                                                                                   })

                                     }

                           ).placeAt("content");

  </script>

 

 

Now, directly under WebContent I will place a file called Component.js

Lets see some of the main parts of this file:

 

declaration and metadata-routing

Screen Shot 2014-08-18 at 3.23.57 pm.png

so, its very much self explanatory, the important point is to note that for pattern "" we have given a Main view as landing view. This is the view that will get added to app, when we access http://........index.html for instance but will not load if a navigation parameter for instnace ..index.html#<paraName> is given. For this <paraName> must be added to routes aggregation.


Now, the next step is to understand where and how to create the app


This is in next part of the same file as show below:

Screen Shot 2014-08-18 at 3.30.30 pm.png


createContent is responsible for creating the object that will be placed in component container that we instantiated in index.html


Now, lets look closer into the Main.view.xml to see the extension point concept


Screen Shot 2014-08-18 at 3.34.46 pm.png

So, here we note two things, we can have core:Extensions and along with it we can also give a default visualisation. For instance here the label is default visualisation which will get overridden by the actual extension. the core:extension is just an aggregation and we can put any UI5 object, view in it.


Now, apart from this, for all four type of extensions mentioned above, we really do not need any other extension points, in a way the other 3 are implicit enhancements points.


Just for completeness please note that the first button has id "toggButton" and below is the controller file

Screen Shot 2014-08-18 at 3.40.43 pm.png


Now lets do the extensions:


First step is to create an empty mobile application which will be deployed in same server, say NEWUI5RNDEXT1


Basic setups:

  1. register paths from where the resources of original application can be accessed:Screen Shot 2014-08-18 at 3.44.06 pm.png


       2. create Component.js and extend the component declared in original application

Screen Shot 2014-08-18 at 3.47.43 pm.png




Now, Customizing!


1. ViewExtensions


Let us extend the original Main view on the extension point declared and put a button in it.


  1. Lets create a view with a button, the extension also supports fragments Screen Shot 2014-08-18 at 3.52.55 pm.png
  2. Now, actual extension is done under customizing aggregation of the metadata the custom Component.js file as shown below. Note that extension is done for a particular view -extension combination. In this case the Main view and extension extActionBarScreen Shot 2014-08-18 at 3.57.59 pm.png

Output is as shown below:

Original:

Screen Shot 2014-08-18 at 4.00.53 pm.png

Custom:

Screen Shot 2014-08-18 at 4.01.38 pm.png

 

So, the application is extended with a new button Refresh

 

2. ViewModification

 

Now, let us look at modifying the actual view rather than extending it. So, let say we try to hide the Toggle Secondary Content button. You would have noticed that the id of this button was "toggButton". Below is the sytax in customizing to achieve this:

Screen Shot 2014-08-18 at 4.06.44 pm.png



2. ViewReplacement

 

Now, let us look at replacing the view completely

Screen Shot 2014-08-18 at 4.08.47 pm.png

2. Control Extension

 

Now, let us look at extending the controller. Here we can override the existing functions or add new ones.


Screen Shot 2014-08-18 at 4.10.22 pm.png


So with this we are now ready for creating extensible UI5 applications.


Happy Coding.

Fun = Agile + SAPUI5; //Part 2

0
0

This blog is a follow up on my previous blog, where I introduced the project scope, approach, etc. I think this blog makes more sense after reading the previous one.

 

As mentioned, the most exciting aspect of this project was the responsive design for “all newer browsers” on desktop, tablet and smartphone. This resulted in a css with several thousands of line of code and we even had a review session with a css expert, who suggested tricks like replacing gradient borders with before selector.

 

Some more design lessons learned

  • It is hard to create a site which makes use of the screen property in an optimal way on all screen formats. It required a lot of interaction among designers, users and developers. Testing is a big challenge. We used browserstack which allows for virtual testing on many devices and operating systems. For the most used devices, think of IPhone, iPad, Samsung Galaxy, etc, we used physical devices for testing. Browsertack did a 99% job, but for these top devices we aimed to know with 100% certainty what works and what not.
  • The designer came up with a dropdown hover menu for desktop and a separate touch-based menu for phones. Since tablets don’t support hover, we used the touch-based menu for tablets too.
  • In order to handle all the different formats, we used a combination of two approaches for the css. We detect the device (e.g. sap.ui.Device.system.desktop) and also the screen width ($(window).width()). We have to know if the user has e.g. a large tablet (big widths, but touch) or a small monitor (small width, but hover), etc. to offer the optimal design.

 

Some more technical lessons learned

  • The Application Cache Buster introduced a significant improvement to the performance. We turned it on for production, but left the development system without it.
  • Still, the initial load of the SAPUI5 libraries takes some time. I understand SAP is working on this area. We just adopted a simple technique described by Konstantin Anikeev: we added a spinning wheel and load the SAPUI5 libraries as described in the blog. From a user point of view, this was a huge improvement.
  • We integrated Google Analytics as described by Craig Gutjahr in his blog. We raise our own events and I must say the business loves to see the usage in the real time dashboard. It was also very useful for the go-live, because we could monitor how the usage was taking up.
  • We created a deployment script. It does some adjustments to the code, which are necessary before transporting to production. One example is to minify the code. We use yuicompressor.

 

As always, I am curious if you recognize these points or your experience is different.

Getting a Local Copy (hack) of SAPUI5 on your Laptop for Performance/Offline Development

0
0

SAPUI5 Resources for the Rest of Us

Now while for those who live in countries next to HANA data centres with WiFi access on planes, trains and automobiles; this may not be an issue; or alternatively, if you are happy developing in the UI5 Eclipse environment which takes care of SAPUI5 libraries automatically for you; this post is not for you. Similarly, if you’ve got everything you need in OpenUI5, then move along, there’s nothing to see here.

 

So whoever’s left, you may find it quite tricky to get the SAPUI5 libraries standalone. I know a few of us have. I tried downloading the latest version from the Service Marketplace, but on both occasions, on separate computers, the files were corrupted (wonder if SAP know about it)…Possibly a temporary thing, but the fact I need to download SAPCAR to get it makes this seem like the Basis way of doing it and not the Developer way.

 

So I’ve taken the opportunity, while on a plane of course offline; to document what I hope is a temporary hack until SAP make it easier for SAP developers to download the latest SAPUI5 SDK.

 

Note – Since where I’m currently working, we plan to push the UI5 libraries to an Apache server, I hope someone comes back with the right way of doing this since that latest download for UI5 in Service Marketplace last week was corrupt.

 

Anyway, the quick hack solution:

 

Install Eclipse or SAP HANA Studio and then load up the SAP UI Development toolkit for HTML5 (e.g. SAPUI5 plug-ins) ensuring you’ve got the latest version if you already had it installed.

 

Now locate the relevant jar files for SAPUI5, which will depend on your installation. If you have a minute, just do a search of your drive for “com.sap.ui5*.jar”.

FYI – My files were in C:\Users\<UserName>\.eclipse\org.eclipse.platform_4.3.0_511115836_win32_win32_x86_64\plugins

 

Once found, order by date modified, and grab all the com.sap.ui5*.jar libraries that relate to the current version, plus the com.sap.ca.*.jar libraries.  Put them into a directory, and use something like WinRAR archiver to unzip all of them at once; allowing it to overwrite the one common file between them all.

 

Now if you open the Meta-inf directory that was created, you’ll find the familiar resources folder which you can move to where you need it or virtual directory straight to it from your web server (ensuring you set the right cache-control to ensure your browser runs quickly).

 

Also interestingly, there are a bunch of resources in the libraries folder like XSD files and templates for XML views and JS views that are used within Eclipse that would be good to port into Sublime Text 3 if anyone is keen to do this!  E.g. You type Button in an XML view in Eclipse, and you get to select the type of Button you want and it inserts a template signature just like snippets.

pic1.jpg

Alt-Space after Button

pic2.jpg

Inserting a RadioButton template.

Why not just use OpenUI5?

 

Now why would you want SAPUI5 versus OpenUI5 – well if you’re developing for SAP software, you may want to take advantage of a few controls (beyond just graphs) that are quite convenient. Don’t believe me – well take a look at a few of them here (pointing at Australian UI5 site because we don’t have a SAPUI5 CDN yet!)

So hopefully this blog will be replaced by someone telling us the right way to do this and get the full SDK but for now – if you were stuck with this also - Enjoy!

 

Fiori Launchpad Info

Just after I published this I realised I referred to the UI5 libraries being loaded into Apache, but since the post from Craig Haworth I've realised that to truly integrate with the Fiori Launchpad with your own Fiori(TM)-Like app; you are restricted to using the Launchpad UI5 libraries, which seem to be linked to 7.40 support pack stack release which is tied to the Gateway release which is tied to your backend IW_BEP version; so if you're developer says, "can we use 1.23 SAPUI5?" and your Launchpad is on 1.22; you should immediately panic unless you are at the beginning of the project and can afford to upgrade everything. Not to mention every minor patch involves several notes because of the size of the ui5 libraries.  Fun!

SAPUI5 WebSocket Chat with WhatsApp

0
0

Intro

 

I would like to show you how to create a WebSocket chat application to send and receive a WhatsApp message from the SAPUI5 web browser with the open source Yowsup.

 

c1.jpgc2.jpg

 

c3.PNG

 

How it works?

 

c4.jpg

Firstly, client will establish the connection to the server via the websocket address: ws://localhost:8080/fd6/websocket and register the following event listeners:


onerror: When a WebSocket encounters a problem, the "onerror" event handler is called.

onopen: When a WebSocket in the open state, the "onopen" event handler is called.

onmessage: When a WebSocket receives new data from the server, the "onmessage" event handler is called.


var webSocket = new WebSocket('ws://localhost:8080/fd6/websocket');  webSocket.onerror = function(event) {  onError(event)  };  webSocket.onopen = function(event) {  onOpen(event)  };  webSocket.onmessage = function(event) {  onMessage(event)  };

Once the connection to the server is established, it can send and receive the WhatsApp message with the following steps:


Send Message to WhatsApp


Step 1


When user sends a message from the browser, the function sendMsg() will send the message to the server: webSocket.send(msg);


function sendMsg() {  var msg = oMsg.getValue();  if (msg == "")  notify('Info', 'Please enter a message', 'information');  else {  webSocket.send(msg);  oMsg.setValue();  oMsg.focus();  lastMsg = oModel.oData.chat;  if (lastMsg.length > 0)  lastMsg += "\r\n";  oModel.setData({  chat : lastMsg + "You:" + msg  }, true);  $('#chatBox').scrollTop($('#chatBox')[0].scrollHeight);  }  return false;  }


Step 2


Method goInteractive in the python Yowsup code listens for the incoming message from the server: message = self.ws.recv() and send the message to the WhatsApp:msgId = self.methodsInterface.call("message_send", (jid, message))


def goInteractive(self, jid):  print("Starting Interactive chat with %s" % jid)  jid = "%s@s.whatsapp.net" % jid  print(self.getPrompt())  while True:  message = self.ws.recv()  if not len(message):  continue  if not self.runCommand(message.strip()):  msgId = self.methodsInterface.call("message_send", (jid, message))  self.sentCache[msgId] = [int(time.time()), message]  self.done = True


Receive Message from WhatsApp


Step 3


If there is any incoming message from WhatsApp, method onMessageReceived is called. It will send the message to the server: self.ws.send(messageContent)


def onMessageReceived(self, messageId, jid, messageContent, timestamp, wantsReceipt, pushName, isBroadcast):  if jid[:jid.index('@')] != self.phoneNumber:  return  formattedDate = datetime.datetime.fromtimestamp(timestamp).strftime('%d-%m-%Y %H:%M')  print("%s [%s]:%s"%(jid, formattedDate, messageContent))  if wantsReceipt and self.sendReceipts:  self.methodsInterface.call("message_ack", (jid, messageId))  print(self.getPrompt())  self.ws.send(messageContent)


Step 4


Finally, the function onMessage will print out the  incoming message from the server to the client browser.

 

function onMessage(event) {  msg = event.data  lastMsg = oModel.oData.chat;  if (lastMsg.length > 0)  lastMsg += "\r\n";  oModel.setData({  chat : lastMsg + "WhatsApp:" + msg  }, true);  $('#chatBox').scrollTop($('#chatBox')[0].scrollHeight);  notify('WhatsApp', msg, 'information');  }

 

To display the message, I am using noty - a jQuery Notification Plugin:

 

function notify(title, text, type) {  // [alert|success|error|warning|information|confirm]  noty({  text : text,  template : '<div class="noty_message"><b>'  + title  + ':</b> <span class="noty_text"></span><div class="noty_close"></div></div>',  layout : "center",  type : type,  timeout : 4000  });  }

 

It's pretty easy to use and implement the WebSocket in SAPUI5. Thanks for reading my blog and let me know if you have any comments/questions. Enjoy chatting !

 

Source Code:

 

I have attached the complete source code fd6.war (rename fd6.war.txt to fd6.war) and the modified Yowsup python code in the GitHub:

ferrygun/WebSocketChat · GitHub

 

References:


Set Location on Google Map, just by providing an Address - UI5 Custom Control

0
0

Hii

 

This is a simple custom control that creates a Google Map and sets the location based on the address provided ! The control can be instantiated in a simpler way just like this,

 

var oMap = new ref.google.Map({ address:"Bangalore" });

This will produce,

 

Capture.JPG

The Address just doesn't have to be a city, it can be any valid address.

 

Don't forget to check out this snippet, http://jsbin.com/zetel/1/edit where i have done some sample implementations with various address by creating a JSON Model.

 

The custom control code is avail - https://gist.github.com/ikiw/775a2a438571ba4e00d3

 

This control requires Google maps library which can be loaded next to the sapui5 bootstrap script

 

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>

 

Let me know if you've got something to collaborate/enhance this.

 

 

Regards

Sakthivel

Viewing all 789 articles
Browse latest View live




Latest Images