Commit ea3b93fb authored by Romain Courteaud's avatar Romain Courteaud

[erp5_web_renderjs_ui] Rewrite relation field

Support calling render method multiple times.
parent 7b480c8f
/*jslint indent: 2, maxerr: 3, nomen: true */ /*jslint indent: 2, maxerr: 3, nomen: true, unparam: true, maxlen: 80 */
/*global window, rJS, RSVP, document */ /*global window, rJS, RSVP, document */
(function (window, rJS, RSVP, document) { (function (window, rJS, RSVP, document) {
"use strict"; "use strict";
rJS(window) function addRelationInput(gadget, value_relative_url, value_text,
value_uid, value_portal_type, index) {
///////////////////////////////////////////////////////////////// var input_gadget;
// ready
/////////////////////////////////////////////////////////////////
// Init local properties
.ready(function (gadget) {
gadget.props = {};
return gadget.getElement()
.push(function (element) {
gadget.props.element = element;
});
})
.allowPublicAcquisition("addRelationInput", function () {
var fieldset = document.createElement("fieldset"),
gadget = this,
container = gadget.props.element.querySelector('.container');
return gadget.declareGadget('gadget_erp5_relation_input.html', { return gadget.declareGadget('gadget_erp5_relation_input.html', {
element: fieldset element: document.createElement("fieldset")
}) })
.push(function (relation_input) { .push(function (result) {
var field_json = gadget.props.field_json, input_gadget = result;
index; return input_gadget.render({
if (field_json.default.value) { editable: gadget.state.editable,
index = field_json.default.relation_item_relative_url.length; query: gadget.state.query,
field_json.default.relation_item_relative_url.push(''); catalog_index: gadget.state.catalog_index,
field_json.default.value.push(''); allow_jump: gadget.state.allow_jump,
} else { // required: field_json.required,
index = field_json.relation_item_relative_url.length; title: gadget.state.title,
field_json.relation_item_relative_url.push(''); key: gadget.state.key,
field_json.default.push(''); view: gadget.state.view,
} url: gadget.state.url,
gadget.props.gadget_list.push(relation_input); allow_creation: gadget.state.allow_creation,
return relation_input.render({field_json: gadget.props.field_json}, { portal_types: gadget.state.portal_types,
index: index, value_relative_url: value_relative_url,
addRelationInput: true value_text: value_text,
value_uid: value_uid,
value_portal_type: value_portal_type,
relation_index: index
}); });
}) })
.push(function () { .push(function () {
container.appendChild(fieldset); gadget.element.appendChild(input_gadget.element);
}); });
}) }
rJS(window)
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareMethod('render', function (options) { .declareMethod('render', function (options) {
var field_json = options.field_json || {},
state_dict = {
editable: field_json.editable,
query: field_json.query,
catalog_index: field_json.catalog_index,
allow_jump: field_json.allow_jump,
required: field_json.required,
title: field_json.title,
key: field_json.key,
view: field_json.view,
url: field_json.url,
allow_creation: field_json.allow_creation,
portal_types: field_json.portal_types,
relation_field_id: field_json.relation_field_id
};
if (field_json.default.hasOwnProperty('value_text_list')) {
//load non saved value
state_dict.value_relative_url_list =
JSON.stringify(field_json.default.value_relative_url_list);
state_dict.value_text_list =
JSON.stringify(field_json.default.value_text_list);
state_dict.value_uid_list =
JSON.stringify(field_json.default.value_uid_list);
state_dict.value_portal_type_list =
JSON.stringify(field_json.default.value_portal_type_list);
} else {
state_dict.value_relative_url_list =
JSON.stringify(field_json.relation_item_relative_url);
state_dict.value_text_list =
JSON.stringify(field_json.default);
state_dict.value_uid_list = JSON.stringify([]);
state_dict.value_portal_type_list = JSON.stringify([]);
}
return this.changeState(state_dict);
})
.onStateChange(function () {
var gadget = this, var gadget = this,
i, i,
list = [], queue = new RSVP.Queue(),
fieldset, element = gadget.element,
container = gadget.props.element.querySelector('.container'), value_relative_url_list =
field_json = options.field_json || {}, JSON.parse(gadget.state.value_relative_url_list),
relation_item_relative_url; value_text_list =
gadget.props.field_json = field_json; JSON.parse(gadget.state.value_text_list),
if (field_json.default.value) { value_uid_list =
if (field_json.default.relation_item_relative_url[field_json.default.relation_item_relative_url.length - 1]) { JSON.parse(gadget.state.value_uid_list),
//return form listbox value_portal_type_list =
field_json.default.value.push(""); JSON.parse(gadget.state.value_portal_type_list);
field_json.default.relation_item_relative_url.push("");
}
relation_item_relative_url = field_json.default.relation_item_relative_url; // Always display an empty value at the end
} else { value_relative_url_list.push("");
field_json.relation_item_relative_url.push(''); value_text_list.push("");
field_json.default.push('');
relation_item_relative_url = field_json.relation_item_relative_url; // Clear first to DOM, append after to reduce flickering/manip
} while (element.firstChild) {
for (i = 0; i < relation_item_relative_url.length; i += 1) { element.removeChild(element.firstChild);
fieldset = document.createElement("fieldset"); }
container.appendChild(fieldset);
list.push(gadget.declareGadget('gadget_erp5_relation_input.html', { function enQueue() {
element: fieldset var argument_list = arguments;
})); queue
}
return new RSVP.Queue()
.push(function () { .push(function () {
return RSVP.all(list); return addRelationInput.apply(this, argument_list);
})
.push(function (gadget_list) {
list = [];
gadget.props.gadget_list = gadget_list;
for (i = 0; i < gadget_list.length; i += 1) {
list.push(gadget_list[i].render(options, {
index: i,
addRelationInput: (i === gadget_list.length - 1)
}));
}
return RSVP.all(list);
}); });
}
for (i = 0; i < value_relative_url_list.length; i += 1) {
enQueue(gadget, value_relative_url_list[i], value_text_list[i],
value_uid_list[i], value_portal_type_list[i], i);
}
return queue;
}) })
.declareMethod('getContent', function (options) {
var list = [], .declareAcquiredMethod("notifyChange", "notifyChange")
i, .allowPublicAcquisition('notifyChange', function (argument_list, scope) {
gadget = this, // An empty relation should be created when the last one is modified
length = gadget.props.gadget_list.length; // An empty relation should be removed
if (options.format === 'erp5') {
length -= 1; var gadget = this,
sub_gadget;
return gadget.getDeclaredGadget(scope)
.push(function (result) {
sub_gadget = result;
return sub_gadget.getContent();
})
.push(function (result) {
var value = result.value_text;
if (sub_gadget.element === gadget.element.lastChild) {
if (value) {
return addRelationInput(gadget, '', '', undefined, undefined,
gadget.element.childNodes.length);
}
/*
} else {
if (!value) {
gadget.element.removeChild(sub_gadget.element);
} }
for (i = 0; i < length; i += 1) { */
list.push(gadget.props.gadget_list[i].getContent(options, {"type": "MultiRelationField"}));
} }
return new RSVP.Queue() })
.push(function () { .push(function () {
return RSVP.all(list); return gadget.notifyChange();
});
}) })
.declareMethod('getContent', function (options) {
var i,
element = this.element,
queue = new RSVP.Queue(),
final_result = {},
result_list = [],
gadget = this;
function calculateSubContent(node) {
queue
.push(function () {
var scope = node.getAttribute('data-gadget-scope');
if (scope !== null) {
return gadget.getDeclaredGadget(
node.getAttribute('data-gadget-scope')
)
.push(function (result) { .push(function (result) {
var tmp = {}, return result.getContent();
key, })
key1; .push(function (result) {
for (i = 0; i < result.length; i += 1) { result_list.push(result);
for (key in result[i]) { });
if (result[i].hasOwnProperty(key)) {
if (options.format === 'erp5') {
if (tmp[key] === undefined) {
tmp[key] = [];
}
tmp[key].push(result[i][key]);
} else {
if (tmp[key] === undefined) {
tmp[key] = {};
} }
for (key1 in result[i][key]) { });
if (result[i][key].hasOwnProperty(key1)) {
if (tmp[key][key1] === undefined) {
tmp[key][key1] = [];
} }
tmp[key][key1].push(result[i][key][key1][0]);
if (this.state.editable) {
for (i = 0; i < element.childNodes.length; i += 1) {
calculateSubContent(element.childNodes[i]);
} }
return queue
.push(function () {
var result = {},
j,
k = 0,
input_result;
if (options.format === "erp5") {
result[gadget.state.key] = [];
} else {
result[gadget.state.key] = {
value_text_list: [],
value_relative_url_list: [],
value_portal_type_list: [],
value_uid_list: []
};
}
for (j = 0; j < result_list.length; j += 1) {
input_result = result_list[j];
if (options.format === "erp5") {
if (input_result.hasOwnProperty('value_text')) {
if (input_result.value_text) {
if (input_result.value_portal_type) {
result[gadget.state.relation_field_id + '_' + k] =
"_newContent_" + input_result.value_portal_type;
} }
result[gadget.state.key].push(input_result.value_text);
} }
} }
k += 1;
} else {
result[gadget.state.key].value_text_list
.push(input_result.value_text);
result[gadget.state.key].value_relative_url_list
.push(input_result.value_relative_url);
result[gadget.state.key].value_portal_type_list
.push(input_result.value_portal_type);
result[gadget.state.key].value_uid_list.push(undefined);
} }
} }
return tmp; return result;
}); });
}
return final_result;
}); });
}(window, rJS, RSVP, document)); }(window, rJS, RSVP, document));
\ No newline at end of file
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>952.33012.29157.25361</string> </value> <value> <string>954.57674.49472.38673</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1468331865.64</float> <float>1477584183.47</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" /> <meta name="viewport" content="width=device-width, user-scalable=no" />
<title>ERP5 Relationstringfield</title> <title>ERP5 Relation Input</title>
<script src="rsvp.js" type="text/javascript"></script> <script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script> <script src="renderjs.js" type="text/javascript"></script>
<script src="jiodev.js" type="text/javascript"></script> <script src="jiodev.js" type="text/javascript"></script>
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
</script> </script>
<script id="relation-input-template" type="text/x-handlebars-template"> <script id="relation-input-template" type="text/x-handlebars-template">
<div class="relation-input ui-input-text ui-body-inherit ui-corner-all ui-shadow-inset ui-input-has-clear ui-input-has-icon {{readonly}}"> <div class="relation-input ui-input-text ui-body-inherit ui-corner-all ui-shadow-inset ui-input-has-clear ui-input-has-icon">
<div> <div>
<input type='search' title="{{title}}" name="{{name}}" autocomplete="off" {{{input_readonly}}} data-enhanced="true" value="{{value}}" > <input type='search' title="{{title}}" name="{{name}}" autocomplete="off" data-enhanced="true" value="{{value}}" >
<ul class="ui-listview ui-corner-all search_ul"></ul> <ul class="ui-listview ui-corner-all search_ul"></ul>
</div> </div>
<a href={{href}} tabindex="-1" class="{{class_name}}" >Jump to this document</a> <a href={{href}} tabindex="-1" class="{{class_name}}" >Jump to this document</a>
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>954.45675.44850.53452</string> </value> <value> <string>954.54399.20164.63317</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1476956228.04</float> <float>1477475951.1</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint indent: 2, maxerr: 3, nomen: true */ /*jslint indent: 2, maxerr: 3, nomen: true, maxlen: 80 */
/*global window, rJS, RSVP, URI, loopEventListener, Handlebars, /*global window, rJS, RSVP, URI, Handlebars,
SimpleQuery, ComplexQuery, Query, QueryFactory, promiseEventListener*/ SimpleQuery, ComplexQuery, Query, QueryFactory, promiseEventListener*/
(function (window, rJS, RSVP, URI, loopEventListener, promiseEventListener, (function (window, rJS, RSVP, URI, promiseEventListener,
SimpleQuery, ComplexQuery, Query, QueryFactory, Handlebars) { SimpleQuery, ComplexQuery, Query, QueryFactory, Handlebars) {
"use strict"; "use strict";
...@@ -21,37 +21,43 @@ ...@@ -21,37 +21,43 @@
relation_listview_source = gadget_klass.__template_element relation_listview_source = gadget_klass.__template_element
.getElementById("relation-listview-template") .getElementById("relation-listview-template")
.innerHTML, .innerHTML,
relation_listview_template = Handlebars.compile(relation_listview_source), relation_listview_template = Handlebars.compile(relation_listview_source);
searching = "ui-btn ui-corner-all ui-btn-icon-notext" + function displayNonEditableLink(gadget) {
" ui-input-clear ui-icon-spinner ui-icon-spin", return gadget.getUrlFor({
jump_on = "ui-btn ui-corner-all ui-btn-icon-notext " + command: 'index',
"ui-icon-plane ui-shadow-inset ui-btn-inline", options: {
jump_off = "ui-btn ui-corner-all ui-btn-icon-notext " + jio_key: gadget.state.value_relative_url
"ui-icon-plane ui-shadow-inset ui-btn-inline ui-disabled", }
jump_add = "ui-btn ui-corner-all ui-btn-icon-notext " + })
"ui-icon-plus ui-shadow-inset ui-btn-inline ui-disabled", .push(function (href) {
jump_unknown = "ui-btn ui-corner-all ui-btn-icon-notext " + // XXX Use html5 element gadget
"ui-icon-warning ui-shadow-inset ui-btn-inline ui-disabled"; gadget.element.innerHTML = relation_link_template({
value: gadget.state.value_text,
href: href
});
});
}
rJS(window) function displayNonEditableText(gadget) {
gadget.element.textContent = gadget.state.value_text;
}
///////////////////////////////////////////////////////////////// function displayEditableLink(gadget, class_name) {
// ready return gadget.translateHtml(relation_input_template({
///////////////////////////////////////////////////////////////// href: "#",
// Init local properties value: gadget.state.value_text,
.ready(function (my_gadget) { title: gadget.state.title,
my_gadget.props = { name: gadget.state.key,
input_deferred: RSVP.defer() class_name: class_name
}; }))
return my_gadget.getElement() .push(function (html) {
.push(function (element) { gadget.element.innerHTML = html;
my_gadget.props.element = element;
}); });
}) }
gadget_klass
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// acquired methods // acquired methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -62,375 +68,335 @@ ...@@ -62,375 +68,335 @@
.declareAcquiredMethod("redirect", "redirect") .declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("getFormContent", "getFormContent") .declareAcquiredMethod("getFormContent", "getFormContent")
.declareAcquiredMethod("translateHtml", "translateHtml") .declareAcquiredMethod("translateHtml", "translateHtml")
.declareAcquiredMethod("addRelationInput", "addRelationInput") // .declareAcquiredMethod("addRelationInput", "addRelationInput")
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareMethod('render', function (options, options2) { .declareMethod('render', function (options) {
var state_dict = {
editable: options.editable,
query: options.query,
catalog_index: options.catalog_index,
allow_jump: options.allow_jump,
// required: field_json.required,
title: options.title,
key: options.key,
view: options.view,
url: options.url,
allow_creation: options.allow_creation,
portal_types: options.portal_types,
has_focus: false,
relation_index: options.relation_index,
value_relative_url: options.value_relative_url,
value_uid: options.value_uid,
value_text: options.value_text,
value_portal_type: options.value_portal_type
};
return this.changeState(state_dict);
})
.onStateChange(function (modification_dict) {
var gadget = this, var gadget = this,
field_json = options.field_json || {},
target_url,
queue = new RSVP.Queue(), queue = new RSVP.Queue(),
create_object, value_text = gadget.state.value_text,
unknown, // target_url,
relation_item_relative_url, SEARCHING_CLASS_STR = "ui-btn ui-corner-all ui-btn-icon-notext" +
uid, " ui-input-clear ui-icon-spinner ui-icon-spin",
value = "", JUMP_ON_CLASS_STR = "ui-btn ui-corner-all ui-btn-icon-notext " +
not_selected = true, "ui-icon-plane ui-shadow-inset ui-btn-inline",
index = options2.index || 0; JUMP_OFF_CLASS_STR = "ui-btn ui-corner-all ui-btn-icon-notext " +
gadget.props.field_json = field_json; "ui-icon-plane ui-shadow-inset ui-btn-inline ui-disabled",
JUMP_ADD_CLASS_STR = "ui-btn ui-corner-all ui-btn-icon-notext " +
if (!field_json.editable) { "ui-icon-plus ui-shadow-inset ui-btn-inline ui-disabled",
if (field_json.relation_item_relative_url) { JUMP_UNKNOWN_CLASS_STR = "ui-btn ui-corner-all ui-btn-icon-notext " +
return gadget.getUrlFor({ "ui-icon-warning ui-shadow-inset ui-btn-inline ui-disabled";
command: 'index',
options: { // Non editable
jio_key: field_json.relation_item_relative_url[index] if (!gadget.state.editable) {
} if ((gadget.state.value_relative_url) && (gadget.state.allow_jump)) {
}) return displayNonEditableLink(gadget);
.push(function (href) {
gadget.props.element.innerHTML = relation_link_template({
value: field_json.default[index] || "",
href: href
});
});
} }
return; return displayNonEditableText(gadget);
} }
gadget.props.index = index; if (modification_dict.hasOwnProperty('editable')) {
gadget.props.addRelationInput = options2.addRelationInput; // First display of the input
if (field_json.default.value) { queue.push(function () {
//load non saved value return displayEditableLink(gadget, JUMP_UNKNOWN_CLASS_STR);
create_object = field_json.default.create_object ? field_json.default.create_object[index] : false; });
unknown = field_json.default.jump_unknown ? field_json.default.jump_unknown[index] : false;
relation_item_relative_url = field_json.default.relation_item_relative_url || [];
uid = field_json.default.uid;
value = field_json.default.value[index] || "";
} else {
create_object = field_json.create_object ? field_json.create_object[index] : false;
unknown = field_json.jump_unknown ? field_json.jump_unknown[index] : false;
relation_item_relative_url = field_json.relation_item_relative_url;
uid = field_json.uid;
value = field_json.default[index] || "";
}
gadget.props.jump_url = [relation_item_relative_url[index]];
if (relation_item_relative_url) {
target_url = relation_item_relative_url[index];
} }
gadget.props.query = QueryFactory.create(new URI(field_json.query).query(true).query);
gadget.props.create_object_type = create_object; return queue
if (!value && target_url && uid) {
//return from listbox
not_selected = false;
queue
.push(function () { .push(function () {
var plane = gadget.element.querySelector("a"),
ul = gadget.element.querySelector(".search_ul"),
input = gadget.element.querySelector("input");
ul.innerHTML = "";
plane.href = '';
if (input.value !== gadget.state.value_text) {
input.value = gadget.state.value_text;
}
// uid is known
// User selected a document from a listbox
if (gadget.state.value_uid) {
plane.className = SEARCHING_CLASS_STR;
return gadget.jio_allDocs({ return gadget.jio_allDocs({
"query": Query.objectToSearchText(new SimpleQuery({ "query": Query.objectToSearchText(new SimpleQuery({
key: "catalog.uid", key: "catalog.uid",
value: uid, value: gadget.state.value_uid,
limit: [0, 1] limit: [0, 1]
})), })),
"select_list": [field_json.catalog_index] "select_list": [gadget.state.catalog_index]
});
}) })
.push(function (result) { .push(function (result) {
value = result.data.rows[0].value[field_json.catalog_index]; return gadget.changeState({
value_text: result.data.rows[0]
.value[gadget.state.catalog_index],
value_uid: null
});
}); });
} }
if (target_url) {
queue
.push(function () { // Expected portal type has been selected.
// User want to create a new document
if (gadget.state.value_portal_type) {
plane.className = JUMP_ADD_CLASS_STR;
return;
}
// Relative URL is known. Display plane icon
if (gadget.state.value_relative_url) {
if (gadget.state.allow_jump) {
return gadget.getUrlFor({ return gadget.getUrlFor({
command: 'index', command: 'index',
options: { options: {
jio_key: target_url jio_key: gadget.state.value_relative_url
}
});
});
}
queue
.push(function (href) {
var class_name,
jump_href = '#';
if (create_object) {
class_name = jump_add;
} else {
if ((field_json.error_text || unknown) && not_selected) {
class_name = jump_unknown;
} else {
if (href) {
if (field_json.allow_jump) {
jump_href = href;
class_name = jump_on;
} else {
class_name = jump_off;
}
} else {
class_name = jump_off;
} }
}
}
return gadget.translateHtml(relation_input_template({
href: jump_href,
create_object: create_object,
readonly: field_json.editable ? "" : "ui-state-readonly",
input_readonly: field_json.editable ? "" : 'readonly="readonly"',
required: field_json.required ? "required" : "",
value: value,
title: field_json.title,
name: field_json.key,
class_name: class_name
}));
}) })
.push(function (html) { .push(function (url) {
gadget.props.element.innerHTML = html; plane.href = url;
gadget.props.input = plane.className = JUMP_ON_CLASS_STR;
gadget.props.element.querySelector("input");
gadget.props.new_tag_div = gadget.props.element.querySelector(".new_tag");
gadget.props.spinner = gadget.props.element.querySelector("a");
gadget.props.plane = gadget.props.element.querySelector("a");
gadget.props.input_deferred.resolve();
}); });
return queue;
})
.declareMethod('getContent', function (options, options2) {
var element = this.props.element.querySelector('input'),
result = {},
tmp = {},
field_json = this.props.field_json;
if (!field_json.editable) {
return {};
} }
if (options.format === "erp5") {
if (this.props.plane.className === jump_add) { if (modification_dict.hasOwnProperty('value_text')) {
if (options2 && options2.type === 'MultiRelationField') { plane.className = JUMP_UNKNOWN_CLASS_STR;
result[field_json.relation_field_id + '_' + this.props.index] = "_newContent_" + this.props.create_object_type;
} else { } else {
result[field_json.relation_field_id] = "_newContent_" + this.props.create_object_type; plane.className = JUMP_OFF_CLASS_STR;
}
} }
result[element.getAttribute('name')] = element.value; return;
return result;
}
tmp.value = [element.value];
tmp.create_object = [""];
tmp.jump_unknown = [""];
tmp.relation_item_relative_url = [""];
if (this.props.plane.className === jump_add) {
tmp.create_object = [this.props.create_object_type];
} else {
if (this.props.plane.className === jump_unknown) {
tmp.jump_unknown = [true];
} else {
tmp.relation_item_relative_url = this.props.jump_url;
} }
// No text, user want to delete the content
if (!gadget.state.value_text) {
plane.className = JUMP_OFF_CLASS_STR;
return;
} }
result[element.getAttribute('name')] = tmp;
return result;
})
///////////////////////////////////////////////////////////////// // User entered text, but didn't select
// declared services // from the list
///////////////////////////////////////////////////////////////// if (!gadget.state.has_focus) {
.declareService(function () { plane.className = JUMP_UNKNOWN_CLASS_STR;
var gadget = this,
props = gadget.props,
input,
search_query,
simple_query,
field_json = props.field_json,
ul;
function generateList(event) {
var index = field_json.catalog_index,
begin_from = props.begin_from || 0,
lines = field_json.lines || 10,
my_value = event.target.value;
props.plane.className = jump_off;
props.jump_url = [];
ul.innerHTML = "";
if (my_value === "") {
props.spinner.className = jump_off;
return; return;
} }
simple_query = new SimpleQuery({
key: index, // User typed some text.
value: my_value // Propose some documents in a list
}); plane.className = SEARCHING_CLASS_STR;
props.spinner.className = searching;
search_query = Query.objectToSearchText(new ComplexQuery({
operator: "AND",
query_list: [gadget.props.query, simple_query]
}));
return new RSVP.Queue() return new RSVP.Queue()
.push(function () {
// Wait a bit before launching the catalog query
// as user may still type new characters
return RSVP.delay(200);
})
.push(function () { .push(function () {
return gadget.jio_allDocs({ return gadget.jio_allDocs({
"query": search_query, query: Query.objectToSearchText(new ComplexQuery({
"limit": [begin_from, begin_from + lines], operator: "AND",
"select_list": [index] query_list: [
QueryFactory.create(
new URI(gadget.state.query).query(true).query
),
new SimpleQuery({
key: gadget.state.catalog_index,
value: value_text
})
]
})),
limit: [0, 10],
select_list: [gadget.state.catalog_index]
}); });
}) })
.push(function (result) { .push(function (result) {
var list = [], var list = [],
i, i,
type = field_json.allow_creation ? field_json.portal_types : [], type;
html; if (gadget.state.allow_creation) {
type = gadget.state.portal_types;
} else {
type = [];
}
for (i = 0; i < result.data.rows.length; i += 1) { for (i = 0; i < result.data.rows.length; i += 1) {
list.push({ list.push({
id: result.data.rows[i].id, id: result.data.rows[i].id,
value: result.data.rows[i].value[index] value: result.data.rows[i].value[gadget.state.catalog_index]
}); });
} }
props.spinner.className = jump_off; plane.className = JUMP_UNKNOWN_CLASS_STR;
html = relation_listview_template({ ul.innerHTML = relation_listview_template({
list: list, list: list,
type: type, type: type,
value: my_value value: value_text
});
}); });
ul.innerHTML = html;
}); });
}
})
function setSelectedElement(event) {
var element = event.target,
jump_url = element.getAttribute("data-relative-url"),
create_object_type = element.getAttribute("data-create-object"),
explore = element.getAttribute("data-explore");
ul.innerHTML = "";
if (jump_url) { .declareMethod('getContent', function () {
props.input.value = element.textContent; var gadget = this,
props.jump_url = [jump_url]; result = {};
return gadget.getUrlFor({
command: 'index', if (gadget.state.editable) {
options: { result = {
jio_key: jump_url value_relative_url: gadget.state.value_relative_url,
value_text: gadget.state.value_text,
value_portal_type: gadget.state.value_portal_type
};
} }
}).push(function (url) { return result;
if (field_json.allow_jump) { })
props.plane.href = url;
props.plane.className = jump_on;
/////////////////////////////////////////////////////////////////
// declared services
/////////////////////////////////////////////////////////////////
.onEvent('blur', function () {
var gadget = this,
ul,
new_state = {
has_focus: false
};
if (!gadget.state.editable) {
return;
} }
});
ul = gadget.element.querySelector(".search_ul");
return new RSVP.Queue()
.push(function () {
return RSVP.any([
new RSVP.Queue()
.push(function () {
return RSVP.delay(200);
})
.push(function () {
return gadget.changeState(new_state);
}),
new RSVP.Queue()
.push(function () {
return promiseEventListener(ul, "click", true);
})
.push(function (event) {
// Check which 'li' element was clicked
var li = event.target,
data_relative_url = li.getAttribute("data-relative-url"),
data_portal_type = li.getAttribute("data-create-object"),
data_explore = li.getAttribute("data-explore");
// User want to create a new document
if (data_portal_type) {
new_state.value_portal_type = data_portal_type;
return gadget.changeState(new_state);
} }
if (create_object_type) {
gadget.props.create_object_type = create_object_type; // User selected an existing document
props.plane.className = jump_add; if (data_relative_url) {
return; new_state.value_text = li.textContent;
new_state.value_relative_url = data_relative_url;
return gadget.changeState(new_state);
} }
if (explore) {
// Go to the search listbox
if (data_explore) {
return gadget.getFormContent({ return gadget.getFormContent({
format: "json" format: "json"
}) })
.push(function (content) { .push(function (content) {
var input = gadget.element.querySelector('input');
return gadget.redirect({ return gadget.redirect({
command: 'index', command: 'index',
options: { options: {
page: "relation_search", page: "relation_search",
url: gadget.props.field_json.url, url: gadget.state.url,
extended_search: Query.objectToSearchText(simple_query), extended_search: Query.objectToSearchText(
view: gadget.props.field_json.view, new SimpleQuery({
back_field: gadget.props.field_json.key, key: gadget.state.catalog_index,
target_index: gadget.props.index value: input.value
})
),
view: gadget.state.view,
back_field: gadget.state.key,
relation_index: gadget.state.relation_index
}, },
form_content: content form_content: content
}); });
}); });
} }
props.plane.className = jump_unknown;
}
return new RSVP.Queue() // No idea what has been clicked...
.push(function () { return gadget.changeState({
return gadget.props.input_deferred.promise; has_focus: false
});
}) })
.push(function () {
input = gadget.props.element.querySelector('input');
ul = gadget.props.element.querySelector(".search_ul");
return RSVP.all([
loopEventListener(input, 'input', false, generateList),
loopEventListener(input, 'blur', false, function () {
return new RSVP.Queue()
.push(function () {
return RSVP.any([
RSVP.delay(200),
promiseEventListener(ul, "click", true)
]); ]);
}) })
.push(function (event) {
var queue = new RSVP.Queue();
if (event) {
queue
.push(function () { .push(function () {
return setSelectedElement(event); return gadget.notifyChange();
});
}
if (ul.innerHTML) {
ul.innerHTML = "";
props.plane.className = jump_unknown;
if (gadget.props.addRelationInput) {
gadget.props.addRelationInput = false;
queue.push(function () {
return gadget.addRelationInput();
});
}
}
return queue;
});
})]);
}); });
}) }, true, false)
.declareService(function () {
var gadget = this;
function notifyInvalid(evt) { .declareMethod('checkValidity', function () {
return gadget.notifyInvalid(evt.target.validationMessage); return true;
}
return new RSVP.Queue()
.push(function () {
return gadget.props.input_deferred.promise;
})
.push(function () {
// Listen to input change
return loopEventListener(
gadget.props.element.querySelector('input'),
'invalid',
false,
notifyInvalid
);
});
}) })
.declareService(function () { // XXX Use html5 input
//////////////////////////////////// .onEvent('invalid', function (evt) {
// Check field validity when the value changes // invalid event does not bubble
//////////////////////////////////// return this.notifyInvalid(evt.target.validationMessage);
var gadget = this; }, true, false)
function notifyChange() { .onEvent('change', function () {
return gadget.notifyChange(); return RSVP.all([
this.checkValidity(),
this.notifyChange()
]);
}, false, false)
.onEvent('input', function (event) {
if (!this.state.editable) {
return;
} }
return new RSVP.Queue()
.push(function () { return this.changeState({
return gadget.props.input_deferred.promise; value_text: event.target.value,
}) value_relative_url: null,
.push(function () { value_uid: null,
return loopEventListener( value_portal_type: null,
gadget.props.element.querySelector('input'), has_focus: true
'change',
false,
notifyChange
);
});
}); });
}, true, false);
}(window, rJS, RSVP, URI, loopEventListener, promiseEventListener, }(window, rJS, RSVP, URI, promiseEventListener,
SimpleQuery, ComplexQuery, Query, QueryFactory, Handlebars)); SimpleQuery, ComplexQuery, Query, QueryFactory, Handlebars));
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>953.41070.65129.47718</string> </value> <value> <string>954.57692.7289.25070</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1472800801.64</float> <float>1477583820.22</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint indent: 2, maxerr: 3, nomen: true */ /*jslint indent: 2, maxerr: 3, nomen: true, maxlen: 80 */
/*global window, rJS */ /*global window, rJS */
(function (window, rJS) { (function (window, rJS) {
"use strict"; "use strict";
rJS(window) rJS(window)
.allowPublicAcquisition("addRelationInput", function () {
return;
})
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// declared methods // declared methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareMethod('render', function (options) { .declareMethod('render', function (options) {
var gadget = this,
field_json = options.field_json || {};
return this.getDeclaredGadget("relation_input") return this.getDeclaredGadget("relation_input")
.push(function (gadget) { .push(function (gadget) {
return gadget.render(options, {index: 0}); var render_options = {
editable: field_json.editable,
query: field_json.query,
catalog_index: field_json.catalog_index,
allow_jump: field_json.allow_jump,
// required: field_json.required,
title: field_json.title,
key: field_json.key,
view: field_json.view,
url: field_json.url,
allow_creation: field_json.allow_creation,
portal_types: field_json.portal_types,
value_relative_url: field_json.relation_item_relative_url[0],
relation_index: 0
};
if (field_json.default.hasOwnProperty('value_text_list')) {
//load non saved value
render_options.value_relative_url =
field_json.default.value_relative_url_list[0];
render_options.value_uid =
field_json.default.value_uid_list[0];
render_options.value_text =
field_json.default.value_text_list[0];
render_options.value_portal_type =
field_json.default.value_portal_type_list[0];
} else {
render_options.value_text = field_json.default[0] || "";
}
return gadget.render(render_options);
})
.push(function () {
return gadget.changeState({
key: options.field_json.key,
relation_field_id: options.field_json.relation_field_id
});
}); });
}) })
.declareMethod('getContent', function (options) { .declareMethod('getContent', function (options) {
var gadget = this;
return this.getDeclaredGadget("relation_input") return this.getDeclaredGadget("relation_input")
.push(function (gadget) { .push(function (input_gadget) {
return gadget.getContent(options); return input_gadget.getContent();
})
.push(function (input_result) {
var result = {};
if (!input_result.hasOwnProperty('value_text')) {
return result;
}
if (options.format === "erp5") {
if (input_result.value_portal_type) {
result[gadget.state.relation_field_id] =
"_newContent_" + input_result.value_portal_type;
}
result[gadget.state.key] = input_result.value_text;
} else {
result[gadget.state.key] = {
value_text_list: [input_result.value_text],
value_relative_url_list: [input_result.value_relative_url],
value_portal_type_list: [input_result.value_portal_type],
value_uid_list: [undefined]
};
}
return result;
}); });
}); });
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>954.45675.44850.53452</string> </value> <value> <string>954.57675.64427.52462</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1477037965.54</float> <float>1477582815.99</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -446,7 +446,7 @@ ...@@ -446,7 +446,7 @@
function execHistoryPreviousCommand(gadget, previous_options, load_options) { function execHistoryPreviousCommand(gadget, previous_options, load_options) {
var history = previous_options.history, var history = previous_options.history,
jio_key = previous_options.jio_key, jio_key = previous_options.jio_key,
target_index = previous_options.target_index, relation_index = previous_options.relation_index,
field = previous_options.back_field, field = previous_options.back_field,
queue = new RSVP.Queue(), queue = new RSVP.Queue(),
previous_id; previous_id;
...@@ -473,9 +473,9 @@ ...@@ -473,9 +473,9 @@
if (results) { if (results) {
results = JSON.parse(results.target.result); results = JSON.parse(results.target.result);
if (load_options.uid) { if (load_options.uid) {
results[field].value[target_index] = ""; results[field].value_text_list[relation_index] = "";
results[field].relation_item_relative_url[target_index] = load_options.jio_key; results[field].value_relative_url_list[relation_index] = load_options.jio_key;
results[field].uid = load_options.uid; results[field].value_uid_list[relation_index] = load_options.uid;
} }
gadget.props.form_content = results; gadget.props.form_content = results;
} }
...@@ -491,8 +491,8 @@ ...@@ -491,8 +491,8 @@
return gadget.props.jio_gadget.get(history.options_id); return gadget.props.jio_gadget.get(history.options_id);
}) })
.push(function (result) { .push(function (result) {
var result_list = [result, previous_id]; var result_list = [result, previous_id],
var options = result_list[0].data, options = result_list[0].data,
next_jio_key = options.jio_key; next_jio_key = options.jio_key;
delete options.jio_key; delete options.jio_key;
return addNavigationHistoryAndDisplay(gadget, next_jio_key, options); return addNavigationHistoryAndDisplay(gadget, next_jio_key, options);
......
...@@ -232,7 +232,7 @@ ...@@ -232,7 +232,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>954.47260.43395.7014</string> </value> <value> <string>954.57620.63396.46779</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -250,7 +250,7 @@ ...@@ -250,7 +250,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1476957907.92</float> <float>1477580291.06</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
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