Standards (proposed)
Code Files
Should put all code, other than $(document).ready() blocks, within self-executing closures with important namespaces passed in:
// Example Widget function(app, ns, data, utils){ // Create Widget short name for local reference exWdgt = {}; // Use closures for private code var testFunc(); // Add all widget code to widget namespace. ns.WidgetModel = can.Model({...}); ns.WidgetControl = can.Control({...}); // Add an initialization function if the widget should be initialized externally ns.initWidget = function(/*params*/){...}; // Pass in external values that will be used by this code }( raft.app, // The app namespace raft.widgets.ExWidget, // The specific namespace to which the resulting objects and functions from this file will be added. raft.data.ExWidget, // The specific data namespace for this widget/page/object. Cached and local data should go here raft.utils // The namespace containing app framework utilities )); $(document).ready(function()){ // Code to run when document is finished loading }
Standard Page files and Naming
pages/PageName/PageNameDef.js: Creates namespace for page and data and optionally dynamically loads files required.
pages/PageName/PageName.css: Styles specific to this page
pages/PageName/PageNameModel.js: Models used by this page
pages/PageName/PageNameCtrl.js: Controllers used by this page
pages/PageName/PageNameView.ejs: Main page view template
pages/PageName/PageNameViews.ejs: Optional second/third/... view templates
Standard Widget files and Naming
widgets/WidgetName/WidgetNameDef.js: Creates namespace for widget and data and optionally dynamically loads files required.
widgets/WidgetName/WidgetName.css: Styles specific to this widget
widgets/WidgetName/WidgetNameModel.js: Models used by this widget
widgets/WidgetName/WidgetNameCtrl.js: Controllers used by this widget
widgets/WidgetName/WidgetNameView.ejs: Main widget view template
widgets/WidgetName/WidgetNameViews.ejs: Optional second/third/... view templates
Sample Widget/Page Definition File
// Example Widget Definition function(app, ns, data, utils){ // Create Widget short name for local reference ns.ExampleWidget = { SomeWidgetFunctionObjectOrEnum : {...} }; // Create Widget data namespace data.ExampleWidget = { WidgetDataVal1 : "foo", WidgetDataVal2 : {...} }; // It's common to always defer loading of css and data since they aren't debugged utils.requireCSS("widgets/ExampleWidget/ExampleWidget.CSS"); utils.requireScript("widgets/ExampleWidget/widget_test_data.js", false); // Only defer load these if it's turned on if (app.config.isDeferLoad) { utils.requireScript("widgets/ExampleWidget/ExampleWidgetModel.js", true); utils.requireScript("widgets/ExampleWidget/ExampleWidgetCtrl.js", true); } // Pass in external values that will be used by this code }( raft.app, // The app namespace raft.widgets, // The widget or page namespace raft.data, // The data namespace raft.utils // Application framework utilities namespace )); $(document).ready(function()){ // Code to run when document is finished loading }
Utilities
Helper Functions
$.isDefined(obj) // Returns true if object is not undefined and not null String.isString(obj) // Returns true if object is a string literal or String object String.isEmpty(obj) // Returns true if object is a zero-length string String.isNonEmpty(obj) // Returns true if object is a non-zero-length string Number.isNumber(obj) // Returns true if object is a primitive number or a Number object
Dynamic Loader Functions
requireScript(): Loads the specified script, synchronously by default. If the file has already been loaded it will not be loaded again and a comment will be logged to that effect. The return value is a promise.
raft.utils.requireScript(path).always(...).then(...);
requireCSS(): Adds a tag to the document.head element which loads the specified CSS file.
raft.utils.requiresCSS(path);
Misc:
- Always include both params when calling can.Model()
- Discovered that calling can.route.link() returns an escaped string. This means that using it from within a view to create an <a href> does not work and instead adds "<a href>" to the page. The only way to do this that I have discovered so far is to use the can.route.link() call from within an append() call in the controller after the view finishes rendering. There may be other ways to do this but I haven't looked for them.