Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added minified version to be included in downloaded tarball; added so…

…me tests
  • Loading branch information...
commit a050c9a0c9905478b76d88e28f91dd137e97c292 1 parent 7293f12
@flosse authored
View
7 README.txt
@@ -1,9 +1,10 @@
# scaleApp
-scaleApp is a tiny JavaScript framework for One-Page-Applications.
-It is inspired by the talk of Nicholas C. Zakas — "Scalable JavaScript Application Architecture".
+scaleApp is a tiny JavaScript framework for scalable One-Page-Applications.
+It is inspired by the talk of Nicholas C. Zakas —
+"Scalable JavaScript Application Architecture" (http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture).
Unlike his recommendations to abstract DOM manipulations and separating the framework from the base library,
-scaleApp explicitly ueses jQuery as base library. Therefore you can use the full power of jQuery in every layer.
+scaleApp explicitly ueses jQuery as base library. Therefore you can use the full power of jQuery on every layer.
scaleApp is licensed under the MIT license.
View
15 build/scaleApp.min.js
@@ -0,0 +1,15 @@
+/* scaleApp.js */
+var scaleApp=function(){var t=function(d,h){var g={debug:function(e){d.log.debug(e,h)},info:function(e){d.log.info(e,h)},warn:function(e){d.log.warn(e,h)},error:function(e){d.log.error(e,h)},fatal:function(e){d.log.fatal(e,h)}};return{subscribe:function(e,i){d.subscribe(h,e,i)},unsubscribe:function(e){d.unsubscribe(h,e)},publish:function(e,i){d.publish(e,i)},startSubModule:function(e,i,k){d.startSubModule(e,i,k,h)},stopSubModule:function(e){d.stop(e)},getModel:function(e){return d.getModel(h,e)},
+getView:function(e){return d.getView(h,e)},debug:g.debug,info:g.info,warn:g.warn,error:g.error,fatal:g.fatal,_:function(e){return d.i18n._(h,e)}}};return function(){var d={},h={},g={},e={},i={},k={},u=function(a){if(typeof a!=="object"){d.log.error("could not register module - option has to be an object","core");return false}if(a.views){if(typeof a.views!=="object"){d.log.error("could not register module - 'views' property has to be an object","core");return false}for(var b in a.views)if(a.views[b]){if(typeof a.views[b]!==
+"function"){d.log.error("could not register module - the view "+b+" is not a function","core");return false}if(typeof a.views[b]()!=="object"){d.log.error("could not register module - the view "+b+" does not return an object","core");return false}}}if(a.models){if(typeof a.models!=="object"){d.log.error("could not register module - the 'models' property has to be an object","core");return false}for(var c in a.models)if(a.models[c]){b=a.models[c];if(typeof b!=="function"){d.log.error("could not register module - the model "+
+c+" is not a function","core");return false}if(typeof b()!=="object"){d.log.error("could not register module - the model "+c+" does not return an object","core");return false}}}return true},v=function(a,b,c){if(typeof a!=="string"){d.log.error("could not register module- mouduleId has to be a string","core");return false}if(typeof b!=="function"){d.log.error("could not register module - creator has to be a constructor function","core");return false}a=b();if(typeof a!=="object"||typeof a.init!=="function"||
+typeof a.destroy!=="function"){d.log.error("could not register module - creator has to return an object with the functions 'init' and 'destroy'","core");return false}if(c)if(!u(c))return false;return true},q=function(a,b,c){if(typeof a==="string"&&(typeof b==="string"&&!c||typeof b==="object"&&!c||typeof b==="string"&&typeof c==="object"||!b&&!c)){if(typeof b==="object"&&!c){c=b;b=a}if(!b&&!c){b=a;c={}}return{moduleId:a,instanceId:b,opt:c}}d.log.error("could not start module '"+a+"' - illegal arguments.",
+"core")},s=function(a,b,c){if(a=q(a,b,c)){d.log.debug("start '"+a.moduleId+"'","core");b=a.instanceId;var f;var j=a.moduleId;c=a.instanceId;var m=h[j];if(m){f={};$.extend(true,f,m.opt,a.opt);j=new t(d,c,f);m=m.creator(j);m.opt=f;if(f.models){for(var l in f.models)if(f.models[l]){var n=c,o=l,w=f.models[l](j);i[n]||(i[n]={});i[n][o]=w}delete f.models}if(f.views){for(var r in f.views)if(f.views){l=c;n=r;o=f.views[r](j);k[l]||(k[l]={});k[l][n]=o}delete f.views}f=m}else d.log.error("could not start module '"+
+j+"' - module does not exist.","core");g[b]=f;g[a.instanceId].init();return true}return false},p=function(a){var b=g[a];if(b){b.destroy();delete g[a];for(var c in e[a])e[a][c]&&p(e[a][c])}else d.log.error("could not stop instance '"+a+"' - instance does not exist.","core")};return d={register:function(a,b,c){if(!v(a,b,c))return false;c||(c={});h[a]={creator:b,opt:c};return true},start:s,startSubModule:function(a,b,c,f){a=q(a,b,c);if(s(a.moduleId,a.instanceId,a.opt)&&typeof f==="string"){(f=e[f])||
+(f=[]);f.push(a.instanceId)}},stop:p,stopAll:function(){for(var a in g)g.hasOwnProperty(a)&&p(a)},publish:function(a,b){for(var c in g)if(g[c].subscriptions){var f=g[c].subscriptions[a];if(f)for(var j in f)typeof f[j]==="function"&&f[j](b)}},subscribe:function(a,b,c){d.log.debug("subscribe to '"+b+"'",a);a=g[a];if(!a.subscriptions)a.subscriptions={};a=a.subscriptions;a[b]||(a[b]=[]);a[b].push(c)},getModel:function(a,b){if(i[a])return i[a][b]},getView:function(a,b){if(k[a])return k[a][b]},getInstance:function(a){return g[a]},
+log:{debug:function(){},info:function(){},warn:function(){},error:function(){},fatal:function(){}}}}()}();
+/* scaleApp.log.js */
+scaleApp.log=function(){if(!console){console={};console.log=function(){};console.debug=function(){};console.info=function(){};console.warn=function(){};console.error=function(){};console.fatal=function(){}}var b={DEBUG:0,INFO:1,WARN:2,ERROR:3,FATAL:4},d=function(c,a,e){if(e)if(typeof a==="object"){d(c,e+":");d(c,a);return}else a=e+": "+a;switch(c){case b.DEBUG:0<=b.DEBUG&&console.debug(a);break;case b.INFO:0<=b.INFO&&console.info(a);break;case b.WARN:0<=b.WARN&&console.warn(a);break;case b.ERROR:0<=
+b.ERROR&&console.error(a);break;case b.FATAL:0<=b.FATAL&&console.error(a);break;default:console.log(a)}};return{debug:function(c,a){d(b.DEBUG,c,a)},info:function(c,a){d(b.INFO,c,a)},warn:function(c,a){d(b.WARN,c,a)},error:function(c,a){d(b.ERROR,c,a)},fatal:function(c,a){d(b.FATAL,c,a)}}}();
+/* scaleApp.i18n.js */
+scaleApp.i18n=function(e){var d=function(){return navigator.language||navigator.browserLanguage},b=d();return{setLanguage:function(a){if(typeof a==="string"){b=a;this.publish("languageChanged",a);return true}return false},getBrowserLanguage:d,getLanguage:function(){return b},_:function(a,f){var c=e.getInstance(a);if(c.opt)if(c.opt.i18n)return c.opt.i18n[b][f];return""}}}(scaleApp);
View
42 src/scaleApp.i18n.js
@@ -9,19 +9,10 @@
* It is licensed under the MIT licence.
*/
+/**
+ * Class: scaleApp.i18n
+ */
scaleApp.i18n = (function( core ){
-
- var lang = "en";
-
- /**
- * Function: getLanguage
- *
- * Returns:
- * (String) the current language code, that is used globally
- */
- var getLanguage = function(){
- return lang;
- }
/**
* Function: getBrowserLanguage
@@ -33,6 +24,21 @@ scaleApp.i18n = (function( core ){
return navigator.language || navigator.browserLanguage;
};
+ /**
+ * Holds the current global language code.
+ * By default the browsers language is used.
+ */
+ var lang = getBrowserLanguage();
+
+ /**
+ * Function: getLanguage
+ *
+ * Returns:
+ * (String) the current language code, that is used globally.
+ */
+ var getLanguage = function(){
+ return lang;
+ };
/**
* Function: setLanguage
@@ -52,9 +58,19 @@ scaleApp.i18n = (function( core ){
return false;
};
+ /**
+ * Function: _
+ *
+ * Parameters:
+ * (String) instanceId
+ * (String) textId
+ *
+ * Returns
+ * (String) the localized string.
+ */
var _ = function( instanceId, textId ){
var inst = core.getInstance( instanceId );
- core.log.debug(inst)
+
if( inst.opt ){
if( inst.opt.i18n ){
return inst.opt.i18n[ lang ][ textId ];
View
198 src/scaleApp.js
@@ -69,17 +69,21 @@ var scaleApp = (function(){
instance.opt = instanceOpts;
if( instanceOpts.models ){
-
+
for( var i in instanceOpts.models ){
- addModel( instanceId, i, instanceOpts.models[i]( sb ) );
+ if( instanceOpts.models[i] ){
+ addModel( instanceId, i, instanceOpts.models[i]( sb ) );
+ }
}
delete instanceOpts.models;
}
if( instanceOpts.views ){
-
- for( var i in instanceOpts.views ){
- addView( instanceId, i, instanceOpts.views[i]( sb ) );
+
+ for( var j in instanceOpts.views ){
+ if( instanceOpts.views ){
+ addView( instanceId, j, instanceOpts.views[j]( sb ) );
+ }
}
delete instanceOpts.views;
}
@@ -92,15 +96,78 @@ var scaleApp = (function(){
};
/**
- * Function: register
+ * PrivateFunction: checkOptionObject
+ * Checks whether the passed option object is valid or not.
*
* Parameters:
- * (String) moduleId - The module id
- * (Function) creator - The module creator function
- * (Object) ops - The default options for this module
- */
- var register = function( moduleId, creator, opt ){
-
+ * (Object) opt
+ *
+ * Returns:
+ * False if it is not valid, true if everything is ok.
+ */
+ var checkOptionObject = function( opt ){
+
+ var errString = "could not register module";
+
+ if( typeof opt !== "object" ){
+ that.log.error( errString + " - option has to be an object", "core" );
+ return false;
+ }
+
+ if( opt.views ){
+ if( typeof opt.views !== "object" ){
+ that.log.error( errString + " - 'views' property has to be an object", "core" );
+ return false;
+ }
+ for( var i in opt.views ){
+ if( opt.views[i] ){
+ if( typeof opt.views[i] !== "function" ){
+ that.log.error( errString + " - the view "+ i +" is not a function", "core" );
+ return false;
+ }
+ if( typeof opt.views[i]() !== "object" ){
+ that.log.error( errString + " - the view "+ i +" does not return an object", "core" );
+ return false;
+ }
+ }
+ }
+ }
+
+ if( opt.models ){
+ if( typeof opt.models !== "object" ){
+ that.log.error( errString + " - the 'models' property has to be an object", "core" );
+ return false;
+ }
+ for( var j in opt.models ){
+ if( opt.models[j] ){
+ var m = opt.models[j];
+ if( typeof m !== "function" ){
+ that.log.error( errString + " - the model "+ j +" is not a function", "core" );
+ return false;
+ }
+ if( typeof m() !== "object" ){
+ that.log.error( errString + " - the model "+ j +" does not return an object", "core" );
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ };
+
+ /**
+ * PrivateFunction: checkRegisterParameters
+ *
+ * Parameters:
+ * (String) moduleId
+ * (Function) creator
+ * (Object) opt
+ *
+ * Returns:
+ * True if everything is ok.
+ */
+ var checkRegisterParameters = function( moduleId, creator, opt ){
+
var errString = "could not register module";
if( typeof moduleId !== "string" ){
@@ -118,12 +185,35 @@ var scaleApp = (function(){
that.log.error( errString + " - creator has to return an object with the functions 'init' and 'destroy'", "core" );
return false;
}
+
+ if( opt ){
+ if( !checkOptionObject( opt ) ){ return false; }
+ }
+
+ return true;
+
+ };
+
+ /**
+ * Function: register
+ *
+ * Parameters:
+ * (String) moduleId - The module id
+ * (Function) creator - The module creator function
+ * (Object) ops - The default options for this module
+ *
+ * Returns:
+ * True if registration was successfull.
+ */
+ var register = function( moduleId, creator, opt ){
+
+ if( !checkRegisterParameters( moduleId, creator, opt ) ){ return false; }
if( !opt ){ opt = {}; }
modules[ moduleId ] = {
creator: creator,
- opt: { }
+ opt: opt
};
return true;
@@ -137,6 +227,8 @@ var scaleApp = (function(){
* (String) instanceId
* (Object) opt
*
+ * Returns:
+ * True, if parameters are valid.
*/
var hasValidStartParameter = function( moduleId, instanceId, opt ){
@@ -340,7 +432,15 @@ var scaleApp = (function(){
var getInstance = function( id ){
return instances[ id ];
};
-
+
+ /**
+ * PrivateFunction: addModel
+ *
+ * Paraneters:
+ * (String) instanceId
+ * (String) id
+ * (Function) model
+ */
var addModel = function( instanceId, id, model ){
if( !models[ instanceId ] ){
models[ instanceId ] = { };
@@ -348,6 +448,14 @@ var scaleApp = (function(){
models[ instanceId ][ id ] = model;
};
+ /**
+ * PrivateFunction: addView
+ *
+ * Paraneters:
+ * (String) instanceId
+ * (String) id
+ * (Function) view
+ */
var addView = function( instanceId, id, view ){
if( !views[ instanceId ] ){
views[ instanceId ] = { };
@@ -355,12 +463,32 @@ var scaleApp = (function(){
views[ instanceId ][ id ] = view;
};
+ /**
+ * Function: getModel
+ *
+ * Paraneters:
+ * (String) instanceId
+ * (String) id
+ *
+ * Returns:
+ * (Object) model
+ */
var getModel = function( instanceId, id ){
if( models[ instanceId ] ){
return models[ instanceId ][ id ];
}
};
+ /**
+ * Function: getView
+ *
+ * Paraneters:
+ * (String) instanceId
+ * (String) id
+ *
+ * Returns:
+ * (Object) view
+ */
var getView = function( instanceId, id ){
if( views[ instanceId ] ){
return views[ instanceId ][ id ];
@@ -410,8 +538,7 @@ var scaleApp = (function(){
* Parameters:
* (String) topic
* (Function) callback
- */
-
+ */
var subscribe = function( topic, callback ){
core.subscribe( instanceId, topic, callback );
};
@@ -490,35 +617,72 @@ var scaleApp = (function(){
}
};
+ /**
+ * Function: startSubModule
+ *
+ * Parameters:
+ * (String) moduleId
+ * (String) subInstanceId
+ * (Object) opt
+ */
var startSubModule = function( moduleId, subInstanceId, opt ){
core.startSubModule( moduleId, subInstanceId, opt, instanceId );
};
+ /**
+ * Function: stopSubModule
+ *
+ * Parameters:
+ * (String) instanceId
+ */
var stopSubModule = function( instanceId ){
core.stop( instanceId );
};
+ /**
+ * Function: getModel
+ *
+ * Paraneters:
+ * (String) id
+ *
+ * Returns:
+ * (Object) model
+ */
var getModel = function( id ){
return core.getModel( instanceId, id );
};
+ /**
+ * Function: getView
+ *
+ * Paraneters:
+ * (String) id
+ *
+ * Returns:
+ * (Object) view
+ */
var getView = function( id ){
return core.getView( instanceId, id );
};
+ // not used at the moment
var addModel = function( id , model ){
return core.addModel( instanceId, id, model );
};
+ // not used at the moment
var addView = function( id, view ){
return core.addView( instanceId, id, view );
};
/**
* Function: _
-
+ *
* Parameters:
* (String) textId
+ *
+ * Returns:
+ * The localized text.
*/
var _ = function( textId ){
return core.i18n._( instanceId, textId );
View
5 src/scaleApp.log.js
@@ -9,6 +9,9 @@
* It is licensed under the MIT licence.
*/
+/**
+ * Class: scaleApp.log
+ */
scaleApp.log = (function(){
/**
@@ -19,7 +22,7 @@ scaleApp.log = (function(){
if( !console ){
console = {};
- console.log = function( msg ) { return; };
+ console.log = function( msg ) { return; };
console.debug = function( msg ) { return; };
console.info = function( msg ) { return; };
console.warn = function( msg ) { return; };
View
44 test/scaleApp.apiTest.js
@@ -10,8 +10,7 @@ TestCase("scaleApp API tests", {
};
},
-
- "test the scaleApp namespace should exist": function(){
+ "test scaleApp namespace should exist": function(){
assertEquals( "object", typeof( scaleApp ) );
},
@@ -20,20 +19,53 @@ TestCase("scaleApp API tests", {
},
"test register function should return true, if module is valid": function(){
- assertEquals( true, scaleApp.register( "myModule", this.validModule ) );
+ assertTrue( scaleApp.register( "myModule", this.validModule ) );
},
"test register function should return false, if module creator is not a function": function(){
- assertEquals( false, scaleApp.register( "myModule", { } ) );
+ assertFalse( scaleApp.register( "myModule", { } ) );
},
"test register function should return false, if module creator does not return an object": function(){
- assertEquals( false, scaleApp.register( "myModule", function(){ return "I'm not an object" } ) );
+ assertFalse( scaleApp.register( "myModule", function(){ return "I'm not an object" } ) );
},
"test register function should return false, if created module object has not the functions init and destroy": function(){
- assertEquals( false, scaleApp.register( "myModule", function(){ return {} } ) );
+ assertFalse( scaleApp.register( "myModule", function(){ return {} } ) );
+ },
+
+ "test register function should return true, if option is an object": function(){
+ assertTrue( scaleApp.register( "myModule", this.validModule, { } ) );
+ },
+
+ "test register function should return false, if option is not an object": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , "I'm not an object" ) );
+ },
+
+ "test register function should return false, if property views of option object is not an object": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { views: " " } ) );
+ },
+
+ "test register function should return false, if views are no functions": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { views: { "myView": "I'm not a function" } } ) );
},
+
+ "test register function should return false, if view creators don't return objects": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { views: { "myView": function(){ return "I'm not an object"; } } } ) );
+ },
+
+ "test register function should return false, if property models of option object is not an object": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { models: " " } ) );
+ },
+
+ "test register function should return false, if models are no functions": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { models: { "myModel": "I'm not a function" } } ) );
+ },
+
+ "test register function should return false, if model creators don't return objects": function(){
+ assertFalse( scaleApp.register( "myModule", this.validModule , { models: { "myModel": function(){ return "I'm not an object"; } } } ) );
+ },
+
"test start function should exist": function(){
assertEquals( "function", typeof( scaleApp.start ) );
Please sign in to comment.
Something went wrong with that request. Please try again.