slapos_jio: rewrite JSON editor
* jslint * drop duplicated loopEventListener * use rjs.onEvent method to reduce the number of created listeners * use domsugar to make the code more readable * start to use mutex
Showing
/*jslint nomen: true, maxlen: 200, indent: 2*/ | /*jslint nomen: true, maxlen: 200, indent: 2, unparam: true*/ | ||
/*global rJS, console, window, document, RSVP, btoa, atob, $, XMLSerializer, jQuery, URI, vkbeautify */ | /*global rJS, console, window, document, RSVP, btoa, atob, $, XMLSerializer, | ||
jQuery, URI, vkbeautify, domsugar, Boolean */ | |||
(function (window, document, rJS, $, XMLSerializer, jQuery, vkbeautify) { | (function (window, document, rJS, $, XMLSerializer, jQuery, vkbeautify, | ||
loopEventListener, domsugar, Boolean) { | |||
"use strict"; | "use strict"; | ||
var gk = rJS(window); | var DISPLAY_JSON_FORM = 'display_json_form', | ||
DISPLAY_RAW_XML = 'display_raw_xml'; | |||
function jsonDictToParameterXML(json) { | function jsonDictToParameterXML(json) { | ||
var parameter_id, | var parameter_id, | ||
xml_output = $($.parseXML('<?xml version="1.0" encoding="utf-8" ?><instance />')); | xml_output = $($.parseXML('<?xml version="1.0" encoding="UTF-8" ?>\n<instance />')); | ||
// Used by serialisation XML | // Used by serialisation XML | ||
for (parameter_id in json) { | for (parameter_id in json) { | ||
if (json.hasOwnProperty(parameter_id)) { | if (json.hasOwnProperty(parameter_id)) { | ||
... | @@ -25,7 +28,7 @@ | ... | @@ -25,7 +28,7 @@ |
} | } | ||
function jsonDictToParameterJSONInXML(json) { | function jsonDictToParameterJSONInXML(json) { | ||
var xml_output = $($.parseXML('<?xml version="1.0" encoding="utf-8" ?><instance />')); | var xml_output = $($.parseXML('<?xml version="1.0" encoding="UTF-8" ?>\n<instance />')); | ||
// Used by serialisation XML | // Used by serialisation XML | ||
$('instance', xml_output).append( | $('instance', xml_output).append( | ||
$('<parameter />', xml_output) | $('<parameter />', xml_output) | ||
... | @@ -37,133 +40,68 @@ | ... | @@ -37,133 +40,68 @@ |
); | ); | ||
} | } | ||
function loopEventListener(target, type, useCapture, callback, | |||
prevent_default) { | |||
////////////////////////// | |||
// Infinite event listener (promise is never resolved) | |||
// eventListener is removed when promise is cancelled/rejected | |||
////////////////////////// | |||
var handle_event_callback, | |||
callback_promise; | |||
if (prevent_default === undefined) { | |||
prevent_default = true; | |||
} | |||
function cancelResolver() { | |||
if ((callback_promise !== undefined) && | |||
(typeof callback_promise.cancel === "function")) { | |||
callback_promise.cancel(); | |||
} | |||
} | |||
function canceller() { | |||
if (handle_event_callback !== undefined) { | |||
target.removeEventListener(type, handle_event_callback, useCapture); | |||
} | |||
cancelResolver(); | |||
} | |||
function itsANonResolvableTrap(resolve, reject) { | |||
var result; | |||
handle_event_callback = function (evt) { | |||
if (prevent_default) { | |||
evt.stopPropagation(); | |||
evt.preventDefault(); | |||
} | |||
cancelResolver(); | |||
try { | |||
result = callback(evt); | |||
} catch (e) { | |||
result = RSVP.reject(e); | |||
} | |||
callback_promise = result; | |||
new RSVP.Queue() | |||
.push(function () { | |||
return result; | |||
}) | |||
.push(undefined, function (error) { | |||
if (!(error instanceof RSVP.CancellationError)) { | |||
canceller(); | |||
reject(error); | |||
} | |||
}); | |||
}; | |||
target.addEventListener(type, handle_event_callback, useCapture); | |||
} | |||
return new RSVP.Promise(itsANonResolvableTrap, canceller); | |||
} | |||
function render_selection(json_field, default_value) { | function render_selection(json_field, default_value) { | ||
var input = document.createElement("select"), | var option_list = [domsugar('option', { | ||
option = document.createElement("option"), | value: "", | ||
option_index, | selected: (default_value === undefined) | ||
optionz; | })], | ||
input.size = 1; | option_index; | ||
option.value = ""; | |||
if (default_value === undefined) { | |||
option.selected = true; | |||
} | |||
input.appendChild(option); | |||
for (option_index in json_field['enum']) { | for (option_index in json_field['enum']) { | ||
if (json_field['enum'].hasOwnProperty(option_index)) { | if (json_field['enum'].hasOwnProperty(option_index)) { | ||
optionz = document.createElement("option"); | option_list.push(domsugar('option', { | ||
optionz.value = json_field['enum'][option_index]; | value: json_field['enum'][option_index], | ||
optionz.textContent = json_field['enum'][option_index]; | text: json_field['enum'][option_index], | ||
if (json_field['enum'][option_index] === default_value) { | selected: (json_field['enum'][option_index] === default_value) | ||
optionz.selected = true; | })); | ||
} | |||
input.appendChild(optionz); | |||
} | } | ||
} | } | ||
return input; | return domsugar('select', { | ||
size: 1 | |||
}, option_list); | |||
} | } | ||
function render_selection_oneof(json_field, default_value) { | function render_selection_oneof(json_field, default_value) { | ||
var input = document.createElement("select"), | var option_list = [domsugar('option', { | ||
option = document.createElement("option"), | value: "", | ||
optionz; | selected: (default_value === undefined) | ||
input.size = 1; | })]; | ||
option.value = ""; | |||
if (default_value === undefined) { | json_field.oneOf.forEach(function (element) { | ||
option.selected = true; | |||
} | |||
input.appendChild(option); | |||
json_field.oneOf.forEach(function (element, index) { | |||
if ((element['const'] !== undefined) && (element.title !== undefined)) { | if ((element['const'] !== undefined) && (element.title !== undefined)) { | ||
var value; | var value; | ||
if ((json_field.type == 'array') || (json_field.type == 'object')) { | if ((json_field.type === 'array') || (json_field.type === 'object')) { | ||
// Support for unusual types | // Support for unusual types | ||
value = JSON.stringify(element['const']); | value = JSON.stringify(element['const']); | ||
} else { | } else { | ||
value = element['const']; | value = element['const']; | ||
} | } | ||
optionz = document.createElement("option"); | option_list.push(domsugar('option', { | ||
optionz.value = value; | value: value, | ||
optionz.textContent = element.title; | text: element.title, | ||
if (value === default_value) { | selected: (value === default_value) | ||
optionz.selected = true; | })); | ||
} | |||
input.appendChild(optionz); | |||
} | } | ||
}); | }); | ||
return input; | |||
return domsugar('select', { | |||
size: 1 | |||
}, option_list); | |||
} | } | ||
function render_textarea(json_field, default_value, data_format) { | function render_textarea(json_field, default_value, data_format) { | ||
var input = document.createElement("textarea"); | var value = ''; | ||
if (default_value !== undefined) { | if (default_value !== undefined) { | ||
if (default_value instanceof Array) { | if (default_value instanceof Array) { | ||
input.value = default_value.join("\n"); | value = default_value.join("\n"); | ||
} else { | } else { | ||
input.value = default_value; | value = default_value; | ||
} | } | ||
} | } | ||
input["data-format"] = data_format; | return domsugar('textarea', { | ||
return input; | value: value, | ||
"data-format": data_format | |||
}); | |||
} | } | ||
function render_field(json_field, default_value) { | function render_field(json_field, default_value) { | ||
... | @@ -195,23 +133,27 @@ | ... | @@ -195,23 +133,27 @@ |
return render_textarea(json_field, default_value, "string"); | return render_textarea(json_field, default_value, "string"); | ||
} | } | ||
var input = document.createElement("input"); | var value, | ||
type; | |||
if (default_value !== undefined) { | if (default_value !== undefined) { | ||
input.value = default_value; | value = default_value; | ||
} | } | ||
if (json_field.type === "integer") { | if (json_field.type === "integer") { | ||
input.type = "number"; | type = "number"; | ||
} else if (json_field.type === "number") { | } else if (json_field.type === "number") { | ||
input.type = "number"; | type = "number"; | ||
} else if (json_field.type === "hidden") { | } else if (json_field.type === "hidden") { | ||
input.type = "hidden"; | type = "hidden"; | ||
} else { | } else { | ||
input.type = "text"; | type = "text"; | ||
} | } | ||
return input; | return domsugar('input', { | ||
value: value, | |||
type: type | |||
}); | |||
} | } | ||
function render_subform(json_field, default_dict, root, path, restricted) { | function render_subform(json_field, default_dict, root, path, restricted) { | ||
... | @@ -219,7 +161,6 @@ | ... | @@ -219,7 +161,6 @@ |
key, | key, | ||
div, | div, | ||
label, | label, | ||
close_span, | |||
input, | input, | ||
default_value, | default_value, | ||
default_used_list = [], | default_used_list = [], | ||
... | @@ -238,54 +179,56 @@ | ... | @@ -238,54 +179,56 @@ |
if (json_field.patternProperties !== undefined) { | if (json_field.patternProperties !== undefined) { | ||
if (json_field.patternProperties['.*'] !== undefined) { | if (json_field.patternProperties['.*'] !== undefined) { | ||
div = document.createElement("div"); | div = domsugar("div", { | ||
div.setAttribute("class", "subfield"); | "class": "subfield", | ||
div.title = json_field.description; | title: json_field.description | ||
}); | |||
if (restricted !== true) { | if (restricted !== true) { | ||
div_input = domsugar("div", { | |||
div_input = document.createElement("div"); | "class": "input" | ||
div_input.setAttribute("class", "input"); | }, [ | ||
domsugar('input', { | |||
input = document.createElement("input"); | type: "text", | ||
input.type = "text"; | // Name is only meaningfull to automate tests | ||
// Name is only meaningfull to automate tests | name: "ADD" + path | ||
input.name = "ADD" + path; | }), | ||
div_input.appendChild(input); | domsugar('button', { | ||
value: btoa(JSON.stringify(json_field.patternProperties['.*'])), | |||
input = document.createElement("button"); | "class": "add-sub-form", | ||
input.value = btoa(JSON.stringify(json_field.patternProperties['.*'])); | type: "button", | ||
input.setAttribute("class", "add-sub-form"); | name: path, | ||
input.type = "button"; | text: "+" | ||
input.name = path; | }) | ||
input.textContent = "+"; | ]); | ||
div_input.appendChild(input); | |||
div.appendChild(div_input); | div.appendChild(div_input); | ||
} | } | ||
for (default_value in default_dict) { | for (default_value in default_dict) { | ||
if (default_dict.hasOwnProperty(default_value)) { | if (default_dict.hasOwnProperty(default_value)) { | ||
default_div = document.createElement("div"); | default_div = domsugar("div", { | ||
default_div.setAttribute("class", "slapos-parameter-dict-key"); | "class": "slapos-parameter-dict-key" | ||
label = document.createElement("label"); | }, [ | ||
label.textContent = default_value; | domsugar('label', { | ||
label.setAttribute("class", "slapos-parameter-dict-key"); | text: default_value, | ||
close_span = document.createElement("span"); | 'class': "slapos-parameter-dict-key" | ||
close_span.textContent = "×"; | }, [ | ||
close_span.setAttribute("class", "bt_close CLOSE" + path + "/" + default_value); | domsugar('span', { | ||
close_span.setAttribute("title", "Remove this parameter section."); | text: "×", | ||
label.appendChild(close_span); | "class": "bt_close CLOSE" + path + "/" + default_value, | ||
default_div.appendChild(label); | title: "Remove this parameter section." | ||
default_div = render_subform( | }) | ||
]) | |||
]); | |||
div.appendChild(render_subform( | |||
json_field.patternProperties['.*'], | json_field.patternProperties['.*'], | ||
default_dict[default_value], | default_dict[default_value], | ||
default_div, | default_div, | ||
path + "/" + default_value, | path + "/" + default_value, | ||
restricted | restricted | ||
); | )); | ||
div.appendChild(default_div); | |||
} | } | ||
} | } | ||
root.appendChild(div); | root.appendChild(div); | ||
... | @@ -337,15 +280,15 @@ | ... | @@ -337,15 +280,15 @@ |
if (default_used_list.indexOf(key) < 0) { | if (default_used_list.indexOf(key) < 0) { | ||
div = document.createElement("div"); | div = document.createElement("div"); | ||
div.title = key; | div.title = key; | ||
if (typeof default_dict[key] === 'object') { | if (typeof default_dict[key] === 'object') { | ||
div_input = document.createElement("div"); | div_input = document.createElement("div"); | ||
div_input.setAttribute("class", "input"); | div_input.setAttribute("class", "input"); | ||
label.setAttribute("class", "slapos-parameter-dict-key"); | label.setAttribute("class", "slapos-parameter-dict-key"); | ||
div_input = render_subform({}, | div_input = render_subform({}, | ||
default_dict[key], | default_dict[key], | ||
div_input, | div_input, | ||
path + "/" + key, | path + "/" + key, | ||
restricted); | restricted); | ||
} else if (restricted === true) { | } else if (restricted === true) { | ||
div_input = document.createElement("div"); | div_input = document.createElement("div"); | ||
div_input.setAttribute("class", "input"); | div_input.setAttribute("class", "input"); | ||
... | @@ -433,10 +376,6 @@ | ... | @@ -433,10 +376,6 @@ |
return multi_level_dict; | return multi_level_dict; | ||
} | } | ||
function validateForm(gadget, json_url) { | |||
return gadget.processValidation(json_url); | |||
} | |||
function collapseParameter(element) { | function collapseParameter(element) { | ||
$(element).parent().children("div").toggle(300); | $(element).parent().children("div").toggle(300); | ||
if ($(element).hasClass("slapos-parameter-dict-key-colapse")) { | if ($(element).hasClass("slapos-parameter-dict-key-colapse")) { | ||
... | @@ -453,21 +392,21 @@ | ... | @@ -453,21 +392,21 @@ |
return false; | return false; | ||
} | } | ||
function addSubForm(element) { | function addSubForm(gadget, element) { | ||
var subform_json = JSON.parse(atob(element.value)), | var subform_json = JSON.parse(atob(element.value)), | ||
input_text = element.parentNode.querySelector("input[type='text']"), | input_text = element.parentNode.querySelector("input[type='text']"), | ||
div = document.createElement("div"), | div; | ||
label; | |||
if (input_text.value === "") { | if (input_text.value === "") { | ||
return false; | return false; | ||
} | } | ||
div.setAttribute("class", "slapos-parameter-dict-key"); | div = domsugar('div', { | ||
label = document.createElement("label"); | 'class': "slapos-parameter-dict-key" | ||
label.textContent = input_text.value; | }, [domsugar('label', { | ||
label.setAttribute("class", "slapos-parameter-dict-key"); | 'class': "slapos-parameter-dict-key", | ||
div.appendChild(label); | text: input_text.value | ||
})]); | |||
div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value); | div = render_subform(subform_json, {}, div, element.name + "/" + input_text.value); | ||
... | @@ -477,54 +416,6 @@ | ... | @@ -477,54 +416,6 @@ |
return div; | return div; | ||
} | } | ||
function loadEventList(gadget) { | |||
var g = gadget, | |||
field_list = g.element.querySelectorAll(".slapos-parameter"), | |||
button_list = g.element.querySelectorAll('button.add-sub-form'), | |||
label_list = g.element.querySelectorAll('label.slapos-parameter-dict-key'), | |||
close_list = g.element.querySelectorAll(".bt_close"), | |||
i, | |||
promise_list = []; | |||
for (i = 0; i < field_list.length; i = i + 1) { | |||
promise_list.push(loopEventListener( | |||
field_list[i], | |||
'change', | |||
false, | |||
validateForm.bind(g, g, g.options.value.parameter.json_url) | |||
)); | |||
} | |||
for (i = 0; i < button_list.length; i = i + 1) { | |||
promise_list.push(loopEventListener( | |||
button_list[i], | |||
'click', | |||
false, | |||
addSubForm.bind(g, button_list[i]) | |||
)); | |||
} | |||
for (i = 0; i < label_list.length; i = i + 1) { | |||
promise_list.push(loopEventListener( | |||
label_list[i], | |||
'click', | |||
false, | |||
collapseParameter.bind(g, label_list[i]) | |||
)); | |||
} | |||
for (i = 0; i < close_list.length; i = i + 1) { | |||
promise_list.push(loopEventListener( | |||
close_list[i], | |||
'click', | |||
false, | |||
removeSubParameter.bind(g, close_list [i]) | |||
)); | |||
} | |||
return RSVP.all(promise_list); | |||
} | |||
function getSoftwareTypeFromForm(element) { | function getSoftwareTypeFromForm(element) { | ||
var input = element.querySelector(".slapos-software-type"); | var input = element.querySelector(".slapos-software-type"); | ||
... | @@ -543,7 +434,7 @@ | ... | @@ -543,7 +434,7 @@ |
return ""; | return ""; | ||
} | } | ||
/* | |||
function getSchemaUrlFromForm(element) { | function getSchemaUrlFromForm(element) { | ||
var input = element.querySelector(".parameter_schema_url"); | var input = element.querySelector(".parameter_schema_url"); | ||
... | @@ -552,130 +443,140 @@ | ... | @@ -552,130 +443,140 @@ |
} | } | ||
return ""; | return ""; | ||
} | } | ||
*/ | |||
gk.declareMethod("loadJSONSchema", function (url, serialisation) { | function showParameterForm(g) { | ||
return this.getDeclaredGadget('loadschema') | var e = g.element.getElementsByTagName('select')[0], | ||
.push(function (gadget) { | to_hide = g.element.querySelector("button.slapos-show-form"), | ||
return gadget.loadJSONSchema(url, serialisation); | to_show = g.element.querySelector("button.slapos-show-raw-parameter"); | ||
}); | |||
}) | |||
.declareMethod("validateJSON", function (base_url, schema_url, generated_json) { | if (e === undefined) { | ||
return this.getDeclaredGadget('loadschema') | throw new Error("Select not found."); | ||
.push(function (gadget) { | } | ||
return gadget.validateJSON(base_url, schema_url, generated_json); | |||
}); | |||
}) | |||
.declareMethod("getBaseUrl", function (url) { | $(to_hide).addClass("hidden-button"); | ||
return this.getDeclaredGadget('loadschema') | $(to_show).removeClass("hidden-button"); | ||
.push(function (gadget) { | |||
return gadget.getBaseUrl(url); | |||
}); | |||
}) | |||
.declareMethod("loadSoftwareJSON", function (url) { | |||
return this.getDeclaredGadget('loadschema') | |||
.push(function (gadget) { | |||
return gadget.loadSoftwareJSON(url); | |||
}); | |||
}) | |||
.declareMethod('processValidation', function (json_url) { | return g.changeState({ | ||
var g = this, | display_step: DISPLAY_JSON_FORM, | ||
software_type = getSoftwareTypeFromForm(g.element), | softwareindex: e.selectedOptions[0]["data-id"], | ||
json_dict = getFormValuesAsJSONDict(g.element), | // Force refresh in any case | ||
schema_url = getSchemaUrlFromForm(g.element), | render_timestamp: new Date().getTime() | ||
serialisation_type = getSerialisationTypeFromForm(g.element); | }); | ||
} | |||
if (software_type === "") { | function showRawParameter(g) { | ||
if (g.options.value.parameter.shared) { | var e = g.element.querySelector("button.slapos-show-raw-parameter"), | ||
throw new Error("The software type is not part of the json (" + software_type + " as slave)"); | to_show = g.element.querySelector("button.slapos-show-form"); | ||
} | |||
throw new Error("The software type is not part of the json (" + software_type + ")"); | |||
} | |||
return g.getBaseUrl(json_url) | $(e).addClass("hidden-button"); | ||
.push(function (base_url) { | $(to_show).removeClass("hidden-button"); | ||
return g.validateJSON(base_url, json_url, json_dict); | |||
}) | |||
.push(function (validation) { | |||
var error_index, | |||
parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0], | |||
field_name, | |||
div, | |||
divm, | |||
missing_index, | |||
missing_field_name, | |||
xml_output; | |||
$(g.element.querySelectorAll("span.error")).each(function (i, span) { | |||
span.textContent = ""; | |||
}); | |||
$(g.element.querySelectorAll("div.error-input")).each(function (i, div) { | return g.changeState({ | ||
div.setAttribute("class", ""); | display_step: DISPLAY_RAW_XML, | ||
}); | // Force refresh in any case | ||
if (serialisation_type === "json-in-xml") { | render_timestamp: new Date().getTime() | ||
xml_output = jsonDictToParameterJSONInXML(json_dict); | }); | ||
} else { | } | ||
xml_output = jsonDictToParameterXML(json_dict); | |||
} | |||
parameter_hash_input.value = btoa(xml_output); | |||
g.options.value.parameter.parameter_hash = btoa(xml_output); | |||
// console.log(parameter_hash_input.value); | |||
// console.log(xml_output); | |||
if (validation.valid) { | |||
return xml_output; | |||
} | |||
for (error_index in validation.errors) { | |||
if (validation.errors.hasOwnProperty(error_index)) { | |||
field_name = validation.errors[error_index].dataPath; | |||
div = $(".slapos-parameter[name='/" + field_name + "']")[0].parentNode; | |||
div.setAttribute("class", "slapos-parameter error-input"); | |||
div.querySelector("span.error").textContent = validation.errors[error_index].message; | |||
} | |||
} | |||
for (missing_index in validation.missing) { | function updateParameterForm(g) { | ||
if (validation.missing.hasOwnProperty(missing_index)) { | var e = g.element.getElementsByTagName('select')[0], | ||
missing_field_name = validation.missing[missing_index].dataPath; | parameter_shared = g.element.querySelector('input.parameter_shared'); | ||
divm = $('.slapos-parameter[name=/' + missing_field_name + "']")[0].parentNode; | |||
divm.setAttribute("class", "error-input"); | if (e === undefined) { | ||
divm.querySelector("span.error").textContent = validation.missing[missing_index].message; | throw new Error("Select not found."); | ||
} | } | ||
} | |||
return "ERROR"; | |||
}); | |||
}) | |||
.declareMethod('renderParameterForm', function (json_url, default_dict, restricted_parameter, serialisation) { | parameter_shared.value = e.selectedOptions[0]["data-shared"]; | ||
return g.changeState({ | |||
softwareindex: e.selectedOptions[0]["data-id"], | |||
// Force refresh in any case | |||
render_timestamp: new Date().getTime() | |||
}); | |||
} | |||
var g = this; | ///////////////////////////////////////////////////// | ||
return g.loadJSONSchema(json_url, serialisation) | // check the form validity | ||
.push(function (json) { | ///////////////////////////////////////////////////// | ||
var fieldset_list = g.element.querySelectorAll('fieldset'), | function checkValidity(g) { | ||
fieldset = document.createElement("fieldset"); | var json_url = g.state.json_url, | ||
software_type = getSoftwareTypeFromForm(g.element), | |||
json_dict = getFormValuesAsJSONDict(g.element), | |||
// schema_url = getSchemaUrlFromForm(g.element), | |||
serialisation_type = getSerialisationTypeFromForm(g.element); | |||
if (software_type === "") { | |||
if (g.state.shared) { | |||
throw new Error("The software type is not part of the json (" + software_type + " as slave)"); | |||
} | |||
throw new Error("The software type is not part of the json (" + software_type + ")"); | |||
} | |||
fieldset = render_subform(json, default_dict, fieldset, undefined, restricted_parameter); | return g.getBaseUrl(json_url) | ||
|
|||
$(fieldset_list[1]).replaceWith(fieldset); | .push(function (base_url) { | ||
return fieldset_list; | return g.validateJSON(base_url, json_url, json_dict); | ||
}) | |||
.push(function (validation) { | |||
var error_index, | |||
parameter_hash_input = g.element.querySelectorAll('.parameter_hash_output')[0], | |||
field_name, | |||
div, | |||
divm, | |||
missing_index, | |||
missing_field_name, | |||
xml_output; | |||
$(g.element.querySelectorAll("span.error")).each(function (i, span) { | |||
span.textContent = ""; | |||
}); | }); | ||
}) | |||
.declareMethod('renderFailoverTextArea', function (content, error) { | $(g.element.querySelectorAll("div.error-input")).each(function (i, div) { | ||
var g = this, | div.setAttribute("class", ""); | ||
div = document.createElement("div"), | }); | ||
div_error = document.createElement("div"), | if (serialisation_type === "json-in-xml") { | ||
span_error = document.createElement("span"), | xml_output = jsonDictToParameterJSONInXML(json_dict); | ||
detail_error = document.createElement("details"), | } else { | ||
detail_error_summary = document.createElement("summary"), | xml_output = jsonDictToParameterXML(json_dict); | ||
detail_error_span = document.createElement("span"), | } | ||
textarea = document.createElement("textarea"), | parameter_hash_input.value = btoa(xml_output); | ||
fieldset = document.createElement("fieldset"), | // g.options.value.parameter.parameter_hash = btoa(xml_output); | ||
fieldset_list = g.element.querySelectorAll('fieldset'), | // console.log(parameter_hash_input.value); | ||
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"), | // console.log(xml_output); | ||
show_form_button = g.element.querySelector("button.slapos-show-form"); | if (validation.valid) { | ||
return xml_output; | |||
} | |||
for (error_index in validation.errors) { | |||
if (validation.errors.hasOwnProperty(error_index)) { | |||
field_name = validation.errors[error_index].dataPath; | |||
div = $(".slapos-parameter[name='/" + field_name + "']")[0].parentNode; | |||
div.setAttribute("class", "slapos-parameter error-input"); | |||
div.querySelector("span.error").textContent = validation.errors[error_index].message; | |||
} | |||
} | |||
for (missing_index in validation.missing) { | |||
if (validation.missing.hasOwnProperty(missing_index)) { | |||
missing_field_name = validation.missing[missing_index].dataPath; | |||
divm = $('.slapos-parameter[name=/' + missing_field_name + "']")[0].parentNode; | |||
divm.setAttribute("class", "error-input"); | |||
divm.querySelector("span.error").textContent = validation.missing[missing_index].message; | |||
} | |||
} | |||
return "ERROR"; | |||
}); | |||
} | |||
///////////////////////////////////////////////////// | |||
// main render display functions | |||
///////////////////////////////////////////////////// | |||
function renderDisplayRawXml(g, error_text) { | |||
var fieldset, | |||
fieldset_list = g.element.querySelectorAll('fieldset'), | |||
div_error, | |||
show_raw_button = g.element.querySelector("button.slapos-show-raw-parameter"), | |||
show_form_button = g.element.querySelector("button.slapos-show-form"); | |||
if (error_text) { | |||
if (show_raw_button !== null) { | if (show_raw_button !== null) { | ||
$(show_raw_button).addClass("hidden-button"); | $(show_raw_button).addClass("hidden-button"); | ||
} | } | ||
... | @@ -684,437 +585,443 @@ | ... | @@ -684,437 +585,443 @@ |
$(show_form_button).removeClass("hidden-button"); | $(show_form_button).removeClass("hidden-button"); | ||
} | } | ||
div.setAttribute("class", "field"); | div_error = domsugar('div', { | ||
textarea.setAttribute("rows", "10"); | 'class': 'error' | ||
textarea.setAttribute("cols", "80"); | }, [ | ||
domsugar('span', { | |||
textarea.setAttribute("name", "text_content"); | 'class': 'error', | ||
textarea.textContent = content; | text: "Parameter form is not available, use the textarea above for edit the instance parameters." | ||
}), | |||
span_error.setAttribute("class", "error"); | domsugar('details', [ | ||
span_error.textContent = "Parameter form is not available, use the textarea above for edit the instance parameters."; | domsugar('summary', { | ||
text: "More information..." | |||
detail_error_summary.textContent = "More information..." | }), | ||
detail_error_span.setAttribute("class", "error_msg"); | domsugar('span', { | ||
detail_error_span.textContent = error; | 'class': 'error_msg', | ||
text: error_text | |||
detail_error.appendChild(detail_error_summary); | }) | ||
detail_error.appendChild(detail_error_span); | ]) | ||
div_error.setAttribute("class", "error"); | ]); | ||
} else { | |||
div.appendChild(textarea); | div_error = domsugar('div'); | ||
div_error.appendChild(span_error); | } | ||
div_error.appendChild(detail_error); | fieldset = domsugar('fieldset', [ | ||
domsugar('div', { | |||
fieldset.appendChild(div); | 'class': 'field' | ||
fieldset.appendChild(div_error); | }, [ | ||
domsugar('textarea', { | |||
// Do not hide the Software type, let the user edit it. | rows: "10", | ||
//fieldset_list[0].innerHTML = ''; | cols: "80", | ||
$(fieldset_list[1]).replaceWith(fieldset); | name: "text_content", | ||
fieldset_list[2].innerHTML = ''; | text: g.state.parameter_xml | ||
}) | |||
return fieldset; | ]), | ||
}) | // div error | ||
div_error | |||
.declareMethod('renderRawParameterTextArea', function (content) { | ]); | ||
var g = this, | |||
div = document.createElement("div"), | |||
div_error = document.createElement("div"), | |||
textarea = document.createElement("textarea"), | |||
fieldset = document.createElement("fieldset"), | |||
fieldset_list = g.element.querySelectorAll('fieldset'); | |||
div.setAttribute("class", "field"); | |||
textarea.setAttribute("rows", "10"); | |||
textarea.setAttribute("cols", "80"); | |||
textarea.setAttribute("name", "text_content"); | |||
textarea.textContent = content; | |||
div.appendChild(textarea); | |||
div.appendChild(textarea); | |||
fieldset.appendChild(div); | |||
fieldset.appendChild(div_error); | |||
$(fieldset_list[1]).replaceWith(fieldset); | |||
fieldset_list[2].innerHTML = ''; | |||
return fieldset; | |||
}) | |||
.declareMethod('render', function (options) { | |||
var gadget = this, | |||
to_hide = gadget.element.querySelector("button.slapos-show-form"), | |||
to_show = gadget.element.querySelector("button.slapos-show-raw-parameter"), | |||
softwaretype, | |||
json_url = options.value.parameter.json_url; | |||
gadget.options = options; | // Do not hide the Software type, let the user edit it. | ||
$(fieldset_list[1]).replaceWith(fieldset); | |||
fieldset_list[2].innerHTML = ''; | |||
if (options.value.parameter.parameter_hash !== undefined) { | return fieldset; | ||
// A JSON where provided via gadgetfield | } | ||
options.value.parameter.parameter_xml = atob(options.value.parameter.parameter_hash); | |||
} | |||
if (json_url === undefined) { | function renderDisplayJsonForm(gadget) { | ||
throw new Error("undefined json_url"); | |||
} | var serialisation = gadget.state.serialisation, | ||
json_url = gadget.state.json_url, | |||
parameter_xml = gadget.state.parameter_xml, | |||
restricted_softwaretype = gadget.state.restricted_softwaretype, | |||
restricted_parameter = gadget.state.restricted_parameter, | |||
shared = gadget.state.shared, | |||
softwaretype = gadget.state.softwaretype, | |||
softwareindex = gadget.state.softwareindex, | |||
to_hide = gadget.element.querySelector("button.slapos-show-form"), | |||
to_show = gadget.element.querySelector("button.slapos-show-raw-parameter"); | |||
if (json_url === undefined) { | |||
throw new Error("undefined json_url"); | |||
} | |||
if (to_hide !== null) { | if (to_hide !== null) { | ||
$(to_hide).addClass("hidden-button"); | $(to_hide).addClass("hidden-button"); | ||
} | } | ||
if (to_show !== null) { | if (to_show !== null) { | ||
$(to_show).removeClass("hidden-button"); | $(to_show).removeClass("hidden-button"); | ||
} | } | ||
return gadget.loadSoftwareJSON(json_url) | return gadget.loadSoftwareJSON(json_url) | ||
.push(function (json) { | .push(function (json) { | ||
var option_index, | var option_index, | ||
option, | option, | ||
option_selected = options.value.parameter.softwaretype, | option_selected = softwaretype, | ||
option_selected_index = options.value.parameter.softwaretypeindex, | option_selected_index = softwareindex, | ||
restricted_softwaretype = options.value.parameter.restricted_softwaretype, | input = gadget.element.querySelector('select.slapos-software-type'), | ||
input = gadget.element.querySelector('select.slapos-software-type'), | parameter_shared = gadget.element.querySelector('input.parameter_shared'), | ||
parameter_shared = gadget.element.querySelector('input.parameter_shared'), | parameter_schema_url = gadget.element.querySelector('input.parameter_schema_url'), | ||
parameter_schema_url = gadget.element.querySelector('input.parameter_schema_url'), | s_input = gadget.element.querySelector('input.slapos-serialisation-type'), | ||
s_input = gadget.element.querySelector('input.slapos-serialisation-type'), | selection_option_list = [], | ||
selection_option_list = [], | lowest_index = 999, | ||
lowest_index = 999, | lowest_option_index; | ||
lowest_option_index; | |||
if (input.children.length === 0) { | |||
if (input.children.length === 0) { | if (option_selected === undefined) { | ||
if (option_selected === undefined) { | // search by the lowest index | ||
// search by the lowest index | for (option_index in json['software-type']) { | ||
for (option_index in json['software-type']) { | if (json['software-type'].hasOwnProperty(option_index)) { | ||
if (json['software-type'].hasOwnProperty(option_index)) { | if (json['software-type'][option_index].index === undefined) { | ||
if (json['software-type'][option_index].index === undefined) { | json['software-type'][option_index].index = 999; | ||
json['software-type'][option_index].index = 999; | } | ||
} | |||
if (json['software-type'][option_index].index < lowest_index) { | if (json['software-type'][option_index].index < lowest_index) { | ||
lowest_index = json['software-type'][option_index].index; | lowest_index = json['software-type'][option_index].index; | ||
lowest_option_index = option_index; | lowest_option_index = option_index; | ||
} | |||
} | } | ||
} | } | ||
} | } | ||
} | |||
for (option_index in json['software-type']) { | for (option_index in json['software-type']) { | ||
if (json['software-type'].hasOwnProperty(option_index)) { | if (json['software-type'].hasOwnProperty(option_index)) { | ||
option = document.createElement("option"); | option = document.createElement("option"); | ||
if (json['software-type'][option_index]['software-type'] !== undefined) { | if (json['software-type'][option_index]['software-type'] !== undefined) { | ||
option.value = json['software-type'][option_index]['software-type']; | option.value = json['software-type'][option_index]['software-type']; | ||
} else { | } else { | ||
option.value = option_index; | option.value = option_index; | ||
} | } | ||
option['data-id'] = option_index; | |||
option.textContent = json['software-type'][option_index].title; | |||
if (json['software-type'][option_index].index) { | |||
option['data-index'] = json['software-type'][option_index].index; | |||
} else { | |||
option['data-index'] = 999; | |||
} | |||
option['data-id'] = option_index; | if (option_index === lowest_option_index) { | ||
option.textContent = json['software-type'][option_index].title; | option_selected = option.value; | ||
if (json['software-type'][option_index].index) { | option.selected = true; | ||
option['data-index'] = json['software-type'][option_index].index; | option_selected_index = option_index; | ||
if (json['software-type'][option_index].shared === true) { | |||
parameter_shared.value = true; | |||
} else { | } else { | ||
option['data-index'] = 999; | parameter_shared.value = false; | ||
} | } | ||
if (shared === undefined) { | |||
if (option_index === lowest_option_index) { | shared = parameter_shared.value; | ||
option_selected = option.value; | |||
option.selected = true; | |||
option_selected_index = option_index; | |||
if (json['software-type'][option_index].shared === true) { | |||
parameter_shared.value = true; | |||
} else { | |||
parameter_shared.value = false; | |||
} | |||
if (options.value.parameter.shared === undefined) { | |||
options.value.parameter.shared = parameter_shared.value; | |||
} | |||
} | } | ||
} | |||
if (json['software-type'][option_index].shared === undefined) { | if (json['software-type'][option_index].shared === undefined) { | ||
json['software-type'][option_index].shared = false; | json['software-type'][option_index].shared = false; | ||
} | } | ||
option['data-shared'] = json['software-type'][option_index].shared; | |||
option['data-shared'] = json['software-type'][option_index].shared; | if ((option_selected_index === undefined) && | ||
if ((option_selected_index === undefined) && | |||
(option.value === option_selected) && | (option.value === option_selected) && | ||
(options.value.parameter.shared == json['software-type'][option_index].shared)) { | (Boolean(shared) === Boolean(json['software-type'][option_index].shared))) { | ||
option.selected = true; | option.selected = true; | ||
option_selected_index = option_index; | option_selected_index = option_index; | ||
if (json['software-type'][option_index].shared === true) { | if (json['software-type'][option_index].shared === true) { | ||
parameter_shared.value = true; | parameter_shared.value = true; | ||
} else { | } else { | ||
parameter_shared.value = false; | parameter_shared.value = false; | ||
} | |||
} | } | ||
} | |||
if (restricted_softwaretype === true) { | if (restricted_softwaretype === true) { | ||
if (option.value === options.value.parameter.softwaretype) { | if (option.value === softwaretype) { | ||
if (options.value.parameter.shared == json['software-type'][option_index].shared) { | if (Boolean(shared) === Boolean(json['software-type'][option_index].shared)) { | ||
selection_option_list.push(option); | selection_option_list.push(option); | ||
} | |||
} | } | ||
} else { | |||
selection_option_list.push(option); | |||
} | } | ||
} else { | |||
selection_option_list.push(option); | |||
} | } | ||
} | } | ||
} | } | ||
} | |||
selection_option_list.sort(function (a, b) { | |||
return a["data-index"] - b["data-index"]; | |||
}); | |||
for (option_index in selection_option_list) { | selection_option_list.sort(function (a, b) { | ||
return a["data-index"] - b["data-index"]; | |||
}); | |||
for (option_index in selection_option_list) { | |||
if (selection_option_list.hasOwnProperty(option_index)) { | |||
input.appendChild(selection_option_list[option_index]); | input.appendChild(selection_option_list[option_index]); | ||
} | } | ||
} | |||
if (softwaretype === undefined) { | if (softwaretype === undefined) { | ||
softwaretype = option_selected; | softwaretype = option_selected; | ||
} | } | ||
if (input.children.length === 0) { | if (input.children.length === 0) { | ||
if (options.value.parameter.shared) { | if (shared) { | ||
throw new Error("The software type is not part of the json (" + softwaretype + " as slave)"); | throw new Error("The software type is not part of the json (" + softwaretype + " as slave)"); | ||
} | |||
throw new Error("The software type is not part of the json (" + softwaretype + ")"); | |||
} | |||
if (json['software-type'][option_selected_index] === undefined) { | |||
throw new Error("The sotware type is not part of the json (" + softwaretype + ")"); | |||
} | } | ||
throw new Error("The software type is not part of the json (" + softwaretype + ")"); | |||
} | |||
if (json['software-type'][option_selected_index] === undefined) { | |||
throw new Error("The sotware type is not part of the json (" + softwaretype + ")"); | |||
} | |||
if (json['software-type'][option_selected_index].serialisation !== undefined) { | if (json['software-type'][option_selected_index].serialisation !== undefined) { | ||
s_input.value = json['software-type'][option_selected_index].serialisation; | s_input.value = json['software-type'][option_selected_index].serialisation; | ||
options.serialisation = json['software-type'][option_selected_index].serialisation; | serialisation = json['software-type'][option_selected_index].serialisation; | ||
} else { | |||
s_input.value = json.serialisation; | |||
serialisation = json.serialisation; | |||
} | |||
// Save current schema on the field | |||
parameter_schema_url.value = json['software-type'][option_selected_index].request; | |||
return parameter_schema_url.value; | |||
}) | |||
.push(function (parameter_json_schema_url) { | |||
var parameter_dict = {}, parameter_list, json_url_uri, prefix, parameter_entry; | |||
if (parameter_xml !== undefined) { | |||
if (serialisation === "json-in-xml") { | |||
parameter_list = jQuery.parseXML( | |||
parameter_xml | |||
).querySelectorAll("parameter"); | |||
if (parameter_list.length > 1) { | |||
throw new Error("The current parameter should contains only _ parameter (json-in-xml)."); | |||
} | |||
parameter_entry = jQuery.parseXML( | |||
parameter_xml | |||
).querySelector("parameter[id='_']"); | |||
if (parameter_entry !== null) { | |||
parameter_dict = JSON.parse(parameter_entry.textContent); | |||
} else if (parameter_list.length === 1) { | |||
throw new Error( | |||
"The current parameter should contains only _ parameter (json-in-xml)." | |||
); | |||
} | |||
} else if (["", "xml"].indexOf(serialisation) >= 0) { | |||
parameter_entry = jQuery.parseXML( | |||
parameter_xml | |||
).querySelector("parameter[id='_']"); | |||
if (parameter_entry !== null) { | |||
throw new Error("The current parameter values should NOT contains _ parameter (xml)."); | |||
} | |||
$(jQuery.parseXML(parameter_xml) | |||
.querySelectorAll("parameter")) | |||
.each(function (key, p) { | |||
parameter_dict[p.id] = p.textContent; | |||
}); | |||
} else { | } else { | ||
s_input.value = json.serialisation; | throw new Error("Unknown serialisation: " + serialisation); | ||
options.serialisation = json.serialisation; | |||
} | } | ||
} | |||
// Save current schema on the field | if (URI(parameter_json_schema_url).protocol() === "") { | ||
parameter_schema_url.value = json['software-type'][option_selected_index].request; | // URL is relative, turn into absolute | ||
json_url_uri = URI(json_url); | |||
prefix = json_url_uri.path().split("/"); | |||
prefix.pop(); | |||
prefix = json_url.split(json_url_uri.path())[0] + prefix.join("/"); | |||
parameter_json_schema_url = prefix + "/" + parameter_json_schema_url; | |||
} | |||
return gadget.loadJSONSchema(parameter_json_schema_url, serialisation) | |||
.push(function (json) { | |||
var fieldset_list = gadget.element.querySelectorAll('fieldset'), | |||
fieldset = document.createElement("fieldset"); | |||
fieldset = render_subform(json, parameter_dict, fieldset, undefined, restricted_parameter); | |||
$(fieldset_list[1]).replaceWith(fieldset); | |||
return fieldset_list; | |||
}); | |||
}) | |||
.push(function () { | |||
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'), | |||
label_list = gadget.element.querySelectorAll('label.slapos-parameter-dict-key'); | |||
return parameter_schema_url.value; | // console.log("Collapse paramaters"); | ||
}) | |||
.push(function (parameter_json_schema_url) { | |||
var parameter_dict = {}, parameter_list, json_url_uri, prefix, parameter_entry, | |||
restricted_parameter = options.value.parameter.restricted_parameter; | |||
if (options.value.parameter.parameter_xml !== undefined) { | |||
if (options.serialisation === "json-in-xml") { | |||
parameter_list = jQuery.parseXML( | |||
options.value.parameter.parameter_xml) | |||
.querySelectorAll("parameter") | |||
if (parameter_list.length > 1) { | |||
throw new Error("The current parameter should contains only _ parameter (json-in-xml).") | |||
} | |||
parameter_entry = jQuery.parseXML( | |||
options.value.parameter.parameter_xml | |||
).querySelector("parameter[id='_']"); | |||
if (parameter_entry !== null) { | |||
parameter_dict = JSON.parse(parameter_entry.textContent); | |||
} else if (parameter_list.length == 1) { | |||
throw new Error( | |||
"The current parameter should contains only _ parameter (json-in-xml).") | |||
} | |||
} else if (["", "xml"].indexOf(options.serialisation) >= 0) { | |||
parameter_entry = jQuery.parseXML( | |||
options.value.parameter.parameter_xml | |||
).querySelector("parameter[id='_']"); | |||
if (parameter_entry !== null) { | |||
throw new Error("The current parameter values should NOT contains _ parameter (xml)."); | |||
} | |||
$(jQuery.parseXML(options.value.parameter.parameter_xml) | |||
.querySelectorAll("parameter")) | |||
.each(function (key, p) { | |||
parameter_dict[p.id] = p.textContent; | |||
}); | |||
} else { | |||
throw new Error("Unknown serialisation: " + options.serialisation); | |||
} | |||
} | |||
if (URI(parameter_json_schema_url).protocol() === "") { | for (i = 0; i < div_list.length; i = i + 1) { | ||
// URL is relative, turn into absolute | $(div_list[i]).hide(); | ||
json_url_uri = URI(options.value.parameter.json_url); | } | ||
prefix = json_url_uri.path().split("/"); | |||
prefix.pop(); | |||
prefix = options.value.parameter.json_url.split(json_url_uri.path())[0] + prefix.join("/"); | |||
parameter_json_schema_url = prefix + "/" + parameter_json_schema_url; | |||
} | |||
return gadget.renderParameterForm(parameter_json_schema_url, | |||
parameter_dict, restricted_parameter, | |||
options.serialisation); | |||
}) | |||
.push(function () { | |||
var i, div_list = gadget.element.querySelectorAll('.slapos-parameter-dict-key > div'), | |||
label_list = gadget.element.querySelectorAll('label.slapos-parameter-dict-key'); | |||
// console.log("Collapse paramaters"); | for (i = 0; i < label_list.length; i = i + 1) { | ||
$(label_list[i]).addClass("slapos-parameter-dict-key-colapse"); | |||
} | |||
}) | |||
for (i = 0; i < div_list.length; i = i + 1) { | .fail(function (error) { | ||
$(div_list[i]).hide(); | console.warn(error); | ||
} | console.log(error.stack); | ||
return renderDisplayRawXml(gadget, error.toString()); | |||
}); | |||
} | |||
for (i = 0; i < label_list.length; i = i + 1) { | ///////////////////////////////////////////////////// | ||
$(label_list[i]).addClass("slapos-parameter-dict-key-colapse"); | // Gadget methods | ||
} | ///////////////////////////////////////////////////// | ||
return gadget; | rJS(window) | ||
}) | .setState({ | ||
display_step: DISPLAY_JSON_FORM | |||
}) | |||
.declareMethod("loadJSONSchema", function (url, serialisation) { | |||
return this.getDeclaredGadget('loadschema') | |||
.push(function (gadget) { | .push(function (gadget) { | ||
/* console.log("FINISHED TO RENDER, RETURNING THE GADGET"); */ | return gadget.loadJSONSchema(url, serialisation); | ||
return loadEventList(gadget); | |||
}) | |||
.fail(function (error) { | |||
var parameter_xml = ''; | |||
console.warn(error); | |||
console.log(error.stack); | |||
if (gadget.options.value.parameter.parameter_hash !== undefined) { | |||
parameter_xml = atob(gadget.options.value.parameter.parameter_hash); | |||
} | |||
return gadget.renderFailoverTextArea(parameter_xml, error.toString()) | |||
.push(function () { | |||
error = undefined; | |||
return loadEventList(gadget); | |||
}); | |||
}); | }); | ||
}) | }) | ||
.declareService(function () { | .declareMethod("validateJSON", function (base_url, schema_url, generated_json) { | ||
var g = this, | return this.getDeclaredGadget('loadschema') | ||
element = g.element.getElementsByTagName('select')[0]; | .push(function (gadget) { | ||
return gadget.validateJSON(base_url, schema_url, generated_json); | |||
if (element === undefined) { | }); | ||
return true; | }) | ||
} | |||
function updateParameterForm(evt) { | .declareMethod("getBaseUrl", function (url) { | ||
var e = g.element.getElementsByTagName('select')[0], | return this.getDeclaredGadget('loadschema') | ||
parameter_shared = g.element.querySelector('input.parameter_shared'); | .push(function (gadget) { | ||
return gadget.getBaseUrl(url); | |||
}); | |||
}) | |||
.declareMethod("loadSoftwareJSON", function (url) { | |||
return this.getDeclaredGadget('loadschema') | |||
.push(function (gadget) { | |||
return gadget.loadSoftwareJSON(url); | |||
}); | |||
}) | |||
if (e === undefined) { | .declareMethod('render', function (options) { | ||
throw new Error("Select not found."); | var parameter_hash = options.value.parameter.parameter_hash, | ||
} | // XXX Do we directly get parameter_xml parameter? | ||
parameter_xml = options.value.parameter.parameter_xml; | |||
g.options.value.parameter.softwaretype = e.value; | if (parameter_hash !== undefined) { | ||
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"]; | // A JSON where provided via gadgetfield | ||
parameter_shared.value = e.selectedOptions[0]["data-shared"]; | parameter_xml = atob(parameter_hash); | ||
return g.render(g.options) | |||
.push(function () { | |||
return loadEventList(g); | |||
}); | |||
} | } | ||
return loopEventListener( | return this.changeState({ | ||
element, | // Not used parameters | ||
'change', | // editable: options.editable, | ||
false, | // hidden: options.hidden, | ||
updateParameterForm.bind(g) | // key: options.key, | ||
); | serialisation: options.serialisation, | ||
json_url: options.value.parameter.json_url, | |||
parameter_xml: parameter_xml, | |||
restricted_softwaretype: options.value.parameter.restricted_softwaretype, | |||
restricted_parameter: options.value.parameter.restricted_parameter, | |||
shared: options.value.parameter.shared, | |||
softwaretype: options.value.parameter.softwaretype, | |||
softwareindex: options.value.parameter.softwareindex, | |||
// Force refresh in any case | |||
render_timestamp: new Date().getTime() | |||
}); | |||
}) | }) | ||
.declareService(function () { | .onStateChange(function () { | ||
var g = this, | if (this.state.display_step === DISPLAY_JSON_FORM) { | ||
element = g.element.querySelector("button.slapos-show-raw-parameter"); | return renderDisplayJsonForm(this); | ||
if (element === undefined) { | |||
return true; | |||
} | } | ||
if (this.state.display_step === DISPLAY_RAW_XML) { | |||
return renderDisplayRawXml(this); | |||
} | |||
throw new Error('Unhandled display step: ' + this.state.display_step); | |||
}) | |||
function showRawParameter(evt) { | .onEvent("change", function (evt) { | ||
var e = g.element.querySelector("button.slapos-show-raw-parameter"), | var gadget = this, | ||
to_show = g.element.querySelector("button.slapos-show-form"), | software_type_element = gadget.element.getElementsByTagName('select')[0]; | ||
parameter_xml; | |||
if (g.options.value.parameter.parameter_hash !== undefined) { | |||
parameter_xml = atob(g.options.value.parameter.parameter_hash); | |||
} | |||
$(e).addClass("hidden-button"); | if (evt.target === software_type_element) { | ||
$(to_show).removeClass("hidden-button"); | return updateParameterForm(gadget); | ||
} | |||
return g.renderRawParameterTextArea(parameter_xml) | if (evt.target.className.indexOf("slapos-parameter") !== -1) { | ||
.push(function () { | // getContent is protected by a mutex which prevent | ||
return loadEventList(g); | // onchangestate to be called in parallel | ||
}); | return gadget.getContent(); | ||
} | } | ||
return loopEventListener( | }, false, false) | ||
element, | |||
'click', | .onEvent("click", function (evt) { | ||
false, | // Only handle click on BUTTON element | ||
showRawParameter.bind(g) | var gadget = this, | ||
); | queue, | ||
}) | tag_name = evt.target.tagName; | ||
.declareService(function () { | if ((tag_name === 'LABEL') && | ||
var g = this, | (evt.target.className.indexOf("slapos-parameter-dict-key") !== -1)) { | ||
element = g.element.querySelector("button.slapos-show-form"); | return collapseParameter(evt.target); | ||
} | |||
function showParameterForm(evt) { | if (evt.target.className.indexOf("bt_close") !== -1) { | ||
var e = g.element.getElementsByTagName('select')[0], | return removeSubParameter(evt.target); | ||
to_hide = g.element.querySelector("button.slapos-show-form"), | } | ||
to_show = g.element.querySelector("button.slapos-show-raw-parameter"), | |||
text_content = g.element.querySelector('textarea[name=text_content]'); | |||
if (e === undefined) { | if (tag_name === 'BUTTON') { | ||
throw new Error("Select not found."); | // Disable any button. It must be managed by this gadget | ||
} | evt.preventDefault(); | ||
} | |||
$(to_hide).addClass("hidden-button"); | // Always get content to ensure the possible displayed form | ||
$(to_show).removeClass("hidden-button"); | // is checked and content propagated to the gadget state value | ||
queue = gadget.getContent(); | |||
g.options.value.parameter.softwaretype = e.value; | if ((tag_name === 'BUTTON') && | ||
g.options.value.parameter.softwaretypeindex = e.selectedOptions[0]["data-id"]; | (evt.target.className.indexOf("slapos-show-form") !== -1)) { | ||
g.options.value.parameter.parameter_xml = text_content.value; | return queue | ||
g.options.value.parameter.parameter_hash = btoa(text_content.value); | |||
return g.render(g.options) | |||
.push(function () { | .push(function () { | ||
return loadEventList(g); | return showParameterForm(gadget); | ||
}); | }); | ||
} | } | ||
if ((tag_name === 'BUTTON') && | |||
(evt.target.className.indexOf("slapos-show-raw-parameter") !== -1)) { | |||
return queue | |||
.push(function () { | |||
return showRawParameter(gadget); | |||
}); | |||
} | |||
return loopEventListener( | if ((tag_name === 'BUTTON') && | ||
element, | (evt.target.className.indexOf("add-sub-form") !== -1)) { | ||
'click', | return queue | ||
false, | .push(function () { | ||
showParameterForm.bind(g) | return addSubForm(gadget, evt.target); | ||
); | }); | ||
}) | } | ||
}, false, false) | |||
.declareService(function () { | |||
return loadEventList(this); | |||
}) | |||
.declareMethod('getContent', function () { | .declareMethod('getContent', function () { | ||
var gadget = this, | var gadget = this, | ||
content_dict = {}; | content_dict = {}; | ||
return gadget.getElement() | return gadget.getElement() | ||
.push(function (element) { | .push(function (element) { | ||
var text_content = element.querySelector('textarea[name=text_content]'), | var text_content = element.querySelector('textarea[name=text_content]'), | ||
software_type = element.querySelector('select[name=software_type]'), | software_type = element.querySelector('select[name=software_type]'), | ||
shared = element.querySelector('input[name=shared]'); | shared = element.querySelector('input[name=shared]'); | ||
if (software_type !== null) { | if (software_type !== null) { | ||
gadget.state.softwaretype = software_type.value; | |||
content_dict.software_type = software_type.value; | content_dict.software_type = software_type.value; | ||
} | } | ||
if ((shared !== null) && (shared.value === "true")) { | if ((shared !== null) && (shared.value === "true")) { | ||
gadget.state.shared = 1; | |||
content_dict.shared = 1; | content_dict.shared = 1; | ||
} | } | ||
if (text_content !== null) { | if (text_content !== null) { | ||
return text_content.value; | return text_content.value; | ||
} | } | ||
return gadget.processValidation(gadget.options.value.parameter.json_url); | return checkValidity(gadget); | ||
}) | }) | ||
.push(function (xml_result) { | .push(function (xml_result) { | ||
// Update gadget state | |||
gadget.state.parameter_xml = xml_result; | |||
content_dict.text_content = xml_result; | content_dict.text_content = xml_result; | ||
return content_dict; | return content_dict; | ||
}) | |||
.fail(function (e) { | |||
return {}; | |||
}); | }); | ||
}); | }, {mutex: 'statechange'}); | ||
//.declareService(function () { | //.declareService(function () { | ||
// var gadget = this; | // var gadget = this; | ||
... | @@ -1133,4 +1040,5 @@ | ... | @@ -1133,4 +1040,5 @@ |
// }); | // }); | ||
//}); | //}); | ||
}(window, document, rJS, $, XMLSerializer, jQuery, vkbeautify)); | }(window, document, rJS, $, XMLSerializer, jQuery, vkbeautify, | ||
\ No newline at end of file | rJS.loopEventListener, domsugar, Boolean)); | ||
\ No newline at end of file |