Salesforce Lightning Components and image dependencies

I am developing some Salesforce Lightning components at the moment as while Lightning Components are great they have a major drawback in my mind. Some background first… Salesforce Lightning is our “new” component based UI based on HTML / Javascript and components are automatically mobile ready and responsive. A Lightning Component is not a single “thing” but rather a folder with stuff that is a number of files named using a predefined format. The component name is the name of the folder – e.g. MyComponent. The actual markup goes in the component file called MyComponent.cmp. Besides the markup there is the client side controller (MyComponentController.js), CSS styling (MyComponent.css) and that’s basically it. There are few more potential files but they are not important for this post. All is well described on the web. What’s not included in the component is graphics that may be used by the component.

The way graphics are added to components a either by using the sprites supplied with the Salesforce Lightning Design System (SLDS), by using custom graphics or you can use the classic icons which are supplied by Salesforce. The latter are really not ideal as do not look nice as they look old and the colors cannot be easily changed. The issue with using custom graphics or the SLDS sprites is that the resources are kept in Salesforce as static resources which is great for performance as they are automatically loaded through our CDN but they are outside the Lightning component. So now a component is no longer self contained but has dependencies to other metadata elements. To make it even worse these dependencies cannot be declared for the component that the normal dependency detection doesn’work eg. changesets will not detect the dependency. Not good…

To solve this I’ve started to use base64 encoded images as they can easily be used in img-tags and may be embedded in either markup or in JavaScript. An img-tag can use base64 instead of an image reference as below. This solves the above issue as images are now fully contained in the component code or markup so no external dependencies are required. An easy solution to a complicated problem.

&ltimg src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAL" />

This

On Mac (and Linux probably) getting an image as a base64 encoded image for easily done using the base64 command and I normally cut lines to 80 characters as the developer console doesn’t handle looooooong lines well. Combining with sed can add the quotes and pluses to make it easier to get it into Javascript. A little tweaking if required but it is faster.

base64 -b 80 -i ./picture1.png
base64 -i Downloads/gold_star.png -b 80 | sed -e 's/^(.*)$/"1"+/'

Loading widget data in IBM Connections 5 by the aggregator

One of the areas that changed fundamentally in IBM Connections 5 is how widget resources (JavaScript and CSS) is loaded by the browser. In prior versions the resources were loaded by the end-user browser through the AJAX proxy in IBM Connections Profiles or Communities depending on the feature in use. Starting with IBM Connections 5 the resources are aggregated and loaded by the Common feature that now also caches the resources. For end users this is great as speed and performance improves but for developers and admins it can be hard to diagnose what’s going on.

In Profiles it’s pretty easy – once you know how – to see what the aggregator is aggregating for the current user. The below video shows how to see this is Profiles. I’m still trying to fully understand it in Communities and will post the info once I have it.

Generating DOM events from JavaScript

For the OnTime Group Calendar API Explorer I needed manipulate a dropdown element on the page using JavaScript which is easy enough but when doing it this way no onchange events are emitted which caused my page logic to break. Luckily for me there is a simple way to have the element emit an event using the dispatchEvent mechanism of the DOM. The element.dispatchEvent method is your friend here. The documentation shows you how to create a mouse event but I really needed a HTML based event. To create a such is done like below:

// get element
var elem = document.getElementById("some_dropdown");

// set selected option
elem.selectedIndex = 2;

// generate an 'onchange' event from 'elem'
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
event.eventName = "change";
elem.dispatchEvent(event);

Reusing IBM Connections Atom date formatting for custom widgets


In a recent IBM Connections project I needed to display dates in the same as IBM Connections does it that is full dates sometimes but also using “yesterday”, “today” etc. Plus it needed to cater for the fact that the customer might at some future point in time allow the user to change the UI language. Coding this is tedious and would take quite some time so I wanted to figure out if IBM Connections had some libraries that could help me.

And it did.

By messing around in Firebug I found out that the way IBM Connections does it is by using a nifty JavaScript object called lconn.core.DateUtil.AtomDateToString. This object is actually a helper object that does two things – first it is able to convert an Atom date/time string (such as 2012-08-01T12:44:42.713Z) into a JavaScript Date object and then format it according to i18n settings and the language set in the UI.

Once I knew what to look for in the IBM Connections code it was simple enough. They do it by adding a hidden span-tag (CSS class “lotusHidden”) with a special tagging CSS class called “formatDate” as shown below.

<span class="formatDate lotusHidden">
  2012-08-01T12:44:42.713Z
</span>

Then using dojo.query they locate the nodes with the formatDate CSS class, use the utility class to convert the Atom date string and then remove the “lotusHidden” CSS class to make it visible.

// expand dates
if (lconn && lconn.core && lconn.core.DateUtil &&
lconn.core.DateUtil.AtomDateToString) {
   dojo.query(".formatDate", root).forEach(function(item){
      item.innerHTML=lconn.core.
         DateUtil.AtomDateToString(item.innerHTML);
      dojo.removeClass(item,"lotusHidden");
   });
}

Bookmark to IBM Connections bookmarks from iOS

Bookmarks (aka Dogear) in IBM Connections is great and IBM provides a nifty bookmarklet to allow easy bookmarking from your browser. I couldn’t however make this bookmarklet work in Safari on iOS so I decided to look into it. And I’m happpy to say I got it to working with some inspiration from the Instapaper bookmarklet. The way it works for me now is that I have the bookmark bar visible on my iPhone and iPad and when I need to bookmark I use the bookmarklet which redirects to the IBM Connections bookmark page and back to the original page once done. Super easy and it works great.

Here is how to make it work.

  1. Open Safari and make a bookmark to a random page but be sure to place it in the bookmark bar (the bookmark bar can be made visible all the time in Safari options).
  2. Edit that bookmark and change the title to something that makes sense (I use “IV Dogear”).
  3. Clear the location field and paste in the JavaScript code from below replacing the hostname (lc.intravision.dk) with a hostname applicable to you.
  4. Save the bookmark and start bookmarking.

pre.wrap {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}

javascript:function%20abcdefg()%7Bvar%20h='http://lc.intravision.dk/dogear';var%20d=document;var%20b=d.body;var%20e=encodeURIComponent;var%20u=h+'/bookmarklet/post?url='+e(location.href)+'&title='+e(d.title);location.href=u+'&inframe=true&ver=';%7D;abcdefg();void(0);

The JavaScript Module Pattern – adding namespace

The Module Pattern has as added benefit of allowing you to add namespace to classes. The below extends the previous example to make the class COM.LEKKIMWORLD.ModuleAbc. Very cool in my eyes and reduces the chance for name collisions much like with Dojo classes.

// Create a COM namespace
var COM = (function() {
  return {};
}());

// Create a LEKKIMWORLD namespace
COM.LEKKIMWORLD = (function() {
  return {};
}());

// Add a class called ModuleAbc to the COM.LEKKIMWORLD namespace
COM.LEKKIMWORLD.ModuleAbc = (function(secret) {
  // the object we're incapsulating
  var OBJ = {};

  // private variables (these are truely private and
  // cannot be accessed from the outside)
  var secret = "my secret is: "

  // my property
  OBJ.myproperty = "my property value";

  // echo method
  OBJ.echo = function(v) {
    return "Echo: " + v;
  };

  // return the object
  return OBJ;

});

The JavaScript Module Pattern

If you are like me you like object oriented programming and you try to encapsulate the functionality to the best of your ability. And that goes for JavaScript as well of course. JavaScript pose an interesting problem though as JavaScript objects are as opaque as air that is you can see right through it.

Normally an object in JavaScript – whether declared though dojo.declare or function/json isn’t able to hide it’s member variables at all. You can try with “this.” or using _neverUser naming but fundamentally the “private” variables of a JavaScript class are available from the outside. Consider the below examples:

// enter the dojo
var DojoAbc = dojo.declare(null, {
  constructor: function(secret) {
    this.mysecret = secret;
  },
  myproperty: "my property value",
  echo: function(v) {
    return "Echo: " + v;
  }
});
var myDojoAbc =
   new DojoAbc("my little secret");
alert(myDojoAbc.echo(new Date()));
alert(myDojoAbc.myproperty);
alert(myDojoAbc.mysecret);

// plain ol' JavaScript
var PlainAbc = function(secret) {
  this.mysecret = secret;
  this.myproperty = "my property value";
  this.echo = function(v) {
    return "Echo: " + v;
  }
};
var myPlainAbc =
   new PlainAbc("my little secret");
alert(myPlainAbc.echo(new Date()));
alert(myPlainAbc.myproperty);
alert(myPlainAbc.mysecret);

In both examples the “mysecret” variable is accessible although I didn’t mean it to. There is no way in the above example to make the mysecret-variable invisible to the outside. That is a user of your class can access it and see it using a JavaScript debugging such as Firebug.

Bummer I thought. What then? How do I do it? Well I’m glad you asked as there is a way. It’s called the Module Pattern. Let me show you but let me also warn you – it is a little conveluted to look at.

The below code starts by creates a class like above but nothing besides the myproperty-property and the echo-method are available (even in Firebug) from the outside. So the last alert will actually say “undefined” as mysecret is available to the outside. It’s super cool and it’s the way I’m going to do my objects from now on.

var ModuleAbc = (function(secret) {
  // the object we're incapsulating
  var OBJ = {};

  // private variables (these are
  // truely private and cannot be
  // accessed from the outside)
  var secret = "my secret is: "

  // my property
  OBJ.myproperty = "my property value";

  // echo method
  OBJ.echo = function(v) {
    return "Echo: " + v;
  };

  // return the object
  return OBJ;

});

// use case
var myModuleAbc =
   new ModuleAbc("my little secret");
alert(myModuleAbc.echo(new Date()));
alert(myModuleAbc.myproperty);
alert(myModuleAbc.mysecret);

More information about the pattern incl. composition, inheritance etc. can be found on the the Adequately Good blog in the JavaScript Module Pattern: In-Depth post.

Have an excellent Friday.