grocy/public/js/grocy.js
Bernd Bestel a3617cffb8
Small different UI improvements
Show the cursor as pointer on stock overview page while hovering the product name cell to highlight that the productcard can be opened
Show a waiting cursor and disable all form inputs while doing background XHR calls to highlight that the user should wait
Place the search field (to search a table) on all pages to the left most place
2018-11-24 19:40:50 +01:00

386 lines
7.7 KiB
JavaScript

L = function(text, ...placeholderValues)
{
var localizedText = Grocy.LocalizationStrings[text];
if (localizedText === undefined)
{
if (Grocy.Mode === 'dev')
{
jsonData = {};
jsonData.text = text;
Grocy.Api.Post('system/log-missing-localization', jsonData,
function(result)
{
// Nothing to do...
},
function(xhr)
{
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
}
);
}
localizedText = text;
}
for (var i = 0; i < placeholderValues.length; i++)
{
localizedText = localizedText.replace('#' + (i + 1), placeholderValues[i]);
}
return localizedText;
}
U = function(relativePath)
{
return Grocy.BaseUrl.replace(/\/$/, '') + relativePath;
}
Pluralize = function(number, singularForm, pluralForm)
{
var text = singularForm;
if (number != 1 && pluralForm !== null && !pluralForm.isEmpty())
{
text = pluralForm;
}
return text;
}
if (!Grocy.ActiveNav.isEmpty())
{
var menuItem = $('#sidebarResponsive').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
menuItem.addClass('active-page');
var parentMenuSelector = menuItem.data("sub-menu-of");
if (typeof parentMenuSelector !== "undefined")
{
$(parentMenuSelector).collapse("show");
$(parentMenuSelector).prev(".nav-link-collapse").addClass("active-page");
}
}
var observer = new MutationObserver(function(mutations)
{
mutations.forEach(function(mutation)
{
if (mutation.attributeName === "class")
{
var attributeValue = $(mutation.target).prop(mutation.attributeName);
if (attributeValue.contains("sidenav-toggled"))
{
window.localStorage.setItem("sidebar_state", "collapsed");
}
else
{
window.localStorage.setItem("sidebar_state", "expanded");
}
}
});
});
observer.observe(document.body, {
attributes: true
});
if (window.localStorage.getItem("sidebar_state") === "collapsed")
{
$("#sidenavToggler").click();
}
$.timeago.settings.allowFuture = true;
RefreshContextualTimeago = function()
{
$("time.timeago").each(function()
{
var element = $(this);
var timestamp = element.attr("datetime");
element.timeago("update", timestamp);
});
}
RefreshContextualTimeago();
toastr.options = {
toastClass: 'alert',
closeButton: true,
timeOut: 20000,
extendedTimeOut: 5000
};
window.FontAwesomeConfig = {
searchPseudoElements: true
}
// Don't show tooltips on touch input devices
if (IsTouchInputDevice())
{
var css = document.createElement("style");
css.innerHTML = ".tooltip { display: none; }";
document.body.appendChild(css);
}
Grocy.Api = { };
Grocy.Api.Get = function(apiFunction, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
if (xhr.status === 200)
{
if (success)
{
success(JSON.parse(xhr.responseText));
}
}
else
{
if (error)
{
error(xhr);
}
}
}
};
xhr.open('GET', url, true);
xhr.send();
};
Grocy.Api.Post = function(apiFunction, jsonData, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/' + apiFunction);
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
if (xhr.status === 200)
{
if (success)
{
success(JSON.parse(xhr.responseText));
}
}
else
{
if (error)
{
error(xhr);
}
}
}
};
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify(jsonData));
};
Grocy.Api.UploadFile = function(file, group, fileName, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/file/' + group + '?file_name=' + encodeURIComponent(fileName));
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
if (xhr.status === 200)
{
if (success)
{
success(JSON.parse(xhr.responseText));
}
}
else
{
if (error)
{
error(xhr);
}
}
}
};
xhr.open('PUT', url, true);
xhr.setRequestHeader('Content-type', 'application/octet-stream');
xhr.send(file);
};
Grocy.Api.DeleteFile = function(fileName, group, success, error)
{
var xhr = new XMLHttpRequest();
var url = U('/api/file/' + group + '?file_name=' + encodeURIComponent(fileName));
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE)
{
if (xhr.status === 200)
{
if (success)
{
success(JSON.parse(xhr.responseText));
}
}
else
{
if (error)
{
error(xhr);
}
}
}
};
xhr.open('DELETE', url, true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send();
};
Grocy.FrontendHelpers = { };
Grocy.FrontendHelpers.ValidateForm = function(formId)
{
var form = document.getElementById(formId);
if (form.checkValidity() === true)
{
$(form).find(':submit').removeClass('disabled');
}
else
{
$(form).find(':submit').addClass('disabled');
}
$(form).addClass('was-validated');
}
Grocy.FrontendHelpers.BeginUiBusy = function(formId = null)
{
$("body").addClass("cursor-busy");
if (formId !== null)
{
$("#" + formId + " :input").attr("disabled", true);
}
}
Grocy.FrontendHelpers.EndUiBusy = function(formId = null)
{
$("body").removeClass("cursor-busy");
if (formId !== null)
{
$("#" + formId + " :input").attr("disabled", false);
}
}
Grocy.FrontendHelpers.ShowGenericError = function(message, exception)
{
toastr.error(L(message) + '<br><br>' + L('Click to show technical details'), '', {
onclick: function()
{
bootbox.alert({
title: L('Error details'),
message: JSON.stringify(exception, null, 4)
});
}
});
console.error(exception);
}
$("form").on("keyup paste", "input, textarea", function()
{
$(this).closest("form").addClass("is-dirty");
});
$("form").on("click", "select", function()
{
$(this).closest("form").addClass("is-dirty");
});
// Auto saving user setting controls
$(".user-setting-control").on("change", function()
{
var element = $(this);
var settingKey = element.attr("data-setting-key");
var inputType = "unknown";
if (typeof element.attr("type") !== typeof undefined && element.attr("type") !== false)
{
inputType = element.attr("type").toLowerCase();
}
if (inputType === "checkbox")
{
value = element.is(":checked");
}
else
{
var value = element.val();
}
Grocy.UserSettings[settingKey] = value;
jsonData = { };
jsonData.value = value;
Grocy.Api.Post('user/settings/' + settingKey, jsonData,
function(result)
{
// Nothing to do...
},
function(xhr)
{
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
}
);
});
// Show file name Bootstrap custom file input
$('input.custom-file-input').on('change', function()
{
$(this).next('.custom-file-label').html(GetFileNameFromPath($(this).val()));
});
// Translation of "Browse"-button of Bootstrap custom file input
if ($(".custom-file-label").length > 0)
{
$("<style>").html('.custom-file-label::after { content: "' + L("Select file") + '"; }').appendTo("head");
}
ResizeResponsiveEmbeds = function(fillEntireViewport = false)
{
if (!fillEntireViewport)
{
var maxHeight = $("body").height() - $("#mainNav").outerHeight() - 62;
}
else
{
var maxHeight = $("body").height();
}
$(".embed-responsive").attr("height", maxHeight.toString() + "px");
}
$(window).on('resize', function()
{
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-card"));
});
$("iframe").on("load", function()
{
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-card"));
});
function WindowMessageBag(message, payload = null)
{
var obj = { };
obj.Message = message;
obj.Payload = payload;
return obj;
}
// Add border around anchor link section
if (window.location.hash)
{
$(window.location.hash).addClass("p-2 border border-info rounded");
}