Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
scaleapp
Advanced tools
Changelog
v0.4.4 (07-2014)
global
Readme
scaleApp is a tiny JavaScript framework for scalable and maintainable One-Page-Applications / Single-Page-Applications. The framework allows you to easily create complex web applications.
You can dynamically start and stop/destroy modules that acts as small parts of your whole application.
scaleApp is based on a decoupled, event-driven architecture that is inspired by the talk of Nicholas C. Zakas - "Scalable JavaScript Application Architecture" (Slides). There also is a little Article that describes the basic ideas.
A module is a completely independent part of your application. It has absolutely no reference to another piece of the app. The only thing the module knows is your sandbox. The sandbox is used to communicate with other parts of the application.
The main purpose of the sandbox is to use the facade pattern. In that way you can hide the features provided by the core and only show a well defined custom static long term API to your modules. This is actually one of the most important concept for creating mainainable apps. Change plugins, implementations etc. but keep your API stable for your modules. For each module a separate sandbox will be created.
The core is responsible for starting and stopping your modules. It also handles the messages by using the Publish/Subscribe (Mediator) pattern
Plugins can extend the core or the sandbox with additional features. For example you could extend the core with basic functionalities (like DOM manipulation) or just aliases the features of a base library (e.g. jQuery).
scaleApp itself is very small but it can be extended with plugins. There already are some plugins available:
mvc
- simple MVCi18n
- multi language UIspermission
- take care of method accessstate
- Finite State Machinesubmodule
- cascade modulesdom
- DOM manipulationstrophe
- XMPP communicationmodulestate
- event emitter for init
and destroy
util
- helper methods like mixin
, uniqueId
etc.ls
- list modules, instances & pluginsYou can easily define your own plugin (see plugin section).
or use the CDN:
<script src="//cdnjs.cloudflare.com/ajax/libs/scaleapp/0.4.4/scaleapp.min.js" ></script>
There are some API changes in version 0.4.x (see Changelog). Docs for v0.3.9 can be found within the tar/zip file.
git clone git://github.com/flosse/scaleApp.git
Link scaleApp.min.js
in your HTML file:
<script src="scaleApp.min.js"></script>
or use the CDN:
<script src="//cdnjs.cloudflare.com/ajax/libs/scaleapp/0.4.4/scaleapp.min.js" ></script>
If you're going to use it with node:
npm install scaleapp --save
var sa = require("scaleapp");
or use bower:
bower install scaleapp
First of all create your own sandbox. By doing that you're able to guarantee a stable maintainable API for your modules.
var MySandbox = function(core, instanceId, options, moduleId) {
// define your API
this.myFooProperty = "bar";
// e.g. provide the Mediator methods 'on', 'emit', etc.
core._mediator.installTo(this);
// ... or define your custom communication methods
this.myEmit = function(channel, data){
core.emit(channel + '/' + instanceId, data);
};
// maybe you'd like to expose the instance ID
this.id = instanceId;
return this;
};
// ... and of course you can define shared methods etc.
MySandbox.prototype.foo = function() { /*...*/ };
Now create a new core instance with your sandbox:
var core = new scaleApp.Core(MySandbox);
core.register( "myModuleId", function( sandbox ){
return {
init: function(){ /*...*/ },
destroy: function(){ /*...*/ }
};
});
As you can see the module is a function that takes the sandbox as a parameter
and returns an object that has two functions init
and destroy
(the latter is
optional).
Of course your module can be any usual class with those two functions.
var MyGreatModule = function(sandbox){
return {
init: function(){ alert("Hello world!"); }
destroy: function(){ alert("Bye bye!"); }
};
};
core.register("myGreatModule", MyGreatModule);
The init
function is called by the framework when the module is supposed to
start. The destroy
function is called when the module has to shut down.
You can also init or destroy you module in a asynchronous way:
var MyAsyncModule = function(sandbox){
return {
init: function(options, done){
doSomethingAsync(function(err){
// ...
done(err);
});
},
destroy: function(done){
doSomethingElseAsync(done);
}
};
};
core.register("myGreatModule", MyGreatModule);
core.start("myGreatModule", { done:function(){
alert("now the initialization is done");
}});
After your modules are registered, start your modules:
core
.start( "myModuleId" )
.start( "anOtherModule", function(err){
// 'anOtherModule' is running now
});
You may also want to start several instances of a module:
core.start( "myModuleId", {instanceId: "myInstanceId" } );
core.start( "myModuleId", {instanceId: "anOtherInstanceId" });
All you attach to options
is accessible within your module:
core.register( "mod", function(sandbox){
return {
init: function(opt){
(opt.myProperty === "myValue") // true
},
destroy: function(){ /*...*/ }
};
});
core.start("mod", {
instanceId: "test",
options: { myProperty: "myValue" }
});
If all your modules just needs to be instanciated once, you can simply starting them all:
core.start();
To start some special modules at once you can pass an array with the module names:
core.start(["moduleA","moduleB"]);
You can also pass a callback function:
core.start(function(){
// do something when all modules were initialized
});
Moreover you can use a separate sandbox for each instance:
var MySandbox = function(){/*...*/};
core.start("module", { sandbox: MySandbox });
It's obvious:
core.stop("moduleB");
core.stop(); // stops all running instances
If the module needs to communicate with others, you can use the emit
and
on
methods.
The emit
function takes three parameters whereas the last one is optional:
topic
: the channel name you want to emit todata
: the data itselfcb
: callback methodThe emit function is accessible through the sandbox (as long as you exposed the Mediator methods of course):
sandbox.emit( "myEventTopic", myData );
A message handler could look like this:
var messageHandler = function( data, topic ){
switch( topic ){
case "somethingHappend":
sandbox.emit( "myEventTopic", processData(data) );
break;
case "aNiceTopic":
justProcess( data );
break;
}
};
... and it can listen to one or more channels:
sub1 = sandbox.on( "somthingHappend", messageHandler );
sub2 = sandbox.on( "aNiceTopic", messageHandler );
Or just do it at once:
sandbox.on({
topicA: cbA,
topicB: cbB,
topicC: cbC
});
You can also subscribe to several channels at once:
sandbox.on(["a", "b"], cb);
If you prefer a shorter method name you can use the alias on
.
A subscription can be detached and attached again:
sub.detach(); // don't listen any more
sub.attach(); // receive upcoming messages
You can unsubscribe a function from a channel
sandbox.off("a-channel", callback);
And you can remove a callback function from all channels
sandbox.off(callback);
Or remove all subscriptions from a channel:
sandbox.off("channelName");
var task1 = function(next){
setTimeout(function(){
console.log("task1");
next(null, "one");
},0);
};
var task2 = function(next){
console.log("task2");
next(null, "two");
};
scaleApp.util.runSeries([task1, task2], function(err, result){
// result is ["one", "two"]
});
// console output is:
// "task1"
// "task2"
var task1 = function(next){
setTimeout(function(){
console.log("task1");
next(null, "a");
},0);
};
var task2 = function(next){
console.log("task2");
next(null, "b");
};
scaleApp.util.runParallel([task1, task2],function(err,result){
// result is ["a", "b"]
});
// console output is:
// "task2"
// "task1"
There is also a little helper tool to run the same async task again and again in parallel for different values:
var vals = ["a","b", "c"];
var worker = function(val, next){
console.log(val);
doSomeAsyncValueProcessing(val,function(err,result){
next(err, result);
});
};
scaleApp.util.doForAll(args, worker, function(err, res){
// fini
});
var task1 = function(next){
setTimeout(function(){
next(null, "one", "two");
},0);
};
var task2 = function(res1, res2, next){
// res1 is "one"
// res2 is "two"
next(null, "yeah!");
};
scaleApp.util.runWaterfall([task1, task2], function(err, result){
// result is "yeah!"
});
There are some plugins available within the plugins
folder.
For more information look at the
plugin README.
A single plugin can be registered with it option object in that way:
core.use(plugin,options);
If you want to register multiple plugins at once:
core.use([
plugin1,
plugin2,
{ plugin: plugin3, options: options3 }
]);
It's easy:
core.use(function(core){
core.helloWorld = function(){ alert("helloWorld"); };
};
Here a more complex example:
core.use(function(core, options, done){
// extend the core
core.myCoreFunction = function(){ alert("Hello core plugin") };
core.myBoringProperty = "boring";
// extend the sandbox class
core.Sandbox.prototype.myMethod = function(){/*...*/};
// define a method that gets called when a module starts
var onModuleInit = function(instanceSandbox, options, done){
// e.g. define sandbox methods dynamically
if (options.mySwitch){
instanceSandbox.appendFoo = function(){
core.getContainer.append("foo");
};
}
// or load a something asynchronously
core.myAsyncMethod(function(data){
// do something...
// now tell scaleApp that you're done
done();
});
};
// define a method that gets called when a module stops
var onModuleDestroy = function(done){
myCleanUpMethod(function(){
done()
});
};
// don't forget to return your methods
return {
init: onModuleInit,
destroy: onModuleDestroy
};
});
Usage:
core.myCoreFunction() // alerts "Hello core plugin"
var MyModule = function(sandbox){
init: function(){ sandbox.appendFoo(); }, // appends "foo" to the container
};
If you want scaleApp bundled with special plugins type
grunt custom[:PLUGIN_NAME]
e.g. cake custom:dom:mvc
creates the file scaleApp.custom.js
that
contains scaleApp itself the dom plugin and the mvc plugin.
scaleApp.VERSION
- the current version of scaleAppscaleApp.Mediator
- the Mediator classscaleApp.Sandbox
- the Sandbox classscaleApp.Core
- the Core class// use default sandbox
var core = new scaleApp.Core();
// use your own sandbox
var core = new scaleApp.Core(yourSandboxClass);
core.register(moduleName, module, options)
- register a modulecore.use(plugin, options)
- register a plugincore.use(pluginArray)
- registers an array of pluginscore.boot(callback)
- initialize plugins
(will be executed automatically on ´start´)core.start(moduleId, options, callback)
- start a modulecore.stop(instanceId, callback)
- stop a module// create a mediator
var mediator = new scaleApp.Mediator();
// create a mediator with a custom context object
var mediator = new scaleApp.Mediator(context);
// create a mediator with cascaded channels
var mediator = new scaleApp.Mediator(null, true);
mediator.emit(channel, data, callback)
mediator.on(channel, callback, context)
mediator.off(channel, callback)
mediator.installTo(context, force)
// subscribe
var subscription = mediator.on(channel, callback, context);
subscription.detach
- stop listeningsubscription.attach
- resume listeningvar fn = function(){ /*...*/ };
var obj = { emit: fn };
// the installTo method prevents existing properties by default
mediator.installTo(obj);
obj.emit === fn // true
// set the second paramater to 'true'
// to force the mediator to override existing propeties
mediator.installTo(obj, true);
obj.emit === mediator.emit // true
This is the default sandbox of scaleApp. It's a better idea to use your own one.
var sandbox = new scaleApp.Sandbox(core, instanceId, options, moduleId)` - create a Sandbox
sandbox.emit
is mediator.emit
sandbox.on
is mediator.on
sandbox.off
is mediator.off
global
Mediator.installTo
to force overriding existing propertiesuseGlobalMediator
to the submodule pluginmediator
to the submodule pluginCore
class that can be instantiated (var core = new scaleApp.Core();
)scaleApp.plugins.register
moved to core.use
)
boot
method to initialize asynchronous pluginsstartAll()
is now start()
stopAll()
is now stop()
core.use(X).register("foo",bar).start("foo")
)setInstanceOptions
unregister
and unregisterAll
subscribe
, unsubscribe
and publish
from Mediator API
(use on
, off
and emit
instead)lsModules
, lsInstances
, lsPlugins
moved to the ls
plugindestroy
method of a module is now optionalcallback
property of the start option object was removed.
Use the modulestate
plugin insteadsubmodule
pluginpermission
and i18n
modulestate
plugin to emit events on module state changesMediator
: do not clone objects any more (do it manually instead)publish
methodlsModules
and lsInstances
npm test
WARNING: the demo is totally out of date!
You can try out the sample application that is build on scaleApp. Also have a look at the source code.
scaleApp is licensed under the MIT license. For more information have a look at LICENCE.txt.
FAQs
scaleApp is a JavaScript framework for scalable and maintainable One-Page-Applications
The npm package scaleapp receives a total of 36 weekly downloads. As such, scaleapp popularity was classified as not popular.
We found that scaleapp demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.