diff --git a/modeltranslation/static/modeltranslation/js/tabbed_translation_fields.js b/modeltranslation/static/modeltranslation/js/tabbed_translation_fields.js index 202dd7e..ce3bf3a 100644 --- a/modeltranslation/static/modeltranslation/js/tabbed_translation_fields.js +++ b/modeltranslation/static/modeltranslation/js/tabbed_translation_fields.js @@ -4,159 +4,208 @@ var google, django, gettext; (function () { var jQuery = jQuery || $ || django.jQuery; - /* Add a new selector to jQuery that excludes parent items which match a - given selector */ + /* 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 ($) { - function buildGroupId(id, orig_fieldname) { - /** - * Returns a unique group identifier with respect to Django's way - * of handling inline ids. 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_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' - * - */ - var id_bits = id.split('-'), - id_prefix = 'id_' + orig_fieldname; - if (id_bits.length === 3) { // Standard inlines - id_prefix = id_bits[0] + '-' + id_bits[1] + '-' + id_prefix; - } else if (id_bits.length === 6) { // Generic inlines - id_prefix = id_bits[0] + '-' + id_bits[1] + '-' + id_bits[2] + '-' + - id_bits[3] + '-' + id_bits[4] + '-' + orig_fieldname; - } - return id_prefix; - } + var TranslationField = function (options) { + this.el = options.el; + this.cls = options.cls; + this.id = ''; + this.origFieldname = ''; + this.lang = ''; + this.groupId = ''; - function getGroupedTranslationFields() { - /** - * Returns a grouped set of all text based 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 - * } - * } - * - * They key is a unique group identifier as returned by - * buildGroupId(id, orig_fieldname) to handle inlines properly. - * - */ - var translation_fields = $('.mt').filter( - 'input[type=text]:visible, textarea:visible').filter( - ':parents(.tabular)'), // exclude tabular inlines - grouped_translations = {}; + 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(); + }; - // Handle fields inside collapsed groups as added by zinnia - translation_fields = translation_fields.add('fieldset.collapse-closed .mt'); - - translation_fields.each(function (i, el) { - var field_prefix = 'mt-field-', - id = '', - orig_fieldname = '', - lang = ''; - $.each($(el).attr('class').split(' '), function(j, cls) { - if (cls.substring(0, field_prefix.length) === field_prefix) { - var v = cls.substring(field_prefix.length, cls.length).split('-'); - orig_fieldname = v[0]; - id = buildGroupId($(el).attr('id'), orig_fieldname); - lang = v[1]; - } - }); - if (!grouped_translations[id]) { - grouped_translations[id] = {}; + this.buildGroupId = function () { + /** + * Returns a unique group identifier with respect to Django's way + * of handling inline ids. 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_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' + */ + 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 === 6) { + // Handle generic inlines + idPrefix = idBits[0] + '-' + idBits[1] + '-' + idBits[2] + '-' + + idBits[3] + '-' + idBits[4] + '-' + this.origFieldname; } - grouped_translations[id][lang] = el; + return idPrefix; + }; + + this.init(); + }; + TranslationField.cssPrefix = 'mt-field-'; + + var TranslationFieldGrouper = function (options) { + this.$fieldSelector = options.$fieldSelector; + this.groupedTranslations = {}; + + this.init = function () { + // Handle fields inside collapsed groups as added by zinnia + this.$fieldSelector = this.$fieldSelector.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; + this.$fieldSelector.each(function (idx, el) { + $.each($(el).attr('class').split(' '), function(idx, cls) { + if (cls.substring(0, TranslationField.cssPrefix.length) === TranslationField.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(); + }; + + function handleAddAnotherInline() { + $('.mt').parents('.inline-group').not('.tabular').find('.add-row a').click(function () { + var grouper = new TranslationFieldGrouper({ + $fieldSelector: $(this).parent().prev().prev().find('.mt') + }); + var tabs = createTabs(grouper.groupedTranslations); + + // Update the main switch as it is not aware of the newly created tabs + var $select = $('#content').find('h1 select'); + $select.change(function () { + $.each(tabs, function (i, tab) { + tab.tabs('select', parseInt($select.val())); + }); + }); + // Activate the language tab selected in the main switch + $.each(tabs, function (i, tab) { + tab.tabs('select', parseInt($select.val())); + }); }); - return grouped_translations; } - function createTabs(grouped_translations) { + function createTabs(groupedTranslations) { var tabs = []; - $.each(grouped_translations, function (group_id, lang) { - var tabs_container = $('
'), - tabs_list = $('