2024-03-26 15:56:31 +08:00

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">&#x3d;</option>',
'<option value="noteq">&lt;&gt;</option>',
'<option value="gt">&gt;</option>',
'<option value="gteq">&gt;&#x3d;</option>',
'<option value="lt">&lt;</option>',
'<option value="lteq">&lt;&#x3d;</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">&#x3d;</option>',
'<option value="noteq">&lt;&gt;</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;
})