adesso Blog

In my blog post, I would like to introduce the Dojo Library. In the early 2000s, it contributed significantly to the development of modern web technologies and introduced concepts that are now considered standard. For anyone interested in web development, it is exciting to know that many common techniques and approaches have their origin in Dojo. I would like to present these formative ideas and innovations here.

What is Dojo and what can it do?

Dojo is a JavaScript library that was developed at a time when there were no uniform standards for web development. It was designed to make web applications easier and faster. With many concepts and ideas, Dojo helps to overcome the challenges of early web development and also efficiently solve today's problems.

Dojo has introduced many ideas that we still use today. Some of them are:

  • Modular programming: code was split into smaller parts. This improved loading times and made the code clearer.
  • Reusable components: the Dojo library developed a system for reusing UI components. Similar to what Angular, React or Vue do today.
  • Asynchronous programming: Dojo had tools that made it easy to write asynchronous code early on. This means that actions can be executed in the background without freezing the website.
  • Cross-browser compatibility: Back in the days when web browsers (Internet Explorer, Edge, Firefox, Chrome, Safari) were much more different than they are today, Dojo paved the way for code to look and function the same in every browser.

Modular programming in Dojo

Dojo has always had core features and concepts that were crucial for developing reusable components. Here are the most important features and how they are used in Dojo:

1. Lifecycle Hooks

In Dojo, lifecycle hooks are used primarily in widgets and dijits (Dojo widgets) to control the lifecycle of a component. The main hooks include:

  • constructor(): initialises the widget before it is created.
  • postMixInProperties(): called before the widget's attributes are overwritten with default or custom values.
  • buildRendering(): Creates the widget's DOM tree.
  • postCreate(): Called after the widget's DOM link.
  • startup(): Signals that the widget is ready and has been added to the DOM.
  • destroy(): Removes the widget from the DOM and cleans up any resources.

These lifecycle hooks provide fine-grained control over each stage in a widget's life.

	
		define(["dojo/_base/declare", "dijit/_WidgetBase"], function(declare, _WidgetBase){
		    return declare([_WidgetBase], {
		        constructor: function(){
		            console.log("Widget initialized");
		        },
		        postMixInProperties: function(){
		            console.log("Properties mixed in");
		        },
		        buildRendering: function(){
		            this.inherited(arguments);
		            console.log("DOM elements created");
		        },
		        postCreate: function(){
		            console.log("Widget created and DOM linked");
		        },
		        startup: function(){
		            console.log("Widget started and added to DOM");
		        },
		        destroy: function(){
		            console.log("Widget destroyed and removed from DOM");
		        }
		    });
		});
	
2. Template strings (HTML inline in JavaScript)

In Dojo, templates can be embedded directly in the JavaScript code to define the structure and layout of a component. This makes it possible to define HTML directly in the widget's JavaScript.

	
		define(["dojo/_base/declare", "dijit/_WidgetBase", "dojo/text!./template.html"],
		  function(declare, _WidgetBase, template){
		    return declare([_WidgetBase], {
		    templateString: template,
		    postCreate: function(){
		        console.log("Template linked to DOM!");
		    }
		    });
		});
	
3. Input/output parameters (data binding)

Dojo allows you to pass values and properties to widgets, typically via MixIn properties or constructor parameters. This allows developers to set parameters from the outside and process them in the component.

	
		define(["dojo/_base/declare", "dijit/_WidgetBase"], function(declare, _WidgetBase){
		    return declare([_WidgetBase], {
		      customProperty: "Default Value",
		      postCreate: function(){
		        console.log("Property Value:", this.customProperty);
		      }
		    });
		});
	
4. Separate files for CSS, HTML and JavaScript

Dojo supports the separation of CSS, HTML and JavaScript. HTML templates are often integrated directly into JavaScript files as template strings, while CSS is managed in separate files. This promotes reusability and clarity.

  • JavaScript (widget logic): Contains the business logic and control.
  • HTML (template): Can be integrated within the JavaScript code or used as a separate file.
  • CSS: This is often stored in external files and used for the styling of the widget.

Reusable components in Dojo

Dojo offers a flexible widget system based on the Dijit library, which provides a wide range of UI elements. These widgets are reusable components that can be individually customised and expanded. Examples of Dojo widgets:

  • dijit.form.Button: Reusable button with advanced features.
  • dijit.Dialog: A modal dialogue that can be customised in a variety of ways.
  • dijit.Tree: An interactive hierarchical tree for navigation.

Asynchronous programming in Dojo

Another important feature of Dojo is its support for asynchronous programming. This makes it possible to execute server requests and other time-consuming tasks in the background. With the dojo/request API, HTTP requests can be made easily and efficiently without blocking the user interface.

	
		require(["dojo/request"], function(request){
		    request.get("https://example.com/api/data").then(function(data){
		        console.log("Data received:", data);
		    });
		});  
	

Cross-browser compatibility with Dojo

At the beginning of the millennium, web browsers differed greatly in their support of HTML, CSS and JavaScript. Web developers therefore had to put a lot of effort into making their applications look and work the same in all browsers. Dojo was one of the first libraries to address this problem and provide cross-platform compatibility. It included tools and functions specifically designed to recognise and adjust for differences between browsers, without requiring developers to write separate code for each browser.

Dojo ensured that JavaScript functions could be executed consistently across browsers by handling browser-specific differences internally. For example, Dojo included functions to ensure that event listeners work across all browsers, without developers having to worry about incompatibilities.

Take dojo.connect as an example for adding an event handler for a button click. In the past, you had to write different event handler codes for different browsers because Internet Explorer uses a different syntax from other browsers.

	
		require(["dojo/dom", "dojo/_base/connect", "dojo/domReady!"], function(dom, connect){
		    var button = dom.byId("myButton");
		    connect.connect(button, "onclick", function(){
		        alert("Button wurde geklickt!");
		    });
		});
	

Note: Dojo 1.7 includes a new module, dojo.on, for event handling.

Conclusion

Dojo was one of the first approaches to support modern concepts such as lifecycle hooks, modular programming and separate files for CSS and HTML. Dojo's reusable components are designed for customisation and modularity, providing a solid foundation for developers. For these reasons, Dojo can be said to be a pioneer of modern web development and can be seen as a forerunner of Angular, React and Vue.

Would you like to learn more about exciting topics from the adesso world? Then take a look at our previously published blog posts.

Picture Alexander Korf

Author Alexander Korf

Alexander Korf is a software developer in the Public business line at adesso in Bonn. He works in the Java environment in both frontend and backend development.

Save this page. Remove this page.