Javascript Interface Abstract Notation

Hello everyone, this post is about the library, or rather, the philosophy of developing Javascript applications that I invented a couple of months ago. I constantly use it myself, distributed to all friends. The reviews are positive, so I decided to take a chance to open it to a wider community.
The library itself works as a jQuery tweak. In practice, dependence on jQuery is conditional and it can be shared with the library itself until it was needed.
Jiant allows you to create client applications of any complexity, greatly simplifying their support and development.

Brief Background


I have been developing web applications for over 10 years. For the past couple of years, I have been using GWT constantly. Unfortunately, Google could not solve the most serious problem of this library - slow compilation. After a long pause in the release of new versions (between 2.4 and 2.5) and the transfer of GWT to the side, the leading developers of the company where I work (not widely known) agreed that it was time to tie up with GWT. We decided to continue developing on jQuery. But GWT instilled some very convenient development “reflexes” that were clearly lacking with pure javascript programming. In particular, the MVC approach with the separation of presentation and logic, EventBus. The inconvenience and discomfort of the new situation led to some ideas, which gradually developing and transforming led to the solution described below.
Also, before writing the library, I figured out existing MVC solutions like Backbone and was not very happy with the amount of boilerplate code (redundancy of required declarations).

Benefits


Actually, in order to have an incentive to read, I will run ahead and list the main advantages:
  1. Code completion (autocomplete) - instead of string declarations.
  2. Complete abstraction of the interface and separation of logic and presentation
  3. Validation of binding javascript variables to the actual elements of the web page during application launch, and not during the execution of a specific code fragment. What gives additional protection to the developer of functionality from the playful hands of the designer
  4. Self-documenting at the code level in the simplest way possible - less and at the same time, I have never seen
  5. Easy to embed - anytime, anywhere, you can embed and immediately enjoy the benefits

And much more on the little things.

Principles


The ideology of the library is based on the following theses. If we take them as a basis, then everything further is understood easily:
  • Any interface consists of a set of views (View, View?) - it is difficult to find a word in Russian, since these are not widgets, but also not screens. These are unique, meaningful parts of the interface. It’s easiest to select them if you just listen to the customer’s story: here is the “contact edit screen”, from here we go to the “user list” (there can be several visible Views on the page at the same time).
  • Each View contains a set of elements, such as a "button to return to the list", "container of the list of users", "user picture". These elements are identifiable within the same View.

And also a few technological theses that will lead through the jungle when it is necessary to make a decision “how to do it”? So that it does not contradict the following:
  • What the user sees in the end on the screen is essentially html code. And what is the best way to render html? Only html itself. That is, when we need to show the user a certain interface - we just put his html on the page and use it when necessary. Instead of generating via the DOM, manipulating or concatenating strings on the fly (except in the simplest cases). It will also make life easier for the designer - he will simply design the html code.
  • Repeating elements are generated by templates, which again is just html code on the page


Most importantly, Jiant (javascript interface abstract notation) is more a development philosophy than a set of tricks. If you develop adhering to this philosophy, then everything turns out easily and naturally.

View


Designing

So, at first we design the interface on json, without going into details of implementation. For example, just listening to the narrator (or customer) about the registration form: “Let the user enter a name and email, then press the register button and he will be shown a window that he is registered, which he clicks and gets inside.”
We describe it in json, as we hear and write.

var registration = { //объявим одну переменную, чтобы не засорять глобальное пространство имен 
  views: {  // секция views содержит те самые концептуальнофилософские View
    registrationFormView: {  // форма регистрации
      nameInput: jiant.input, // поле ввода имени
      emailInput: jiant.input, // поле ввода емейла
      registerCtl: jiant.ctl // элемент интерфейса, нажав на который пользователь зарегистрируется
    },
    successView: { // экран с сообщением об успехе
      continueCtl: jiant.ctl // кнопка или ссылка, неважно, для входа в приложение
    },
    errorView: {  // экран с сообщением об ошибке
      errorMessage: jiant.label, // сообщение об ошибке
      disposeCtl: jiant.ctl // кнопка чтобы спрятать сообщение об ошибке и поменять значения в полях ввода
    }
  }
};


How to understand all this? We read the code as follows: “our application consists of three views - a registration form, a success message, and an error message. The registration form contains two input fields and one control ... "and so on. jiant.input and jiant.ctl here are for documentation purposes only. For example, you can write like this and it will work too, but it will be less clear when reading:

var registration = {
  views: {  
    registrationFormView: {  
      nameInput: 1,
      emailInput: 1,
      registerCtl: 1,
    },
    successView: { 
      continueCtl: 1
    },
    errorView: {  
      errorMessage: 1,
      disposeCtl: 1
    }
  }
};


We realize

Now that the interface is described in the most abstract and concise way possible, we implement the application logic with the interface and implement the interface itself in html code. As a result, getting MVC in the form of json-html-javascript. First, we implement the html views themselves, according to the following rules:
  • Each View has an html element with a corresponding id
  • Each View element (nameInput, registerCtl) corresponds to an html element with a corresponding class located inside the View element


Implementation of registrationFormView:
Your name:
Your email:

What is the underscore before the identifier and class name? A little lower it is explained.

Similarly, we implement successView:
Поздравляем с регистрацией, мы Вам очень рады!

and errorView.

Embody the abstraction

So we have an abstract interface definition. There is its implementation. How to connect them?
In the following way:
$(function() {
  jiant.bindUi("_", registration, true);
});


Done.

The bindUi function takes the first parameter as a prefix that is added to each abstract definition of the View or View element. In this case, it is underlined. If you pass an empty string, then the names in json and class identifiers in html will match. I find it convenient to use underlining to increase the readability of html code - meaningful interface elements are immediately visible.
The second parameter is a variable containing an abstract definition of the application. jiant pulls out the views element from it and associates each view with its implementation.
The third parameter is the inclusion of debug mode, which simplifies the search for errors and increases the amount of output to the console.

Magic

A little magic is already starting here. During bindUi, each View is searched from the interface definition by identifier. Then the resulting jQuery wrapper object is attached to the definition variable. That is, after bindUi is executed, the registration.views.registrationFormView variable contains the result of $ ("#_ registrationFormView"). Also, each element of the view is searched by class and filled, that is, registration.views.registrationFormView.registerCtl contains $ ("#_ registrationFormView"). Find ("._ registerCtl").

For each link not found, an error is reported to the console. And if debugging mode is turned on, an alert is issued at the end with a list of all errors, so that the developer does not lose sight of this.

At the output, we have an interface description object that is completely attached to real html elements. Which can now be used in the logic code as follows.

Use

The easiest way is to write your own separate javascript file and register for the onUiBound event, for example:
jiant.onUiBound(function($, app) { // в этот момент все jQuery wrapper объекты присоединены к абстрактному объявлению интерфейса
  var view = app.views.registrationFormView,
        errorView = app.views.errorView; // чтобы меньше писать
  view.registerCtl.click(function() {
    errorView.hide();
    if (view.nameInput.val() == "") {
      errorView.errorMessage.html("Пустое имя!");
      errorView.show();
    } else if (view.emailInput.val() == "") {
      errorView.errorMessage.html("Пустой емейл!");
      errorView.show();
    } else {
      view.hide();
      app.views.successView.show();
    }
  });
});


Ready logic. When reading, this is not felt, but in a good IDE - 75% of this code is auto-completed, i.e. Writing time has been saved and the possibility of errors due to typos has been reduced.

What else


Over time, templates, EventBus, hash navigation, AJAX work with the server were added in the process of use - all this in the form of the most autocomplete friendly and requiring minimal effort from the developer.
Example AJAX definition:
var app = {
   ajax: {
    getDataFromServer: function(id, callback) {}
   }
}

Nothing more is required from the developer - jiant itself implements the AJAX request code.

It remains to use:
  app.ajax.getDataFromServer(6345, function(data) {
    //do smth with data
  });


Who knows GWT - immediately see the complete resemblance to Async service.

Further


If this article is published and arouses interest, I am ready to further describe the remaining functions (templates, AJAX, states, and the event bus). Gihub project code: github.com/vecnas/jiant , a site with a description: sites.google.com/site/jiantscript/home

Also popular now: