From aed6787f2c50d015a6063c1ba5f396056ba148df Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 14:23:01 -0800 Subject: [PATCH] [Forms] Copy mct-form to mct-toolbar Copy mct-form template and scripts to use as a basis for mct-toolbar. WTD-684. --- platform/forms/bundle.json | 4 + platform/forms/res/templates/toolbar.html | 42 +++++++++++ platform/forms/src/MCTToolbar.js | 64 ++++++++++++++++ platform/forms/test/MCTToolbarSpec.js | 90 +++++++++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 platform/forms/res/templates/toolbar.html create mode 100644 platform/forms/src/MCTToolbar.js create mode 100644 platform/forms/test/MCTToolbarSpec.js diff --git a/platform/forms/bundle.json b/platform/forms/bundle.json index 5654d80f2b..020438fb66 100644 --- a/platform/forms/bundle.json +++ b/platform/forms/bundle.json @@ -7,6 +7,10 @@ "key": "mctForm", "implementation": "MCTForm.js" }, + { + "key": "mctToolbar", + "implementation": "MCTToolbar.js" + }, { "key": "mctControl", "implementation": "MCTControl.js", diff --git a/platform/forms/res/templates/toolbar.html b/platform/forms/res/templates/toolbar.html new file mode 100644 index 0000000000..e2d6868263 --- /dev/null +++ b/platform/forms/res/templates/toolbar.html @@ -0,0 +1,42 @@ +
+ +
+ +
+ {{section.name}} +
+
+ +
+ +
+ {{row.name}} + + i + +
+
+
+ + +
+
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/platform/forms/src/MCTToolbar.js b/platform/forms/src/MCTToolbar.js new file mode 100644 index 0000000000..c4642e4544 --- /dev/null +++ b/platform/forms/src/MCTToolbar.js @@ -0,0 +1,64 @@ +/*global define,Promise*/ + +/** + * Module defining MCTForm. Created by vwoeltje on 11/10/14. + */ +define( + ["./controllers/FormController"], + function (FormController) { + "use strict"; + + /** + * The mct-toolbar directive allows generation of displayable + * forms based on a declarative description of the form's + * structure. + * + * This directive accepts three attributes: + * + * * `ng-model`: The model for the form; where user input + * where be stored. + * * `structure`: The declarative structure of the toolbar. + * Describes what controls should be shown and where + * their values should be read/written in the model. + * * `name`: The name under which to expose the form's + * dirty/valid state. This is similar to ng-form's use + * of name, except this will be made available in the + * parent scope. + * + * @constructor + */ + function MCTForm() { + var templatePath = [ + "platform/forms", //MCTForm.bundle.path, + "res", //MCTForm.bundle.resources, + "templates/toolbar.html" + ].join("/"); + + return { + // Only show at the element level + restrict: "E", + + // Load the forms template + templateUrl: templatePath, + + // Use FormController to populate/respond to changes in scope + controller: FormController, + + // Initial an isolate scope + scope: { + + // The model: Where form input will actually go + ngModel: "=", + + // Form structure; what sections/rows to show + structure: "=", + + // Name under which to publish the form + name: "@" + } + }; + } + + return MCTForm; + } +); \ No newline at end of file diff --git a/platform/forms/test/MCTToolbarSpec.js b/platform/forms/test/MCTToolbarSpec.js new file mode 100644 index 0000000000..d18ff40ed6 --- /dev/null +++ b/platform/forms/test/MCTToolbarSpec.js @@ -0,0 +1,90 @@ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../src/MCTToolbar"], + function (MCTToolbar) { + "use strict"; + + describe("The mct-toolbar directive", function () { + var mockScope, + mctToolbar; + + beforeEach(function () { + mockScope = jasmine.createSpyObj("$scope", [ "$watch" ]); + mockScope.$parent = {}; + mctToolbar = new MCTToolbar(); + }); + + it("is restricted to elements", function () { + expect(mctToolbar.restrict).toEqual("E"); + }); + + it("watches for changes in form by name", function () { + // mct-form needs to watch for the form by name + // in order to convey changes in $valid, $dirty, etc + // up to the parent scope. + mctToolbar.controller(mockScope); + + expect(mockScope.$watch).toHaveBeenCalledWith( + "mctForm", + jasmine.any(Function) + ); + }); + + it("conveys form status to parent scope", function () { + var someState = { someKey: "some value" }; + mockScope.name = "someName"; + + mctToolbar.controller(mockScope); + + mockScope.$watch.mostRecentCall.args[1](someState); + + expect(mockScope.$parent.someName).toBe(someState); + }); + + it("allows strings to be converted to RegExps", function () { + // This is needed to support ng-pattern in the template + mctToolbar.controller(mockScope); + + // Should have added getRegExp to the scope, + // to convert strings to regular expressions + expect(mockScope.getRegExp("^\\d+$")).toEqual(/^\d+$/); + }); + + it("returns the same regexp instance for the same string", function () { + // Don't want new instances each digest cycle, for performance + var strRegExp = "^[a-z]\\d+$", + regExp; + + // Add getRegExp to scope + mctToolbar.controller(mockScope); + regExp = mockScope.getRegExp(strRegExp); + + // Same object instance each time... + expect(mockScope.getRegExp(strRegExp)).toBe(regExp); + expect(mockScope.getRegExp(strRegExp)).toBe(regExp); + }); + + it("passes RegExp objects through untouched", function () { + // Permit using forms to simply provide their own RegExp object + var regExp = /^\d+[a-d]$/; + + // Add getRegExp to scope + mctToolbar.controller(mockScope); + + // Should have added getRegExp to the scope, + // to convert strings to regular expressions + expect(mockScope.getRegExp(regExp)).toBe(regExp); + }); + + it("passes a non-whitespace regexp when no pattern is defined", function () { + // If no pattern is supplied, ng-pattern should match anything + mctToolbar.controller(mockScope); + expect(mockScope.getRegExp()).toEqual(/\S/); + expect(mockScope.getRegExp(undefined)).toEqual(/\S/); + }); + + + }); + } +); \ No newline at end of file