├── examples
├── example-basic.html
├── example-embedded.html
├── example-modal.html
├── example-new.html
├── index.html
├── style.css
└── utils.js
├── lib
└── jquery.medea.js
├── readme.md
├── test
├── eslint.json
├── helper
│ └── medea.js
├── index.html
├── lib
│ ├── jasmine-3.1.0
│ │ ├── boot.js
│ │ ├── jasmine-html.js
│ │ ├── jasmine.css
│ │ ├── jasmine.js
│ │ └── jasmine_favicon.png
│ └── jquery.jasmine.js
└── spec
│ ├── medea.core.js
│ ├── medea.events.js
│ ├── medea.helper.js
│ └── medea.usage.js
└── vendor
├── bootstrap
├── css
│ ├── bootstrap-theme.css
│ ├── bootstrap-theme.css.map
│ ├── bootstrap-theme.min.css
│ ├── bootstrap-theme.min.css.map
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ ├── bootstrap.min.css
│ └── bootstrap.min.css.map
├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.svg
│ ├── glyphicons-halflings-regular.ttf
│ ├── glyphicons-halflings-regular.woff
│ └── glyphicons-halflings-regular.woff2
└── js
│ ├── bootlint.js
│ ├── bootstrap.js
│ ├── bootstrap.min.js
│ └── npm.js
└── jquery
└── jquery-3.3.1.js
/examples/example-basic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Medea Example: Basic
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | examples
16 |
17 | Basic Example
18 | Simplest use of medea: turn object into form and vv
19 |
20 | Code
21 | $(selector).medea(object);
22 |
23 |
24 |
25 |
Source
26 |
27 |
Events
28 |
29 |
30 |
34 |
35 |
36 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/examples/example-embedded.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Medea Example: Embedded in Form
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | examples
16 |
17 | Embedded Example
18 | Existing form on the page. Medea object is embedded into the form which works as before
19 |
20 | Code
21 | $("#medea-here").medea(obj, { id: "formid", buttons: false, labelColumns: 2, inputColumns: 8, noForm: true })
22 |
23 |
24 |
25 |
Source
26 |
27 |
Events
28 |
29 |
30 |
53 |
54 |
55 |
77 |
78 |
--------------------------------------------------------------------------------
/examples/example-modal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Medea Example: Modal
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | examples
16 |
17 | Modal Example
18 |
19 | Uses Bootstrap modal to render form
20 |
21 |
22 |
23 | Code
24 | $(selector).medea(obj, {modal: true});
25 |
26 |
27 |
28 |
Source
29 |
30 |
Events
31 |
32 |
33 |
36 |
37 |
38 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/examples/example-new.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Medea Example: New Object
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | examples
16 |
17 | New Object Example
18 | Create full object from scratch
19 |
20 | Code
21 | $(selector).medea({});
22 |
23 |
24 |
25 |
Source
26 |
27 |
Events
28 |
29 |
30 |
34 |
35 |
36 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Medea Examples
6 |
7 |
8 |
9 |
10 |
11 |
12 | Examples
13 |
14 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/style.css:
--------------------------------------------------------------------------------
1 |
2 | label.editable {
3 |
4 | }
5 |
6 | .modal-dialog {
7 | width: 70%;
8 | }
9 |
--------------------------------------------------------------------------------
/examples/utils.js:
--------------------------------------------------------------------------------
1 |
2 | var utils = (function() {
3 |
4 | function prettyPrint(obj) {
5 | return JSON.stringify(obj, null, 2);
6 | }
7 |
8 | function parseEventName(e) {
9 | return e.type + ":" + e.namespace;
10 | }
11 |
12 | function prepContainerForCode(elementName) {
13 | var wrapper = $("#" + elementName);
14 | wrapper.append($(""));
15 | wrapper.find("pre").append($(""));
16 | return wrapper;
17 | }
18 |
19 | function findAndPrepTargetElement(elementName) {
20 | var wrapper = $("#" + elementName);
21 | if(wrapper.find("pre").length === 0) {
22 | prepContainerForCode(elementName);
23 | }
24 | return wrapper.find("code");
25 | }
26 |
27 | function logEvent(container) {
28 | var target = findAndPrepTargetElement(container);
29 | return function(e) {
30 | target.append(parseEventName(e) + "\n");
31 | }
32 | }
33 |
34 | function logObjectChangeEvent(container) {
35 | var target = findAndPrepTargetElement(container);
36 | return function(e, obj) {
37 | target.html(prettyPrint(obj));
38 | }
39 | }
40 |
41 | function prettyPrintSource(obj, container) {
42 | var target = findAndPrepTargetElement(container);
43 | target.html(prettyPrint(obj));
44 | }
45 |
46 | var simpleObject = {
47 | firstName: "John",
48 | lastName: "Smith"
49 | };
50 |
51 | var testObject = {
52 | name: {
53 | firstName: "John",
54 | lastName: "Smith"
55 | },
56 | personal: {
57 | age: 42,
58 | likesIceCream: true
59 | },
60 | hobbies: [
61 | "football",
62 | "golf"
63 | ],
64 | address: {
65 | road: { number: "1", street: "the street" },
66 | town: "townington",
67 | county: "Shireshire"
68 | }
69 | };
70 |
71 | return {
72 | logEvent: logEvent,
73 | logObjectChangeEvent: logObjectChangeEvent,
74 | prettyPrint: prettyPrint,
75 | testObject: testObject,
76 | simpleObject: simpleObject,
77 | prettyPrintSource: prettyPrintSource
78 | };
79 |
80 | }());
81 |
--------------------------------------------------------------------------------
/lib/jquery.medea.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Medea
3 | *
4 | * v0.1.1
5 | *
6 | **/
7 |
8 | window.Medea = (function($) {
9 |
10 | "use strict";
11 |
12 | var options = {};
13 |
14 | var defaults = {
15 | removeOnSubmit: false,
16 | buttons: true,
17 | labelColumns: 2,
18 | inputColumns: 10,
19 | noForm: false,
20 | modal: false,
21 | modalId: guid("")
22 | };
23 |
24 | var events = {
25 | MEDEA_FIELD_ADD: "medea.add",
26 | MEDEA_SUBMITTED: "medea.submit",
27 | MEDEA_CANCELLED: "medea.cancel",
28 | MEDEA_TOGGLE: "medea.toggle"
29 | };
30 |
31 | var elements = {
32 | container: null,
33 | form: null
34 | };
35 |
36 | var css = {
37 | formRowClass: "medea-form-data-row",
38 | buttonRowClass: "medea-form-buttons-row",
39 | };
40 |
41 | function defaultValue(value, def) {
42 | return (typeof value === "undefined") ? def : value;
43 | }
44 |
45 | function regularCase(str) {
46 | if(str === null) { return ""; }
47 | return str
48 | .replace(/([a-z])([A-Z])/g, "$1 $2")
49 | .replace(/\b([A-Z]+)([A-Z])([a-z])/, "$1 $2$3")
50 | .replace(/^./, function(s){ return s.toUpperCase(); });
51 | }
52 |
53 | function form2object(selector, delimiter) {
54 | var form = $(selector);
55 | if(form.length === 0) {
56 | console.warn("medea.form2object: no form found at %s", selector);
57 | return {};
58 | }
59 | delimiter = delimiter || ".";
60 | var formValues = form.find(":input").serializeArray();
61 | var checkBoxValues = form.find("input[type=checkbox]:not(:checked)")
62 | .map(function() {
63 | return { "name": this.name, "value": $(this).is(":checked") }
64 | }).get();
65 | formValues = formValues.concat(checkBoxValues);
66 | if(formValues.length === 0) {
67 | console.warn("medea.form2object: no input fields found at %s", selector);
68 | return {};
69 | }
70 | var result = {};
71 | var arrays = {};
72 | for(var i = 0; i < formValues.length; i++) {
73 | var value = formValues[i].value;
74 | var inputField = form.find("input[name='" + formValues[i].name + "']");
75 | //console.log(inputField.length);
76 | if(inputField.attr("data-json-type")==="number") {
77 | if( (value % 1) !== 0) {
78 | value = parseFloat(value);
79 | }
80 | else {
81 | value = parseInt(value);
82 | }
83 | }
84 | if(inputField.attr("data-json-type")==="boolean") {
85 | var lc = value.toString().toLowerCase();
86 | value = (lc === "true"||lc === "on") ? true : false;
87 | }
88 | if (value === "") { continue; }
89 | var name = formValues[i].name;
90 | var nameParts = name.split(delimiter);
91 | var currResult = result;
92 | for (var j = 0; j < nameParts.length; j++) {
93 | var namePart = nameParts[j];
94 | var arrName;
95 | if(namePart.indexOf("[]") > -1 && j === nameParts.length - 1) {
96 | arrName = namePart.substr(0, namePart.indexOf("["));
97 | if (!currResult[arrName]) { currResult[arrName] = []; }
98 | currResult[arrName].push(value);
99 | }
100 | else {
101 | if(namePart.indexOf("[") > -1) {
102 | arrName = namePart.substr(0, namePart.indexOf("["));
103 | var arrIdx = namePart.replace(/^[a-z]+\[|\]$/gi, "");
104 | if(!arrays[arrName]) {
105 | arrays[arrName] = {};
106 | }
107 | if(!currResult[arrName]) {
108 | currResult[arrName] = [];
109 | }
110 | if(j === nameParts.length - 1) {
111 | currResult[arrName].push(value);
112 | }
113 | else {
114 | if(!arrays[arrName][arrIdx]) {
115 | currResult[arrName].push({});
116 | arrays[arrName][arrIdx] = currResult[arrName][currResult[arrName].length - 1];
117 | }
118 | }
119 | currResult = arrays[arrName][arrIdx];
120 | }
121 | else {
122 | if(j < (nameParts.length - 1)) {
123 | if (!currResult[namePart]) { currResult[namePart] = {}; }
124 | currResult = currResult[namePart];
125 | }
126 | else {
127 | if(!isInteger(currResult)) {
128 | currResult[namePart] = value;
129 | }
130 | else {
131 | // @todo: raise proper (useful) error event
132 | console.error("invalid object");
133 | }
134 | }
135 | }
136 | }
137 | }
138 | }
139 | return result;
140 | }
141 |
142 | function button(context) {
143 | var btn = $("