Skip to content
This repository has been archived by the owner on Jun 27, 2020. It is now read-only.

jWidget SDK documentation. Resources attachment

Egor Nepomnyaschih edited this page Oct 4, 2015 · 1 revision

<< jWidget SDK documentation

jWidget SDK supports a feature of resources (text, JSON, HTML-templates) extraction into separate files.

Formulation of the problem

Let you develop a JS-component which is rendered by HTML-template using jQuery:

component.js

MyApp.Component = function(renderTo)
{
    var el = jQuery(MyApp.Component.template);

    el.find(".myapp-component-hello").click(function(event) {
        event.preventDefault();
        alert("Hello world!");
    });

    jQuery(renderTo).append(el);
}

MyApp.Component.template =
    '<div class="myapp-component">' +
        '<a href="#" class="myapp-component-hello">Click me!</a>' +
    '</div>';

application.js

function main()
{
    MyApp.Component("body");
}

jQuery(main);

Please notice that variable MyApp.Component.template is just a string which contains HTML markup. But we must split this string into multiple parts, quote them up and join by concatenation just to follow JavaScript syntax. This is extremely abusing, especially if template is large. I bet you desire to extract this HTML-template into separate HTML-file, like this:

component.html

<div class="myapp-component">
    <a href="#" class="myapp-component-hello">Click me!</a>
</div>

It is amazing: component representation is extracted into separate HTML-file, so we don't need to adjust its contents to JavaScript string syntax and modern text editors will highlight HTML syntax beautifully. But how can we get an access to the contents of this HTML file?

Dynamic loading solution

We must load this HTML-file with AJAX. But it is abusing, because we can not initialize the application right from main function now: the template is not loaded yet. We must wait for HTML template loading, and initialize the application after that:

application.js

function main()
{
    jQuery.ajax({
        url      : "component.html",
        type     : "get",
        dataType : "text",
        success  : function(response)
        {
            MyApp.Component.template = response;
            MyApp.Component("body");
        }
    });
}

jQuery(main);

The issues start as soon as number of templates will grow. You'll need to send multiple jQuery.ajax requests to load templates asynchronously, and check pending templates count in success handlers. Moreover, if a request has failed, you need to stop loading of remaining templates and show error message.

You can try to use some frameworks for JS and resources dynamic loading to fix this problems, but anyway this will cause performance lapses and browser caching problems. You can learn dynamic loading disadvantages on page Compare jWidget SDK architecture with other JavaScript architectures.

Solution with use of jWidget SDK

jWidget SDK proclaims another solution of remarked problem. Instead of dynamic HTML template loading via AJAX you can simply configure jWidget SDK to convert HTML template to JS file in process of project build, and this file will contain a neccessary string variable MyApp.Component.template.

To make this work, you need to specify resource file in corresponding package:

jwsdk-config/packages/application.json

{
    "resources" : [
        "component.js",
        "component.html : MyApp.Component.template",
        "application.js"
    ]
}

That's it! Now, the next file will be created in process of project compilation automatically:

public/build/resources/component.html.js

MyApp.Component.template = '<div class="myapp-component"><a href="#" class="myapp-component-hello">Click me!</a></div>';

This file is created automatically, it will be ignored by Git version control system (since public/build is listed in .gitignore file), it has JS format, and it will be attached to your HTML page automatically:

public/pages/application.html

...
<script type="text/javascript" charset="utf-8" src="/component.js?timestamp=123456789"></script>
<script type="text/javascript" charset="utf-8" src="/build/resources/component.html.js?timestamp=123456789"></script>
<script type="text/javascript" charset="utf-8" src="/application.js?timestamp=123456789"></script>
...

Moreover, in release mode, this file till be merged with other scripts in corresponding package and compressed into MIN.JS-file:

public/pages/application.html (release version)

...
<script type="text/javascript" charset="utf-8" src="/build/packages/application.min.js?timestamp=123456789"></script>
...

Now we don't need any kind of AJAX loader, and our HTML resource file is loaded statically with all other scripts.

Resource extraction into separate file benefits

  • Explicit separation of application logic, data and representation
  • Lack of quotes and concatenations in resource definition code
  • Syntax highlight in text editors
  • Ability to use the same resource files in other application parts, like Flash-applications and backend
  • Ease of HTML file splitting into separate visual components, if the file is prepared by designer/slicer specialist

Resource attachment instruction

All resources are defined in resources list of package config file.

If resource type corresponds to file extension, you can define it by a single string:

"resources" : [
    ...
    "<resource_file_path> : <param1>, <param2>, ...",
    ...
]

Attachment parameters are splitted from each other by commas and splitted from resource path by colon.

If resource type doesn't correspond to file extension, you can defined it with a JSON:

"resources" : [
    ...
    {
        "path"        : "<resource_file_path>",
        "type"        : "<resource_type>",
        "param_name1" : "<param1>",
        "param_name2" : "<param2>"
    },
    ...
]

Attachment parameters depend on resource type. Usually, one parameter defines a variable name to save the resource into. If variable name doesn't contain dots, it will be defined with var keyword:

var myResource = ...

If variable name contains dots, it requires corresponding namespace to be defined previously (resource doesn't check namespace existance):

MyApp.myResource = ...

Resource types

txt

Text resource.

String definition

"<path>.txt : <variable_name>"

JSON definition

{
    "path" : "<path>",
    "type" : "txt",
    "var"  : "<variable_name>"
}

Source file resource.txt

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.

Build result build/resources/resource.txt.js

<variable_name> = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n\
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim\n\
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\n\
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate\n\
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n\
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id\n\
est laborum.';

json

JSON-resource.

String definition

"<path>.json : <variable_name>"

JSON definition

{
    "path" : "<path>",
    "type" : "json",
    "var"  : "<variable_name>"
}

Source file resource.json

{
    "name" : "Vasya Pupkin",
    "age"  : 28
}

Build result build/resources/resource.json.js

<variable_name> = {"name":"Vasya Pupkin","age":28};

html

HTML-resource.

String definition

"<path>.html : <variable_name>"

JSON definition

{
    "path" : "<path>",
    "type" : "html",
    "var"  : "<variable_name>"
}

Source file resource.html

<div class="myapp-component">
    <a href="#" class="myapp-component-hello">Click me!</a>
</div>

Build result build/resources/resource.html.js

<variable_name> = '<div class="myapp-component"><a href="#" class="myapp-component-hello">Click me!</a></div>';

Unline text (txt) resource, it is possible to optimize html resource: delete excessive spaces and line breaks.

jw.html

JW.UI.Component HTML-template compatible with jWidget UI framework.

String definition

"<path>.jw.html : <component_class>[, <template_name>]"

JSON definition

{
    "path"     : "<path>",
    "type"     : "jw.html",
    "class"    : "<component_class>",
    "template" : "<template_name>"
}

Default template name is main (main template of JW.UI.Component).

Source file resource.jw.html

<div class="myapp-component">
    <a href="#" class="myapp-component-hello">Click me!</a>
</div>

Build result build/resources/resource.jw.html.js

JW.UI.template(<component_class>, { <template_name>: '<div class="myapp-component"><a href="#" class="myapp-component-hello">Click me!</a></div>' });