diff --git a/src/scripts/lib/clay-config.js b/src/scripts/lib/clay-config.js index eef7bad..02e9260 100644 --- a/src/scripts/lib/clay-config.js +++ b/src/scripts/lib/clay-config.js @@ -30,90 +30,11 @@ var componentStore = require('./component-registry'); function ClayConfig(settings, config, $rootContainer) { var self = this; - self.test = Math.random(); - var _settings = _.copyObj(settings); var _items = []; var _itemsById = {}; var _itemsByAppKey = {}; - - self.EVENTS = { - /** - * Called before framework has initialized. This is when you would attach your - * custom components. - * @const - */ - BEFORE_BUILD: 'BEFORE_BUILD', - - /** - * Called after the config has been parsed and all components have their initial value - * set - * @const - */ - AFTER_BUILD: 'AFTER_BUILD' - }; - utils.updateProperties(self.EVENTS, {writable: false}); - - /** - * @param {string} key - * @returns {ClayItem} - */ - self.getItemByAppKey = function(key) { - return _itemsByAppKey[key]; - }; - - /** - * @param {string} key - * @returns {ClayItem} - */ - self.getItemById = function(key) { - return _itemsById[key]; - }; - - /** - * @param {string} key - * @returns {[ClayItem]} - */ - self.getItemsByType = function(type) { - return _items.filter(function(item) { - return item.config.type === type; - }); - }; - - /** - * @returns {object} - */ - self.getSettings = function() { - _.eachObj(_itemsByAppKey, function(appKey, item) { - _settings[appKey] = item.get(); - }); - return _settings; - }; - - /** - * Register a component to Clay. This must be called prior to .build(); - * @param {{}} component - the clay component to register - * @param {string} component.name - the name of the component - * @param {string} component.template - HTML template to use for the component - * @param {{}} component.manipulator - methods to attach to the component - * @param {function} component.manipulator.set - set manipulator method - * @param {function} component.manipulator.get - get manipulator method - * @param {{}} component.defaults - template defaults - * @param {function} [component.initialize] - method to scaffold the component - */ - self.registerComponent = function(component) { - componentStore[component.name] = component; - }; - - self.build = function() { - self.trigger(self.EVENTS.BEFORE_BUILD); - // initialize the config - _addItems(config, $rootContainer); - self.trigger(self.EVENTS.AFTER_BUILD); - }; - - // attach event methods - ClayEvents.call(self, $rootContainer); + var _isBuilt = false; /** * Add item(s) to the config @@ -153,6 +74,116 @@ function ClayConfig(settings, config, $rootContainer) { } }; + /** + * + * @param {string} fnName + * @private + */ + var _checkBuilt = function(fnName) { + if (!_isBuilt) { + throw new Error( + 'ClayConfig not built. build() must be run before ' + + 'you can run ' + fnName + '()' + ); + } + return true; + }; + + self.EVENTS = { + /** + * Called before framework has initialized. This is when you would attach your + * custom components. + * @const + */ + BEFORE_BUILD: 'BEFORE_BUILD', + + /** + * Called after the config has been parsed and all components have their initial + * value set + * @const + */ + AFTER_BUILD: 'AFTER_BUILD' + }; + utils.updateProperties(self.EVENTS, {writable: false}); + + /** + * @returns {ClayItem} + */ + self.getAllItems = function() { + _checkBuilt('getAllItems'); + return _items; + }; + + /** + * @param {string} key + * @returns {ClayItem} + */ + self.getItemByAppKey = function(key) { + _checkBuilt('getItemByAppKey'); + return _itemsByAppKey[key]; + }; + + /** + * @param {string} key + * @returns {ClayItem} + */ + self.getItemById = function(key) { + _checkBuilt('getItemById'); + return _itemsById[key]; + }; + + /** + * @param {string} key + * @returns {[ClayItem]} + */ + self.getItemsByType = function(type) { + _checkBuilt('getItemsByType'); + return _items.filter(function(item) { + return item.config.type === type; + }); + }; + + /** + * @returns {object} + */ + self.getSettings = function() { + _checkBuilt('getSettings'); + _.eachObj(_itemsByAppKey, function(appKey, item) { + _settings[appKey] = item.get(); + }); + return _settings; + }; + + /** + * Register a component to Clay. This must be called prior to .build(); + * @param {{}} component - the clay component to register + * @param {string} component.name - the name of the component + * @param {string} component.template - HTML template to use for the component + * @param {{}} component.manipulator - methods to attach to the component + * @param {function} component.manipulator.set - set manipulator method + * @param {function} component.manipulator.get - get manipulator method + * @param {{}} component.defaults - template defaults + * @param {function} [component.initialize] - method to scaffold the component + */ + self.registerComponent = function(component) { + componentStore[component.name] = component; + }; + + /** + * Build the config page. This must be run before any of the get methods can be run + * @returns {ClayConfig} + */ + self.build = function() { + self.trigger(self.EVENTS.BEFORE_BUILD); + _addItems(config, $rootContainer); + _isBuilt = true; + self.trigger(self.EVENTS.AFTER_BUILD); + return self; + }; + + // attach event methods + ClayEvents.call(self, $rootContainer); + // prevent external modifications of properties utils.updateProperties(self, { writable: false, configurable: false }); diff --git a/src/scripts/lib/clay-item.js b/src/scripts/lib/clay-item.js index 08c2808..fdd2ac8 100644 --- a/src/scripts/lib/clay-item.js +++ b/src/scripts/lib/clay-item.js @@ -15,6 +15,12 @@ function ClayItem(config) { var self = this; var _itemType = componentRegistry[config.type]; + + if (!_itemType) { + throw new Error('the component: ' + config.type + ' is not registered. ' + + 'Make sure to register it with ClayConfig.registerComponent()'); + } + var _templateData = _.extend({}, _itemType.defaults, config); /** @type {string|null} */ diff --git a/test/fixture.js b/test/fixture.js index d270f9f..65c9362 100644 --- a/test/fixture.js +++ b/test/fixture.js @@ -1,19 +1,32 @@ 'use strict'; var _ = require('../src/scripts/vendor/minified/minified')._; +var $ = require('../src/scripts/vendor/minified/minified').$; +var HTML = require('../src/scripts/vendor/minified/minified').HTML; var ClayItem = require('../src/scripts/lib/clay-item'); +var ClayConfig = require('../src/scripts/lib/clay-config'); var idCounter = 0; +var componentRegistry = require('../src/scripts/lib/component-registry'); + +// add some components to the registry to test +componentRegistry.text = require('../src/scripts/components/text'); +componentRegistry.input = require('../src/scripts/components/input'); +componentRegistry.toggle = require('../src/scripts/components/toggle'); +componentRegistry.footer = require('../src/scripts/components/footer'); +componentRegistry.select = require('../src/scripts/components/select'); + /** - * @param {string} type - * @param {{}} [config] + * @param {string|{}} config * @returns {{}} */ -function configItem(type, config) { +module.exports.configItem = function(config) { + if (typeof config === 'string') { + config = { type: config }; + } var basic = { - type: type, - label: type + '-label', + label: config.type + '-label', appKey: 'appKey-' + idCounter, id: 'id-' + idCounter }; @@ -21,17 +34,39 @@ function configItem(type, config) { idCounter++; return _.extend({}, basic, config); -} +}; /** - * - * @param {string} type - * @param {{}} [config] + * @param {string|{}} [config] * @returns {ClayItem} */ -function clayItem(type, config) { - return new ClayItem(configItem(type, config)); -} +module.exports.clayItem = function(config) { + return new ClayItem(module.exports.configItem(config)); +}; + +/** + * @param {[]} types + * @returns {*} + */ +module.exports.config = function(types) { + return types.map(function(item) { + return Array.isArray(item) ? + {type: 'section', items: module.exports.config(item)} : + module.exports.configItem(item); + }); +}; + +/** + * @param {[]} types + * @param {boolean} [noBuild=false] - don't run the build method on the result + * @param {{}} [settings] - settings to pass to constructor + * @returns {ClayConfig} + */ +module.exports.clayConfig = function(types, noBuild, settings) { + var clayConfig = new ClayConfig( + settings || {}, + module.exports.config(types), $(HTML('