B000004 e MediaWiki:MarcEditorDynamicLinks.js: mudanças entre as páginas

De Wikincat
(Diferenças entre páginas)
Ir para navegação Ir para pesquisar
imported>Jaideraf
Sem resumo de edição
 
Sem resumo de edição
 
Linha 1: Linha 1:
// Author: @vitorsilverio
{{BibRecord
// Author: @jaideraf
|dateEnteredOnFile=030415
/*jshint esversion: 6 */
|itemType=01
function main() {
|recordStatus=a
let tag = '';
|typeOfRecord=m
let tagFromDropdown = '';
|bibliographicLevel=s

|encodingLevel=2
function createMarcFieldHelpLink() {
|descriptiveCatalogingForm=a
const tagInputs = document.body.querySelectorAll('.tagInput');
|multipartResourceRecordLevel= 
tagInputs.forEach((elem) => {
|typeOfDate=s
const marcFieldHelpLink = document.createElement('a');
|date1=2000
marcFieldHelpLink.setAttribute('target', '_blank');
|placeOfPublication=SPB
marcFieldHelpLink.innerText = '(?)';
|illustrations=a

|targetAudience=g
const marcFieldHelpLinkClass = elem.closest('table')
|formOfItem= 
.querySelector('.marcFieldHelpLink');
|natureOfContents= 
marcFieldHelpLinkClass.innerHTML = "";
|governmentPublication= 
marcFieldHelpLinkClass.appendChild(marcFieldHelpLink);
|conferencePublication= 

|festschrift= 
// find the tag value from the chosen dropdown
|index= 
marcFieldHelpLinkClass.addEventListener('mouseover', (event) => {
|literaryForm=1
tagFromDropdown = event.target.closest('.instanceMain')
|biography=d
.querySelector('.oo-ui-inputWidget-input')
|language=POR
.getAttribute('title') || '00x';
|modifiedRecord= 
tagFromDropdown = tagFromDropdown.substring(0, 3);
|catalogingSource=d
marcFieldHelpLink.setAttribute(
}}
'title',
{{Field
`Documentação do campo ${tagFromDropdown}`
|tag=020
);
|authorityType=Nenhuma
// build the URL
|ind1=4
if (window.location.href.match(/A\d{6}/)
|ind2=5
|| window.location.href.match(/AutRecord/)) {
|data=$a 8533613377 $q v. 1
marcFieldHelpLink.setAttribute(
}}
'href',
{{Field
`http://marc.febab.org/a${tagFromDropdown}`
|tag=020
);
|authorityType=Nenhuma
} else {
|ind1=#
marcFieldHelpLink.setAttribute(
|ind2=#
'href',
|data=$a 9788533613379 $q reimpr.
`https://www.loc.gov/marc/bibliographic/bd${tagFromDropdown}.html`
}}
);
{{Field
}
|tag=020
});
|authorityType=Nenhuma
});
|ind1=#
}
|ind2=#

|data=$a 9788533613386 $q reimpr.
function createAuthorityLinks() {
}}
const inputs = document.body.querySelectorAll('.instanceMain div table .oo-ui-inputWidget-input');
{{Field
inputs.forEach((elem) => {
|tag=020
const authorityLink = document.createElement('a');
|authorityType=Nenhuma
authorityLink.setAttribute('title', 'Abre uma nova aba para criar ou editar um registro de autoridade');
|ind1=#
authorityLink.setAttribute('target', '_blank');
|ind2=#
authorityLink.innerText = 'Criar registro de autoridade';
|data=$a 8533613385 $q v. 2
authorityLink.style.display = 'none';
}}

{{Field
const createAuthorityLink = elem.closest('table')
|tag=020
.querySelector('.createAuthorityLink');
|authorityType=Nenhuma
createAuthorityLink.innerHTML = "";
|ind1=#
createAuthorityLink.appendChild(authorityLink);
|ind2=#

|data=$a 8533613393 $q v. 3
const pattern1 = /\$0\sA\d{6}/;
}}
const pattern2 = /\$0\s\(BN\)\d{9}/;
{{Field

|tag=035
elem.addEventListener('focusout', () => {
|authorityType=Nenhuma
// if already recorded
|ind1=#
if (pattern1.test(elem.value)) {
|ind2=#
// build the URL for Wikincat aut record edit
|data=$a (BIBLIODATA)SC000644855
authorityLink.innerText = 'Editar autoridade';
}}
authorityLink.setAttribute(
{{Field
'href',
|tag=040
`/wiki/Special:FormEdit/AutRecord/Autoridade:${
|authorityType=Nenhuma
elem.value.match(/A\d{6}/)}`
|ind1=#
);
|ind2=#
} else if (pattern2.test(elem.value)) {
|data=$a BR-FlUSC $c BR-FlUSC $d BR-FlWIK
// build the URL for BN aut record view
}}
authorityLink.innerText = 'Ver registro de autoridade na BN';
{{Field
authorityLink.setAttribute(
|tag=041
'href',
|authorityType=Nenhuma
`http://acervo.bn.gov.br/sophia_web/autoridade/detalhe/${
|ind1=1
elem.value.match(/\d{9}/)}`
|ind2=#
);
|data=$a Por $h Eng
} else {
}}
// find the tag value from the chosen dropdown
{{Field
tagFromDropdown = elem.closest('.instanceMain')
|tag=080
.querySelector('.oo-ui-inputWidget-input')
|authorityType=Nenhuma
.getAttribute('title') || '00x';
|ind1=#
tagFromDropdown = tagFromDropdown.substring(0, 3);
|ind2=#
// find the tag value from checked radio button
|data=$a 820-31

}}
const tagFromRadio = elem.closest('.instanceMain')
{{Field
.querySelector('input[origname=\'Field[authorityType]\']:checked')
|tag=090
.value;
|authorityType=Nenhuma

|ind1=#
const authorityTypes = {
|ind2=#
'Pessoa': '100',
|data=$a 820-31 $b T649 $c 2. ed.
'Entidade coletiva': '110',
}}
'Evento': '111',
{{Field
'Título uniforme': '130',
|tag=100
'Tópico': '150',
|authorityType=Pessoa
'Local': '151'
|ind1=1
};
|ind2=#

|authorityData100=$a Tolkien, J. R. R. $q (John Ronald Reuel), $d 1892-1973 $0 A000012
if (tagFromRadio in authorityTypes) {
}}
tag = authorityTypes[tagFromRadio];
{{Field
}
|tag=100

|authorityType=Pessoa
// declare the indicators default values
|ind1=#
let ind1 = elem.closest('.instanceMain')
|ind2=#
.querySelector('select[origname=\'Field[ind1]\'] option:checked')
|authorityData100=$a Assis, Machado de, $d 1839-1908 $0 A000001
.value;
}}
let ind2 = elem.closest('.instanceMain')
{{Field
.querySelector('select[origname=\'Field[ind2]\'] option:checked')
|tag=240
.value;
|authorityType=Nenhuma

|ind1=1
// declare the 008 field default values
|ind2=4
let directOrIndirectGeogSubdiv = ''; // 06
|data=$a The lord of the rings. $l Português
let kindOfRecord = ''; // 09
}}
let descriptiveCatalogingRules = 'c'; // 10
{{Field
let subjectHeadingSystem = 'n'; // 11
|tag=245
let typeOfSeries = 'n'; // 12
|authorityType=Nenhuma
let numberedOrUnnumberedSeries = 'n'; // 13
|ind1=1
let headingUseMainOrAddedEntry = 'a'; // 14
|ind2=2
let headingUseSubjectAddedEntry = 'a'; // 15
|data=$a O senhor dos anéis / $c J. R. R. Tolkien ; tradução: Lenita Maria Rímoli Esteves, Almiro Pisetta ; revisão técnica e consultoria: Ronald Eduard Kyrmse ; coordenação: Luís Carlos Borges
let headingUseSeriesAddedEntry = 'b'; // 16
}}
let typeOfSubjectSubdivision = 'n'; // 17
{{Field
let undifferentiatedPersonalName = 'n'; // 32
|tag=250
let levelOfEstablishment = 'a'; // 33
|authorityType=Nenhuma

|ind1=#
// set the 008 field and indicadors specific values
|ind2=#
if (tag === '100') {
|data=$a 2. ed.
undifferentiatedPersonalName = 'a';
}}
ind2 = '';
{{Field
}
|tag=260
if (tag === '110') {
|authorityType=Nenhuma
// in case of autocomplete of 260
|ind1=#
if (tagFromDropdown === '260') {
|ind2=#
directOrIndirectGeogSubdiv = 'n';
|data=$a São Paulo : $b M. Fontes, $c 2000.
kindOfRecord = 'b';
}}
headingUseMainOrAddedEntry = 'b';
{{Field
headingUseSubjectAddedEntry = 'b';
|tag=300
levelOfEstablishment = 'n';
|authorityType=Nenhuma
ind1 = '1';
|ind1=#
}
|ind2=#
ind2 = '';
|data=$a v. : $b il. ; $c 20 cm
}
}}
if (tag === '111') {
{{Field
ind1 = '2';
|tag=505
ind2 = '';
|authorityType=Nenhuma
}
|ind1=8
if (tag === '130') {
|ind2=#
typeOfSeries = 'a';
|data=$a v. 1. A sociedade do anel -- v. 2. As duas torres -- v. 3. O retorno do rei.
numberedOrUnnumberedSeries = 'b';
}}
headingUseSeriesAddedEntry = 'a';
{{Field
if (tagFromDropdown === '130'
|tag=590
|| tagFromDropdown === '630'
|authorityType=Nenhuma
|| tagFromDropdown === '730') {
|ind1=#
ind2 = ind1; // an inverted value happens here, see and
|ind2=#
ind1 = ''; // compare bib. and auth. 130 MARC definitions
|data=$a A Biblioteca possui a 3. tiragem 2001, 4. tiragem 2002, 7. tiragem 2009, 12. e 13. reimpr. de 2014, 14. reimpr. de 2015.
}
}}
ind1 = '';
{{Field
}
|tag=650
if (tag === '150' || tag === '151') {
|authorityType=Nenhuma
descriptiveCatalogingRules = 'n';
|ind1=0
subjectHeadingSystem = 'z';
|ind2=4
headingUseMainOrAddedEntry = 'b';
|data=$a Ficção inglesa
ind1 = ''; // 150 and 151 indicators must be empty in
}}
ind2 = ''; // authority MARC records
{{Field
if (tag === '151') {
|tag=650
typeOfSubjectSubdivision = 'd';
|authorityType=Nenhuma
}
|ind1=0
}
|ind2=4
// build the URL
|data=$a Literatura inglesa
const autRecordParams = {
}}
AutRecord: {
{{Field
directOrIndirectGeogSubdiv,
|tag=740
kindOfRecord,
|authorityType=Nenhuma
descriptiveCatalogingRules,
|ind1=2
subjectHeadingSystem,
|ind2=2
typeOfSeries,
|data=$a A sociedade do anel
numberedOrUnnumberedSeries,
}}
headingUseMainOrAddedEntry,
{{Field
headingUseSubjectAddedEntry,
|tag=740
headingUseSeriesAddedEntry,
|authorityType=Nenhuma
typeOfSubjectSubdivision,
|ind1=3
undifferentiatedPersonalName,
|ind2=2
levelOfEstablishment
|data=$a As duas torres
},
}}
Field: {
{{Field
'1': {
|tag=740
tag: '040',
|authorityType=Nenhuma
data: '$a BR-FlWIK $b por $c BR-FlWIK $d BR-FlUSC'
|ind1=2
},
|ind2=2
'2': {
|data=$a O retorno do rei
tag,
}}
ind1,
{{EndOfRecord}}
ind2,
data: elem.value
},
'3': {
tag: '670',
data: '$a '
}
}
};

const url = new URL(`${window.location.origin}/wiki/Special:FormEdit/AutRecord`);
// function to transform a 3rd level object to URL query strings
const makeUrlParams = (obj) => {
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'object') {
for (const [key2, value2] of Object.entries(value)) {
if (typeof value2 === 'object') {
for (const [key3, value3] of Object.entries(value2)) {
url.searchParams.set(`${key}[${key2}][${key3}]`, value3);
}
} else {
url.searchParams.set(`${key}[${key2}]`, value2);
}
}
} else {
url.searchParams.set(key, value);
}
}
};
makeUrlParams(autRecordParams);
authorityLink.innerText = 'Criar registro de autoridade';
authorityLink.setAttribute('href', url.pathname + url.search);
}
authorityLink.style.display = '';
});
});
}

function rmCarriageReturn() {
const textareas = document.body.querySelectorAll('textarea');
textareas.forEach((textarea) => {
const element = textarea;
element.value = element.value.replace('
', '');
});
}

function rmHtmlTags() {
const textareas = document.body.querySelectorAll('textarea');
textareas.forEach((textarea) => {
const element = textarea;
element.value = element.value.replace(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g, '');
});
}

function rmTxtFromHiddenFields() {
const spans = document.body.querySelectorAll('span.hiddenByPF');
spans.forEach((elem) => {
elem.querySelectorAll('.input.oo-ui-inputWidget-input').forEach((input) => {
const element = input;
element.value = '';
});
elem.querySelectorAll('textarea').forEach((input) => {
const element = input;
element.value = '';
});
});
}

function normalizeInput() {
const instanceMains = document.body.querySelectorAll('.instanceMain div table');
instanceMains.forEach((instanceMain) => {
instanceMain.querySelectorAll('.oo-ui-inputWidget-input').forEach((input) => {
const normalizedInput = input;
normalizedInput.value = normalizedInput.value
// "$a Bar \n$b Baz" > " $a Bar $b Baz"
.replace(/\s*(\$[a-z0-8])\s*/g, ' $1 ')
// "$a Bar\nFoo" > "$a Bar Foo" ou "$a Bar Foo" > "$a Bar Foo"
.replace(/\n|\s\s+|\t/g, ' ')
// replace "|" by "%7C" (Ex.: http://viaf.org/processed/WKP|Q2484404)
.replace('|', '%7C');
});
instanceMain.querySelectorAll('textarea').forEach((textarea) => {
const normalizedInput = textarea;
textarea.value = normalizedInput.value
// "$a Bar \n$b Baz" > " $a Bar $b Baz"
.replace(/\s*(\$[a-z0-8])\s*/g, ' $1 ')
// "$a Bar\nFoo" > "$a Bar Foo" ou "$a Bar Foo" > "$a Bar Foo"
.replace(/\n|\s\s+|\t/g, ' ')
// replace "|" by "%7C" (Ex.: http://viaf.org/processed/WKP|Q2484404)
.replace('|', '%7C');
});
});
}

// calls main functions
createMarcFieldHelpLink();
createAuthorityLinks();
rmCarriageReturn();
rmHtmlTags();

// Como instâncias do formulário são criadas pelo botão "Adicionar campo",
// é necessário observar o DOM a partir da classe ".multipleTemplateList".
// Toda vez que o DOM é alterado (mais especificamente, quando uma nova
// child de ".multipleTemplateList" é criada), as funções
// createMarcFieldHelpLink() e createAuthorityLinks() são novamente chamadas.
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

// create an observer instance
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const newNodes = mutation.addedNodes; // DOM NodeList
if (newNodes.length !== 0) { // if there are new nodes added
createMarcFieldHelpLink();
createAuthorityLinks();
}
});
});

// select the target node
const target = document.querySelector('.multipleTemplateList');

// configuration of the observer
const config = {
childList: true,
attributes: false,
subtree: false,
};

// pass in the target node, as well as the observer options
observer.observe(target, config);

// when clicking save...
const saveBtn = document.body.querySelector('#wpSave');
saveBtn.addEventListener('click', () => {
observer.disconnect();
rmTxtFromHiddenFields();
rmCarriageReturn();
rmHtmlTags();
normalizeInput();
});
}

if (document.readyState === 'complete' || (document.readyState !== 'loading')) {
main();
} else {
document.addEventListener('DOMContentLoaded', main);
}

// for no obvious reason to me, the first call to the "main" function is not
// occurring, so wait 3 seconds and call it anyway.
setTimeout(main, 3000);

Edição das 22h05min de 24 de fevereiro de 2024

// Author: @vitorsilverio
// Author: @jaideraf
/*jshint esversion: 6 */
function main() {
  let tag = '';
  let tagFromDropdown = '';

  function createMarcFieldHelpLink() {
    const tagInputs = document.body.querySelectorAll('.tagInput');
    tagInputs.forEach((elem) => {
      const marcFieldHelpLink = document.createElement('a');
      marcFieldHelpLink.setAttribute('target', '_blank');
      marcFieldHelpLink.innerText = '(?)';

      const marcFieldHelpLinkClass = elem.closest('table')
        .querySelector('.marcFieldHelpLink');
      marcFieldHelpLinkClass.innerHTML = "";  
      marcFieldHelpLinkClass.appendChild(marcFieldHelpLink);

      // find the tag value from the chosen dropdown
      marcFieldHelpLinkClass.addEventListener('mouseover', (event) => {
        tagFromDropdown = event.target.closest('.instanceMain')
          .querySelector('.oo-ui-inputWidget-input')
          .getAttribute('title') || '00x';
        tagFromDropdown = tagFromDropdown.substring(0, 3);
        marcFieldHelpLink.setAttribute(
          'title',
          `Documentação do campo ${tagFromDropdown}`
        );
        // build the URL
        if (window.location.href.match(/A\d{6}/)
                    || window.location.href.match(/AutRecord/)) {
          marcFieldHelpLink.setAttribute(
            'href',
            `http://marc.febab.org/a${tagFromDropdown}`
          );
        } else {
          marcFieldHelpLink.setAttribute(
            'href',
            `https://www.loc.gov/marc/bibliographic/bd${tagFromDropdown}.html`
          );
        }
      });
    });
  }

  function createAuthorityLinks() {
    const inputs = document.body.querySelectorAll('.instanceMain div table .oo-ui-inputWidget-input');
    inputs.forEach((elem) => {
      const authorityLink = document.createElement('a');
      authorityLink.setAttribute('title', 'Abre uma nova aba para criar ou editar um registro de autoridade');
      authorityLink.setAttribute('target', '_blank');
      authorityLink.innerText = 'Criar registro de autoridade';
      authorityLink.style.display = 'none';

      const createAuthorityLink = elem.closest('table')
        .querySelector('.createAuthorityLink');
	  createAuthorityLink.innerHTML = "";  
      createAuthorityLink.appendChild(authorityLink);

      const pattern1 = /\$0\sA\d{6}/;
      const pattern2 = /\$0\s\(BN\)\d{9}/;

      elem.addEventListener('focusout', () => {
        // if already recorded
        if (pattern1.test(elem.value)) {
          // build the URL for Wikincat aut record edit
          authorityLink.innerText = 'Editar autoridade';
          authorityLink.setAttribute(
            'href',
            `/wiki/Special:FormEdit/AutRecord/Autoridade:${
              elem.value.match(/A\d{6}/)}`
          );
        } else if (pattern2.test(elem.value)) {
          // build the URL for BN aut record view
          authorityLink.innerText = 'Ver registro de autoridade na BN';
          authorityLink.setAttribute(
            'href',
            `http://acervo.bn.gov.br/sophia_web/autoridade/detalhe/${
              elem.value.match(/\d{9}/)}`
          );
        } else {
          // find the tag value from the chosen dropdown
          tagFromDropdown = elem.closest('.instanceMain')
            .querySelector('.oo-ui-inputWidget-input')
            .getAttribute('title') || '00x';
          tagFromDropdown = tagFromDropdown.substring(0, 3);
          // find the tag value from checked radio button

          const tagFromRadio = elem.closest('.instanceMain')
            .querySelector('input[origname=\'Field[authorityType]\']:checked')
            .value;

          const authorityTypes = {
            'Pessoa': '100',
            'Entidade coletiva': '110',
            'Evento': '111',
            'Título uniforme': '130',
            'Tópico': '150',
            'Local': '151'
          };

          if (tagFromRadio in authorityTypes) {
            tag = authorityTypes[tagFromRadio];
          }

          // declare the indicators default values
          let ind1 = elem.closest('.instanceMain')
            .querySelector('select[origname=\'Field[ind1]\'] option:checked')
            .value;
          let ind2 = elem.closest('.instanceMain')
            .querySelector('select[origname=\'Field[ind2]\'] option:checked')
            .value;

          // declare the 008 field default values
          let directOrIndirectGeogSubdiv = ''; // 06
          let kindOfRecord = ''; // 09
          let descriptiveCatalogingRules = 'c'; // 10
          let subjectHeadingSystem = 'n'; // 11
          let typeOfSeries = 'n'; // 12
          let numberedOrUnnumberedSeries = 'n'; // 13
          let headingUseMainOrAddedEntry = 'a'; // 14
          let headingUseSubjectAddedEntry = 'a'; // 15
          let headingUseSeriesAddedEntry = 'b'; // 16
          let typeOfSubjectSubdivision = 'n'; // 17
          let undifferentiatedPersonalName = 'n'; // 32
          let levelOfEstablishment = 'a'; // 33

          // set the 008 field and indicadors specific values
          if (tag === '100') {
            undifferentiatedPersonalName = 'a';
            ind2 = '';
          }
          if (tag === '110') {
            // in case of autocomplete of 260
            if (tagFromDropdown === '260') {
              directOrIndirectGeogSubdiv = 'n';
              kindOfRecord = 'b';
              headingUseMainOrAddedEntry = 'b';
              headingUseSubjectAddedEntry = 'b';
              levelOfEstablishment = 'n';
              ind1 = '1';
            }
            ind2 = '';
          }
          if (tag === '111') {
            ind1 = '2';
            ind2 = '';
          }
          if (tag === '130') {
            typeOfSeries = 'a';
            numberedOrUnnumberedSeries = 'b';
            headingUseSeriesAddedEntry = 'a';
            if (tagFromDropdown === '130'
                            || tagFromDropdown === '630'
                            || tagFromDropdown === '730') {
              ind2 = ind1; // an inverted value happens here, see and
              ind1 = ''; // compare bib. and auth. 130 MARC definitions
            }
            ind1 = '';
          }
          if (tag === '150' || tag === '151') {
            descriptiveCatalogingRules = 'n';
            subjectHeadingSystem = 'z';
            headingUseMainOrAddedEntry = 'b';
            ind1 = ''; // 150 and 151 indicators must be empty in
            ind2 = ''; // authority MARC records
            if (tag === '151') {
              typeOfSubjectSubdivision = 'd';
            }
          }
          // build the URL
          const autRecordParams = {
            AutRecord: {
              directOrIndirectGeogSubdiv,
              kindOfRecord,
              descriptiveCatalogingRules,
              subjectHeadingSystem,
              typeOfSeries,
              numberedOrUnnumberedSeries,
              headingUseMainOrAddedEntry,
              headingUseSubjectAddedEntry,
              headingUseSeriesAddedEntry,
              typeOfSubjectSubdivision,
              undifferentiatedPersonalName,
              levelOfEstablishment
            },
            Field: {
              '1': {
                tag: '040',
                data: '$a BR-FlWIK $b por $c BR-FlWIK $d BR-FlUSC'
              },
              '2': {
                tag,
                ind1,
                ind2,
                data: elem.value
              },
              '3': {
                tag: '670',
                data: '$a '
              }
            }
          };

          const url = new URL(`${window.location.origin}/wiki/Special:FormEdit/AutRecord`);
          // function to transform a 3rd level object to URL query strings
          const makeUrlParams = (obj) => {
            for (const [key, value] of Object.entries(obj)) {
              if (typeof value === 'object') {
                for (const [key2, value2] of Object.entries(value)) {
                  if (typeof value2 === 'object') {
                    for (const [key3, value3] of Object.entries(value2)) {
                      url.searchParams.set(`${key}[${key2}][${key3}]`, value3);
                    }
                  } else {
                    url.searchParams.set(`${key}[${key2}]`, value2);
                  }
                }
              } else {
                url.searchParams.set(key, value);
              }
            }
          };
          makeUrlParams(autRecordParams);
          authorityLink.innerText = 'Criar registro de autoridade';
          authorityLink.setAttribute('href', url.pathname + url.search);
        }
        authorityLink.style.display = '';
      });
    });
  }

  function rmCarriageReturn() {
    const textareas = document.body.querySelectorAll('textarea');
    textareas.forEach((textarea) => {
      const element = textarea;
      element.value = element.value.replace('&#13;', '');
    });
  }

  function rmHtmlTags() {
    const textareas = document.body.querySelectorAll('textarea');
    textareas.forEach((textarea) => {
      const element = textarea;
      element.value = element.value.replace(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g, '');
    });
  }

  function rmTxtFromHiddenFields() {
    const spans = document.body.querySelectorAll('span.hiddenByPF');
    spans.forEach((elem) => {
      elem.querySelectorAll('.input.oo-ui-inputWidget-input').forEach((input) => {
        const element = input;
        element.value = '';
      });
      elem.querySelectorAll('textarea').forEach((input) => {
        const element = input;
        element.value = '';
      });
    });
  }

  function normalizeInput() {
    const instanceMains = document.body.querySelectorAll('.instanceMain div table');
    instanceMains.forEach((instanceMain) => {
    	instanceMain.querySelectorAll('.oo-ui-inputWidget-input').forEach((input) => {
    		const normalizedInput = input;
    		normalizedInput.value = normalizedInput.value
    		// "$a   Bar   \n$b    Baz" > " $a Bar $b Baz"
    		.replace(/\s*(\$[a-z0-8])\s*/g, ' $1 ')
    		// "$a Bar\nFoo" > "$a Bar Foo" ou "$a Bar  Foo" > "$a Bar Foo"
    		.replace(/\n|\s\s+|\t/g, ' ')
    		// replace "|" by "%7C" (Ex.: http://viaf.org/processed/WKP|Q2484404)
    		.replace('|', '%7C');
    	});
    	instanceMain.querySelectorAll('textarea').forEach((textarea) => {
    		const normalizedInput = textarea;
    		textarea.value = normalizedInput.value
    		// "$a   Bar   \n$b    Baz" > " $a Bar $b Baz"
    		.replace(/\s*(\$[a-z0-8])\s*/g, ' $1 ')
    		// "$a Bar\nFoo" > "$a Bar Foo" ou "$a Bar  Foo" > "$a Bar Foo"
    		.replace(/\n|\s\s+|\t/g, ' ')
    		// replace "|" by "%7C" (Ex.: http://viaf.org/processed/WKP|Q2484404)
    		.replace('|', '%7C');
    	});
    });
  }

  // calls main functions
  createMarcFieldHelpLink();
  createAuthorityLinks();
  rmCarriageReturn();
  rmHtmlTags();

  // Como instâncias do formulário são criadas pelo botão "Adicionar campo",
  // é necessário observar o DOM a partir da classe ".multipleTemplateList".
  // Toda vez que o DOM é alterado (mais especificamente, quando uma nova
  // child de ".multipleTemplateList" é criada), as funções
  // createMarcFieldHelpLink() e createAuthorityLinks() são novamente chamadas.
  // https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

  // create an observer instance
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      const newNodes = mutation.addedNodes; // DOM NodeList
      if (newNodes.length !== 0) { // if there are new nodes added
        createMarcFieldHelpLink();
        createAuthorityLinks();
      }
    });
  });

  // select the target node
  const target = document.querySelector('.multipleTemplateList');

  // configuration of the observer
  const config = {
    childList: true,
    attributes: false,
    subtree: false,
  };

  // pass in the target node, as well as the observer options
  observer.observe(target, config);

  // when clicking save...
  const saveBtn = document.body.querySelector('#wpSave');
  saveBtn.addEventListener('click', () => {
    observer.disconnect();
    rmTxtFromHiddenFields();
    rmCarriageReturn();
    rmHtmlTags();
    normalizeInput();
  });
}

if (document.readyState === 'complete' || (document.readyState !== 'loading')) {
  main();
} else {
  document.addEventListener('DOMContentLoaded', main);
}

// for no obvious reason to me, the first call to the "main" function is not 
// occurring, so wait 3 seconds and call it anyway.
setTimeout(main, 3000);