This is a big set of changes, and it requires a little explanation. But there are a lot of advantages to what we have changed here, including the ease of swapping out different visualization systems like dagre -> visjs, etc. This all applies to issues #24 and #15
Changes!
1. Module Changes
The files dagre.js, load.js, and sparql.js are all wrapped in a special function that "exports" them as modules:
var DB = (function(module) {
....
return module;
})(DB || {});
The module names are DB for sparql.js, GRAPH for dagre.js, and LOAD for load.js. These are so we could switch out sparql or dagre if we needed to without having to change the names of any function calls in the other files.
Another positive benefit to this is that it allows us to load the modules asynchronously, and now the page loads twice as fast as it did before (initial page load, not data load from a query)
2. Bindings
Inside those module wrappers, there is a "binding" wrapper around all the rest of the functions of that file. Here's the example from the LOAD module:
This allows us to set the EtyTree object as the base for each module so that all other modules can always be called by calling etyBase.MODULE.FUNCTION() such as etyBase.DB.lemmaQuery(). This is particularly helpful because now that means that any change we make to the data from within the modules should still stay linked properly. It also helps ensure that things stay separated so we can always keep the modules working in the future.
3. EtyTree Command Center
The etytree.js file now contains much less code. The functions that start up the tree have been moved to other files as init() functions, but they get called from etytree.js. Now etytree.js is the command center -- code that goes there is mainly to get basic settings in place and to coordinate between modules. Everything else can happen elsewhere.
EtyTree is now an object with a create() and an init() function. I'm sure that this could have been done with ES6 classes, but it was faster for me to do it this way for now. It can be changed to a class later.
The create() function binds the modules to the EtyTree object and adds config info. This is now where the ENDPOINT and debug info is stored.
The init() function runs the init() functions of any modules that have one. It also adds the etyBase.tree, which is where some data can be stored in the future. This is key because it now allows us to story information as a property of the EtyTree instead of passing it around the functions. This is where things like "inner", "g", "LangMap", and data from query responses should be stored so that they can be accessed by functions in all modules. THIS IS THE KEY TO WHY WE ARE USING MODULES -- as of now, only the LangMap gets assigned as a property of etyBase.tree, but we can start abstracting other things out of that.
The variable var ety is created as an instance of EtyTree and initialized after document load, making sure that all dependencies are loaded before anything runs.
Working With Modules
Now that we have this module system, it is critical that we continue to use the same format. It takes a little getting used to, but it will keep the etytree from falling apart.
It is very simple:
Always make sure new functions for modules are declared INSIDE the module.bindModule function.
Add the new functions to the module by creating a this.FUNCTIONNAME = FUNCTIONNAME; line at the bottom of the module.bindModule function but above etyBase[moduleName] = this;
Always call functions with the structure etyBase.MODULE.etc so that you are sure to always access the correct data.
That's it!
Please take a look at these changes and make sure it all makes sense. Let me know if you have any questions.
Follow Up?
After this is merged, this opens us up to:
More easily switch out dagre for visjs
Add remove some of the "global" information from function arguments and set them as EtyTree properties
Test different functions by only switching the reference that is assigned to the module and not having to rewrite the function call in multiple places in multiple files. ( this.render = render1 => this.render = render2, but everywhere else you would just call etyBase.GRAPH.render() ).
This is a big set of changes, and it requires a little explanation. But there are a lot of advantages to what we have changed here, including the ease of swapping out different visualization systems like dagre -> visjs, etc. This all applies to issues #24 and #15
Changes!
1. Module Changes
The files dagre.js, load.js, and sparql.js are all wrapped in a special function that "exports" them as modules:
The module names are DB for sparql.js, GRAPH for dagre.js, and LOAD for load.js. These are so we could switch out sparql or dagre if we needed to without having to change the names of any function calls in the other files.
Another positive benefit to this is that it allows us to load the modules asynchronously, and now the page loads twice as fast as it did before (initial page load, not data load from a query)
2. Bindings
Inside those module wrappers, there is a "binding" wrapper around all the rest of the functions of that file. Here's the example from the LOAD module:
This allows us to set the EtyTree object as the base for each module so that all other modules can always be called by calling
etyBase.MODULE.FUNCTION()
such asetyBase.DB.lemmaQuery()
. This is particularly helpful because now that means that any change we make to the data from within the modules should still stay linked properly. It also helps ensure that things stay separated so we can always keep the modules working in the future.3. EtyTree Command Center
The etytree.js file now contains much less code. The functions that start up the tree have been moved to other files as
init()
functions, but they get called from etytree.js. Now etytree.js is the command center -- code that goes there is mainly to get basic settings in place and to coordinate between modules. Everything else can happen elsewhere.EtyTree is now an object with a
create()
and aninit()
function. I'm sure that this could have been done with ES6 classes, but it was faster for me to do it this way for now. It can be changed to a class later.The
create()
function binds the modules to the EtyTree object and adds config info. This is now where the ENDPOINT and debug info is stored.The
init()
function runs theinit()
functions of any modules that have one. It also adds theetyBase.tree
, which is where some data can be stored in the future. This is key because it now allows us to story information as a property of the EtyTree instead of passing it around the functions. This is where things like "inner", "g", "LangMap", and data from query responses should be stored so that they can be accessed by functions in all modules. THIS IS THE KEY TO WHY WE ARE USING MODULES -- as of now, only the LangMap gets assigned as a property ofetyBase.tree
, but we can start abstracting other things out of that.The variable
var ety
is created as an instance ofEtyTree
and initialized after document load, making sure that all dependencies are loaded before anything runs.Working With Modules
Now that we have this module system, it is critical that we continue to use the same format. It takes a little getting used to, but it will keep the etytree from falling apart.
It is very simple:
module.bindModule
function.this.FUNCTIONNAME = FUNCTIONNAME;
line at the bottom of themodule.bindModule
function but aboveetyBase[moduleName] = this;
etyBase.MODULE.etc
so that you are sure to always access the correct data.That's it!
Please take a look at these changes and make sure it all makes sense. Let me know if you have any questions.
Follow Up?
After this is merged, this opens us up to:
this.render = render1
=>this.render = render2
, but everywhere else you would just calletyBase.GRAPH.render()
).