diff --git a/dev/config-2.js b/dev/config-2.js new file mode 100644 index 0000000..37d60e4 --- /dev/null +++ b/dev/config-2.js @@ -0,0 +1,38 @@ +'use strict'; +/* eslint-disable quotes */ + +module.exports = [ + { + "type": "heading", + "id": "main-heading", + "defaultValue": "Clay Test Page", + "size": 1 + }, + { + "type": "text", + "defaultValue": "This is config 2" + }, + { + "type": "section", + "items": [ + { + "type": "heading", + "defaultValue": "This is a section" + }, + { + "type": "input", + "appKey": "email", + "defaultValue": "", + "label": "Input Field", + "description": "This is a new field", + "attributes": { + "placeholder": "Placeholder set with attributes" + } + } + ] + }, + { + "type": "submit", + "defaultValue": "Save" + } +]; diff --git a/dev/custom-fn.js b/dev/custom-fn.js index fe004aa..d6202a4 100644 --- a/dev/custom-fn.js +++ b/dev/custom-fn.js @@ -16,10 +16,20 @@ module.exports = function() { } } + /** + * @returns {void} + */ + function handleButtonClick() { + Clay.config = Clay.meta.userData.config2; + Clay.build(); + } + Clay.on(Clay.EVENTS.AFTER_BUILD, function() { var coolStuffToggle = Clay.getItemByAppKey('cool_stuff'); toggleBackground.call(coolStuffToggle); coolStuffToggle.on('change', toggleBackground); + + Clay.getItemById('testButton').on('click', handleButtonClick); }); console.log('userData: ', Clay.meta.userData); diff --git a/dev/dev.js b/dev/dev.js index 72cccee..502edd2 100644 --- a/dev/dev.js +++ b/dev/dev.js @@ -6,7 +6,10 @@ window.claySettings = {}; window.customFn = require('./custom-fn.js'); window.clayComponents = require('../src/scripts/components'); window.clayMeta = require('../test/fixture').meta({ - userData: {foo: 'bar'} + userData: { + foo: 'bar', + config2: require('./config-2') + } }); var platform = window.navigator.userAgent.match(/Android/) ? 'android' : 'ios'; diff --git a/src/scripts/lib/clay-config.js b/src/scripts/lib/clay-config.js index e809876..4546f6f 100644 --- a/src/scripts/lib/clay-config.js +++ b/src/scripts/lib/clay-config.js @@ -33,10 +33,22 @@ function ClayConfig(settings, config, $rootContainer, meta) { var self = this; var _settings = _.copyObj(settings); - var _items = []; - var _itemsById = {}; - var _itemsByAppKey = {}; - var _isBuilt = false; + var _items; + var _itemsById; + var _itemsByAppKey; + var _isBuilt; + + /** + * Initialize the item arrays and objects + * @private + * @return {void} + */ + function _initializeItems() { + _items = []; + _itemsById = {}; + _itemsByAppKey = {}; + _isBuilt = false; + } /** * Add item(s) to the config @@ -97,6 +109,7 @@ function ClayConfig(settings, config, $rootContainer, meta) { } self.meta = meta; + self.$rootContainer = $rootContainer; self.EVENTS = { /** @@ -111,7 +124,21 @@ function ClayConfig(settings, config, $rootContainer, meta) { * value set * @const */ - AFTER_BUILD: 'AFTER_BUILD' + AFTER_BUILD: 'AFTER_BUILD', + + /** + * Called if .build() is executed after the page has already been built and + * before the existing content is destroyed + * @const + */ + BEFORE_DESTROY: 'BEFORE_DESTROY', + + /** + * Called if .build() is executed after the page has already been built and after + * the existing content is destroyed + * @const + */ + AFTER_DESTROY: 'AFTER_DESTROY' }; utils.updateProperties(self.EVENTS, {writable: false}); @@ -172,18 +199,39 @@ function ClayConfig(settings, config, $rootContainer, meta) { // @todo maybe don't do this and force the static method self.registerComponent = ClayConfig.registerComponent; + /** + * Empties the root container + * @return {void} + */ + self.destroy = function() { + var el = $rootContainer[0]; + self.trigger(self.EVENTS.BEFORE_DESTROY); + while (el.firstChild) { + el.removeChild(el.firstChild); + } + _initializeItems(); + self.trigger(self.EVENTS.AFTER_DESTROY); + }; + /** * Build the config page. This must be run before any of the get methods can be run + * If you call this method after the page has already been built, teh page will be + * destroyed and built again. * @returns {ClayConfig} */ self.build = function() { + if (_isBuilt) { + self.destroy(); + } self.trigger(self.EVENTS.BEFORE_BUILD); - _addItems(config, $rootContainer); + _addItems(self.config, $rootContainer); _isBuilt = true; self.trigger(self.EVENTS.AFTER_BUILD); return self; }; + _initializeItems(); + // attach event methods ClayEvents.call(self, $rootContainer); diff --git a/test/spec/lib/clay-config.js b/test/spec/lib/clay-config.js index dba8b34..69537b9 100644 --- a/test/spec/lib/clay-config.js +++ b/test/spec/lib/clay-config.js @@ -254,6 +254,50 @@ describe('ClayConfig', function() { }); }); + describe('.destroy().', function() { + it('Destroys all the items on the page and in the items array', function() { + var clayConfig = fixtures.clayConfig(['input', 'text', 'input'], false); + + clayConfig.build(); + clayConfig.destroy(); + + // this should throw because the config has not been built yet + assert.throws(clayConfig.getAllItems); + + // there should be no DOM inside the container + assert.strictEqual(clayConfig.$rootContainer[0].children.length, 0); + }); + + it('dispatches the BEFORE_DESTROY event at the right time', function(done) { + var clayConfig = fixtures.clayConfig(['input', 'text', 'input'], false); + + clayConfig.on(clayConfig.EVENTS.BEFORE_DESTROY, function() { + assert.strictEqual(clayConfig.getAllItems().length, 3); + done(); + }); + + clayConfig.build(); + clayConfig.destroy(); + + assert.strictEqual(clayConfig.getAllItems().length, 0); + }); + + it('dispatches the AFTER_DESTROY event at the right time', function(done) { + var clayConfig = fixtures.clayConfig(['input', 'text', 'input'], false); + + clayConfig.on(clayConfig.EVENTS.AFTER_DESTROY, function() { + + // this should throw because the config has not been built yet + assert.throws(clayConfig.getAllItems); + done(); + }); + + clayConfig.build(); + assert.strictEqual(clayConfig.getAllItems().length, 3); + clayConfig.destroy(); + }); + }); + describe('.build()', function() { it('dispatches the BEFORE_BUILD event at the right time', function(done) { var clayConfig = fixtures.clayConfig(['input', 'text', 'input'], false);