451 lines
21 KiB
JavaScript
451 lines
21 KiB
JavaScript
define([], function () {
|
|
var allowConditionQuestions = [3, 4, 5, 8, 9, 11, 12, 19];
|
|
var dropdownType = 8;
|
|
var bannedLookupSources = [2, 3];
|
|
var fuelRecordsType = 15;
|
|
var numberQuestionTypes = [3, 4, 11, 12];
|
|
var integerQuestionTypes = [4];
|
|
var dropQuestionTypes = [5, 8, 9, 19];
|
|
var numberSubTypes = [8, 10, 11, 12];
|
|
var integerSubTypes = [10];
|
|
var dropSubTypes = [9];
|
|
|
|
var selectorChanged = function (id) {
|
|
var c = this.conditional;
|
|
c.QuestionId = id;
|
|
if (['-', 'or', 'and'].includes(id)) {
|
|
this.addbutton.show();
|
|
this.span.hide();
|
|
this.selector.css('width', 80);
|
|
} else {
|
|
c.SubItems = [];
|
|
this.addbutton.hide();
|
|
this.span.show();
|
|
this.selector.css('width', 150);
|
|
var pagemodule = this.wrapper.pagemodule;
|
|
var question;
|
|
for (var i = 0; i < pagemodule.sectionmodules.length; i++) {
|
|
var section = pagemodule.sectionmodules[i];
|
|
for (var j = 0; j < section.questionmodules.length; j++) {
|
|
var q = section.questionmodules[j].question;
|
|
if (q.Id == id) {
|
|
question = q;
|
|
}
|
|
}
|
|
}
|
|
if (question == null) {
|
|
return;
|
|
}
|
|
this.question = question;
|
|
var qtype = Number(question.QuestionType);
|
|
var stype = Number(question.SubType);
|
|
var isnumber = numberQuestionTypes.includes(qtype);
|
|
var isdrop = dropQuestionTypes.includes(qtype);
|
|
isnumber |= qtype == fuelRecordsType && numberSubTypes.includes(stype);
|
|
isdrop |= qtype == fuelRecordsType && dropSubTypes.includes(stype);
|
|
var operator = this.operator;
|
|
if (isnumber) {
|
|
operator.empty().attr('data-vtype', '0').append(
|
|
'<option value="eq">=</option>',
|
|
'<option value="noteq"><></option>',
|
|
'<option value="gt">></option>',
|
|
'<option value="gteq">>=</option>',
|
|
'<option value="lt"><</option>',
|
|
'<option value="lteq"><=</option>',
|
|
$('<option value="between"></option>').text(GetTextByKey('P_CDH_BETWEEN', 'Between'))
|
|
);
|
|
if (c.Operator?.length > 0 && c.Operator !== 'in') {
|
|
operator.val(c.Operator).trigger('change');
|
|
} else {
|
|
operator.val(c.Operator = 'gt').trigger('change');
|
|
}
|
|
}
|
|
if (isdrop) {
|
|
operator.empty().attr('data-vtype', '1').append(
|
|
'<option value="eq">=</option>',
|
|
'<option value="noteq"><></option>',
|
|
$('<option value="in"></option>').text(GetTextByKey('P_CDH_IN', 'In'))
|
|
);
|
|
var op = c.Operator;
|
|
if (['eq', 'noteq', 'in'].includes(op)) {
|
|
operator.val(op).trigger('change');
|
|
} else {
|
|
operator.val(c.Operator = op = 'eq').trigger('change');
|
|
}
|
|
if (['eq', 'noteq'].includes(op) && (question.SelectItems?.length > 0 || question.QuestionType == 19)) {
|
|
var valueDrop = this.valueDrop;
|
|
if (question.QuestionType == 19) {
|
|
valueDrop.empty().append(
|
|
$('<option value="In Use"></option>').text(GetTextByKey('P_MA_INUSE', 'In Use')),
|
|
$('<option value="Available"></option>').text(GetTextByKey('P_MA_AVAILABLE', 'Available')),
|
|
$('<option value="Standby"></option>').text(GetTextByKey('P_MA_STANDBY', 'Standby')),
|
|
$('<option value="Down"></option>').text(GetTextByKey('P_MA_DOWN', 'Down'))
|
|
);
|
|
var r = String(c.Value);
|
|
if (['In Use', 'Available', 'Standby', 'Down'].includes(r)) {
|
|
valueDrop.val(r);
|
|
} else {
|
|
c.Value = 'In Use';
|
|
}
|
|
} else {
|
|
valueDrop.empty().append(
|
|
...question.SelectItems.map(function (it) {
|
|
return $('<option></option>').val(it.Text).text(it.Text);
|
|
})
|
|
);
|
|
var r = String(c.Value);
|
|
if (question.SelectItems.map(function (it) { return it.Text }).includes(r)) {
|
|
valueDrop.val(r);
|
|
} else {
|
|
var i0 = question.SelectItems[0];
|
|
c.Value = i0.Text;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (typeof this.wrapper.onchanged === 'function') {
|
|
this.wrapper.onchanged(id);
|
|
}
|
|
};
|
|
|
|
var onAdded = function () {
|
|
var conditional = this.conditional;
|
|
if (this.selector.val() == '-') {
|
|
this.selector.val('or');
|
|
conditional.QuestionId = 'or';
|
|
}
|
|
var c = { SubItems: [] };
|
|
conditional.SubItems.push(c);
|
|
var item = new conditionalTree(this.wrapper, c);
|
|
var items = this.children;
|
|
items.push(item);
|
|
item.ondelete = function () {
|
|
var i = items.indexOf(this);
|
|
if (i >= 0) {
|
|
items.splice(i, 1);
|
|
}
|
|
i = conditional.SubItems.indexOf(this.conditional);
|
|
if (i >= 0) {
|
|
conditional.SubItems.splice(i, 1);
|
|
}
|
|
this.tree.remove();
|
|
};
|
|
this.container.append(item.tree);
|
|
item.refresh(true);
|
|
};
|
|
|
|
var onOperatorChanged = function (op, type) {
|
|
this.conditional.Operator = op;
|
|
if (type == '1') {
|
|
this.value2.hide();
|
|
// drop
|
|
if (['eq', 'noteq'].includes(op) && (this.question.SelectItems?.length > 0 || this.question.QuestionType == 19)) {
|
|
this.value1.hide();
|
|
this.valueDrop.show();
|
|
} else {
|
|
this.value1.show();
|
|
this.valueDrop.hide();
|
|
}
|
|
} else {
|
|
this.valueDrop.hide();
|
|
this.value1.show();
|
|
if (op == 'between') {
|
|
this.value2.show();
|
|
} else {
|
|
this.value2.hide();
|
|
}
|
|
}
|
|
};
|
|
|
|
var conditionalTree = function (obj, c, root) {
|
|
this.wrapper = obj;
|
|
this.conditional = c;
|
|
this.children = [];
|
|
this.isroot = root;
|
|
var This = this;
|
|
var tree = $('<div></div>').addClass(root ? 'conditional-item-root' : 'conditional-item');
|
|
var selector = $('<select style="width: 80px; height: 26px; border: 1px solid #a9a9a9; margin-left: 6px" class="question-input"></select>')
|
|
.on('change', function () { selectorChanged.call(This, this.value) });
|
|
if (root) {
|
|
selector.append('<option selected value="-">--</option>');
|
|
}
|
|
selector.append(
|
|
$('<option selected value="or"></option>').text(GetTextByKey('P_CDH_OR', 'OR')),
|
|
$('<option value="and"></option>').text(GetTextByKey('P_CDH_AND', 'AND'))
|
|
);
|
|
tree.append(selector);
|
|
this.tree = tree;
|
|
this.selector = selector;
|
|
|
|
var addbutton = $('<span class="spanbtn iconadd" style="font-size: 14px"></span>');
|
|
addbutton.on('click', onAdded.bind(this));
|
|
tree.append(addbutton);
|
|
this.addbutton = addbutton;
|
|
|
|
var span = $('<span style="display: none"></span>');
|
|
var operator = $('<select style="width: 80px; height: 26px; border: 1px solid #a9a9a9; margin-left: 4px" class="question-input"></select>')
|
|
.on('change', function () { onOperatorChanged.call(This, this.value, $(this).attr('data-vtype')) });
|
|
var value1 = $('<input type="text" class="question-input" maxlength="200" autocomplete="off" style="width: 130px; box-sizing: border-box; height: 26px"></input>')
|
|
.on('change', function () { c.Value = this.value });
|
|
var value2 = $('<input type="text" class="question-input" maxlength="200" autocomplete="off" style="display: none; width: 130px; margin-left: 4px; box-sizing: border-box; height: 26px"></input>')
|
|
.on('change', function () { c.Value1 = this.value });
|
|
var valueDrop = $('<select class="question-input" style="display: none; height: 26px; width: 130px; border: 1px solid #a9a9a9"></select>')
|
|
.on('change', function () { c.Value = this.value });
|
|
span.append(operator, $('<span style="margin-left: 4px"></span>').append(value1, value2, valueDrop));
|
|
tree.append(span);
|
|
this.span = span;
|
|
this.operator = operator;
|
|
this.value1 = value1;
|
|
this.value2 = value2;
|
|
this.valueDrop = valueDrop;
|
|
|
|
if (!root) {
|
|
var removebutton = $('<span class="spanbtn icondelete" style="font-size: 14px"></span>');
|
|
removebutton.on('click', function () {
|
|
if (typeof This.ondelete === 'function') {
|
|
This.ondelete();
|
|
}
|
|
});
|
|
tree.append(removebutton);
|
|
}
|
|
|
|
var container = $('<div style="padding-left: 20px; overflow-y: hidden"></div>');
|
|
tree.append(container);
|
|
this.container = container;
|
|
};
|
|
|
|
conditionalTree.prototype.fill = function () {
|
|
var conditional = this.conditional;
|
|
this.selector.val(conditional.QuestionId).trigger('change');
|
|
this.operator.val(conditional.Operator).trigger('change');
|
|
this.value1.val(conditional.Value);
|
|
this.value2.val(conditional.Value1);
|
|
this.valueDrop.val(conditional.Value);
|
|
|
|
var container = this.container;
|
|
container.empty();
|
|
var items = [];
|
|
this.children = items;
|
|
if (conditional.SubItems?.length > 0) {
|
|
for (var i = 0; i < conditional.SubItems.length; i++) {
|
|
var c = conditional.SubItems[i];
|
|
var item = new conditionalTree(this.wrapper, c);
|
|
items.push(item);
|
|
item.ondelete = function () {
|
|
var i = items.indexOf(this);
|
|
if (i >= 0) {
|
|
items.splice(i, 1);
|
|
}
|
|
i = conditional.SubItems.indexOf(this.conditional);
|
|
if (i >= 0) {
|
|
conditional.SubItems.splice(i, 1);
|
|
}
|
|
this.tree.remove();
|
|
};
|
|
container.append(item.tree);
|
|
item.refresh(true);
|
|
}
|
|
}
|
|
};
|
|
|
|
conditionalTree.prototype.refresh = function (force) {
|
|
if (!force && this.wrapper.initialized) {
|
|
return;
|
|
}
|
|
this.wrapper.initialized = true;
|
|
var idIndex = this.wrapper.module.idIndex;
|
|
var secs = this.wrapper.pagemodule.sectionmodules.map(function (s) {
|
|
var qs = s.questionmodules.filter(function (q) {
|
|
return (
|
|
allowConditionQuestions.includes(Number(q.question.QuestionType)) ||
|
|
(q.question.QuestionType == fuelRecordsType && numberSubTypes.concat(dropSubTypes).includes(Number(q.question.SubType)))
|
|
) &&
|
|
idIndex > q.idIndex &&
|
|
(q.question.QuestionType != dropdownType || !bannedLookupSources.includes(Number(q.question.LookupSource)))
|
|
});
|
|
return qs.length > 0 && $('<optgroup></optgroup>').attr('label', s.section.DisplayText || s.section.Name).append(
|
|
...qs.map(function (q) {
|
|
return $('<option></option>').val(q.question.Id).text(`#${q.idIndex} - ${q.txtDisplayText?.val() || q.question.DisplayText || q.question.Name}`);
|
|
})
|
|
);
|
|
}).filter(function (s) { return s });
|
|
this.selector.children('optgroup').remove();
|
|
this.selector.append(...secs);
|
|
|
|
// fill selected
|
|
if (this.conditional.QuestionId == null) {
|
|
if (this.isroot) {
|
|
this.conditional.QuestionId = '-';
|
|
} else if (secs.length > 0) {
|
|
var f = secs[0].children('option')?.[0];
|
|
if (f != null) {
|
|
this.conditional.QuestionId = f.value;
|
|
}
|
|
}
|
|
if (this.conditional.QuestionId == null) {
|
|
this.conditional.QuestionId = 'or';
|
|
}
|
|
this.selector.val(this.conditional.QuestionId).trigger('change');
|
|
} else if (this.conditional.QuestionId?.length > 0) {
|
|
setTimeout(this.fill.bind(this), 10);
|
|
}
|
|
};
|
|
|
|
var conditionalWrapper = function (module, key, pagemodule) {
|
|
this.module = module;
|
|
this.key = key;
|
|
this.pagemodule = pagemodule;
|
|
var conditional = module.conditional;
|
|
if (conditional == null) {
|
|
conditional = module[key].Conditional;
|
|
}
|
|
if (conditional == null) {
|
|
conditional = { SubItems: [] };
|
|
}
|
|
module.conditional = conditional;
|
|
var root = new conditionalTree(this, conditional, true);
|
|
this.root = root;
|
|
};
|
|
|
|
conditionalWrapper.prototype.refresh = function () {
|
|
this.root.refresh();
|
|
};
|
|
|
|
Object.defineProperty(conditionalWrapper.prototype, 'tree', {
|
|
get: function () {
|
|
return this.root.tree;
|
|
}
|
|
});
|
|
|
|
conditionalWrapper.prototype.init = function () {
|
|
var idIndex = this.module.idIndex;
|
|
var array = this.pagemodule.sectionmodules.reduce(function (array, s) {
|
|
return array.concat(s.questionmodules.filter(function (q) {
|
|
return (
|
|
allowConditionQuestions.includes(Number(q.question.QuestionType)) ||
|
|
(q.question.QuestionType == fuelRecordsType && numberSubTypes.concat(dropSubTypes).includes(Number(q.question.SubType)))
|
|
) &&
|
|
idIndex > q.idIndex &&
|
|
(q.question.QuestionType != dropdownType || !bannedLookupSources.includes(Number(q.question.LookupSource)))
|
|
}));
|
|
}, []);
|
|
return array.length > 0;
|
|
};
|
|
|
|
conditionalWrapper.prototype.getConditional = function (nocheck, alerttitle) {
|
|
var module = this.module;
|
|
var conditional = module.conditional;
|
|
if (conditional != null) {
|
|
var questionTitle = '#' + module.idIndex + ' - ' + module[this.key].DisplayText + '\n\n';
|
|
var questions = this.pagemodule.sectionmodules.reduce(function (array, s) {
|
|
return array.concat(s.questionmodules.map(function (q) { return q }));
|
|
}, []);
|
|
var checkConditional = function (c) {
|
|
if (c.QuestionId == null || c.QuestionId == '-') {
|
|
if (c.SubItems?.length > 0) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_MUSTBEORAND', 'If there are child nodes, the root must be "OR" or "AND".'), alerttitle);
|
|
return false;
|
|
}
|
|
return 'null';
|
|
} else if (c.QuestionId == 'or' || c.QuestionId == 'and') {
|
|
if (c.SubItems == null || c.SubItems.length == 0) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_NOSUBITEMS', 'When the parent node is "OR" or "AND", the child node cannot be empty.'), alerttitle);
|
|
return false;
|
|
}
|
|
for (var i = c.SubItems.length - 1; i >= 0; i--) {
|
|
var sub = c.SubItems[i];
|
|
var result = checkConditional(sub);
|
|
if (result === false) {
|
|
return false;
|
|
} else if (result === 'null') {
|
|
c.SubItems.splice(i, 1);
|
|
}
|
|
}
|
|
if (c.SubItems.length === 0) {
|
|
return 'null';
|
|
}
|
|
} else {
|
|
var qmodule = questions.find(function (q) { return q.question.Id == c.QuestionId });
|
|
var q = qmodule?.question;
|
|
if (q == null) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_NOTFOUNDQUESTION', 'Could not find the specified question: {name}.').replace('{name}', c.QuestionId), alerttitle);
|
|
return false;
|
|
}
|
|
var qname = q.DisplayText || q.Name;
|
|
if (c.Operator == null || c.Operator.length == 0) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_INVALIDOPERATOR', 'Invalid operator of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
if (c.Value == null || c.Value.length == 0) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_VALUEREQUIRED', 'The conditional value is required of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
if (c.Operator == 'between' && (c.Value1 == null || c.Value1.length == 0)) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_VALUE2REQUIRED', 'If the operator is "Between", both of the values are required of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
// validate question index
|
|
if (qmodule.idIndex > module.idIndex) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_INVALIDQUESTION', 'You can only set a previous question to be a conditional one: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
return 'null';
|
|
}
|
|
// validate question value
|
|
var qtype = Number(q.QuestionType);
|
|
var stype = Number(q.SubType);
|
|
var isnumber = numberQuestionTypes.includes(qtype);
|
|
var isdrop = dropQuestionTypes.includes(qtype);
|
|
isnumber |= qtype == fuelRecordsType && numberSubTypes.includes(stype);
|
|
isdrop |= qtype == fuelRecordsType && dropSubTypes.includes(stype);
|
|
if (isnumber) {
|
|
var nvalue = Number(c.Value);
|
|
var n2value = Number(c.Value1);
|
|
if (isNaN(nvalue)) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_ISVALUENAN', 'Invalid number of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
if (c.Operator == 'between' && isNaN(n2value)) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_ISVALUE2NAN', 'Invalid end number of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
if (integerQuestionTypes.includes(qtype) || (qtype == fuelRecordsType && integerSubTypes.includes(stype))) {
|
|
// integer
|
|
if (Math.floor(nvalue) != nvalue) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_ISVALUENOTINTEGER', 'Invalid integer of question: {name}.').replace('{name}', q.DisplayText || q.Name), alerttitle);
|
|
return false;
|
|
}
|
|
if (c.Operator == 'between' && Math.floor(n2value) != n2value) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_ISVALUE2NOTINTEGER', 'Invalid end integer of question: {name}.').replace('{name}', q.DisplayText || q.Name), alerttitle);
|
|
return false;
|
|
}
|
|
}
|
|
if (c.Operator == 'between' && n2value < nvalue) {
|
|
showAlert(questionTitle + GetTextByKey('P_CDH_INVALIDVALUERANGE', 'The end number must be greater than or equal to the start number of question: {name}.').replace('{name}', qname), alerttitle);
|
|
return false;
|
|
}
|
|
} else if (!isdrop) {
|
|
//showAlert(questionTitle + 'The question type is not supported: ' + qname + '.', alerttitle);
|
|
//return false;
|
|
return 'null';
|
|
}
|
|
}
|
|
};
|
|
if (nocheck) {
|
|
if (conditional != null && conditional.QuestionId == null && conditional.SubItems?.length == 0) {
|
|
return null;
|
|
}
|
|
return conditional;
|
|
} else {
|
|
var result = checkConditional(conditional);
|
|
if (result === false) {
|
|
return false;
|
|
}
|
|
return result === 'null' ? null : conditional;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return conditionalWrapper;
|
|
}) |