translations_pack-1.0.0-beta3/js/tabs.js
js/tabs.js
(function(Drupal) {
Drupal.behaviors.translation_tabs = {
initialized: false,
attach: function(context, settings) {
if (context.nodeName != '#document') {
if (context.parentElement && ('langPack' in context.parentElement.dataset)) {
this.associate_form(context.parentElement);
}
return;
}
if (this.initialized) {
return;
}
this.initialized = true;
this.selector_form = document.forms['translations-pack-language-selector'];
this.packed_form = this.selector_form.parentElement.querySelector('form[data-lang-code]');
this.packed_change = 0;
this.forms = {};
this.forms[this.packed_form.dataset.langCode] = this.packed_form;
other_forms = this.packed_form.parentElement.querySelectorAll('form[data-lang-root]');
for (let form of other_forms) {
var langcode = form.dataset.langRoot.split('_').pop();
this.forms[langcode] = form;
};
// setup tabs
var packs = this.packed_form.querySelectorAll('.translation-pack');
this.tabs_init(packs);
// handle hidden tabs validation
this.pack_validate();
this.invalid_tabs();
// package all translation data to form submission
this.pack_submission(context, settings);
// propogate change in translations to the master packed form
this.pack_change_trigger();
if (settings.hasOwnProperty('translations_pack_switch')) {
var langcode = settings.translations_pack_switch;
this.packed_form
.querySelector(`.translations-tabs .language-tab[data-code=${langcode}]`)
.click();
}
},
associate_form: function (wrapper) {
var code = wrapper.dataset.langPack;
if (code == 'original') {
return;
}
var form_id = this.forms[code].id;
var widgets = wrapper.querySelectorAll('[name]');
for (let w of widgets) {
w.setAttribute('form', form_id);
}
},
tabs_init: function(packs) {
var item_list = this.packed_form.querySelector('.translations-tabs');
this.tabs = new translationTabs(item_list, packs);
for (pack of packs) {
for (let next_element of pack.querySelectorAll('[data-lang-pack]')) {
this.associate_form(next_element);
}
}
},
pack_validate: function() {
var handler = {
context: this,
handleEvent: function(event) {
for (let langcode in this.context.forms) {
if (langcode == this.context.packed_form.dataset.langCode) {
continue;
}
let checkbox_name = 'language_selection['+ langcode +']';
if (!this.context.selector_form.elements[checkbox_name].checked) {
continue;
}
let next_form = this.context.forms[langcode];
if (!next_form.checkValidity()) {
this.context.tabs.showByCode(langcode);
next_form.reportValidity();
this.context.reportTabErrors();
event.preventDefault();
return;
}
}
}
};
this.packed_form.addEventListener('submit', handler);
var original_handler = {
context: this,
handleEvent: function(event) {
let langcode = this.context.packed_form.dataset.langCode;
let next_form = this.context.packed_form;
if (!next_form.checkValidity()) {
this.context.tabs.showByCode(langcode);
next_form.reportValidity();
this.context.reportTabErrors();
event.preventDefault();
return;
}
}
};
var op_element = this.packed_form.elements['op'];
if ('length' in op_element) {
for (let action of op_element) {
action.addEventListener('click', original_handler);
}
}
else {
op_element.addEventListener('click', original_handler);
}
},
invalid_tabs: function() {
this.vertical_tab_menu_items =
this.packed_form.querySelectorAll('.vertical-tabs__menu .vertical-tabs__menu-item');
this.vertical_tab_errors = new Set();
var handler = {
context: this,
handleEvent: function(event) {
var group_tab = this.groupTab(event.target);
if (group_tab) {
this.context.vertical_tab_errors.add('#'+group_tab);
}
},
groupTab: function(elm) {
while (!elm.classList.contains('field-group-tab')) {
elm = elm.parentElement;
if (elm.tagName == 'FORM') {
console.log('Failed to find group tab');
return false;
}
}
return elm.dataset.drupalSelector;
},
};
for (let elm of this.packed_form.querySelectorAll('input')) {
elm.addEventListener('invalid', handler);
}
for (let tab_item of this.vertical_tab_menu_items) {
tab_item.addEventListener('click', function(event) {
this.classList.remove('has-error');
});
}
},
reportTabErrors: function() {
if (!this.vertical_tab_menu_items) {
return;
}
for (let tab_item of this.vertical_tab_menu_items) {
let group_tab = tab_item.firstChild.hash;
if (this.vertical_tab_errors.has(group_tab)) {
this.vertical_tab_errors.delete(group_tab);
tab_item.classList.add('has-error');
}
}
},
clearTabErrors: function() {
if (!this.vertical_tab_menu_items) {
return;
}
for (let tab_item of this.vertical_tab_menu_items) {
tab_item.classList.remove('has-error');
}
},
pack_submission: function() {
var handler = {
context: this,
handleEvent: function(event) {
var control_names = ['form_id', 'form_build_id', 'form_token'];
let data = event.formData;
let form_data = new FormData(this.context.selector_form);
for (let data_item of form_data.entries()) {
if (control_names.includes(data_item[0])) {
data_item[0] += '_language_selector';
}
data.append(data_item[0], data_item[1]);
}
for (let langcode in this.context.forms) {
if (langcode == this.context.packed_form.dataset.langCode) {
continue;
}
let checkbox_name = 'language_selection['+ langcode +']';
if (!this.context.selector_form.elements[checkbox_name].checked) {
continue;
}
let next_form = this.context.forms[langcode];
let form_data = new FormData(next_form);
for (let data_item of form_data.entries()) {
data.append(data_item[0], data_item[1]);
}
}
}
};
this.packed_form.addEventListener('formdata', handler);
},
pack_change_trigger: function() {
var handler = {
context: this,
handleEvent: function(event) {
this.context.pack_inc();
}
}
for (let code in this.forms) {
this.forms[code].addEventListener('change', handler);
}
},
pack_inc: function() {
this.packed_change++;
this.packed_form.elements['translations_pack_change'].value =
this.packed_change;
}
}
function translationTabs(item_list, packs) {
this.item_list = item_list;
this.packs = packs;
var self = this;
this.item_list.addEventListener('click', function (event) {
var tab = null;
if (event.target.nodeName == 'A') {
tab = event.target.parentElement;
self.cancel_language(tab);
return;
}
tab = event.target;
active_code = self.item_list.querySelector('.language-tab.active').dataset.code;
var form = Drupal.behaviors.translation_tabs.forms[active_code];
if (form.checkValidity()) {
Drupal.behaviors.translation_tabs.clearTabErrors();
self.show(tab);
self.update_language(tab);
}
else {
form.reportValidity();
Drupal.behaviors.translation_tabs.reportTabErrors();
}
});
}
translationTabs.prototype.update_language = function(tab) {
if (tab.dataset.state == 'off') {
tab.dataset.state = 'on';
var cancel = document.createElement('a');
cancel.textContent = ' [X] ';
cancel.title = Drupal.t('Cancel');
tab.appendChild(cancel);
this.enable(tab.dataset.code);
var name = 'language_selection['+tab.dataset.code+']';
var selector_form = Drupal.behaviors.translation_tabs.selector_form;
selector_form.elements[name].checked = true;
}
};
translationTabs.prototype.cancel_language = function(tab) {
tab.dataset.state = 'off';
var a = tab.querySelector('a');
if (a) {
tab.removeChild(a);
}
this.disable(tab.dataset.code);
var name = 'language_selection['+tab.dataset.code+']';
var selector_form = Drupal.behaviors.translation_tabs.selector_form;
selector_form.elements[name].checked = false;
};
translationTabs.prototype.show = function(tab) {
this.item_list.querySelector('.language-tab.active').classList.remove('active');
tab.classList.add('active');
this.packs.forEach((pack) => {
let active = pack.querySelectorAll('.active[data-lang-pack]');
if (active) {
active.forEach((elm) => { elm.classList.remove('active'); });
}
active = pack.querySelectorAll('.field-language-' + tab.dataset.code);
if (active) {
active.forEach((elm) => { elm.classList.add('active'); });
}
});
};
translationTabs.prototype.showByCode = function(code) {
for (tab of this.item_list.querySelectorAll('.language-tab')) {
if (tab.dataset.code == code) {
this.show(tab);
break;
}
}
}
translationTabs.prototype.disable = function(lang_code) {
var tab = this.item_list.querySelector(`.language-tab[data-code="${lang_code}"`);
var first_tab = this.item_list.querySelector('.language-tab:first-child');
this.show(first_tab);
};
translationTabs.prototype.enable = function(lang_code) {
var tab = this.item_list.querySelector(`.language-tab[data-code="${lang_code}"`);
};
})(Drupal);
