-
Notifications
You must be signed in to change notification settings - Fork 0
Using ajile
ajile ♻️ asynchronous javascript importing & loading extension ✅ enables asynchronous javascript importing, loading & module management in web browsers, webviews & other javascript & DOM-enabled environments.
Getting started with ajile is simple, just add this <script>
tag to any HTML page and set its src
attribute to ajile's actual location:
<script src="path/to/ajile/com.iskitz.ajile.js" type="text/javascript"></script>
Once that's done, ajile's ready for use!
ajile provides both Manual and Automatic Script Loading.
Manual script loading is done via ajile's Load() API:
Load ("//ajile.net/play/api/scripts/LoadExample.js");
In the example above, the LoadExample.js
script is dynamically loaded into the current page. The Load() API allows any inline or external script to programmatically load any other inline or external script. It eliminates the need to manually modify pages each time their script list changes. It allows using JavaScript rather than HTML to define exactly which scripts are loaded at runtime.
Automatic script loading uses Shared and Page Loader scripts and is enabled by default to get you up and running quickly.
TIP: Shared and Page Loaders separate HTML and JavaScript which is an important first step towards developing with the Model-View-Controller (MVC) software architecture pattern.
Shared Loader is the script used to store code shared by multiple pages. It's the index.js
script at ajile's location (i.e. path/to/ajile/index.js
) that's automatically loaded whenever a page using ajile is launched.
The shared loader is enabled by default but can be disabled by setting the mvcshareoff launch option in ajile's <script>
tag's src
attribute:
<script src="path/to/ajile/com.iskitz.ajile.js?mvcshareoff" type="text/javascript"></script>
To re-enable the shared loader, remove the mvcshareoff launch option or replace it with mvcshare.
TIP: The shared loader is useful for loading code that's shared by multiple pages. Social widgets, analytics, and GUI libraries are examples of such shared code. When used, the shared loader is the only script that needs to be updated when the list of scripts being used by multiple pages changes. It removes the need to directly modify each affected page.
A Page loader is a page-specific script that's automatically loaded whenever its page is launched. It uses the same name and location as its page (i.e. /my/Page.js
for /my/Page.htm
) and is the starting point for all of its page's scripts.
Page loaders are enabled by default but can be disabled by setting the mvcoff launch option in ajile's script
tag's src
attribute:
<script src="path/to/ajile/com.iskitz.ajile.js?mvcoff" type="text/javascript"></script>
To re-enable page loaders remove the mvcoff launch option or replace it with mvc.
FYI: ajile's API Examples page (api/index.htm) uses its own page loader (api/index.js) for automatic script loading.
ajile provides APIs for defining namespaces, modules and their dependencies.
The Namespace() API enables defining namespaces.
Namespace ("com.iskitz.ajile.examples"); // Creates the following globally accessible
com; // com namespace,
com.iskitz; // com.iskitz namespace,
com.iskitz.ajile; // com.iskitz.ajile namespace, and
com.iskitz.ajile.examples; // com.iskitz.ajile.examples namespace objects.
The Namespace() API shown in the Namespacing section above creates namespaces that can be used for storing modules.
Namespace ("com.iskitz.ajile.examples"); // Creates a global namespace.
com.iskitz.ajile.examples.NamespaceExample = function() // Adds a module to that namespace.
{
alert("This is the NamespaceExample!"); // The module shows a popup message.
};
In the example above, the com.iskitz.ajile.examples
namespace is created and the NamespaceExample
module, a function, is added to it. A reversed domain name is used as its namespace to assure that the module is uniquely named. The ability to identify individual modules is especially important when using multiple modules from varied sources within the same page or site.
When working with modules within an Intranet or non-Internet environment, it may be sufficient to use simpler namespaces. ajile provides the flexibility to create namespaces of any desired depth.
Once a module is created as shown in the Defining a module section above, it needs to be packaged in order to be included or imported. ajile supports packaging By File Name and By File Path.
To package the NamespaceExample
module shown in the Defining a module section above, by file name, save the module's source code in a file named: com.iskitz.ajile.examples.NamespaceExample.js
Next, place that file in the same directory as the ajile module:
path/to/ajile/com.iskitz.ajile.examples.NamespaceExample.js
FYI: ajile supports replacing all (.) characters in a packaged module's filename with any valid operating system filename character but requires that one (.) remain immediately before the file's extension i.e.:
com-iskitz-ajile-examples-NamespaceExample.js
,com_iskitz_ajile_examples_NamespaceExample.js
To package the NamespaceExample
module shown in the Defining a module section above, by file path, save the NamespaceExample
module's source code in a similarly named file within the ajile module's directory:
path/to/ajile/com/iskitz/ajile/examples/NamespaceExample.js
Namespaces are effective for interoperability but can complicate development by requiring the use of long module names. ajile's solution to this challenge is the Import() API.
The Import() API provides these key benefits
- Simple names to reference uniquely named JavaScript modules.
- Simple definition of JavaScript module dependencies.
- Simple programmatic loading of external JavaScript modules.
Import ("com.iskitz.ajile.examples.Complex");
function testImport()
{
var complex = new Complex();
complex.sayHello();
}
The Import() API in the code above indicates that there is a dependency that must be imported. The externally defined com.iskitz.ajile.examples.Complex.js
JavaScript module is automatically imported and made accessible via its short name, Complex
. The imported Complex
module is then used by the testImport
function.
Namespace ("com.iskitz.ajile.examples");
Import ("com.iskitz.ajile.examples.Simple");
com.iskitz.ajile.examples.Complex = function()
{
var simple = new Simple();
this.sayHello = function sayHello()
{
var message = "Hello World!\n\nThis is a " + this.toString()
+ " object that imported and is\nusing a "
+ simple.toString() + " object!"
;
alert(message);
};
this.toString = function toString()
{
return "[Complex]";
};
};
The Import() API used in the code above automatically imports the externally defined com.iskitz.ajile.examples.Simple.js
JavaScript module then makes it available via its short name Simple.
Namespace ("com.iskitz.ajile.examples");
com.iskitz.ajile.examples.Simple = function()
{
this.toString = function toString()
{
return "[Simple]";
};
};
When importing multiple modules it is possible to encounter naming conflicts. ajile provides the ImportAs() API as a solution to this problem.
The ImportAs() API provides two benefits in addition to those provided by the Import() API:
- Flexibility to import a module using any un-used short name.
- Ability to handle naming conflicts by assigning aliases to similarly named modules.
Import ("com.iskitz.ajile.examples.Complex");
ImportAs ("AComplex", "com.iskitz.ajile.examples.ambiguity.Complex");
function testAmbiguity()
{
var complex = new Complex();
complex.sayHello();
var aComplex = new AComplex();
aComplex.sayHello();
return false;
}
In the code above, two modules with the identical short name Complex
are imported. The Import() API automatically imports the externally defined com.iskitz.ajile.examples.Complex.js
JavaScript module as is. The ImportAs() API also automatically imports the externally defined com.iskitz.ajile.examples.ambiguity.Complex.js
JavaScript module but performs the extra step of assigning it the AComplex
alias.
By assigning the AComplex
alias to the imported com.iskitz.ajile.examples.ambiguity.Complex
module, the testAmbiguity()
function is able to reference both modules without encountering naming conflicts.
Namespace ("com.iskitz.ajile.examples.ambiguous");
Import ("com.iskitz.ajile.examples.Simple");
com.iskitz.ajile.examples.ambiguous.Complex = function()
{
var simple = new Simple();
this.sayHello = function sayHello()
{
var message = "Hello World!\n\nThis is an ambiguous " + this.toString()
+ " object that\nimported and is using a "
+ simple.toString() + " object!"
;
alert(message);
};
this.toString = function toString()
{
return "[Complex]";
};
};