namespace("kivi", function(ns) {
+ "use strict";
+
ns._locale = {};
ns._date_format = {
sep: '.',
};
ns.parse_amount = function(amount) {
- if ((amount == undefined) || (amount == ''))
+ if ((amount === undefined) || (amount === ''))
return 0;
if (ns._number_format.decimalSep == ',')
amount = amount.replace(/[\',]/g, "")
- return eval(amount);
+ // Make sure no code wich is not a math expression ends up in eval().
+ if (!amount.match(/^[0-9 ()\-+*/.]*$/))
+ return 0;
+
+ /* jshint -W061 */
+ try {
+ return eval(amount);
+ } catch (err) {
+ return 0;
+ }
};
ns.round_amount = function(amount, places) {
ns.format_amount = function(amount, places) {
amount = amount || 0;
- if ((places != undefined) && (places >= 0))
+ if ((places !== undefined) && (places >= 0))
amount = ns.round_amount(amount, Math.abs(places));
var parts = ("" + Math.abs(amount)).split(/\./);
var dec = parts.length > 1 ? parts[1] : "";
var sign = amount < 0 ? "-" : "";
- if (places != undefined) {
+ if (places !== undefined) {
while (dec.length < Math.abs(places))
dec += "0";
dec = d.substr(0, places);
}
- if ((ns._number_format.thousandSep != "") && (intg.length > 3)) {
+ if ((ns._number_format.thousandSep !== "") && (intg.length > 3)) {
var len = ((intg.length + 2) % 3) + 1,
start = len,
res = intg.substr(0, len);
intg = res;
}
- var sep = (places != 0) && (dec != "") ? ns._number_format.decimalSep : "";
+ var sep = (places !== 0) && (dec !== "") ? ns._number_format.decimalSep : "";
return sign + intg + sep + dec;
};
$(elt).datepicker();
});
- if (ns.PartPicker)
- ns.run_once_for('input.part_autocomplete', 'part_picker', function(elt) {
- kivi.PartPicker($(elt));
- });
+ if (ns.Part) ns.Part.reinit_widgets();
if (ns.ProjectPicker)
ns.run_once_for('input.project_autocomplete', 'project_picker', function(elt) {
return true;
};
+ // This function submits an existing form given by "form_selector"
+ // and sets the "action" input to "action_to_call" before submitting
+ // it. Any existing input named "action" will be removed prior to
+ // submitting.
+ ns.submit_form_with_action = function(form_selector, action_to_call) {
+ $('[name=action]').remove();
+
+ var $form = $(form_selector);
+ var $hidden = $('<input type=hidden>');
+
+ $hidden.attr('name', 'action');
+ $hidden.attr('value', action_to_call);
+ $form.append($hidden);
+
+ $form.submit();
+ };
+
+ // This function exists solely so that it can be found with
+ // kivi.get_functions_by_name() and called later on. Using something
+ // like "var func = history["back"]" works, but calling it later
+ // with "func.apply()" doesn't.
+ ns.history_back = function() {
+ history.back();
+ };
+
// Return a function object by its name (a string). Works both with
// global functions (e.g. "check_right_date_format") and those in
// namespaces (e.g. "kivi.t8").
params.dialog || { },
{ // Options that must not be changed:
close: function(event, ui) {
+ dialog.dialog('close');
+
if (custom_close)
custom_close();
if (params.url || params.html)
dialog.remove();
- else
- dialog.dialog('close');
}
});
return;
}
- $(selector).filter(function() { return $(this).data(attr_name) != true; }).each(function(idx, elt) {
+ $(selector).filter(function() { return $(this).data(attr_name) !== true; }).each(function(idx, elt) {
var $elt = $(elt);
$elt.data(attr_name, true);
fn($elt);
ns.run = function(function_name, args) {
var fn = ns.get_function_by_name(function_name);
if (fn)
- return fn.apply({}, args);
+ return fn.apply({}, args || []);
console.error('kivi.run("' + function_name + '"): No function by that name found');
return undefined;
};
+
+ ns.detect_duplicate_ids_in_dom = function() {
+ var ids = {},
+ found = false;
+
+ $('[id]').each(function() {
+ if (this.id && ids[this.id]) {
+ found = true;
+ console.warn('Duplicate ID #' + this.id);
+ }
+ ids[this.id] = 1;
+ });
+
+ if (!found)
+ console.log('No duplicate IDs found :)');
+ };
+
+ // Verifies that at least one checkbox matching the
+ // "checkbox_selector" is actually checked. If not, an error message
+ // is shown, and false is returned. Otherwise (at least one of them
+ // is checked) nothing is shown and true returned.
+ //
+ // Can be used in checks when clicking buttons.
+ ns.check_if_entries_selected = function(checkbox_selector) {
+ if ($(checkbox_selector + ':checked').length > 0)
+ return true;
+
+ alert(kivi.t8('No entries have been selected.'));
+
+ return false;
+ };
+
+ // Performs various validation steps on the descendants of
+ // 'selector'. Elements that should be validated must have an
+ // attribute named "data-validate" which is set to a space-separated
+ // list of tests to perform. Additionally, the attribute
+ // "data-title" must be set to a human-readable name of the field
+ // that can be shown as part of an error message.
+ //
+ // Supported validation tests are:
+ // - "required": the field must be set (its .val() must not be empty)
+ //
+ // The validation will abort and return "false" as soon as
+ // validation routine fails.
+ //
+ // The function returns "true" if all validations succeed for all
+ // elements.
+ ns.validate_form = function(selector) {
+ var validate_field = function(elt) {
+ var $elt = $(elt);
+ var tests = $elt.data('validate').split(/ +/);
+ var info = {
+ title: $elt.data('title'),
+ value: $elt.val(),
+ };
+
+ for (var test_idx in tests) {
+ var test = tests[test_idx];
+
+ if (test === "required") {
+ if ($elt.val() === '') {
+ alert(kivi.t8("The field '#{title}' must be set.", info));
+ return false;
+ }
+
+ } else {
+ var error = "kivi.validate_form: unknown test '" + test + "' for element ID '" + $elt.prop('id') + "'";
+ console.error(error);
+ alert(error);
+
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ selector = selector || '#form';
+ var ok = true;
+ var to_check = $(selector + ' [data-validate]').toArray();
+
+ for (var to_check_idx in to_check)
+ if (!validate_field(to_check[to_check_idx]))
+ return false;
+
+ return true;
+ };
});
kivi = namespace('kivi');