I am developing a query builder which consumes OData Web API (won't go into details on how it works in the back end).
I have this EDM/Metadata which I am using to generate UI components. I created a JSFiddle as well. Is there any way I can improve this code?
function init() {
$container = $("#container");
$queryBuilderForm = $('<form autocomplete="off" id="queryBuilderForm"><div id="url" style=""></div><button id="btnUpdateUrl" type="button">Update Url</button></form>');
$container.append($queryBuilderForm);
$entityFilters = $("<div id='entityFilters'></div>");
$queryBuilderForm.append($entityFilters);
}
function processData() {
this.metadata = getMetadata();
for (var e in this.metadata.dataServices.schema) {
var schema = this.metadata.dataServices.schema[e];
if (schema.entityType) {
entities = schema.entityType;
break;
}
}
}
function addExpand(id, options) {
var generateOptions = constructOptions(options, true);
$entityFilters.append($([
'<div id="entityFilter_' + id + '" class="entity-filter">',
'<select id="entities_' + id + '">', generateOptions, '</select>',
'<div id="entities_' + id + '_cols"></div>',
'</div>'
].join('')));
function constructOptions(options, addEmptySelect) {
var opt = [];
if (addEmptySelect) {
opt.push('<option value=-1> -- Select -- </option>');
}
$.each(options, function(index, e) {
opt.push('<option value=' + e.name + '>' + e.name + '</option>');
});
return opt.join('');
}
}
function addEvents(id) {
var $entities = $('#entities_' + id);
$('body').on('change', $entities, function(event) {
var $e = $(event.target);
var entityName = singularize($e.val());
var entity = $.grep(entities, function(e) {
return e.name == entityName;
})[0];
var columns = entity.property; // if index is not -1
$e.parent().nextAll(".entity-filter").remove();
var $entities_cols = $e.next().empty();
$.each(columns, function(index, e) {
var selectColumnHtmlId = 'selectcolumn_' + e.name;
var $selectColumnLabel = $('<label />', {
'for': selectColumnHtmlId,
text: e.name
});
$selectColumnLabel.appendTo($entities_cols);
$('<input />', {
type: 'checkbox',
id: selectColumnHtmlId,
value: e.name
}).prependTo($selectColumnLabel);
});
if ($(".entity-filter").length < config.expandLimit)
addExpand($(".entity-filter").length, entity.navigationProperty);
});
$("#btnUpdateUrl").on("click", function() {
updateUrl();
})
}
function updateUrl() {
var temp_ents = "";
var temp_path = "";
var temp_paths = [];
var temp_cols = "&$select="; // if no expand remove "&"
$("#entityFilters select").each(function(ei, ed) {
if (ei === 1)
temp_ents = temp_ents + "?$expand=";
else {
temp_ents = temp_ents + "/";
}
temp_ents = temp_ents + (ei === 0 ? singularize($(ed).val(), true) : $(ed).val());
if (ei !== 0)
temp_path = temp_path + (temp_path ? "/" : "") + $(ed).val();
$(this).siblings().find("input:checked").each(function(ci, cd) {
if (ei !== 0) {
temp_cols = temp_cols + temp_path + "/"
}
temp_cols = temp_cols + $(this).val() + ",";
});
temp_paths.push(temp_path + (temp_path ? ", " : ""));
});
console.log(temp_ents + temp_cols);
$("#url").text(temp_ents + temp_cols);
}
function singularize(s, reverse) {
if (s.endsWith("1") || s.endsWith("2"))
s = s.substring(0, s.length - 1);
for (var i = 0; i < entityMapping.length; ++i) {
var e = entityMapping[i];
if (reverse) {
if (e[0] === s)
return e[1];
} else {
if (e[1] === s)
return e[0];
}
}
return s;
}
var config = {
expandLimit: 3,
};
var entityMapping = [
['Address', 'Addresses'],
['Category', 'Categories']
];
var $container;
var $queryBuilderForm;
var $entityFilters;
var entities;
init();
processData();
addExpand(1, entities);
addEvents(1);
.entity-filter {
min-height: 200px;
max-width: 200px;
float: left;
}
.entity-filter label {
display: block
}
.entity-filter>div {
max-height: 400px;
overflow-y: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container"></div>
Edit
I had to remove metadata from this question as it was too much, it is still in JSFiddle added with full working example. Thanks