-
Notifications
You must be signed in to change notification settings - Fork 144
Client Modules
- Hypergrid Client Modules are CommonJS modules wrapped with a few lines of code to insert them into the
window.fin.Hypergrid.modules
namespace. - Inside a client module, the
module
,module.exports
,exports
, andrequire()
all work as usual. - The Hypergrid CDN hosts build files for Hypergrid core and other modules on github.com/fin-hypergrid.
Skip this section if you are already familiar with modules, build files, and loading them from the CDN.
Although .html
files can accommodate JavaScript code inside <script>...</script>
elements, this approach quickly gets out of hand for all but the simplest applications. Code can be moved to a separate .js
file which the .html
file can load using an empty <script src="source.js"></script>
with a reference to the file in its src
attribute. When the .js
file "exports" a single object, we call it a module.
For serious development with Hypergrid, we recommend using a module bundler, to bundle an application module (i.e., a .js
file) + the fin-hypergrid module + any other npm modules into a single .js
file using Browserify or webpack. There are many advantages to this approach for serious development.
That said, we recognize that:
- There are dev teams out there who cannot for various reasons use npm.
- There are dev teams out there who simply prefer to work with build files from a CDN via a series of
<script>
tags. - For very simple projects such as quick & easy prototyping/proof-of-concept, using the CDN build file is just simpler.
For applications that load modules separately, the Hypergrid CDN hosts build files for this purpose. The CDN index has sample <script>
tags you can can copy & paste into your application .html
file.
The Hypergrid build file is a module that defines the Hypergrid
constructor/namespace, including the Hypergrid Module Loader.
Note: The Hypergrid build file is not itself a Hypergrid Client Module. Rather, it includes the code that defines client modules and how they load other modules; it is required before attempting to load client modules.
A sample <script>
tag to load Hypergrid, as shown in the CDN index, looks like this:
<script src='https://fin-hypergrid.github.io/core/3.0.0/build/fin-hypergrid.min.js'></script>
Note: A fully qualified version number is always required to load any build file from the CDN.
Once an application page loads the fin-hypergrid.js
(or fin-hypergrid.min.js
) module, its scripts have access to the Hypergrid
constructor/namespace object via the global property window.fin.Hypergrid
.
Previously, other modules (such as plug-ins, data source modules, library modules, mix-ins, etc.) were not available on the CDN; the application developer was on his or her own when it came to working with modules. The CDN now hosts all the modules whose repos are housed under the fin-hypergrid
GitHub organization; see the CDN index for the full list.
Hypergrid 3.0.0's module loader, which has no dependencies on import
or any external module loader, is implicitly invoked inside Hypergrid Client Modules with a local require()
function. Other types of modules, including straight JavaScript or bundled modules, can invoke fin.Hypergrid.require
explicitly to get references to Client Modules that were loaded earlier into the browser.
Hypergrid offers a simple module ecosystem called Client Modules, loaded into the fin.Hypergrid
namespace by the Hypergrid Module Loader.
A Hypergrid Client Module is a CommonJS module with a Hypergrid Client Module Wrapper.
All modules hosted under github.com/fin-hypergrid
are CommonJS modules and many of these are also published to the Hypergrid CDN with a Client Module wrapper. This makes migrating between approaches (module loader vs. module bundler) painless because the same source files (without the wrapper) can be used for either.
All the modules listed in the CDN Index
— with the exception of the Hypergrid build itself (fin-hypergrid/core
) — are wrapped as Hypergrid Client Modules.
Hypergrid Client Modules look and behave like CommonJS modules and include the following features:
- Each module is in a closure (so all their local vars are private)
-
module.exports
andexports
are fully supported (CommonJS stuff) -
require()
is supported as follows (CommonJS subset):-
require('fin-hypergrid')
— Access toHypergrid
itself -
require('fin-hypergrid/src/...')
— Access to a selected set of internal Hypergrid modules -
require('other-module')
— Access to other Client Modules - Note that the local file construct (
) is not supported!require('./local-file')
-
- No global object "pollution" (beyond
window.fin.Hypergrid.modules
)
Modules need to be "wrapped" before they are served using the following header and footer.
Hypergrid Client Module header:
(function(require, module, exports) {
Hypergrid Client Module footer:
})(fin.Hypergrid.require, fin.Hypergrid.modules, fin.Hypergrid.modules.exports = {});
fin.Hypergrid.modules['module-name'] = fin.Hypergrid.modules.exports;
Wrap your modules manually by including the code snippits above at the top and bottom of your source file. (This is generally not recommended however as the file will no longer be a CommonJS module.)
A better approach is to keep the source file as is, and wrap a copy of it.
The copy typically has the same name but is put in a ./build/
subfolder.
Here is a simple Node app to wrap your module files:
wrap.js:
var fs = require('fs');
var process = require('process');
var Wrapper = require('fin-hypergrid-client-module-wrapper');
var buildDir = 'build/';
if (!fs.existsSync(buildDir)) fs.mkdirSync(buildDir);
process.argv.slice(2).forEach(function(filenameWithOptionalVersion) {
var matches = filenameWithOptionalVersion.match(/^((.*)\.js)(@(.*))?$/),
filename = matches[1], modname = matches[2], version = matches[4] || '';
var wrapper = new Wrapper({ name: modname, version: version });
fs.writeFileSync(buildDir + filename, wrapper.wrap(fs.readFileSync(filename)));
});
The above is invoked as follows:
node wrap A.js@1.5.0 B.js@2.1.0
# or:
node wrap *.js # but no version information
Caveat: As you can see, we have moved away from bare naked development with Notepad.exe, and at this point we would again recommend using
npm
and a module bundler instead if at all possible!
If you are into gulp, fin-hypergrid-client-module-maker
defines a build
task that uses fin-hypergrid-client-module-wrapper
(which supplies the above strings) to wrap your source file using the name defined in package.json
. It also defines lint
, test
, and doc
tasks for your convenience.
Let's say we have an app module my-app
that depends on some Client Modules from the fin-hypergrid CDN
, plus a couple of local modules which we'll call A
and B
. B
is a Hypergrid plug-in which depends on A
.
Note: By convention, a module's filename should reflect the module's name, although this is not required.
fin-hypergrid
, the Hypergrid build file, must always be loaded first as it contains the Module Loader which all other modules depend on.
Then load other modules in dependency order.
Note: Predefined modules do not need to be loaded as they are "baked into" (predefined in) Hypergrid.
index.html
(excerpt):
<script src='https://fin-hypergrid.github.io/core/3.0.0/build/fin-hypergrid.min.js'></script>
<script src='A.js'></script>
<script src='B.js'></script>
<script src='my-app.js'></script>
<script>
window.onload = function() {
var app = Hypergrid.require('my-app');
var grid = app.grid;
}
</script>
B.js
(excerpt):
var A = require('A');
my-app.js
(excerpt):
var Hypergrid = require('fin-hypergrid');
function App() {
this.grid = new Hypergrid({ plugins: [require('B')] });
}
var app = new App();
// add app stuff here like event handlers, etc
app.grid.addEventListener(...);
...
module.exports = app;
As of version Hypergrid 3 you can "bring your own" data source using the new DataSource
option.
Note: The
datasaur-local
data source is still included in 3.0.0 an is still the default when theDataSource
option is not defined. However,datasaur-local
will be removed as of Hypergrid 4.0.0, after which time there will be no default data source; you will need to supply one. So it is a good idea to start defining it now in your application source.
index.html
(excerpt):
<script src='https://fin-hypergrid.github.io/core/3.0.0/build/fin-hypergrid.min.js'></script>
<script src='https://fin-hypergrid.github.io/datasaur-base/3.0.0/build/datasaur-base.js'></script>
<script src='https://fin-hypergrid.github.io/datasaur-local/3.0.0/build/datasaur-local.js'></script>
<script src='my-app.js'></script>
<script>
window.onload = function() {
var app = Hypergrid.require('my-app');
var grid = app.grid;
}
</script>
my-app.js
(excerpt):
var Hypergrid = require('fin-hypergrid');
function App() {
this.grid = new Hypergrid({ DataSource: [require('datasaur-local')] });
}
var app = new App();
...
module.exports = app;
Note:
require('datasaur-local')
will work in Hypergrid 3.0.0 even without the<script>
tag that loads it because as mentioned above,datasaur-local
is still included. However, as of Hypergrid 4.0.0, the<script>
tag will be required.
Although the legacy expression fin.Hypergrid
would still work, don't use it! Use require('fin-hypergrid')
instead. This will allow you to move to Browserify without having to make any changes later to my-app.js to accommodate the move.
Modules hosted under github.com/fin-hypergrid
actually have package names with fin-hypergrid-
prepended. This creates an informal “scope” for the npmjs.org registry.
The set of predefined modules includes two subsets, Internal Modules and External Modules.
These are modules that are objects that Hypergrid defines; they are not available outside of the Hypergrid build except through Hypergrid Module Loader using the following syntax:
var module = require('fin-hypergrid/src/subfolder/module');
The legacy syntax Hypergrid.subfolder.module
is deprecated. Though still functional, a console warning will be issued; the functionality will be removed entirely in version 4. Please convert to the new syntax now.
Permissible subfolder names include (see each index file for available module names):
Note: Access internal modules is provided as a stop-gap measure for missing functionality. When such functionality is eventually provided, the exposed objects will be deprecated following a warning period.
Note: Access to internal modules is limited to the subfolders listed above. By contrast, the Browserify require() interface has no such limitations. As the former is a subset of the later, migration from the former to the latter is guaranteed, but not necessarily the vice versa.
Several external modules included in the fin.Hypergrid
build are accessible with the following syntax:
var module = require('module');
Replace module with any of the following:
-
extend-me
— Hypergrid augmentsrequire('extend-me').Base
with several convenience members. (See _______ for more information.) fin-hypergrid-field-tools
rectangular
datasaur-base
datasaur-local
Note: In the interests of maintaining a flat dependency graph, these modules should not be loaded separately.
Note: The two
datasaur
packages will be removed as of Hypergrid 4.0.0 but therequire()
syntax will still work providing you load the packages explicitly (with<script>
tags).