Category Archives: JavaScript

Love it, or hate it – it’s got the power.

Cached Data Library

In my previous post I described a technique for storing the results of Ajax calls in the browser and looking them up before making subsequent calls. This way unneeded Ajax calls can be prevented and a huge performance gain can be achieved. This is especially effective for Coach Views that are used inside of Tables in IBM Business Process Manager.

Since I am lazy and don’t want to think about how to actually implement this technique every time I want to make an Ajax call in a custom Coach View, I prefer to keep functions like these in a utility JavaScript library that handles everything for me. This could look like this:

var cachedData = (function(){
	// Create a unique string identifier from the ajax service's url and the given params
	var _createAjaxId = function(fnAjax,params){
		var url = fnAjax.toString().replace(/[^]*url\s=\s\"(.*)\"[^]*/,"$1"),
			serviceId = url.replace(/.*service\/(.*)\?.*/,"$1").replace(/-/g,'_').replace(/[^\w]/g,"");
			paramid = JSON.stringify(params).replace(/\s*"[^"]+"\s*:/g,"").replace(/[^\w]/g,"");
		return 'ajx'+ serviceId + paramid;
	},
	
	// Creates a shared object for the given properties:
	_createShared = function(p_sName){
		cachedData._shared = cachedData._shared||{};
		cachedData._shared[p_sName] = cachedData._shared[p_sName]||{ ready: false, loading: false};
		return cachedData._shared[p_sName];	
	},

	// Returns the globally shared object. If it cannot be found, it is created.
	_getSharedObj = function(p_sName){
		try{ return cachedData._shared[p_sName]||_createShared(p_sName); }
		catch(e){ return _createShared(p_sName);}
	},

	// Returns the content of the globally shared object:
	getShared = function(p_sName){
		return _getSharedObj(p_sName).content;
	},

	// Sets the shared object and executes all registered handler functions:
	setShared = function(sName,oData){
		if(oData){
			_getSharedObj(sName).content = oData;
			_getSharedObj(sName).ready = true;
			
			var handlers = _getSharedObj(sName).onloadhandlers, i;
			for(i=0; i<handlers.length; i++){
				 if(typeof handlers[i] == "function")handlers[i](oData);
			}
		}
		_getSharedObj(sName).loading = false;	
	},
	
	// The main function which wraps the ajax call:
	ajaxCached = function(props){
		if(!props.load||!props.context)return;
		var fnAfterLoad = props.load,
			sServiceName = props.serviceName,
			oContext = props.context,
			params = props.params,
			sName = _createAjaxId(oContext.options[sServiceName],params);

		// Load data and store in shared object:
		if(_getSharedObj(sName).ready){
			fnAfterLoad(getShared(sName));
		}
		else {
			_getSharedObj(sName).onloadhandlers = _getSharedObj(sName).onloadhandlers || [];
			_getSharedObj(sName).onloadhandlers[_getSharedObj(sName).onloadhandlers.length] = fnAfterLoad;
			if(!_getSharedObj(sName).loading){
				oContext.options[sServiceName]({
					params: JSON.stringify(params),
					load:function(data){
						setShared(sName,data);
					}
				});
				_getSharedObj(sName).loading = true;
			}
		}
	};

	// Expose public methods:
	return {
		get : getShared,
		set : setShared,
		ajax : ajaxCached
	}
})();

What it does is provide a wrapper function for the Ajax call. All that needs to be done to get this to work is upload it to your project (Process App or Toolkit), link to it in the Coach View where you make your Ajax call, and then make the call in the following fashion:

var _this = this;
cachedData.ajax({
	context: _this.context,
	serviceName: "sampleAjaxService",
	params: {text: "sampleInput"},
	
	// Callback after shared data is loaded:
	load: function(data){
		console.log(data);
	}
});

Adjust sampleAjaxService and params to your specific use case and voilĂ : Your Ajax calls’ results will be cached and unneccessary calls will be prevented using the cached data instead.

Note that in order to store the results a unique key is created from the Ajax service’s name (based on its URL, not the name of the configuration option as that is not unique) and any parameters that were submitted via the params property. This means that the same Ajax service only uses the cache if the parameter configuration is the same as from a previous call.

Wrapping Existing Event Handlers in JavaScript

When working with frameworks, such as Intrexx or IBM Business Process Manager, you often want to extend existing UI controls. You want to prepend or append event handlers to the ones already in place. This post explains how this can be done.

Why not addEventListener?

The obvious solution is simply using addEventListener. However, sometimes you want to do a little more, and need a little more control. Perhaps the event handler that needs to be extended is not a standard event. Or perhaps you need to do something specifically before or after the existing function is called.

Wrapping an existing function

Suppose we have an object obj with a property change(). The trick is to store the original function away and replace it with a new function which calls the original function. The concept looks like this:

// Store original function:
var _change = obj.change;

// Replace with new function:
obj.change = function(){
  // Do something before...
  _change();
  // Do something after...
}

A full example can be seen below. Changing the value of the text field triggers the change funtion. In the JavaScript tab you can see the additional function that “wraps” the original function, i.e. calls the original function.

See the Pen Example 1 by Christian Templin (@cianty) on CodePen.

Fixing this

The above pattern is a bit buggy. Since we “move” the original function into our new function any code which uses the this keyword gets broken. Take a look at the following example: On every change the original functionality calls an alert which prints the text input’s value. By moving the function, this no longer refers to the text input.

See the Pen Example 2: We broke this by Christian Templin (@cianty) on CodePen.

The solution to this is using call or apply. When executing the function via call/apply you can explicitly provide the this context, so that the original functionality is kept intact.

See the Pen Example 3: Fixed this by Christian Templin (@cianty) on CodePen.

Conclusion

The following pattern can be used to prepend or append code to an existing JavaScript function. Whether to use call or apply depends on how you want (need) to pass your arguments.

// Store original function:
var _change = obj.change;

// Replace with new function:
obj.change = function(){
  // Do something before...
  _change.call(this);
  // Do something after...
}

Generating Table of Contents with JavaScript

Inspired by Chris Coyier’s article at CSS-Tricks I decided to implement dynamically generated tables of contents for this blog.

Goals and Features

The purpose of the JavaScript function is to generate a table of contents for articles based on the headings found inside. So far, so good. Now, if you take a deeper look at it, there are a couple of things to consider.

  • Take all heading tags (H1 to H6) into account
  • Add ID attributes to the article headings where missing so they are not needed in the original markup
  • Handle multiple articles per page and make proper tables for each
  • Offer some settings for the wrapping jQuery selector, headline text and class name

The Code

Mostly the “handle multiple articles” aspect required special attention. How to set up a working jQuery selector will depend on the structure of your site’s markup – mine is based on WordPress’ Twenty Twelve default theme.
For the development I set up a pen on CodePen:

See the Pen JS-generated Table of Contents by Christian Templin (@cianty) on CodePen

Include JavaScript into WordPress

There are various ways for using JavaScript in WordPress. I put the code into a separate file custom.js and uploaded it to the blog’s folder. Then in footer.php the file is included right before the closing body tag:

<script src="http://code.jquery.com/jquery-1.10.1.min.js" type="text/javascript"></script>
<script type="text/javascript" src="<path to your file>/custom.js"></script>
</body>

Now the tables are automatically inserted into each article.

If you wanted you could easily include an enumeration by either using CSS counter-increment or the JavaScript variable that is already there in the function for the generation of the IDs.
For additional inspiration check out this pen by Joel Newcomer using the jQuery Waypoints plugin.