2019-03-28 15:53:31 +03:00

1513 lines
54 KiB
JavaScript

// form config.js
/* global uiLocale, urlVersions */
// from core.js
/* global isEmpty, deleteFromRest, fillSelect, MessageTypesEnum, showFeedbackMessage, getCurrentVersionData */
/* global getFromRestWithParams, getFromRest */
/* global postToRestWithVersionAndParams, putToRestWithVersionAndParams */
// TODO: settings for table selection mode (single, multiple)
var odinMetaList = "/meta/list";
var odinMetaElement = "/meta/element";
var odinCopy = "/copy-from-version";
/* exported OdinTableWithMeta */
function OdinTableWithMeta(divId, dataUrl, disableCopy) {
return OdinTableWithMetaAndParams(divId, dataUrl, "", disableCopy, "");
}
/* exported OdinTableWithMetaAndGlobalCallback */
function OdinTableWithMetaAndGlobalCallback(divId, dataUrl, disableCopy, globalSaveCallback, globalSelectCallback) {
return OdinTableWithMetaAndParams(divId, dataUrl, "", disableCopy, globalSaveCallback, globalSelectCallback);
}
/* exported OdinTableWithMetaAndParams */
function OdinTableWithMetaAndParams(divId, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback) {
return new OdinTable(divId, dataUrl + odinMetaList, dataUrl + odinMetaElement, dataUrl,
params, disableCopy, globalSaveCallback, globalSelectCallback);
}
function OdinTable(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback) {
var CLICK_DELAY = 250;
var DATA_ATTR = "odin-data";
var DATA_VIEW_ATTR = "odin-data-view";
var TYPE_ATTR = "type";
var ID_ATTR = "id";
var DISABLED_ATTR = "disabled";
var REQUIRED_ATTR = "required";
var LABELS_SELECTOR = "label";
var INPUTS_SELECTOR = ":input";
var BUTTONS_SELECTOR = ":button";
var CHECKED_ATTR = "checked";
var NOT_CHECKED_ATTR = "";
var PAGINATOR_ITEMS_PER_PAGE = 10;
var PAGINATOR_VISIBLE_BUTTONS_COUNT = 3;
var odinTable;
var L10nEnum = {
VIEW: "Наименование",
COLLECTION: "Коллеция объектов",
GO_TO: "Перейти",
BUTTON_ADD: "Добавить",
BUTTON_CREATE: "Создать",
BUTTON_EDIT: "Изменить",
BUTTON_DELETE: "Удалить",
BUTTON_COPY: "Копировать",
BUTTON_OK: "Продолжить",
BUTTON_CANCEL: "Отмена",
BUTTON_SAVE: "Записать",
BUTTON_CLOSE: "Закрыть",
CAPTION_CREATE_FORM: "Новый элемент",
CAPTION_EDIT_FORM: "(редактирование)",
CAPTION_CHOOSE_FORM: "Выбор объекта",
CAPTION_COPY_FORM: "Копирование данных",
CAPTION_DEFAULT_TAB: "Реквизиты",
CPATION_FORM_DEFAULT: "...",
QUESTION_LOST_CHANGES: "Закрыть без сохранения?",
QUESTION_DELETE_ITEM: "Выполнить удаление?",
QUESTION_DEFAULT_CAPTION: "Продолжит?",
ERROR_VERSIONS_MATCH: "Версии совпадают"
};
Object.freeze(L10nEnum);
var FieldTypesEnum = {
BOOLEAN: "boolean",
DATE: "date",
NUMERIC: "numeric",
STRING: "string",
COLLECTION: "collection",
OBJECT: "object"
};
Object.freeze(FieldTypesEnum);
var DateTypesEnum = {
DATETIME: "datetime",
DATE: "date",
TIME: "time"
};
Object.freeze(DateTypesEnum);
var StringTypesEnum = {
STRING: "string",
PASSWORD: "password",
TEXT: "text",
EMAIL: "email",
HREF: "href"
};
Object.freeze(StringTypesEnum);
var VisibleTypesEnum = {
ALL: "all",
ON_CREATE: "on_create",
ON_UPDATE: "on_update",
NONE: "none"
};
Object.freeze(VisibleTypesEnum);
var InputTypesEnum = {
CHECKBOX: "checkbox",
PASSWORD: "password",
TEXT: "text",
EMAIL: "email",
DATE: "date",
DATETIME: "datetime-local",
TIME: "time",
NUMBER: "number",
HIDDEN: "hidden",
SUBMIT: "submit"
};
Object.freeze(InputTypesEnum);
var FormTypesEnum = {
FORM: "form",
CONFIRM: "confirm",
SIMPLE: "simple"
};
Object.freeze(FormTypesEnum);
var NumberAttrEnum = {
MIN: "min",
MAX: "max",
STEP: "step"
};
Object.freeze(NumberAttrEnum);
var StringAttrEnum = {
MIN: "minlength",
MAX: "maxlength"
};
Object.freeze(StringAttrEnum);
$(document.body).append("<div id=\"odinTemplates\"></div>");
$("#odinTemplates").load("/templates/odin.html", function () {
$("#" + divId).append("<div id='preloader'>" +
" <i class='fa fa-spinner fa-spin'></i>" +
"</div>");
odinTable = new OdinTableMain(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, params, disableCopy, globalSaveCallback, globalSelectCallback);
});
this.getSelectedItems = function () {
return odinTable.getSelectedItems();
}
function format(str, args) {
if (isEmpty(str) || isEmpty(args)) {
return str;
}
if (!Array.isArray(args)) {
throw "Odin: Format args is not array";
}
return str.replace(/\{(\d+)\}/g,
function (match, number) {
return typeof args[number] !== "undefined" ?
args[number] : match;
});
}
function centerDiv(component) {
if (isEmpty(component)) {
return;
}
component.offset({
top: ($(window).height() - component.height()) / 2,
left: ($(window).width() - component.width()) / 2
});
}
function tmpl(id) {
var html = $("#odinTemplates").find("#" + id).html();
if (isEmpty(html)) {
throw "Odin: Template load error";
}
var template = format(html.trim(), Array.prototype.slice.call(arguments, 1));
return $(template);
}
function find(object, selector) {
var result = object.find(selector);
if (isEmpty(result)) {
throw "Can't find elements by selector " + selector;
}
return result;
}
function findFiltered(object, selector, notSelector) {
var result = object.find(selector).not(notSelector);
if (isEmpty(result)) {
throw "Can't find elements by selector " + selector;
}
return result;
}
function OdinFormCommon(type) {
var BUTTON_CLOSE_SELECTOR = "i.fa";
var CAPTION_SELECTOR = "#caption";
var PANEL_SELECTOR = ".panel";
var FORM_INPUTS_SELECTOR = ":input";
var DATA_CHANGED_ATTR = "changed";
var form;
var header;
var content;
var footer;
var createForm = function () {
switch (type) {
case FormTypesEnum.FORM:
form = tmpl("form");
break;
case FormTypesEnum.CONFIRM:
form = tmpl("formConfirm");
break;
default:
form = tmpl("formSimple");
}
if (isEmpty(form)) {
throw "Odin: Unknown form type";
}
header = createFormHeader();
content = createFormContent();
footer = createFormFooter();
var formPanel = tmpl("formPanel");
formPanel.append(header);
formPanel.append(content);
formPanel.append(footer);
form.append(formPanel);
setCaption(L10nEnum.CPATION_FORM_DEFAULT);
$(document.body).append(form);
};
var createFormHeader = function () {
var fHeader = tmpl("formHeader");
fHeader.find(BUTTON_CLOSE_SELECTOR).click(function () {
hideForm();
});
return fHeader;
};
var createFormContent = function () {
return tmpl("formContent");
};
var createFormFooter = function () {
return tmpl("formFooter");
};
var setCaption = function (caption) {
if (isEmpty(caption)) {
throw "Odin: Caption is not set";
}
find(header, CAPTION_SELECTOR).text(caption);
};
var addFormClass = function (clazz) {
if (isEmpty(clazz)) {
throw "Odin: Additional class is not set";
}
form.addClass(clazz);
};
var isModified = function () {
return form.data(DATA_CHANGED_ATTR);
};
var setFormSubmit = function (callBack) {
if (isEmpty(callBack)) {
throw "Odin: Callback is not set";
}
form.submit(function () {
callBack();
return false;
});
};
var showForm = function () {
form.show(0, function () {
centerDiv(find(form, PANEL_SELECTOR));
});
if (type === FormTypesEnum.FORM) {
find(form, FORM_INPUTS_SELECTOR).change(function () {
form.data(DATA_CHANGED_ATTR, true);
});
}
};
var hideForm = function () {
var callBack = function () {
form.hide();
form.remove();
};
callBack();
};
this._getHeader = function () {
return header;
};
this._getContent = function () {
return content;
};
this._getFooter = function () {
return footer;
};
this._setCaption = function (caption) {
setCaption(caption);
};
this._setFormSubmit = function (callBack) {
setFormSubmit(callBack);
};
this._addFormClass = function (clazz) {
addFormClass(clazz);
};
this._isModified = function () {
return isModified();
};
this._show = function () {
showForm();
};
this._hide = function () {
hideForm();
};
createForm();
}
function OdinToolbar(tableDiv, createCallBack, editCallBack, deleteCallBack) {
var SELECTOR_ODIN_TABLE = ".odin-table";
var toolbar;
var createButton;
var editButton;
var deleteButton;
var initialize = function () {
if (isEmpty(tableDiv)) {
throw "Odin-Toolbar: Target div is not set";
}
var table = find(tableDiv, SELECTOR_ODIN_TABLE);
toolbar = tmpl("toolbar");
toolbar.insertBefore(table, null);
if (!isEmpty(createCallBack)) {
createButton = tmpl("createButton", L10nEnum.BUTTON_CREATE);
createButton.click(function () {
createCallBack();
});
toolbar.append(createButton);
}
if (!isEmpty(editCallBack)) {
editButton = tmpl("editButton", L10nEnum.BUTTON_EDIT);
editButton.click(function () {
editCallBack();
});
setEditButtonState(false);
toolbar.append(editButton);
}
if (!isEmpty(deleteCallBack)) {
deleteButton = tmpl("deleteButton", L10nEnum.BUTTON_DELETE);
deleteButton.click(function () {
deleteCallBack();
});
setDeleteButtonState(false);
toolbar.append(deleteButton);
}
};
var setEditButtonState = function (state) {
if (isEmpty(editButton)) {
return;
}
editButton.attr("disabled", !state);
};
var setDeleteButtonState = function (state) {
if (isEmpty(deleteButton)) {
return;
}
deleteButton.attr("disabled", !state);
};
this.addButton = function (caption, callBack) {
if (isEmpty(caption) || isEmpty(callBack)) {
throw "Odin-Toolbar: Caption or callback is not set";
}
var button = tmpl("basicButton", caption);
button.click(function () {
callBack();
});
toolbar.append(button);
};
this.setEditButtonState = function (state) {
setEditButtonState(state);
};
this.setDeleteButtonState = function (state) {
setDeleteButtonState(state);
};
initialize();
}
function OdinPaginator(tableDiv, callBack) {
var SELECTOR_PAGINATOR_CONTENT = ".odin-paginator-content";
var SELECTOR_PAGINATOR_BUTTON = "a";
var PAGINATOR_BUTTON_PREFIX = "odin-paginator-";
var PAGINATOR_SELECTED_BUTTON_CLASS = "active";
var initialize = function () {
if (isEmpty(tableDiv)) {
throw "Odin-Paginator: Target div is not set";
}
if (isEmpty(callBack)) {
throw "Odin-Paginator: Callback is not set";
}
tableDiv.append(tmpl("paginator"));
};
var drawPaginator = function (data, offset) {
var paginatorContentDiv = find(tableDiv, SELECTOR_PAGINATOR_CONTENT);
paginatorContentDiv.empty();
if (isEmpty(data)) {
return;
}
$.each(data, function (index, value) {
if (value.name) {
paginatorContentDiv.append(tmpl("paginatorButton", value.offset, value.name));
} else {
paginatorContentDiv.append(tmpl("paginatorSeparator"));
}
});
var buttons = find(paginatorContentDiv, SELECTOR_PAGINATOR_BUTTON);
buttons.removeClass("active");
buttons.click(function () {
$('#preloader').show();
var offset = $(this).attr(ID_ATTR).replace(PAGINATOR_BUTTON_PREFIX, "");
callBack(offset);
});
find(paginatorContentDiv, "#" + PAGINATOR_BUTTON_PREFIX + offset)
.addClass(PAGINATOR_SELECTED_BUTTON_CLASS);
};
this.drawPaginator = function (offset, count) {
var currentOffset = parseInt(offset ? offset : "0");
var buttonCount = Math.floor(
count <= PAGINATOR_ITEMS_PER_PAGE ? 0 : count / PAGINATOR_ITEMS_PER_PAGE) +
(count < PAGINATOR_ITEMS_PER_PAGE ||
count % PAGINATOR_ITEMS_PER_PAGE === 0 ? 0 : 1);
var data = [];
Array.apply(0, Array(buttonCount)).forEach(function (element, index) {
if (index > 0 && index < buttonCount - 1 &&
buttonCount > PAGINATOR_VISIBLE_BUTTONS_COUNT * 2) {
if (index === currentOffset - PAGINATOR_VISIBLE_BUTTONS_COUNT ||
index === currentOffset + PAGINATOR_VISIBLE_BUTTONS_COUNT + 1) {
data.push({
"offset": null,
"name": null
});
}
if (index <= currentOffset - PAGINATOR_VISIBLE_BUTTONS_COUNT ||
index > currentOffset + PAGINATOR_VISIBLE_BUTTONS_COUNT) {
return true;
}
}
data.push({
"offset": index,
"name": index + 1
});
});
drawPaginator(data, currentOffset);
};
initialize();
}
function OdinTableFormatter() {
var BOOLEAN_TRUE_CLASS = "fa-check";
var BOOLEAN_FALSE_CLASS = "fa-times";
var formatBooleanValue = function (value) {
return tmpl("tableBoolean", (value ? BOOLEAN_TRUE_CLASS : BOOLEAN_FALSE_CLASS));
};
var formatDateValue = function (value, dateType) {
var date = new Date(value);
var formatterSettings = {};
switch (dateType) {
case DateTypesEnum.DATETIME:
formatterSettings = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric"
};
break;
case DateTypesEnum.TIME:
formatterSettings = {
hour: "numeric",
minute: "numeric",
second: "numeric"
};
break;
}
var dateFormatter = new Intl.DateTimeFormat(uiLocale, formatterSettings);
return dateFormatter.format(date);
};
var formatNumericValue = function (value, positiveOnly, scale) {
var numberFormatter = new Intl.NumberFormat(uiLocale, {
useGrouping: false,
minimumFractionDigits: scale
});
var formattedValue = numberFormatter.format(value);
if (positiveOnly && value < 0) {
return tmpl("tableNumericNegative", formattedValue);
}
return formattedValue;
};
var formatStringValue = function (value, maxLength, stringType) {
switch (stringType) {
case StringTypesEnum.HREF:
return tmpl("anchor", value, L10nEnum.GO_TO);
default:
if (isEmpty(maxLength) || maxLength === 0) {
return value;
}
return value.substring(0, Math.min(value.length, maxLength));
}
};
this.formatValue = function (value, fieldParams) {
if (isEmpty(value) || isEmpty(fieldParams)) {
return "";
}
if (fieldParams.hidden) {
return value;
}
switch (fieldParams.fieldType) {
case FieldTypesEnum.BOOLEAN:
return formatBooleanValue(value);
case FieldTypesEnum.DATE:
return formatDateValue(value, fieldParams.type);
case FieldTypesEnum.NUMERIC:
return formatNumericValue(value, fieldParams.positiveOnly, fieldParams.scale);
case FieldTypesEnum.STRING:
return formatStringValue(value, fieldParams.maxLength, fieldParams.type);
case FieldTypesEnum.COLLECTION:
return L10nEnum.COLLECTION;
case FieldTypesEnum.OBJECT:
return value.view;
default:
return value;
}
};
}
function OdinTableView(odinDiv, editCallback, globalSelectCallback) {
var TABLEVIEW_SELECTED_LINE_CLASS = "odin-table-selected-line";
var TABLEVIEW_LINE_SELECTOR = "tr";
var TABLEVIEW_SELECTED_LINE_SELECTOR = TABLEVIEW_LINE_SELECTOR +
"." + TABLEVIEW_SELECTED_LINE_CLASS;
var TABLEVIEW_LINE_DATA_SELECTOR = TABLEVIEW_LINE_SELECTOR +
"[" + DATA_ATTR + "=\"{0}\"]";
var TABLEVIEW_CHOOSABLE_CLASS = "table-hover odin-unselectable";
var TABLEVIEW_LINE_POINTED_CLASS = "odin-table-pointed-line";
var TABLEVIEW_HEAD_COLUMN_SELECTOR = "th:nth-child({0})";
var TABLEVIEW_BODY_COLUMN_SELECTOR = "td:nth-child({0})";
var tTable;
var tHead;
var tBody;
var choosable;
var formatter;
var toolbar;
var createLine = function (idValue) {
var prevent = false;
var timer = 0;
var newLine = tmpl("tableLine");
if (!isEmpty(idValue) && choosable) {
newLine.attr(DATA_ATTR, idValue);
newLine.click(function () {
var btn = $(this);
timer = setTimeout(function () {
if (!prevent) {
btn.toggleClass(TABLEVIEW_SELECTED_LINE_CLASS);
}
prevent = false;
if (!isEmpty(globalSelectCallback)) {
globalSelectCallback(getLines());
}
if (!isEmpty(toolbar)) {
toolbar.setEditButtonState(!isEmpty(getLines()));
toolbar.setDeleteButtonState(!isEmpty(getLines()));
}
}, CLICK_DELAY);
});
if (!isEmpty(editCallback)) {
newLine.dblclick(function () {
clearTimeout(timer);
prevent = true;
editCallback(idValue);
});
}
newLine.addClass(TABLEVIEW_LINE_POINTED_CLASS);
}
return newLine;
};
var addLineToHead = function (line) {
tHead.append(line);
};
var addLineToBody = function (line) {
tBody.append(line);
};
var clearBody = function () {
tBody.empty();
};
var initialize = function () {
if (isEmpty(odinDiv)) {
throw "Odin: Odin div is not set";
}
odinDiv.append(tmpl("table"));
tTable = find(odinDiv, "table");
tHead = find(odinDiv, "thead");
tBody = find(odinDiv, "tbody");
formatter = new OdinTableFormatter();
};
var getLines = function (isAll) {
var selector = isAll ? TABLEVIEW_LINE_SELECTOR : TABLEVIEW_SELECTED_LINE_SELECTOR;
var selectedItems = [];
try {
find(tBody, selector).each(function () {
selectedItems.push({
id: $(this).attr(DATA_ATTR),
view: $(this).attr(DATA_VIEW_ATTR)
});
});
} catch (e) {
// Ignore
}
return selectedItems;
};
var disableToolbar = function () {
if (isEmpty(toolbar)) {
return;
}
toolbar.setEditButtonState(false);
toolbar.setDeleteButtonState(false);
};
this.createHead = function (metaData, isOdinDto) {
if (isEmpty(metaData)) {
throw "Odin: Metadata is not set";
}
choosable = isOdinDto;
if (choosable) {
tTable.addClass(TABLEVIEW_CHOOSABLE_CLASS);
}
var tHeadLine = createLine();
$.each(metaData, function (index, value) {
tHeadLine.append(tmpl("tableHeadColumn", value.caption));
});
addLineToHead(tHeadLine);
$.each(metaData, function (columnIndex, columnParams) {
if (columnParams.visible === VisibleTypesEnum.NONE) {
var index = columnIndex + 1;
find(tHead, format(TABLEVIEW_HEAD_COLUMN_SELECTOR, [index])).hide();
}
});
};
this.fillBody = function (metaData, data) {
clearBody();
$.each(data, function (index, value) {
var idValue = choosable ? value.id : null;
var line = createLine(idValue);
line.attr(DATA_VIEW_ATTR, value.view);
$.each(metaData, function (columnIndex, columnParams) {
var column = tmpl("tableBodyColumn");
column.append(
formatter.formatValue(value[columnParams.fieldName],
columnParams));
line.append(column);
});
addLineToBody(line);
});
if (!isEmpty(data)) {
$.each(metaData, function (columnIndex, columnParams) {
if (columnParams.visible === VisibleTypesEnum.NONE) {
var index = columnIndex + 1;
find(tBody, format(TABLEVIEW_BODY_COLUMN_SELECTOR, [index])).hide();
}
});
}
};
this.getSelectedItems = function () {
return getLines(false);
};
this.getItems = function () {
return getLines(true);
};
// Delete form view only!
this.deleteById = function (id) {
if (isEmpty(id)) {
return;
}
try {
find(tBody, format(TABLEVIEW_LINE_DATA_SELECTOR, [id])).remove();
disableToolbar();
} catch (e) {
// Ignore
}
};
this.setToolbar = function (toolbarVar) {
toolbar = toolbarVar;
};
this.disableToolbar = function () {
disableToolbar();
};
initialize();
}
function OdinTableMain(divId, listMetaDataUrl, elementMetaDataUrl, dataUrl, args, disableCopy, globalSaveCallback, globalSelectCallback) {
if (isEmpty(divId) || isEmpty(listMetaDataUrl) || isEmpty(dataUrl)) {
throw "Odin: Not enough parameters";
}
var OFFSET_ARG = "&offset=";
var COUNT_ARG = "&count=";
var odinDiv;
var tableView;
var paginator;
var currentOffset;
var listMetaData;
var elementMetaData;
var params = isEmpty(args) ? "" : args;
var drawBody = function (offset) {
if (isEmpty(listMetaData)) {
throw "Odin: Meta data is not defined";
}
currentOffset = isEmpty(offset) ? 0 : parseInt(offset);
getFromRestWithParams(dataUrl,
OFFSET_ARG + (currentOffset * PAGINATOR_ITEMS_PER_PAGE) +
COUNT_ARG + PAGINATOR_ITEMS_PER_PAGE + params, function (data) {
if (isEmpty(data)) {
throw "Odin: Response data is null";
}
tableView.fillBody(listMetaData, data.items);
if (data.count > 0) {
paginator.drawPaginator(offset, data.count);
}
tableView.disableToolbar();
$('#preloader').hide();
});
};
var initialize = function () {
odinDiv = find($(document.body), "#" + divId);
tableView = new OdinTableView(odinDiv, editItem, globalSelectCallback);
paginator = new OdinPaginator(odinDiv, drawBody);
getFromRest(listMetaDataUrl, function (data) {
if (isEmpty(data) || isEmpty(data.fields)) {
throw "Odin: Can't load list meta data";
}
var isOdinDto = data.odinDto;
listMetaData = data.fields;
if (isOdinDto && !isEmpty(elementMetaDataUrl)) {
getFromRest(elementMetaDataUrl, function (data) {
if (isEmpty(data) || isEmpty(data.fields)) {
throw "Odin: Can't load element meta data";
}
elementMetaData = data.fields;
var toolbar = new OdinToolbar(odinDiv, createItem, editItem, deleteItem, globalSaveCallback);
tableView.setToolbar(toolbar);
if (!disableCopy) {
toolbar.addButton(L10nEnum.BUTTON_COPY, function () {
new OdinCopyBox(dataUrl, drawBody);
});
}
});
}
tableView.createHead(listMetaData, isOdinDto);
drawBody();
});
};
var updateTable = function () {
// TODO: recalculate offset before redraw table
drawBody(currentOffset);
};
var createItem = function () {
new OdinForm(elementMetaData, dataUrl, updateTable, null, params);
};
var editItem = function (value) {
if (isEmpty(elementMetaDataUrl)) {
return;
}
var curValue = value;
if (isEmpty(value)) {
var selectedItems = tableView.getSelectedItems();
if (!isEmpty(selectedItems)) {
curValue = selectedItems[0].id;
}
}
if (isEmpty(curValue)) {
return;
}
new OdinForm(elementMetaData, dataUrl, updateTable, curValue, params);
};
var deleteItem = function () {
var selectedItems = tableView.getSelectedItems();
if (isEmpty(selectedItems)) {
return;
}
var callBack = function () {
$.each(selectedItems, function (index, value) {
deleteFromRest(dataUrl + "/" + value.id, null, function () {
if (index === selectedItems.length - 1) {
updateTable();
}
});
});
};
new OdinConfirmBox(callBack, L10nEnum.QUESTION_DELETE_ITEM);
};
this.getSelectedItems = function () {
return tableView.getSelectedItems();
};
initialize();
}
function OdinFormControlGenerator() {
this.createInputGroup = function () {
return tmpl("formInputGroup");
};
this.createLabel = function (id, caption) {
return tmpl("formLabel", id, caption);
};
var createInput = function (id, value, type) {
if (isEmpty(id)) {
throw "Odin: Input id is not set";
}
if (isEmpty(type)) {
throw "Odin: Input type is not set";
}
var curValue = isEmpty(value) ? "" : value;
var wrapper = tmpl("formInputWrapper");
if (type === InputTypesEnum.CHECKBOX) {
wrapper.append(tmpl("formInputCheckbox",
id, (curValue ? CHECKED_ATTR : NOT_CHECKED_ATTR)));
} else {
wrapper.append(tmpl("formInput",
id, curValue, type));
}
return wrapper;
};
this.createBooleanInput = function (id, value) {
return createInput(id, value, InputTypesEnum.CHECKBOX);
};
var fixDateUnit = function (dateUnitValue) {
return dateUnitValue < 10 ? "0" + dateUnitValue : dateUnitValue;
};
var dateToStr = function (value, type) {
if (isEmpty(value)) {
return "";
}
var date = new Date(value);
var year = fixDateUnit(date.getFullYear());
var month = fixDateUnit(date.getMonth() + 1);
var day = fixDateUnit(date.getDate());
var hour = fixDateUnit(date.getHours());
var minute = fixDateUnit(date.getMinutes());
var formattedDate;
switch (type) {
case DateTypesEnum.DATETIME:
formattedDate = year + "-" + month + "-" + day + "T" + hour + ":" + minute;
break;
case DateTypesEnum.TIME:
formattedDate = hour + ":" + minute;
break;
default:
formattedDate = year + "-" + month + "-" + day;
}
return formattedDate;
};
this.createDateInput = function (id, value, type) {
var dateType;
switch (type) {
case DateTypesEnum.DATETIME:
dateType = InputTypesEnum.DATETIME;
break;
case DateTypesEnum.TIME:
dateType = InputTypesEnum.TIME;
break;
default:
dateType = InputTypesEnum.DATE;
}
return createInput(id, dateToStr(value, type), dateType);
};
this.createNumericInput = function (id, value) {
return createInput(id, value, InputTypesEnum.NUMBER);
};
this.createStringInput = function (id, value, type) {
var stringType;
switch (type) {
case StringTypesEnum.PASSWORD:
stringType = InputTypesEnum.PASSWORD;
break;
case StringTypesEnum.EMAIL:
stringType = InputTypesEnum.EMAIL;
break;
default:
stringType = InputTypesEnum.TEXT;
}
return createInput(id, value, stringType);
};
this.dateToStr = function (value, type) {
return dateToStr(value, type);
};
}
function OdinFormContentGenerator(createNavTabCallBack, isCreateOperation) {
var PRECISION_CHAR = "9";
var SCALE_PREFIX = "0.";
var SCALE_CHAR = "0";
var SCALE_POSTFIX = "1";
var OBJECT_INPUT_CLASS = "input-group odin-input-group";
var CREATE_BUTTON_TEXT_SELECTOR = ".btn-success > span";
var CHOOSE_BTN_SELECTOR = ".odin-choose-btn";
var CLEAR_BTN_SELECTOR = ".odin-clear-btn";
var CLEARABLE_INPUT_SELECTOR = ".form-control";
var controlGenerator = new OdinFormControlGenerator();
var createBooleanControl = function (id, caption, value) {
var group = controlGenerator.createInputGroup();
group.append(controlGenerator.createLabel(id, caption));
group.append(controlGenerator.createBooleanInput(id, value));
return group;
};
var createDateControl = function (id, caption, value, type) {
var group = controlGenerator.createInputGroup();
group.append(controlGenerator.createLabel(id, caption));
group.append(controlGenerator.createDateInput(id, value, type));
return group;
};
var createNumericControl = function (id, caption, value, positiveOnly, precision, scale) {
var group = controlGenerator.createInputGroup();
group.append(controlGenerator.createLabel(id, caption));
var control = controlGenerator.createNumericInput(id, value);
find(control, INPUTS_SELECTOR).each(function () {
var currentControl = $(this);
if (positiveOnly) {
currentControl.attr(NumberAttrEnum.MIN, 0);
}
if (precision) {
currentControl
.attr(NumberAttrEnum.MAX, Array(precision + 1).join(PRECISION_CHAR));
}
if (scale) {
var step = SCALE_PREFIX + Array(scale).join(SCALE_CHAR) + SCALE_POSTFIX;
currentControl.attr(NumberAttrEnum.STEP, step);
}
});
group.append(control);
return group;
};
var createStringControl = function (id, caption, value, minLength, maxLength, type) {
var group = controlGenerator.createInputGroup();
group.append(controlGenerator.createLabel(id, caption));
var control = controlGenerator.createStringInput(id, value, type);
find(control, INPUTS_SELECTOR).each(function () {
var currentControl = $(this);
currentControl.attr(StringAttrEnum.MIN, minLength);
currentControl.attr(StringAttrEnum.MAX, maxLength);
});
group.append(control);
return group;
};
var createCollectionControl = function (id, caption, values, path) {
// TODO: add required check if needed
var content = $(tmpl("emptyDiv"));
var tabView = new OdinTableView(content, null, null);
var createAction = function () {
new OdinChooseBox(path, function (selectedItems) {
if (isEmpty(selectedItems)) {
return;
}
var currentValues = tabView.getItems();
$.merge(currentValues, selectedItems);
var existingIDs = [];
currentValues = $.grep(currentValues, function (v) {
if ($.inArray(v.id, existingIDs) !== -1) {
return false;
} else {
existingIDs.push(v.id);
return true;
}
});
tabView.fillBody(metaData, currentValues);
});
};
var deleteAction = function () {
var callBack = function () {
$.each(tabView.getSelectedItems(), function (index, value) {
tabView.deleteById(value.id);
});
};
new OdinConfirmBox(callBack, L10nEnum.QUESTION_DELETE_ITEM);
};
content.append(tabView);
var metaData = [
{
"fieldType": "string",
"fieldName": "id",
"caption": "id",
"visible": "none"
},
{
"fieldType": "string",
"fieldName": "view",
"caption": L10nEnum.VIEW,
"visible": "all"
}
];
tabView.createHead(metaData, true);
tabView.fillBody(metaData, values);
createNavTabCallBack(id, caption, content);
var toolbar = new OdinToolbar(content, createAction, null, deleteAction);
tabView.setToolbar(toolbar);
find(content, CREATE_BUTTON_TEXT_SELECTOR).text(L10nEnum.BUTTON_ADD);
return null;
};
var createObjectControl = function (id, caption, value, path) {
// TODO: add required check if needed
var chooseInput = controlGenerator.createStringInput(
id, isEmpty(value) ? "" : value.view, StringTypesEnum.TEXT);
chooseInput.addClass(OBJECT_INPUT_CLASS);
var buttonGroup = tmpl("buttonGroup");
chooseInput.append(buttonGroup);
var chooseButton = tmpl("chooseButton");
buttonGroup.append(chooseButton);
find(buttonGroup, CHOOSE_BTN_SELECTOR).click(function () {
new OdinChooseBox(path, function (selectedItems) {
if (isEmpty(selectedItems)) {
return;
}
find(chooseInput, CLEARABLE_INPUT_SELECTOR).each(function () {
$(this)
.val(selectedItems[0].view)
.attr(DATA_ATTR, selectedItems[0].id);
});
});
});
var clearButton = tmpl("clearButton");
buttonGroup.append(clearButton);
find(buttonGroup, CLEAR_BTN_SELECTOR).click(function () {
find(chooseInput, CLEARABLE_INPUT_SELECTOR).val("");
});
find(chooseInput, CLEARABLE_INPUT_SELECTOR).each(function () {
$(this)
.attr(DISABLED_ATTR, true)
.attr(DATA_ATTR, isEmpty(value) ? "" : value.id);
});
var group = controlGenerator.createInputGroup();
group.append(controlGenerator.createLabel(id, caption));
group.append(chooseInput);
return group;
};
var configureControl = function (control, hidden, readonly, notempty) {
if (isEmpty(control)) {
return;
}
find(control, LABELS_SELECTOR).each(function () {
var currentControl = $(this);
if (hidden) {
currentControl.hide();
}
});
find(control, INPUTS_SELECTOR).each(function () {
var currentControl = $(this);
if (hidden) {
currentControl.hide();
currentControl.attr(TYPE_ATTR, InputTypesEnum.HIDDEN);
}
if (readonly) {
currentControl.attr(DISABLED_ATTR, true);
}
if (notempty) {
currentControl.attr(REQUIRED_ATTR, true);
}
});
return control;
};
this.createFormControl = function (value, fieldParams) {
if (isEmpty(fieldParams)) {
return null;
}
var control;
switch (fieldParams.fieldType) {
case FieldTypesEnum.BOOLEAN:
control = createBooleanControl(fieldParams.fieldName,
fieldParams.caption, value);
break;
case FieldTypesEnum.DATE:
control = createDateControl(fieldParams.fieldName,
fieldParams.caption, value, fieldParams.type);
break;
case FieldTypesEnum.NUMERIC:
control = createNumericControl(fieldParams.fieldName,
fieldParams.caption, value, fieldParams.positiveOnly,
fieldParams.precision, fieldParams.scale);
break;
case FieldTypesEnum.STRING:
control = createStringControl(fieldParams.fieldName,
fieldParams.caption, value, fieldParams.minLength,
fieldParams.maxLength, fieldParams.type);
break;
case FieldTypesEnum.COLLECTION:
control = createCollectionControl(fieldParams.fieldName,
fieldParams.caption, value, fieldParams.path);
break;
case FieldTypesEnum.OBJECT:
control = createObjectControl(fieldParams.fieldName,
fieldParams.caption, value, fieldParams.path);
break;
default:
return null;
}
var hidden;
switch (fieldParams.visible) {
case VisibleTypesEnum.NONE:
hidden = true;
break;
case VisibleTypesEnum.ON_CREATE:
case VisibleTypesEnum.ON_UPDATE:
hidden = isCreateOperation;
break;
default:
hidden = false;
}
return configureControl(control, hidden, fieldParams.readOnly, fieldParams.notEmpty);
};
this.getCurrentDateStr = function () {
return controlGenerator.dateToStr(new Date(), DateTypesEnum.DATE);
};
}
function OdinForm(metaData, dataUrl, tableCallBack, id, args) {
if (isEmpty(metaData) || isEmpty(dataUrl) || isEmpty(tableCallBack)) {
throw "Odin: Not enough parameters";
}
var DEFAULT_TAB_SELECTOR = "odin-values";
var TABS_HEADER_SELECTOR = ".nav-tabs";
var TABS_CONTENT_SELECTOR = ".tab-content";
var TAB_SELECTOR = ".tab-pane";
var COLLECTION_ITEM_SELECTOR = "tbody > tr";
OdinFormCommon.call(this, FormTypesEnum.FORM);
var self = this;
var generator;
var params = isEmpty(args) ? "" : args;
var isCreateForm = function () {
return isEmpty(id);
};
var formToJson = function () {
var formData = {};
try {
findFiltered(self._getContent(), TAB_SELECTOR, "#" + DEFAULT_TAB_SELECTOR)
.each(function () {
var tabData = [];
try {
find($(this), COLLECTION_ITEM_SELECTOR)
.each(function () {
if ($(this).attr(DATA_ATTR)) {
tabData.push({
id: $(this).attr(DATA_ATTR),
view: $(this).attr(DATA_VIEW_ATTR)
});
return true;
}
});
} catch (e) {
// Ignore
}
formData[$(this).attr(ID_ATTR)] = tabData;
});
} catch (e) {
// Ignore
}
findFiltered(self._getContent(), INPUTS_SELECTOR, BUTTONS_SELECTOR)
.each(function () {
if (isEmpty($(this).val())) {
return true;
}
if ($(this).attr(DATA_ATTR)) {
formData[$(this).attr(ID_ATTR)] = {
id: $(this).attr(DATA_ATTR),
view: $(this).val()
};
return true;
}
switch ($(this).attr(TYPE_ATTR)) {
case InputTypesEnum.CHECKBOX:
formData[$(this).attr(ID_ATTR)] = $(this).is(":" + CHECKED_ATTR);
break;
case InputTypesEnum.DATE:
case InputTypesEnum.DATETIME:
formData[$(this).attr(ID_ATTR)] = isEmpty($(this).val) ?
"" : Date.parse($(this).val());
break;
case InputTypesEnum.TIME:
formData[$(this).attr(ID_ATTR)] = isEmpty($(this).val) ?
"" : Date.parse(generator.getCurrentDateStr() +
"T" + $(this).val());
break;
case InputTypesEnum.NUMBER:
formData[$(this).attr(ID_ATTR)] = parseFloat($(this).val());
break;
default:
formData[$(this).attr(ID_ATTR)] = $(this).val();
}
});
return JSON.stringify(formData);
};
var initialize = function () {
generator = new OdinFormContentGenerator(createNavTab, isCreateForm());
self._getContent()
.append(tmpl("formTabs", DEFAULT_TAB_SELECTOR, L10nEnum.CAPTION_DEFAULT_TAB));
var okBtn = tmpl("okButton", L10nEnum.BUTTON_SAVE);
okBtn.attr(TYPE_ATTR, InputTypesEnum.SUBMIT);
var closeBtn = tmpl("cancelButton", L10nEnum.BUTTON_CLOSE);
self._getFooter().append(closeBtn);
self._getFooter().append(okBtn);
if (isCreateForm()) {
configureAndShowForm();
} else {
getFromRest(dataUrl + "/" + id, function (data) {
if (isEmpty(data)) {
throw format("Odin: Can't load data by id {0} and url {1}", [id, dataUrl]);
}
configureAndShowForm(data);
});
}
closeBtn.click(function () {
closeForm();
});
};
var configureAndShowForm = function (data) {
var saveCallBack = function () {
saveData(formToJson());
};
self._setCaption(isEmpty(data) ?
L10nEnum.CAPTION_CREATE_FORM :
data.view + " " + L10nEnum.CAPTION_EDIT_FORM);
self._setFormSubmit(saveCallBack);
$.each(metaData, function (fieldIndex, fieldParams) {
var value = isEmpty(data) ?
null : data[fieldParams.fieldName];
find(self._getContent(), "#" + DEFAULT_TAB_SELECTOR)
.append(generator.createFormControl(value, fieldParams));
});
self._show();
};
var createNavTab = function (id, caption, content) {
find(self._getContent(), TABS_HEADER_SELECTOR).append(tmpl("formTab", id, caption));
var tab = tmpl("formTabContent", id);
tab.append(content);
find(self._getContent(), TABS_CONTENT_SELECTOR).append(tab);
};
var saveData = function (data) {
var saveCallback = function (responseData) {
if (isEmpty(responseData)) {
throw "Odin: Error on data save";
}
self._hide();
tableCallBack();
if (!isEmpty(globalSaveCallback)) {
globalSaveCallback();
}
};
if (isCreateForm()) {
postToRestWithParams(dataUrl, data, params, saveCallback);
} else {
putToRestWithParams(dataUrl, data, params, saveCallback);
}
};
var closeForm = function () {
if (self._isModified()) {
new OdinConfirmBox(self._hide, L10nEnum.QUESTION_LOST_CHANGES);
return;
}
self._hide();
};
initialize();
}
function OdinConfirmBox(callBack, questionText) {
if (isEmpty(callBack) || isEmpty(questionText)) {
throw "Odin: Not enough parameters";
}
OdinFormCommon.call(this, FormTypesEnum.CONFIRM);
var self = this;
var initialize = function () {
var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK);
var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL);
self._setCaption(L10nEnum.QUESTION_DEFAULT_CAPTION);
self._getContent().text(questionText);
self._getFooter().append(yesBtn);
self._getFooter().append(cancelBtn);
self._show();
yesBtn.click(function () {
self._hide();
callBack();
if (!isEmpty(globalSaveCallback)) {
globalSaveCallback();
}
});
cancelBtn.click(function () {
self._hide();
});
};
initialize();
}
function OdinChooseBox(path, callBack) {
if (isEmpty(path) || isEmpty(callBack)) {
throw "Odin: Not enough parameters";
}
var ADDITIONAL_FORM_CLASS = "odin-table-box";
var ADDITIONAL_CONTENT_CLASS = "odin-kill-padding";
var CONTENT_ID_VALUE = "table-block";
OdinFormCommon.call(this);
var self = this;
var initialize = function () {
self._addFormClass(ADDITIONAL_FORM_CLASS);
self._getContent().addClass(ADDITIONAL_CONTENT_CLASS);
self._getContent().attr(ID_ATTR, CONTENT_ID_VALUE);
var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK);
var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL);
self._getFooter().append(cancelBtn);
self._getFooter().append(yesBtn);
var table = new OdinTableMain("table-block", path + odinMetaList, null, path);
self._show();
yesBtn.click(function () {
self._hide();
callBack(table.getSelectedItems());
});
cancelBtn.click(function () {
self._hide();
});
};
initialize();
}
function OdinCopyBox(dataUrl, tableRedrawCallback) {
if (isEmpty(dataUrl) || isEmpty(tableRedrawCallback)) {
throw "Odin: Not enough parameters";
}
var ADDITIONAL_FORM_CLASS = "odin-simple-form";
var FROM_VERSION_SELECTOR = "#fromVersion";
var VERSION_SELECTOR = "#version";
OdinFormCommon.call(this);
var self = this;
var initialize = function () {
self._setCaption(L10nEnum.CAPTION_COPY_FORM);
self._addFormClass(ADDITIONAL_FORM_CLASS);
self._getContent().append(tmpl("copyForm"));
var from = find(self._getContent(), FROM_VERSION_SELECTOR);
var to = find(self._getContent(), VERSION_SELECTOR);
var yesBtn = tmpl("okButton", L10nEnum.BUTTON_OK);
var cancelBtn = tmpl("cancelButton", L10nEnum.BUTTON_CANCEL);
self._getFooter().append(cancelBtn);
self._getFooter().append(yesBtn);
/*getFromRest(urlVersions, function (versions) {
if (isEmpty(versions) || versions.count === 0) {
return;
}
var versionsData = [];
versions.items.forEach(function (version) {
versionsData.push({
id: version.id,
name: version.name + " от " +
new Date(version.date).toLocaleDateString(uiLocale)
});
});
fillSelect(from, versionsData.sort(function (a, b) {
return a.id - b.id;
}));
var currentVersion = getCurrentVersionData();
if (!isEmpty(currentVersion)) {
to.attr(DATA_ATTR, currentVersion.id);
to.val(currentVersion.name);
}
self._show();
});*/
yesBtn.click(function () {
if (isEmpty(from.val()) || isEmpty(to.val())) {
return;
}
if (from.val() === to.attr(DATA_ATTR)) {
showFeedbackMessage(L10nEnum.ERROR_VERSIONS_MATCH, MessageTypesEnum.DANGER);
return;
}
postToRestWithVersionAndParams(dataUrl + odinCopy, null,
"&fromVersionId=" + from.val(), function () {
self._hide();
tableRedrawCallback();
});
});
cancelBtn.click(function () {
self._hide();
});
};
initialize();
}
}