spejstore/static/admin/js/django_admin_hstore_widget/django_admin_hstore_widget.js

217 lines
6.6 KiB
JavaScript

var initDjangoHStoreWidget = function (hstore_field_name, inline_prefix) {
// ignore inline templates
// if hstore_field_name contains "__prefix__"
if (hstore_field_name.indexOf("__prefix__") > -1) {
return;
}
var $ = django.jQuery;
// processing inlines
if (hstore_field_name.indexOf("inline") > -1) {
var inlineClass = $("#id_" + hstore_field_name)
.parents(".inline-related, .grp-group")
.attr("class");
// if using TabularInlines stop here
// TabularInlines not supported
if (inlineClass.indexOf("tabular") > -1) {
return;
}
}
// reusable function that retrieves a template even if ID is not correct
// (written to support inlines)
var retrieveTemplate = function (template_name, field_name) {
var specific_template = $("#" + template_name + "-" + field_name);
// if found specific template return that
if (specific_template.length) {
return specific_template.html();
} else {
// get fallback template
var html = $("." + template_name + "-inline").html();
// replace all occurrences of __prefix__ with field_name
// and return
html = html.replace(/__prefix__/g, inline_prefix);
return html;
}
};
// reusable function that compiles the UI
var compileUI = function (params) {
var hstore_field_id = "id_" + hstore_field_name,
original_textarea = $("#" + hstore_field_id),
original_value = original_textarea.val(),
original_container = original_textarea
.parents(".form-row, .grp-row")
.eq(0),
errorHtml = original_container.find(".errorlist").html(),
json_data = {};
if (original_value !== "") {
// manage case in which textarea is blank
try {
json_data = JSON.parse(original_value);
} catch (e) {
alert("invalid JSON:\n" + e);
return false;
}
}
var hstore_field_data = {
id: hstore_field_id,
label: original_container.find("label").text(),
name: hstore_field_name,
value: original_textarea.val(),
help: original_container.find(".grp-help, .help").text(),
errors: errorHtml,
data: json_data,
},
// compile template
ui_html = retrieveTemplate("hstore-ui-template", hstore_field_name),
compiled_ui_html = _.template(ui_html, hstore_field_data);
// this is just to DRY up a bit
if (params && params.replace_original === true) {
// remove original textarea to avoid having two textareas with same ID
original_textarea.remove();
// inject compiled template and hide original
original_container.after(compiled_ui_html).hide();
}
return compiled_ui_html;
};
// generate UI
compileUI({ replace_original: true });
// cache other objects that we'll reuse
var row_html = retrieveTemplate("hstore-row-template", hstore_field_name),
empty_row = _.template(row_html, { key: "", value: "" }),
$hstore = $("#id_" + hstore_field_name).parents(".hstore");
// reusable function that updates the textarea value
var updateTextarea = function (container) {
// init empty json object
var new_value = {},
raw_textarea = container.find("textarea"),
rows = container.find(".form-row, .grp-row");
// loop over each object and populate json
rows.each(function () {
var inputs = $(this).find("input"),
key = $(this).find(".hs-key").val(),
value = $(this).find(".hs-val").val();
new_value[key] = value;
});
// update textarea value
$(raw_textarea).val(JSON.stringify(new_value, null, 4));
};
// remove row link
$hstore.delegate("a.remove-row", "click", function (e) {
e.preventDefault();
// cache container jquery object before $(this) gets removed
$(this).parents(".form-row, .grp-row").eq(0).remove();
updateTextarea($hstore);
});
// add row link
$hstore.delegate("a.hs-add-row, .hs-add-row a", "click", function (e) {
e.preventDefault();
$hstore.find(".hstore-rows").append(empty_row);
$(".django-select2").djangoSelect2();
$("select").on("select2:close", function () {
$(this).focus();
});
});
// toggle textarea link
$hstore.delegate(".hstore-toggle-txtarea", "click", function (e) {
e.preventDefault();
var raw_textarea = $hstore.find(".hstore-textarea"),
hstore_rows = $hstore.find(".hstore-rows"),
add_row = $hstore.find(".hs-add-row");
if (raw_textarea.is(":visible")) {
var compiled_ui = compileUI();
// in case of JSON error
if (compiled_ui === false) {
return;
}
// jquery < 1.8
try {
var $ui = $(compiled_ui);
} catch (e) {
// jquery >= 1.8
var $ui = $($.parseHTML(compiled_ui));
}
// update rows with only relevant content
hstore_rows.html($ui.find(".hstore-rows").html());
raw_textarea.hide();
hstore_rows.show();
add_row.show();
$(".django-select2").djangoSelect2();
} else {
raw_textarea.show();
hstore_rows.hide();
add_row.hide();
}
});
// update textarea whenever a field changes
$hstore.delegate(".hs-val", "keyup propertychange", function () {
updateTextarea($hstore);
});
$hstore.delegate(".hs-key", "change", function () {
updateTextarea($hstore);
});
};
window.addEventListener("load", function () {
// support inlines
// bind only once
if (django.hstoreWidgetBoundInlines === undefined) {
var $ = django.jQuery;
$(
".grp-group .grp-add-handler, .inline-group .hs-add-row a, .inline-group .add-row"
).click(function (e) {
var hstore_original_textareas = $(this)
.parents(".grp-group, .inline-group")
.eq(0)
.find(".hstore-original-textarea");
// if module contains .hstore-original-textarea
if (hstore_original_textareas.length > 0) {
// loop over each inline
$(this)
.parents(".grp-group, .inline-group")
.find(".grp-items div.grp-dynamic-form, .inline-related")
.each(function (e, i) {
var prefix = i;
// loop each textarea
$(this)
.find(".hstore-original-textarea")
.each(function (e, i) {
// cache field name
var field_name = $(this).attr("name");
// ignore templates
// if name attribute contains __prefix__
if (field_name.indexOf("prefix") > -1) {
// skip to next
return;
}
initDjangoHStoreWidget(field_name, prefix);
});
});
}
});
django.hstoreWidgetBoundInlines = true;
}
});