Commit 19028f05 authored by Tomáš Peterka's avatar Tomáš Peterka Committed by Tomáš Peterka

[renderjs_ui] Add FormBox implementation

parent 6a893b8d
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 FormBox Field</title>
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_field_formbox.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
\ No newline at end of file
/*global window, rJS, URI */
/*jslint nomen: true, indent: 2, maxerr: 3 */
/**
* FormBox displays embedded form in itself.
*
* There are two common CSS classes bound to the FormBox Field
* - "horizontal_align_form_box" renders fields without labels in horizontal manner (useful for phone etc.)
* - "invisible" despite its name should only hide label
*
*/
(function (window, rJS, URI) {
"use strict";
rJS(window)
.setState({
subgadget_template: undefined,
editable: undefined,
css_class: ''
})
.declareAcquiredMethod("jio_getAttachment", "jio_getAttachment")
.declareMethod('render', function (options) {
var element = this.element,
gadget = this,
field_json = options.field_json || {},
new_state = {
value: field_json.value || field_json.default || "",
text_content: field_json.value || field_json.default || "",
editable: field_json.editable,
required: field_json.required,
name: field_json.key,
title: field_json.title,
hidden: field_json.hidden,
view: field_json.view,
css_class: field_json.css_class,
// field_json._embedded is HATEOASed subobj specs included in FormBox
erp5_embedded_document: field_json._embedded
};
// prefer editability from the global context (form)
if (options.editable !== undefined) {
new_state.editable = options.editable;
}
if (gadget.state.subgadget_template === undefined || options.reset === true) {
// render subgadget only when there is none OR render is explicitely requested
return gadget.declareGadget('gadget_erp5_page_form.html', {scope: 'sub'})
.push(function (form_gadget) {
// Clear first to DOM, append after to reduce flickering/manip
while (element.firstChild) {
element.removeChild(element.firstChild);
}
element.appendChild(form_gadget.element);
// Add newly created subgadget to the state
new_state.subgadget_template = 'gadget_erp5_page_form.html';
return gadget.changeState(new_state);
});
}
return gadget.changeState(new_state);
})
.onStateChange(function (modification_dict) {
var gadget = this,
erp5_document_uri = new URI(gadget.state.erp5_embedded_document._view._links.traversed_document.href),
form_options = {
erp5_document: {
_embedded: gadget.state.erp5_embedded_document
},
key: gadget.state.name,
view: gadget.state.view,
jio_key: erp5_document_uri.segment(2),
editable: gadget.state.editable
};
// do not preserve objects in the state
delete gadget.state.erp5_embedded_document;
// pass CSS class to the DIV element
if (modification_dict.hasOwnProperty('css_class')) {
gadget.element.classList.add(modification_dict.css_class);
}
return gadget.getDeclaredGadget('sub')
.push(function (subgadget) {
subgadget.render(form_options);
});
})
.declareMethod('getContent', function () {
if (this.state.editable) {
return this.getDeclaredGadget('sub')
.push(function (gadget) {
return gadget.getContent();
});
}
return {};
})
.declareMethod('checkValidity', function () {
if (this.state.editable) {
return this.getDeclaredGadget('sub')
.push(function (gadget) {
return gadget.checkValidity();
});
}
return true;
});
}(window, rJS, URI));
\ No newline at end of file
/*jslint nomen: true, indent: 2, maxerr: 3 */
/*global window, document, rJS, RSVP*/
(function (window, document, rJS, RSVP) {
"use strict";
/** Form is one of a complicated gadget!
*
* Editability - the form overrides editability of its fields. Editability is
* hard-coded changed either in Page Templates or soft-coded
* changed in FormBox gadget which renders form as a subgadget
**/
function getFieldTypeGadgetUrl(type) {
var field_url = 'gadget_erp5_field_readonly.html';
......@@ -47,46 +54,56 @@
field_url = 'gadget_erp5_field_image.html';
} else if (type === 'EmailField') {
field_url = 'gadget_erp5_field_email.html';
} else if (type === 'FormBox') {
field_url = 'gadget_erp5_field_formbox.html';
}
return field_url;
}
/**
* Physically append rendered field to DOM.
*
* Wraps every field in label gadget.
* @argument field: array<tuple<str, object>> where first item is name, second meta info of the field
* (obsolete to specify the meta information which is returned by JSON style since it is duplicate of information in document instance)
*/
function addField(field, rendered_document, form_definition, form_gadget, group_name, modification_dict) {
var field_name = field[0],
field_element,
suboptions;
function addField(field, rendered_form, form_definition, form_gadget, group, modification_dict) {
if (rendered_form.hasOwnProperty(field[0])) {
// Field is enabled in this context
var sandbox = "public",
field_element = document.createElement("div"),
renderered_field = rendered_form[field[0]],
// suboptions = options[renderered_field.key] || suboption_dict;
suboptions = {};
// XXX Hardcoded for searchfield - remove later!
if (form_definition.extended_search) {
suboptions.extended_search = form_definition.extended_search;
if (!rendered_document.hasOwnProperty(field_name)) {
return;
}
// XXX Hardcoded for listbox's hide functionality
suboptions.hide_enabled = form_definition.hide_enabled;
suboptions.field_url = getFieldTypeGadgetUrl(renderered_field.type);
suboptions.label = false;
suboptions.field_json = renderered_field;
suboptions = {
hide_enabled: form_definition.hide_enabled, // listbox specific
extended_search: form_definition.extended_search, // searchfield specific
field_url: getFieldTypeGadgetUrl(rendered_document[field_name].type),
label: ((group_name !== "bottom") && (rendered_document[field_name].title.length > 0)), // no label for bottom group and field without title
field_json: rendered_document[field_name] // pass
};
// XXX: what is the purpose of this?
suboptions.field_json.view = form_gadget.state.view;
if (group[0] !== "bottom") {
suboptions.label = true;
// if the whole form is non-editable than every field has to be non-editable
if (form_gadget.state.editable === 0) {
suboptions.field_json.editable = 0;
}
field_element = document.createElement("div");
return new RSVP.Queue()
.push(function () {
var rendered_field_name = rendered_document[field_name].key;
if (modification_dict.hasOwnProperty('hash')) {
return form_gadget.declareGadget('gadget_erp5_label_field.html', {
scope: renderered_field.key,
scope: rendered_field_name, // ugly! Should be just `field_name` but too many tests depend on it
element: field_element,
sandbox: sandbox
sandbox: "public"
});
}
return form_gadget.getDeclaredGadget(renderered_field.key);
return form_gadget.getDeclaredGadget(rendered_field_name);
})
.push(function (label_gadget) {
if (modification_dict.hasOwnProperty('hash')) {
......@@ -103,35 +120,29 @@
})
.push(function () {
return field_element;
// return fieldset_element;
// fieldset_element.appendChild(field_element);
});
}
}
function addGroup(group, rendered_form, form_definition, form_gadget, modification_dict) {
function addGroup(group, rendered_document, form_definition, form_gadget, modification_dict) {
// XXX: > Romain: fieldset will be needed later for menus
var fieldset_element = document.createElement("div"),
promise_field_list = [],
j;
group_name = group[0],
field_list = group[1];
fieldset_element.setAttribute("class", group[0]);
fieldset_element.setAttribute("class", group_name);
for (j = 0; j < group[1].length; j += 1) {
promise_field_list.push(addField(group[1][j], rendered_form, form_definition, form_gadget, group, modification_dict));
}
return new RSVP.Queue()
.push(function () {
return RSVP.all(promise_field_list);
return RSVP.all(field_list.map(function (field) {
return addField(field, rendered_document, form_definition, form_gadget, group_name, modification_dict);
}));
})
.push(function (result_list) {
var i;
for (i = 0; i < result_list.length; i += 1) {
if (result_list[i]) {
fieldset_element.appendChild(result_list[i]);
}
}
// append all rendered fields into DOM
result_list.forEach(function (result) {
if (result) {fieldset_element.appendChild(result); }
});
return fieldset_element;
});
}
......@@ -139,7 +150,23 @@
rJS(window)
.ready(function (g) {
g.props = {};
g.props = {
gadget_list: [] // holds references to all subgadgets to be able to grab their content on submit
};
})
.setState({
// erp5 document is an instance of a document referenced by jio_key
erp5_document: undefined,
jio_key: undefined,
// form definition holds positioning of fields
form_definition: undefined,
view: undefined, // Kato: still have no idea what that means
// hash is used to spot changes in positioning of fields
hash: undefined,
// attributes of the form - no magic there
title: undefined,
editable: undefined
})
.allowPublicAcquisition("getFieldTypeGadgetUrl", function (param_list) {
......@@ -155,19 +182,24 @@
.declareMethod('render', function (options) {
var group_list = options.form_definition.group_list,
rendered_form = options.erp5_document._embedded._view,
rendered_document = options.erp5_document._embedded._view,
hash = "",
group_name,
group_field_list,
i,
j,
hash = "";
j;
// Check the list of field to render
// If the list is different, DOM content will be dropped
// and recreated
// Contruct a hash of <placement>+<field names> to snapshot rendering.
// The `hash` will make it to the `onStateChange` only if it has changed.
// If so, DOM content will be dropped and recreated
for (i = 0; i < group_list.length; i += 1) {
hash += group_list[i][0];
for (j = 0; j < group_list[i][1].length; j += 1) {
if (rendered_form.hasOwnProperty(group_list[i][1][j][0])) {
hash += group_list[i][1][j][0];
group_name = group_list[i][0];
group_field_list = group_list[i][1];
hash += group_name;
for (j = 0; j < group_field_list.length; j += 1) {
if (rendered_document.hasOwnProperty(group_field_list[j][0])) {
hash += group_field_list[j][0];
}
}
}
......@@ -175,15 +207,18 @@
return this.changeState({
erp5_document: options.erp5_document,
form_definition: options.form_definition,
jio_key: options.jio_key,
hash: hash,
view: options.view
view: options.view,
editable: options.editable,
title: options.title
});
})
.onStateChange(function (modification_dict) {
var erp5_document = this.state.erp5_document,
form_definition = this.state.form_definition,
rendered_form = erp5_document._embedded._view,
rendered_document = erp5_document._embedded._view,
group_list = form_definition.group_list,
form_gadget = this;
......@@ -193,12 +228,9 @@
return new RSVP.Queue()
.push(function () {
var group_promise_list = [],
j;
for (j = 0; j < group_list.length; j += 1) {
group_promise_list.push(addGroup(group_list[j], rendered_form, form_definition, form_gadget, modification_dict));
}
return RSVP.all(group_promise_list);
return RSVP.all(group_list.map(function (group) {
return addGroup(group, rendered_document, form_definition, form_gadget, modification_dict);
}));
})
.push(function (result_list) {
if (modification_dict.hasOwnProperty('hash')) {
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>955.49459.46929.49339</string> </value>
<value> <string>961.18982.46006.23483</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1480936090.54</float>
<float>1502268077.5</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, document, rJS, RSVP */
/*jslint indent: 2, maxerr: 3 */
/**
* Label gadget takes care of displaying validation errors and label.
*
* Every form field is wrapped in that widget which has some consequences:
*
* - CSS classes sharing: label copy CSS classes of embedded field for itself
* because CSS selectors are not good in selectin up the DOM tree
* - class "invisible" despite its name is supposed to hide only label
* - class "horizontal_align_form_box" will prevent any label to show as well
*
*/
(function (window, document, rJS, RSVP) {
"use strict";
......@@ -9,8 +20,10 @@
.setState({
label_text: '',
error_text: '',
label: true
label: true,
css_class: ''
})
.ready(function () {
return this.changeState({
label_element: this.element.querySelector('label'),
......@@ -28,7 +41,8 @@
error_text: options.field_json.error_text || '',
options: options,
scope: options.field_json.key,
hidden: options.field_json.hidden
hidden: options.field_json.hidden,
css_class: options.field_json.css_class
};
return this.changeState(state_dict);
})
......@@ -48,6 +62,10 @@
}
this.state.label_element.setAttribute('for', gadget.state.scope);
if (modification_dict.hasOwnProperty('css_class') && this.state.css_class) {
this.state.label_element.classList.add(this.state.css_class);
}
if (modification_dict.hasOwnProperty('error_text')) {
this.state.error_element.textContent = "";
if (this.state.error_text) {
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>956.17308.23196.16947</string> </value>
<value> <string>961.17833.11141.14523</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1482938684.96</float>
<float>1502198959.61</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -918,6 +918,9 @@ div[data-gadget-scope='header'] .ui-header ul {
.gadget-content {
padding: 24pt;
padding-top: 66pt;
/* Disclaimer: It is here only for backward-compatibility! Don't rely on
this class because it will be removed.
It was used to force horizontal rendering of fields inside FormBox. */
/*
@media @smartphone {
.ui-field-contain {
......@@ -974,6 +977,9 @@ div[data-gadget-scope='header'] .ui-header ul {
.gadget-content .ui-field-contain div {
width: 100%;
}
.gadget-content .horizontal_align_form_box .ui-field-contain > div {
display: block-inline;
}
.gadget-content .ui-content-header-plain {
font-size: 150%;
}
......@@ -1047,6 +1053,12 @@ div[data-gadget-scope='header'] .ui-header ul {
.gadget-content .ui-field-contain > label {
flex: 1;
color: #777777;
/* Disclaimer: It is here only for backward-compatibility! Don't rely on
this class because it will be removed.
It was used to hide the label of a FormBox. */
}
.gadget-content .ui-field-contain > label.invisible {
display: none;
}
.gadget-content .ui-field-contain > label + div {
flex: 3;
......
......@@ -242,7 +242,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.19028.47293.9045</string> </value>
<value> <string>961.19210.8471.60620</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>1502271576.03</float>
<float>1502444264.19</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -85,7 +85,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_erp5_pt_formpage_html</string> </value>
<value> <string>rjs_gadget_erp5_page_form_html</string> </value>
</item>
<item>
<key> <string>language</string> </key>
......@@ -103,7 +103,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Gadget ERP5 Doc</string> </value>
<value> <string>Gadget ERP5 Form Page</string> </value>
</item>
<item>
<key> <string>version</string> </key>
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>952.64761.25287.18397</string> </value>
<value> <string>960.5523.58984.43537</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1475148161.21</float>
<float>1501681620.31</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS, URI */
/*global window, rJS, URI, RSVP */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS, URI) {
(function (window, rJS, URI, RSVP) {
"use strict";
function loadFormContent(gadget, result) {
......@@ -28,7 +28,29 @@
.declareAcquiredMethod("updatePanel", "updatePanel")
/////////////////////////////////////////////////////////////////
// declared methods
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('triggerSubmit', function () {
return this.getDeclaredGadget('fg')
.push(function (g) {
return g.triggerSubmit();
});
})
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget('fg')
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget('fg')
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// Own methods
/////////////////////////////////////////////////////////////////
.allowPublicAcquisition("jio_allDocs", function (param_list) {
var gadget = this;
......@@ -46,17 +68,29 @@
.allowPublicAcquisition('notifySubmit', function () {
return this.triggerSubmit();
})
.declareMethod('triggerSubmit', function () {
return this.getDeclaredGadget('fg')
.push(function (g) {
return g.triggerSubmit();
});
})
.declareMethod("render", function (options) {
var gadget = this;
return gadget.jio_getAttachment(options.jio_key, options.view)
var gadget = this,
promise_queue = new RSVP.Queue(),
new_state = {
options: options,
erp5_document: undefined,
erp5_form: undefined,
url: undefined
};
if (options.hasOwnProperty('erp5_document')) {
// if we get erp5 document during rendering then no need to fetch it
new_state.erp5_document = options.erp5_document;
// remove reference to erp5_document from options (and new_state.options)
delete options.erp5_document;
} else {
promise_queue
.push(function () {
return gadget.jio_getAttachment(options.jio_key, options.view);
})
.push(function (result) {
var uri;
new_state.erp5_document = result;
if (!result._embedded) {
return gadget.jio_getAttachment(options.jio_key, "links")
.push(function (result2) {
......@@ -66,34 +100,47 @@
}});
});
}
});
}
// options.editable differs when it comes from the erp5_launcher of FormBox - try to unify it here
if (options.editable === "true" || options.editable === true || options.editable === "1" || options.editable === 1) {
options.editable = 1;
} else {
options.editable = 0;
}
uri = new URI(result._embedded._view._links.form_definition.href);
return gadget.jio_getAttachment(uri.segment(2), "view")
return promise_queue
.push(function () {
var uri = new URI(new_state.erp5_document._embedded._view._links.form_definition.href);
return gadget.jio_getAttachment(uri.segment(2), "view");
})
.push(function (erp5_form) {
var url = "gadget_erp5_pt_" + erp5_form.pt;
// XXX Hardcoded specific behaviour for form_view
if ((options.editable !== undefined) && (erp5_form.pt === "form_view")) {
if ((options.editable === 1) && (erp5_form.pt === "form_view")) {
url += "_editable";
}
url += ".html";
return gadget.changeState({
jio_key: options.jio_key,
options: options,
view: options.view,
url: url,
erp5_document: JSON.stringify(result),
erp5_form: JSON.stringify(erp5_form)
});
});
new_state.url = url;
new_state.erp5_form = JSON.stringify(erp5_form);
new_state.erp5_document = JSON.stringify(new_state.erp5_document);
return gadget.changeState(new_state);
});
})
.onStateChange(function (modification_dict) {
var queue,
gadget = this,
options = this.state.options,
page_template_gadget,
clean_dom = modification_dict.hasOwnProperty('url');
// clean_dom === false only in case of displaying errors
clean_dom = modification_dict.hasOwnProperty('url'),
erp5_document = JSON.parse(gadget.state.erp5_document),
erp5_form = JSON.parse(gadget.state.erp5_form);
if (clean_dom) {
queue = gadget.declareGadget(gadget.state.url, {scope: "fg"});
} else {
......@@ -103,9 +150,7 @@
.push(function (result) {
page_template_gadget = result;
var sub_options = options.fg || {},
erp5_document = JSON.parse(gadget.state.erp5_document),
erp5_form = JSON.parse(gadget.state.erp5_form);
var sub_options = options.fg || {};
loadFormContent(gadget, erp5_document._embedded._view);
......@@ -113,11 +158,10 @@
sub_options.form_definition = erp5_form;
sub_options.view = options.view;
sub_options.action_view = options.action_view;
sub_options.jio_key = options.jio_key;
sub_options.editable = options.editable;
sub_options.jio_key = options.jio_key; // jIO identifier of currently rendered ERP5 document
sub_options.editable = options.editable; // form decides on editability of its fields
return page_template_gadget.render(sub_options);
})
.push(function () {
if (clean_dom) {
......@@ -138,7 +182,7 @@
if (/^[^\/]+_module\/.+$/.test(jio_key)) {
/*jslint regexp: false*/
return gadget.updatePanel({
erp5_document: JSON.parse(gadget.state.erp5_document),
erp5_document: erp5_document,
editable: gadget.state.options.editable
});
}
......@@ -153,4 +197,4 @@
return this.changeState({erp5_document: JSON.stringify(erp5_document)});
});
}(window, rJS, URI));
\ No newline at end of file
}(window, rJS, URI, RSVP));
\ No newline at end of file
......@@ -81,7 +81,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_erp5_pt_formpage_js</string> </value>
<value> <string>rjs_gadget_erp5_page_form_js</string> </value>
</item>
<item>
<key> <string>language</string> </key>
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>958.28347.56387.25600</string> </value>
<value> <string>961.16455.47614.10018</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1491391860.07</float>
<float>1502198575.84</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -78,7 +78,21 @@
.declareAcquiredMethod("displayFormulatorValidationError",
"displayFormulatorValidationError")
/////////////////////////////////////////////////////////////////
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
......@@ -88,7 +102,7 @@
.declareMethod('render', function (options) {
var state_dict = {
id: options.jio_key,
jio_key: options.jio_key,
view: options.view,
editable: options.editable,
erp5_document: options.erp5_document,
......@@ -158,6 +172,9 @@
form_options.erp5_document = form_gadget.state.erp5_document;
form_options.form_definition = form_gadget.state.form_definition;
form_options.view = form_gadget.state.view;
form_options.jio_key = form_gadget.state.jio_key;
form_options.editable = form_gadget.state.editable;
return erp5_form.render(form_options);
})
.push(function () {
......@@ -217,7 +234,7 @@
}
return form_gadget.jio_putAttachment(
form_gadget.state.id,
form_gadget.state.jio_key,
action.href,
data
);
......@@ -267,7 +284,7 @@
form_gadget.deferRevokeObjectUrlWithLink(object_url, a);
} else {
jio_key = new URI(location).segment(2);
if (form_gadget.state.id === jio_key) {
if (form_gadget.state.jio_key === jio_key) {
// Do not update navigation history if dialog redirect to the same document
list.push(form_gadget.redirect({command: 'change', options: {jio_key: jio_key, view: "view", page: undefined, editable: form_gadget.state.editable}}));
} else {
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>961.657.32982.5239</string> </value>
<value> <string>961.16461.13159.33399</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1501168424.28</float>
<float>1502116641.07</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -13,6 +13,21 @@
.declareAcquiredMethod("getUrlParameter", "getUrlParameter")
.declareAcquiredMethod("renderEditorPanel", "renderEditorPanel")
/////////////////////////////////////////////////////////////////
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
......@@ -21,7 +36,7 @@
return gadget.getUrlParameter('extended_search')
.push(function (extended_search) {
var state_dict = {
id: options.jio_key,
jio_key: options.jio_key,
view: options.view,
editable: options.editable,
erp5_document: options.erp5_document,
......@@ -44,6 +59,8 @@
form_options.erp5_document = form_gadget.state.erp5_document;
form_options.form_definition = form_gadget.state.form_definition;
form_options.view = form_gadget.state.view;
form_options.jio_key = form_gadget.state.jio_key;
form_options.editable = form_gadget.state.editable;
// XXX Hardcoded for listbox's hide functionality
form_options.form_definition.hide_enabled = true;
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.34605.28227.45721</string> </value>
<value> <string>961.16133.2066.40123</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1476198578.1</float>
<float>1502114387.31</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -16,6 +16,21 @@
.declareAcquiredMethod("displayFormulatorValidationError",
"displayFormulatorValidationError")
/////////////////////////////////////////////////////////////////
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
......@@ -25,7 +40,7 @@
.declareMethod('render', function (options) {
var state_dict = {
id: options.jio_key,
jio_key: options.jio_key,
view: options.view,
editable: options.editable,
erp5_document: options.erp5_document,
......@@ -55,6 +70,8 @@
form_options.erp5_document = form_gadget.state.erp5_document;
form_options.form_definition = form_gadget.state.form_definition;
form_options.view = form_gadget.state.view;
form_options.jio_key = form_gadget.state.jio_key;
form_options.editable = 1;
return erp5_form.render(form_options);
})
......@@ -129,7 +146,7 @@
return RSVP.all([
form_gadget.notifySubmitting(),
form_gadget.jio_putAttachment(
form_gadget.state.id,
form_gadget.state.jio_key,
action.href,
data
)
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>960.32739.63971.65297</string> </value>
<value> <string>961.16418.20259.26675</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1499430902.76</float>
<float>1502116591.57</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, rJS */
/*jslint nomen: true, indent: 2, maxerr: 3 */
(function (window, rJS) {
"use strict";
rJS(window)
/////////////////////////////////////////////////////////////////
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod('render', function (options) {
var state_dict = {
jio_key: options.jio_key,
name: options.name,
view: options.view,
editable: options.editable,
erp5_document: options.erp5_document,
form_definition: options.form_definition,
erp5_form: options.erp5_form || {},
new_content_action: false,
delete_action: false,
save_action: false
};
return this.changeState(state_dict);
})
.onStateChange(function () {
var form_gadget = this;
// render the erp5 form
return form_gadget.getDeclaredGadget("erp5_form")
.push(function (erp5_form) {
var form_options = form_gadget.state.erp5_form;
form_options.erp5_document = form_gadget.state.erp5_document;
form_options.form_definition = form_gadget.state.form_definition;
form_options.view = form_gadget.state.view;
form_options.name = form_gadget.state.name;
form_options.editable = form_gadget.state.editable;
return erp5_form.render(form_options);
})
});
}(window, rJS));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 PT Form View</title>
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<script src="gadget_erp5_pt_embedded_form_render.js" type="text/javascript"></script>
</head>
<body>
<div class="ui-body-c">
<div data-gadget-url="gadget_erp5_form.html"
data-gadget-scope="erp5_form"
data-gadget-sandbox="public">
</div>
</div>
</body>
</html>
\ No newline at end of file
......@@ -3,6 +3,20 @@
(function (window, rJS, RSVP, calculatePageTitle) {
"use strict";
function isGoodNonEditableField(field) {
// ListBox and FormBox should always get a chance to render
if (field.type === "ListBox") {return true; }
if (field.type === "FormBox") {return true; }
// hidden fields should not be obviously rendered
if (field.hidden === 1) {return false; }
// field without default
if (!field.default) {return false; }
if (field.default.length === 0) {return false; }
if (field.default.length === 1 && (!field.default[0])) {return false; }
return true;
}
rJS(window)
/////////////////////////////////////////////////////////////////
// Acquired methods
......@@ -10,12 +24,27 @@
.declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("getUrlFor", "getUrlFor")
/////////////////////////////////////////////////////////////////
// Proxy methods to the child gadget
/////////////////////////////////////////////////////////////////
.declareMethod('checkValidity', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.checkValidity();
});
})
.declareMethod('getContent', function () {
return this.getDeclaredGadget("erp5_form")
.push(function (declared_gadget) {
return declared_gadget.getContent();
});
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod('render', function (options) {
var state_dict = {
id: options.jio_key,
jio_key: options.jio_key,
view: options.view,
editable: options.editable,
erp5_document: options.erp5_document,
......@@ -33,18 +62,13 @@
.push(function (erp5_form) {
var form_options = gadget.state.erp5_form,
rendered_form = gadget.state.erp5_document._embedded._view,
rendered_field,
key;
// Remove all empty fields, and mark all others as non editable
// Remove all empty or otherwise bad non-editable fields
for (key in rendered_form) {
if (rendered_form.hasOwnProperty(key) && (key[0] !== "_")) {
rendered_field = rendered_form[key];
if ((rendered_field.type !== "ListBox") && ((!rendered_field.default) || (rendered_field.hidden === 1) || (rendered_field.default.length === 0)
|| (rendered_field.default.length === 1 && (!rendered_field.default[0])))) {
if (!isGoodNonEditableField(rendered_form[key])) {
delete rendered_form[key];
} else {
rendered_field.editable = 0;
}
}
}
......@@ -52,6 +76,8 @@
form_options.erp5_document = gadget.state.erp5_document;
form_options.form_definition = gadget.state.form_definition;
form_options.view = gadget.state.view;
form_options.jio_key = gadget.state.jio_key;
form_options.editable = 0;
return erp5_form.render(form_options);
})
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.5630.32927.153</string> </value>
<value> <string>961.16419.13605.17578</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1476194151.17</float>
<float>1502116554.64</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -32,7 +32,8 @@
}
};
return form_gadget.render({erp5_document: erp5_document,
form_definition: form_definition});
form_definition: form_definition,
editable: 0});
});
}
......@@ -66,7 +67,7 @@
return this.changeState({
erp5_document: options.erp5_document,
form_definition: options.form_definition,
form_gadget_url: form_gadget_url
form_gadget_url: form_gadget_url,
});
})
.onStateChange(function (modification_dict) {
......@@ -90,7 +91,8 @@
form_gadget = result;
return form_gadget.render({
erp5_document: gadget.state.erp5_document,
form_definition: gadget.state.form_definition
form_definition: gadget.state.form_definition,
editable: 0
});
})
......
......@@ -230,7 +230,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>954.25919.63902.23893</string> </value>
<value> <string>961.16421.12334.2201</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -248,7 +248,7 @@
</tuple>
<state>
<tuple>
<float>1476194238.38</float>
<float>1502116518.17</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -1116,6 +1116,12 @@ div[data-gadget-scope='header'] .ui-header {
width: 100%;
}
}
/* Disclaimer: It is here only for backward-compatibility! Don't rely on
this class because it will be removed.
It was used to force horizontal rendering of fields inside FormBox. */
.horizontal_align_form_box .ui-field-contain > div {
display: block-inline;
}
.ui-content-header-plain {
font-size: 150%;
......@@ -1206,6 +1212,12 @@ div[data-gadget-scope='header'] .ui-header {
& > label {
flex: 1;
color: @grey;
/* Disclaimer: It is here only for backward-compatibility! Don't rely on
this class because it will be removed.
It was used to hide the label of a FormBox. */
&.invisible {
display: none;
}
}
& > label + div {
flex: 3;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment