mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-04 11:34:42 +00:00
style: Apply prettier
This commit is contained in:
parent
1e64fdadf4
commit
8f8ac75c0a
3 changed files with 516 additions and 426 deletions
|
|
@ -1,16 +1,19 @@
|
|||
var jQuery, $, django;
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
(jQuery || $ || django.jQuery)(function ($) {
|
||||
$('.clearable-input').each(function () {
|
||||
var clear = $(this).children().last();
|
||||
$(this).find('input, select, textarea').not(clear).change(function () {
|
||||
if (typeof clear.prop == "undefined") // older jQuery
|
||||
clear.removeAttr('checked');
|
||||
else
|
||||
clear.prop('checked', false);
|
||||
});
|
||||
"use strict";
|
||||
(jQuery || $ || django.jQuery)(function ($) {
|
||||
$(".clearable-input").each(function () {
|
||||
var clear = $(this).children().last();
|
||||
$(this)
|
||||
.find("input, select, textarea")
|
||||
.not(clear)
|
||||
.change(function () {
|
||||
if (typeof clear.prop == "undefined")
|
||||
// older jQuery
|
||||
clear.removeAttr("checked");
|
||||
else clear.prop("checked", false);
|
||||
});
|
||||
});
|
||||
}());
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
if (!jQuery) {
|
||||
jQuery = django.jQuery;
|
||||
jQuery = django.jQuery;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,435 +3,522 @@
|
|||
var google, django, gettext;
|
||||
|
||||
(function () {
|
||||
var jQuery = window.jQuery || $ || django.jQuery;
|
||||
var jQuery = window.jQuery || $ || django.jQuery;
|
||||
|
||||
/* Add a new selector to jQuery that excludes parent items which match a given selector */
|
||||
jQuery.expr[':'].parents = function(a, i, m) {
|
||||
return jQuery(a).parents(m[3]).length < 1;
|
||||
/* Add a new selector to jQuery that excludes parent items which match a given selector */
|
||||
jQuery.expr[":"].parents = function (a, i, m) {
|
||||
return jQuery(a).parents(m[3]).length < 1;
|
||||
};
|
||||
|
||||
jQuery(function ($) {
|
||||
var TranslationField = function (options) {
|
||||
this.el = options.el;
|
||||
this.cls = options.cls;
|
||||
this.id = "";
|
||||
this.origFieldname = "";
|
||||
this.lang = "";
|
||||
this.groupId = "";
|
||||
|
||||
this.init = function () {
|
||||
var clsBits = this.cls
|
||||
.substring(TranslationField.cssPrefix.length, this.cls.length)
|
||||
.split("-");
|
||||
this.origFieldname = clsBits[0];
|
||||
this.lang = clsBits[1];
|
||||
this.id = $(this.el).attr("id");
|
||||
this.groupId = this.buildGroupId();
|
||||
};
|
||||
|
||||
this.buildGroupId = function () {
|
||||
/**
|
||||
* Returns a unique group identifier with respect to the admin's way
|
||||
* of handling inline field name attributes. Essentially that's the
|
||||
* translation field id without the language prefix.
|
||||
*
|
||||
* Examples ('id parameter': 'return value'):
|
||||
*
|
||||
* 'id_name_de':
|
||||
* 'id_name'
|
||||
* 'id_name_zh_tw':
|
||||
* 'id_name'
|
||||
* 'id_name_set-2-name_de':
|
||||
* 'id_name_set-2-name'
|
||||
* 'id_name_set-2-name_zh_tw':
|
||||
* 'id_name_set-2-name'
|
||||
* 'id_name_set-2-0-name_de':
|
||||
* 'id_name_set-2-0-name'
|
||||
* 'id_name_set-2-0-name_zh_tw':
|
||||
* 'id_name_set-2-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-name_de':
|
||||
* 'id_news-data2-content_type-object_id-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-name_zh_cn':
|
||||
* id_news-data2-content_type-object_id-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-1-name_de':
|
||||
* 'id_news-data2-content_type-object_id-0-1-name'
|
||||
* 'id_news-data2-content_type-object_id-0-1-name_zh_cn':
|
||||
* id_news-data2-content_type-object_id-0-1-name'
|
||||
*/
|
||||
// TODO: We should be able to simplify this, the modeltranslation specific
|
||||
// field classes are already build to be easily splittable, so we could use them
|
||||
// to slice off the language code.
|
||||
var idBits = this.id.split("-"),
|
||||
idPrefix = "id_" + this.origFieldname;
|
||||
if (idBits.length === 3) {
|
||||
// Handle standard inlines
|
||||
idPrefix = idBits[0] + "-" + idBits[1] + "-" + idPrefix;
|
||||
} else if (idBits.length === 4) {
|
||||
// Handle standard inlines with model used by inline more than once
|
||||
idPrefix =
|
||||
idBits[0] + "-" + idBits[1] + "-" + idBits[2] + "-" + idPrefix;
|
||||
} else if (idBits.length === 5 && idBits[3] != "__prefix__") {
|
||||
// Handle nested inlines (https://github.com/Soaa-/django-nested-inlines)
|
||||
idPrefix =
|
||||
idBits[0] +
|
||||
"-" +
|
||||
idBits[1] +
|
||||
"-" +
|
||||
idBits[2] +
|
||||
"-" +
|
||||
idBits[3] +
|
||||
"-" +
|
||||
this.origFieldname;
|
||||
} else if (idBits.length === 6) {
|
||||
// Handle generic inlines
|
||||
idPrefix =
|
||||
idBits[0] +
|
||||
"-" +
|
||||
idBits[1] +
|
||||
"-" +
|
||||
idBits[2] +
|
||||
"-" +
|
||||
idBits[3] +
|
||||
"-" +
|
||||
idBits[4] +
|
||||
"-" +
|
||||
this.origFieldname;
|
||||
} else if (idBits.length === 7) {
|
||||
// Handle generic inlines with model used by inline more than once
|
||||
idPrefix =
|
||||
idBits[0] +
|
||||
"-" +
|
||||
idBits[1] +
|
||||
"-" +
|
||||
idBits[2] +
|
||||
"-" +
|
||||
idBits[3] +
|
||||
"-" +
|
||||
idBits[4] +
|
||||
"-" +
|
||||
idBits[5] +
|
||||
"-" +
|
||||
this.origFieldname;
|
||||
}
|
||||
return idPrefix;
|
||||
};
|
||||
|
||||
this.init();
|
||||
};
|
||||
TranslationField.cssPrefix = "mt-field-";
|
||||
|
||||
var TranslationFieldGrouper = function (options) {
|
||||
this.$fields = options.$fields;
|
||||
this.groupedTranslations = {};
|
||||
|
||||
this.init = function () {
|
||||
// Handle fields inside collapsed groups as added by zinnia
|
||||
this.$fields = this.$fields.add("fieldset.collapse-closed .mt");
|
||||
|
||||
this.groupedTranslations = this.getGroupedTranslations();
|
||||
};
|
||||
|
||||
this.getGroupedTranslations = function () {
|
||||
/**
|
||||
* Returns a grouped set of all model translation fields.
|
||||
* The returned datastructure will look something like this:
|
||||
*
|
||||
* {
|
||||
* 'id_name_de': {
|
||||
* 'en': HTMLInputElement,
|
||||
* 'de': HTMLInputElement,
|
||||
* 'zh_tw': HTMLInputElement
|
||||
* },
|
||||
* 'id_name_set-2-name': {
|
||||
* 'en': HTMLTextAreaElement,
|
||||
* 'de': HTMLTextAreaElement,
|
||||
* 'zh_tw': HTMLTextAreaElement
|
||||
* },
|
||||
* 'id_news-data2-content_type-object_id-0-name': {
|
||||
* 'en': HTMLTextAreaElement,
|
||||
* 'de': HTMLTextAreaElement,
|
||||
* 'zh_tw': HTMLTextAreaElement
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The keys are unique group identifiers as returned by
|
||||
* TranslationField.buildGroupId() to handle inlines properly.
|
||||
*/
|
||||
var self = this,
|
||||
cssPrefix = TranslationField.cssPrefix;
|
||||
this.$fields.each(function (idx, el) {
|
||||
$.each($(el).attr("class").split(" "), function (idx, cls) {
|
||||
if (cls.substring(0, cssPrefix.length) === cssPrefix) {
|
||||
var tfield = new TranslationField({ el: el, cls: cls });
|
||||
if (!self.groupedTranslations[tfield.groupId]) {
|
||||
self.groupedTranslations[tfield.groupId] = {};
|
||||
}
|
||||
self.groupedTranslations[tfield.groupId][tfield.lang] = el;
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.groupedTranslations;
|
||||
};
|
||||
|
||||
this.init();
|
||||
};
|
||||
|
||||
jQuery(function ($) {
|
||||
var TranslationField = function (options) {
|
||||
this.el = options.el;
|
||||
this.cls = options.cls;
|
||||
this.id = '';
|
||||
this.origFieldname = '';
|
||||
this.lang = '';
|
||||
this.groupId = '';
|
||||
|
||||
this.init = function () {
|
||||
var clsBits = this.cls.substring(
|
||||
TranslationField.cssPrefix.length, this.cls.length).split('-');
|
||||
this.origFieldname = clsBits[0];
|
||||
this.lang = clsBits[1];
|
||||
this.id = $(this.el).attr('id');
|
||||
this.groupId = this.buildGroupId();
|
||||
function createTabs(groupedTranslations) {
|
||||
var tabs = [];
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
if (groupId.includes("__prefix__")) return;
|
||||
var tabsContainer = $("<div></div>"),
|
||||
tabsList = $("<ul></ul>"),
|
||||
insertionPoint,
|
||||
activeTab = 0;
|
||||
tabsContainer.append(tabsList);
|
||||
$.each(lang, function (lang, el) {
|
||||
var container = $(el).closest(".form-row"),
|
||||
label = $("label", container),
|
||||
fieldLabel = container.find("label"),
|
||||
tabId = "tab_" + $(el).attr("id"),
|
||||
panel,
|
||||
tab;
|
||||
// Remove language and brackets from field label, they are
|
||||
// displayed in the tab already.
|
||||
if (fieldLabel.html()) {
|
||||
fieldLabel.html(fieldLabel.html().replace(/ \[.+\]/, ""));
|
||||
}
|
||||
if (!insertionPoint) {
|
||||
insertionPoint = {
|
||||
insert: container.prev().length
|
||||
? "after"
|
||||
: container.next().length
|
||||
? "prepend"
|
||||
: "append",
|
||||
el: container.prev().length
|
||||
? container.prev()
|
||||
: container.parent(),
|
||||
};
|
||||
}
|
||||
container.find("script").remove();
|
||||
panel = $('<div id="' + tabId + '"></div>').append(container);
|
||||
tab = $(
|
||||
"<li" +
|
||||
(label.hasClass("required") ? ' class="required"' : "") +
|
||||
'><a href="#' +
|
||||
tabId +
|
||||
'">' +
|
||||
lang.replace("_", "-") +
|
||||
"</a></li>"
|
||||
);
|
||||
tabsList.append(tab);
|
||||
tabsContainer.append(panel);
|
||||
if (container.hasClass("errors")) {
|
||||
activeTab = tabsList.find("li").length - 1;
|
||||
tab.addClass("ui-tab-has-errors");
|
||||
}
|
||||
});
|
||||
insertionPoint.el[insertionPoint.insert](tabsContainer);
|
||||
tabsContainer.tabs({
|
||||
active: activeTab,
|
||||
});
|
||||
tabs.push(tabsContainer);
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
|
||||
this.buildGroupId = function () {
|
||||
/**
|
||||
* Returns a unique group identifier with respect to the admin's way
|
||||
* of handling inline field name attributes. Essentially that's the
|
||||
* translation field id without the language prefix.
|
||||
*
|
||||
* Examples ('id parameter': 'return value'):
|
||||
*
|
||||
* 'id_name_de':
|
||||
* 'id_name'
|
||||
* 'id_name_zh_tw':
|
||||
* 'id_name'
|
||||
* 'id_name_set-2-name_de':
|
||||
* 'id_name_set-2-name'
|
||||
* 'id_name_set-2-name_zh_tw':
|
||||
* 'id_name_set-2-name'
|
||||
* 'id_name_set-2-0-name_de':
|
||||
* 'id_name_set-2-0-name'
|
||||
* 'id_name_set-2-0-name_zh_tw':
|
||||
* 'id_name_set-2-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-name_de':
|
||||
* 'id_news-data2-content_type-object_id-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-name_zh_cn':
|
||||
* id_news-data2-content_type-object_id-0-name'
|
||||
* 'id_news-data2-content_type-object_id-0-1-name_de':
|
||||
* 'id_news-data2-content_type-object_id-0-1-name'
|
||||
* 'id_news-data2-content_type-object_id-0-1-name_zh_cn':
|
||||
* id_news-data2-content_type-object_id-0-1-name'
|
||||
*/
|
||||
// TODO: We should be able to simplify this, the modeltranslation specific
|
||||
// field classes are already build to be easily splittable, so we could use them
|
||||
// to slice off the language code.
|
||||
var idBits = this.id.split('-'),
|
||||
idPrefix = 'id_' + this.origFieldname;
|
||||
if (idBits.length === 3) {
|
||||
// Handle standard inlines
|
||||
idPrefix = idBits[0] + '-' + idBits[1] + '-' + idPrefix;
|
||||
} else if (idBits.length === 4) {
|
||||
// Handle standard inlines with model used by inline more than once
|
||||
idPrefix = idBits[0] + '-' + idBits[1] + '-' + idBits[2] + '-' + idPrefix;
|
||||
} else if (idBits.length === 5 && idBits[3] != '__prefix__') {
|
||||
// Handle nested inlines (https://github.com/Soaa-/django-nested-inlines)
|
||||
idPrefix = idBits[0] + '-' + idBits[1] + '-' + idBits[2] + '-' + idBits[3] + '-' + this.origFieldname;
|
||||
} else if (idBits.length === 6) {
|
||||
// Handle generic inlines
|
||||
idPrefix = idBits[0] + '-' + idBits[1] + '-' + idBits[2] + '-' +
|
||||
idBits[3] + '-' + idBits[4] + '-' + this.origFieldname;
|
||||
} else if (idBits.length === 7) {
|
||||
// Handle generic inlines with model used by inline more than once
|
||||
idPrefix = idBits[0] + '-' + idBits[1] + '-' + idBits[2] + '-' +
|
||||
idBits[3] + '-' + idBits[4] + '-' + idBits[5] + '-' + this.origFieldname;
|
||||
}
|
||||
return idPrefix;
|
||||
};
|
||||
function handleAddAnotherInline() {
|
||||
// TODO: Refactor
|
||||
$(".mt")
|
||||
.parents(".inline-group")
|
||||
.not(".tabular")
|
||||
.find(".add-row a")
|
||||
.click(function () {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $(this).parent().prev().prev().find(".mt").add(
|
||||
// Support django-nested-admin stacked inlines
|
||||
$(this)
|
||||
.parent()
|
||||
.prev(".djn-items")
|
||||
.children(".djn-item")
|
||||
.last()
|
||||
.find(".mt")
|
||||
),
|
||||
});
|
||||
var tabs = createTabs(grouper.groupedTranslations);
|
||||
// Update the main switch as it is not aware of the newly created tabs
|
||||
MainSwitch.update(tabs);
|
||||
// Activate the language tab selected in the main switch
|
||||
MainSwitch.activateTab(tabs);
|
||||
});
|
||||
}
|
||||
|
||||
this.init();
|
||||
};
|
||||
TranslationField.cssPrefix = 'mt-field-';
|
||||
var TabularInlineGroup = function (options) {
|
||||
this.id = options.id;
|
||||
this.$id = null;
|
||||
this.$table = null;
|
||||
this.translationColumns = [];
|
||||
// TODO: Make use of this to flag required tabs
|
||||
this.requiredColumns = [];
|
||||
|
||||
var TranslationFieldGrouper = function (options) {
|
||||
this.$fields = options.$fields;
|
||||
this.groupedTranslations = {};
|
||||
this.init = function () {
|
||||
this.$id = $("#" + this.id);
|
||||
this.$table = $(this.$id).find("table");
|
||||
};
|
||||
|
||||
this.init = function () {
|
||||
// Handle fields inside collapsed groups as added by zinnia
|
||||
this.$fields = this.$fields.add('fieldset.collapse-closed .mt');
|
||||
this.getAllGroupedTranslations = function () {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: this.$table.find(".mt").filter("input, textarea, select"),
|
||||
});
|
||||
//this.requiredColumns = this.getRequiredColumns();
|
||||
this.initTable();
|
||||
return grouper.groupedTranslations;
|
||||
};
|
||||
|
||||
this.groupedTranslations = this.getGroupedTranslations();
|
||||
};
|
||||
this.getGroupedTranslations = function ($fields) {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $fields,
|
||||
});
|
||||
return grouper.groupedTranslations;
|
||||
};
|
||||
|
||||
this.getGroupedTranslations = function () {
|
||||
/**
|
||||
* Returns a grouped set of all model translation fields.
|
||||
* The returned datastructure will look something like this:
|
||||
*
|
||||
* {
|
||||
* 'id_name_de': {
|
||||
* 'en': HTMLInputElement,
|
||||
* 'de': HTMLInputElement,
|
||||
* 'zh_tw': HTMLInputElement
|
||||
* },
|
||||
* 'id_name_set-2-name': {
|
||||
* 'en': HTMLTextAreaElement,
|
||||
* 'de': HTMLTextAreaElement,
|
||||
* 'zh_tw': HTMLTextAreaElement
|
||||
* },
|
||||
* 'id_news-data2-content_type-object_id-0-name': {
|
||||
* 'en': HTMLTextAreaElement,
|
||||
* 'de': HTMLTextAreaElement,
|
||||
* 'zh_tw': HTMLTextAreaElement
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The keys are unique group identifiers as returned by
|
||||
* TranslationField.buildGroupId() to handle inlines properly.
|
||||
*/
|
||||
var self = this,
|
||||
cssPrefix = TranslationField.cssPrefix;
|
||||
this.$fields.each(function (idx, el) {
|
||||
$.each($(el).attr('class').split(' '), function(idx, cls) {
|
||||
if (cls.substring(0, cssPrefix.length) === cssPrefix) {
|
||||
var tfield = new TranslationField({el: el, cls: cls});
|
||||
if (!self.groupedTranslations[tfield.groupId]) {
|
||||
self.groupedTranslations[tfield.groupId] = {};
|
||||
}
|
||||
self.groupedTranslations[tfield.groupId][tfield.lang] = el;
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.groupedTranslations;
|
||||
};
|
||||
this.initTable = function () {
|
||||
var self = this;
|
||||
// The table header requires special treatment. In case an inline
|
||||
// is declared with extra=0, the translation fields are not visible.
|
||||
var thGrouper = new TranslationFieldGrouper({
|
||||
$fields: this.$table.find(".mt").filter("input, textarea, select"),
|
||||
});
|
||||
this.translationColumns = this.getTranslationColumns(
|
||||
thGrouper.groupedTranslations
|
||||
);
|
||||
|
||||
this.init();
|
||||
};
|
||||
// The markup of tabular inlines is kinda weird. There is an additional
|
||||
// leading td.original per row, so we have one td more than ths.
|
||||
this.$table.find("th").each(function (idx) {
|
||||
// Hide table heads from which translation fields have been moved out.
|
||||
if ($.inArray(idx + 1, self.translationColumns) !== -1) {
|
||||
// FIXME: Why does this break when we use remove instead of hide?
|
||||
$(this).hide();
|
||||
}
|
||||
|
||||
function createTabs(groupedTranslations) {
|
||||
var tabs = [];
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
if (groupId.includes("__prefix__"))
|
||||
return;
|
||||
var tabsContainer = $('<div></div>'),
|
||||
tabsList = $('<ul></ul>'),
|
||||
insertionPoint,
|
||||
activeTab = 0;
|
||||
tabsContainer.append(tabsList);
|
||||
$.each(lang, function (lang, el) {
|
||||
var container = $(el).closest('.form-row'),
|
||||
label = $('label', container),
|
||||
fieldLabel = container.find('label'),
|
||||
tabId = 'tab_' + $(el).attr('id'),
|
||||
panel,
|
||||
tab;
|
||||
// Remove language and brackets from field label, they are
|
||||
// displayed in the tab already.
|
||||
if (fieldLabel.html()) {
|
||||
fieldLabel.html(fieldLabel.html().replace(/ \[.+\]/, ''));
|
||||
}
|
||||
if (!insertionPoint) {
|
||||
insertionPoint = {
|
||||
'insert': container.prev().length ? 'after' :
|
||||
container.next().length ? 'prepend' : 'append',
|
||||
'el': container.prev().length ? container.prev() : container.parent()
|
||||
};
|
||||
}
|
||||
container.find('script').remove();
|
||||
panel = $('<div id="' + tabId + '"></div>').append(container);
|
||||
tab = $('<li' + (label.hasClass('required') ? ' class="required"' : '') +
|
||||
'><a href="#' + tabId + '">' + lang.replace('_', '-') + '</a></li>');
|
||||
tabsList.append(tab);
|
||||
tabsContainer.append(panel);
|
||||
if (container.hasClass("errors")) {
|
||||
activeTab = tabsList.find("li").length - 1;
|
||||
tab.addClass("ui-tab-has-errors");
|
||||
}
|
||||
});
|
||||
insertionPoint.el[insertionPoint.insert](tabsContainer);
|
||||
tabsContainer.tabs({
|
||||
active: activeTab,
|
||||
});
|
||||
tabs.push(tabsContainer);
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
// Remove language and brackets from table header,
|
||||
// they are displayed in the tab already.
|
||||
if (
|
||||
$(this).html() &&
|
||||
$.inArray(idx + 1, self.translationColumns) === -1
|
||||
) {
|
||||
$(this).html(
|
||||
$(this)
|
||||
.html()
|
||||
.replace(/ \[.+\]/, "")
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function handleAddAnotherInline() {
|
||||
// TODO: Refactor
|
||||
$('.mt').parents('.inline-group').not('.tabular').find('.add-row a').click(function () {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $(this).parent().prev().prev().find('.mt').add(
|
||||
// Support django-nested-admin stacked inlines
|
||||
$(this).parent().prev('.djn-items').children('.djn-item').last().find('.mt')
|
||||
)
|
||||
});
|
||||
var tabs = createTabs(grouper.groupedTranslations);
|
||||
// Update the main switch as it is not aware of the newly created tabs
|
||||
MainSwitch.update(tabs);
|
||||
// Activate the language tab selected in the main switch
|
||||
MainSwitch.activateTab(tabs);
|
||||
});
|
||||
}
|
||||
|
||||
var TabularInlineGroup = function (options) {
|
||||
this.id = options.id;
|
||||
this.$id = null;
|
||||
this.$table = null;
|
||||
this.translationColumns = [];
|
||||
// TODO: Make use of this to flag required tabs
|
||||
this.requiredColumns = [];
|
||||
|
||||
this.init = function () {
|
||||
this.$id = $('#' + this.id);
|
||||
this.$table = $(this.$id).find('table');
|
||||
};
|
||||
|
||||
this.getAllGroupedTranslations = function () {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: this.$table.find('.mt').filter(
|
||||
'input, textarea, select')
|
||||
});
|
||||
//this.requiredColumns = this.getRequiredColumns();
|
||||
this.initTable();
|
||||
return grouper.groupedTranslations;
|
||||
};
|
||||
|
||||
this.getGroupedTranslations = function ($fields) {
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $fields
|
||||
});
|
||||
return grouper.groupedTranslations;
|
||||
};
|
||||
|
||||
this.initTable = function () {
|
||||
var self = this;
|
||||
// The table header requires special treatment. In case an inline
|
||||
// is declared with extra=0, the translation fields are not visible.
|
||||
var thGrouper = new TranslationFieldGrouper({
|
||||
$fields: this.$table.find('.mt').filter('input, textarea, select')
|
||||
});
|
||||
this.translationColumns = this.getTranslationColumns(thGrouper.groupedTranslations);
|
||||
|
||||
// The markup of tabular inlines is kinda weird. There is an additional
|
||||
// leading td.original per row, so we have one td more than ths.
|
||||
this.$table.find('th').each(function (idx) {
|
||||
// Hide table heads from which translation fields have been moved out.
|
||||
if($.inArray(idx + 1, self.translationColumns) !== -1) {
|
||||
// FIXME: Why does this break when we use remove instead of hide?
|
||||
$(this).hide();
|
||||
}
|
||||
|
||||
// Remove language and brackets from table header,
|
||||
// they are displayed in the tab already.
|
||||
if ($(this).html() && $.inArray(idx + 1, self.translationColumns) === -1) {
|
||||
$(this).html($(this).html().replace(/ \[.+\]/, ''));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.getTranslationColumns = function (groupedTranslations) {
|
||||
var translationColumns = [];
|
||||
// Get table column indexes which have translation fields, but omit the first
|
||||
// one per group, because that's where we insert our tab container.
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
var i = 0;
|
||||
$.each(lang, function (lang, el) {
|
||||
var column = $(el).closest('td').prevAll().length;
|
||||
if (i > 0 && $.inArray(column, translationColumns) === -1) {
|
||||
translationColumns.push(column);
|
||||
}
|
||||
i += 1;
|
||||
});
|
||||
});
|
||||
return translationColumns;
|
||||
};
|
||||
|
||||
this.getRequiredColumns = function () {
|
||||
var requiredColumns = [];
|
||||
// Get table column indexes which have required fields, but omit the first
|
||||
// one per group, because that's where we insert our tab container.
|
||||
this.$table.find('th.required').each(function () {
|
||||
requiredColumns.push($(this).index() + 1);
|
||||
});
|
||||
return requiredColumns;
|
||||
};
|
||||
|
||||
this.init();
|
||||
};
|
||||
|
||||
function handleTabularAddAnotherInline(tabularInlineGroup) {
|
||||
tabularInlineGroup.$table.find('.add-row a').click(function () {
|
||||
var tabs = createTabularTabs(
|
||||
tabularInlineGroup.getGroupedTranslations(
|
||||
$(this).parent().parent().prev().prev().find('.mt')));
|
||||
// Update the main switch as it is not aware of the newly created tabs
|
||||
MainSwitch.update(tabs);
|
||||
// Activate the language tab selected in the main switch
|
||||
MainSwitch.activateTab(tabs);
|
||||
});
|
||||
}
|
||||
|
||||
function createTabularTabs(groupedTranslations) {
|
||||
var tabs = [];
|
||||
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
if (groupId.includes("__prefix__"))
|
||||
return;
|
||||
var tabsContainer = $('<td></td>'),
|
||||
tabsList = $('<ul></ul>'),
|
||||
insertionPoint,
|
||||
activeTab = 0;
|
||||
tabsContainer.append(tabsList);
|
||||
|
||||
$.each(lang, function (lang, el) {
|
||||
var $container = $(el).closest('td'),
|
||||
$panel,
|
||||
$tab,
|
||||
tabId = 'tab_' + $(el).attr('id');
|
||||
if (!insertionPoint) {
|
||||
insertionPoint = {
|
||||
'insert': $container.prev().length ? 'after' :
|
||||
$container.next().length ? 'prepend' : 'append',
|
||||
'el': $container.prev().length ? $container.prev() : $container.parent()
|
||||
};
|
||||
}
|
||||
$panel = $('<div id="' + tabId + '"></div>').append($container);
|
||||
|
||||
// Turn the moved tds into divs
|
||||
var attrs = {};
|
||||
$.each($container[0].attributes, function(idx, attr) {
|
||||
attrs[attr.nodeName] = attr.nodeValue;
|
||||
});
|
||||
|
||||
$container.replaceWith(function () {
|
||||
return $('<div />', attrs).append($(this).contents());
|
||||
});
|
||||
|
||||
// TODO: Setting the required state based on the default field is naive.
|
||||
// The user might have tweaked his admin. We somehow have to keep track of the
|
||||
// column indexes _before_ the tds have been moved around.
|
||||
$tab = $('<li' + ($(el).hasClass('mt-default') ? ' class="required"' : '') +
|
||||
'><a href="#' + tabId + '">' + lang.replace('_', '-') + '</a></li>');
|
||||
tabsList.append($tab);
|
||||
tabsContainer.append($panel);
|
||||
if ($container.hasClass("errors")) {
|
||||
activeTab = tabsList.find("li").length - 1;
|
||||
tab.addClass("ui-tab-has-errors");
|
||||
}
|
||||
});
|
||||
insertionPoint.el[insertionPoint.insert](tabsContainer);
|
||||
tabsContainer.tabs({
|
||||
active: activeTab,
|
||||
});
|
||||
tabs.push(tabsContainer);
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
|
||||
var MainSwitch = {
|
||||
languages: [],
|
||||
$select: $('<select>'),
|
||||
|
||||
init: function(groupedTranslations, tabs) {
|
||||
var self = this;
|
||||
$.each(groupedTranslations, function (id, languages) {
|
||||
$.each(languages, function (lang) {
|
||||
if ($.inArray(lang, self.languages) < 0) {
|
||||
self.languages.push(lang);
|
||||
}
|
||||
});
|
||||
});
|
||||
$.each(this.languages, function (idx, language) {
|
||||
self.$select.append($('<option value="' + idx + '">' +
|
||||
language.replace('_', '-') + '</option>'));
|
||||
});
|
||||
this.update(tabs);
|
||||
$('#content').find('h1').append(' ').append(self.$select);
|
||||
},
|
||||
|
||||
update: function(tabs) {
|
||||
var self = this;
|
||||
this.$select.change(function () {
|
||||
$.each(tabs, function (idx, tab) {
|
||||
tab.tabs('option', 'active', parseInt(self.$select.val(), 10));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
activateTab: function(tabs) {
|
||||
var self = this;
|
||||
$.each(tabs, function (idx, tab) {
|
||||
tab.tabs('option', 'active', parseInt(self.$select.val(), 10));
|
||||
});
|
||||
this.getTranslationColumns = function (groupedTranslations) {
|
||||
var translationColumns = [];
|
||||
// Get table column indexes which have translation fields, but omit the first
|
||||
// one per group, because that's where we insert our tab container.
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
var i = 0;
|
||||
$.each(lang, function (lang, el) {
|
||||
var column = $(el).closest("td").prevAll().length;
|
||||
if (i > 0 && $.inArray(column, translationColumns) === -1) {
|
||||
translationColumns.push(column);
|
||||
}
|
||||
};
|
||||
i += 1;
|
||||
});
|
||||
});
|
||||
return translationColumns;
|
||||
};
|
||||
|
||||
if ($('body').hasClass('change-form')) {
|
||||
// Group normal fields and fields in (existing) stacked inlines
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $('.mt').filter(
|
||||
'input, textarea, select, iframe, div').filter(':parents(.tabular)').filter(':parents(.empty-form)')
|
||||
});
|
||||
MainSwitch.init(grouper.groupedTranslations, createTabs(grouper.groupedTranslations));
|
||||
this.getRequiredColumns = function () {
|
||||
var requiredColumns = [];
|
||||
// Get table column indexes which have required fields, but omit the first
|
||||
// one per group, because that's where we insert our tab container.
|
||||
this.$table.find("th.required").each(function () {
|
||||
requiredColumns.push($(this).index() + 1);
|
||||
});
|
||||
return requiredColumns;
|
||||
};
|
||||
|
||||
// Note: The add another functionality in admin is injected through inline javascript,
|
||||
// here we have to run after that (and after all other ready events just to be sure).
|
||||
$(document).ready(function() {
|
||||
$(window).on('load', function() {
|
||||
handleAddAnotherInline();
|
||||
});
|
||||
});
|
||||
this.init();
|
||||
};
|
||||
|
||||
// Group fields in (existing) tabular inlines
|
||||
$('div.inline-group > div.tabular').each(function () {
|
||||
var tabularInlineGroup = new TabularInlineGroup({
|
||||
'id': $(this).parent().attr('id')
|
||||
});
|
||||
MainSwitch.update(
|
||||
createTabularTabs(tabularInlineGroup.getAllGroupedTranslations()));
|
||||
function handleTabularAddAnotherInline(tabularInlineGroup) {
|
||||
tabularInlineGroup.$table.find(".add-row a").click(function () {
|
||||
var tabs = createTabularTabs(
|
||||
tabularInlineGroup.getGroupedTranslations(
|
||||
$(this).parent().parent().prev().prev().find(".mt")
|
||||
)
|
||||
);
|
||||
// Update the main switch as it is not aware of the newly created tabs
|
||||
MainSwitch.update(tabs);
|
||||
// Activate the language tab selected in the main switch
|
||||
MainSwitch.activateTab(tabs);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(window).on('load', function() {
|
||||
handleTabularAddAnotherInline(tabularInlineGroup);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}());
|
||||
function createTabularTabs(groupedTranslations) {
|
||||
var tabs = [];
|
||||
|
||||
$.each(groupedTranslations, function (groupId, lang) {
|
||||
if (groupId.includes("__prefix__")) return;
|
||||
var tabsContainer = $("<td></td>"),
|
||||
tabsList = $("<ul></ul>"),
|
||||
insertionPoint,
|
||||
activeTab = 0;
|
||||
tabsContainer.append(tabsList);
|
||||
|
||||
$.each(lang, function (lang, el) {
|
||||
var $container = $(el).closest("td"),
|
||||
$panel,
|
||||
$tab,
|
||||
tabId = "tab_" + $(el).attr("id");
|
||||
if (!insertionPoint) {
|
||||
insertionPoint = {
|
||||
insert: $container.prev().length
|
||||
? "after"
|
||||
: $container.next().length
|
||||
? "prepend"
|
||||
: "append",
|
||||
el: $container.prev().length
|
||||
? $container.prev()
|
||||
: $container.parent(),
|
||||
};
|
||||
}
|
||||
$panel = $('<div id="' + tabId + '"></div>').append($container);
|
||||
|
||||
// Turn the moved tds into divs
|
||||
var attrs = {};
|
||||
$.each($container[0].attributes, function (idx, attr) {
|
||||
attrs[attr.nodeName] = attr.nodeValue;
|
||||
});
|
||||
|
||||
$container.replaceWith(function () {
|
||||
return $("<div />", attrs).append($(this).contents());
|
||||
});
|
||||
|
||||
// TODO: Setting the required state based on the default field is naive.
|
||||
// The user might have tweaked his admin. We somehow have to keep track of the
|
||||
// column indexes _before_ the tds have been moved around.
|
||||
$tab = $(
|
||||
"<li" +
|
||||
($(el).hasClass("mt-default") ? ' class="required"' : "") +
|
||||
'><a href="#' +
|
||||
tabId +
|
||||
'">' +
|
||||
lang.replace("_", "-") +
|
||||
"</a></li>"
|
||||
);
|
||||
tabsList.append($tab);
|
||||
tabsContainer.append($panel);
|
||||
if ($container.hasClass("errors")) {
|
||||
activeTab = tabsList.find("li").length - 1;
|
||||
tab.addClass("ui-tab-has-errors");
|
||||
}
|
||||
});
|
||||
insertionPoint.el[insertionPoint.insert](tabsContainer);
|
||||
tabsContainer.tabs({
|
||||
active: activeTab,
|
||||
});
|
||||
tabs.push(tabsContainer);
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
|
||||
var MainSwitch = {
|
||||
languages: [],
|
||||
$select: $("<select>"),
|
||||
|
||||
init: function (groupedTranslations, tabs) {
|
||||
var self = this;
|
||||
$.each(groupedTranslations, function (id, languages) {
|
||||
$.each(languages, function (lang) {
|
||||
if ($.inArray(lang, self.languages) < 0) {
|
||||
self.languages.push(lang);
|
||||
}
|
||||
});
|
||||
});
|
||||
$.each(this.languages, function (idx, language) {
|
||||
self.$select.append(
|
||||
$(
|
||||
'<option value="' +
|
||||
idx +
|
||||
'">' +
|
||||
language.replace("_", "-") +
|
||||
"</option>"
|
||||
)
|
||||
);
|
||||
});
|
||||
this.update(tabs);
|
||||
$("#content").find("h1").append(" ").append(self.$select);
|
||||
},
|
||||
|
||||
update: function (tabs) {
|
||||
var self = this;
|
||||
this.$select.change(function () {
|
||||
$.each(tabs, function (idx, tab) {
|
||||
tab.tabs("option", "active", parseInt(self.$select.val(), 10));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
activateTab: function (tabs) {
|
||||
var self = this;
|
||||
$.each(tabs, function (idx, tab) {
|
||||
tab.tabs("option", "active", parseInt(self.$select.val(), 10));
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
if ($("body").hasClass("change-form")) {
|
||||
// Group normal fields and fields in (existing) stacked inlines
|
||||
var grouper = new TranslationFieldGrouper({
|
||||
$fields: $(".mt")
|
||||
.filter("input, textarea, select, iframe, div")
|
||||
.filter(":parents(.tabular)")
|
||||
.filter(":parents(.empty-form)"),
|
||||
});
|
||||
MainSwitch.init(
|
||||
grouper.groupedTranslations,
|
||||
createTabs(grouper.groupedTranslations)
|
||||
);
|
||||
|
||||
// Note: The add another functionality in admin is injected through inline javascript,
|
||||
// here we have to run after that (and after all other ready events just to be sure).
|
||||
$(document).ready(function () {
|
||||
$(window).on("load", function () {
|
||||
handleAddAnotherInline();
|
||||
});
|
||||
});
|
||||
|
||||
// Group fields in (existing) tabular inlines
|
||||
$("div.inline-group > div.tabular").each(function () {
|
||||
var tabularInlineGroup = new TabularInlineGroup({
|
||||
id: $(this).parent().attr("id"),
|
||||
});
|
||||
MainSwitch.update(
|
||||
createTabularTabs(tabularInlineGroup.getAllGroupedTranslations())
|
||||
);
|
||||
|
||||
$(document).ready(function () {
|
||||
$(window).on("load", function () {
|
||||
handleTabularAddAnotherInline(tabularInlineGroup);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in a new issue