Bug 30941: Add cataloguing plugins for 146$bcdef (UNIMARC)
authorJulian Maurice <julian.maurice@biblibre.com>
Wed, 19 Jan 2022 15:09:28 +0000 (16:09 +0100)
committerTomas Cohen Arazi <tomascohen@theke.io>
Fri, 19 Aug 2022 11:55:09 +0000 (08:55 -0300)
Test plan:
1. Configure the default MARC framework to use those value builders:
   - unimarc_field_146b for 146$b
   - unimarc_field_146c for 146$c
   - unimarc_field_146d for 146$d
   - unimarc_field_146e for 146$e
   - unimarc_field_146f for 146$f
2. Verify that they all work correctly according to
https://www.ifla.org/files/assets/uca/unimarc_updates/BIBLIOGRAPHIC/u-b_146.pdf

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
12 files changed:
Koha/CodeList/Unimarc/MediumOfPerformance.pm [new file with mode: 0644]
Koha/I18N.pm
cataloguing/value_builder/unimarc_field_146b.pl [new file with mode: 0644]
cataloguing/value_builder/unimarc_field_146c.pl [new file with mode: 0644]
cataloguing/value_builder/unimarc_field_146d.pl [new file with mode: 0644]
cataloguing/value_builder/unimarc_field_146e.pl [new file with mode: 0644]
cataloguing/value_builder/unimarc_field_146f.pl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146b.tt [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146c.tt [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146d.tt [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146e.tt [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146f.tt [new file with mode: 0644]

diff --git a/Koha/CodeList/Unimarc/MediumOfPerformance.pm b/Koha/CodeList/Unimarc/MediumOfPerformance.pm
new file mode 100644 (file)
index 0000000..12ba763
--- /dev/null
@@ -0,0 +1,473 @@
+package Koha::CodeList::Unimarc::MediumOfPerformance;
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+use utf8;
+
+use Koha::I18N;
+
+sub voices {
+    return {
+        'val' => N__('alto'),
+        'vbr' => N__('baritone'),
+        'vbs' => N__('bass'),
+        'vca' => N__('child alto'),
+        'vcs' => N__('child soprano'),
+        'vct' => N__('countertenor'),
+        'vcv' => N__('child voice'),
+        'vma' => N__('man\'s voice'),
+        'vms' => N__('mezzo-soprano'),
+        'vrc' => N__('reciting child\'s voice'),
+        'vre' => N__('reciting voice'),
+        'vrm' => N__('reciting man\'s voice'),
+        'vrw' => N__('reciting woman\'s voice'),
+        'vso' => N__('soprano'),
+        'vte' => N__('tenor'),
+        'vun' => N__('voice - unspecified'),
+        'vwo' => N__('woman\'s voice'),
+        'vzz' => N__('voice - other'),
+    };
+}
+
+sub woodwinds {
+    return {
+        'wba' => N__('bassoon'),
+        'wbh' => N__('basset-horn'),
+        'wbp' => N__('bagpipe'),
+        'wcl' => N__('clarinet'),
+        'wcr' => N__('cromorne'),
+        'wdb' => N__('double bassoon'),
+        'wdi' => N__('didjeridu'),
+        'wdu' => N__('dulcian'),
+        'wdv' => N__('dvojnice'),
+        'weh' => N__('english horn'),
+        'wfg' => N__('flageolet'),
+        'wfi' => N__('fife'),
+        'wfl' => N__('flute'),
+        'wga' => N__('tabor pipe'),
+        'wge' => N__('gemshorn'),
+        'whp' => N__('hornpipe'),
+        'wmo' => N__('mouth organ'),
+        'wmu' => N__('musette'),
+        'wna' => N__('ney'),
+        'woa' => N__('oboe d\'amore'),
+        'wob' => N__('oboe'),
+        'woh' => N__('oboe da caccia'),
+        'wpi' => N__('piccolo'),
+        'wpo' => N__('pommer'),
+        'wpp' => N__('panpipes'),
+        'wra' => N__('racket'),
+        'wre' => N__('recorder'),
+        'wro' => N__('rothophone'),
+        'wsa' => N__('saxophone'),
+        'wsh' => N__('shakuhachi'),
+        'wsn' => N__('zurna'),
+        'wsr' => N__('sarrusophone'),
+        'wsu' => N__('sordun'),
+        'wun' => N__('woodwind - unspecified'),
+        'wvu' => N__('vox humana'),
+        'wzz' => N__('woodwind - other'),
+    };
+}
+
+sub brass {
+    return {
+        'bah' => N__('alphorn'),
+        'bbd' => N__('bombardon'),
+        'bbh' => N__('bersag horn'),
+        'bbu' => N__('bugle'),
+        'bca' => N__('carnyx'),
+        'bch' => N__('cow horn'),
+        'bcl' => N__('clarion'),
+        'bco' => N__('cornet'),
+        'bct' => N__('cornett'),
+        'bdx' => N__('duplex'),
+        'beu' => N__('euphonium'),
+        'bhh' => N__('hunting horn'),
+        'bho' => N__('horn'),
+        'bht' => N__('herald\'s trumpet'),
+        'bkb' => N__('keyed bugle'),
+        'bol' => N__('oliphant'),
+        'bop' => N__('ophicleide'),
+        'bph' => N__('post horn'),
+        'brh' => N__('russian horn'),
+        'bse' => N__('serpent'),
+        'bsh' => N__('shofar'),
+        'bsr' => N__('sarrusophone'),
+        'btb' => N__('trombone'),
+        'btr' => N__('trumpet'),
+        'btu' => N__('tuba'),
+        'bun' => N__('brass - unspecified'),
+        'bvb' => N__('valved bugle'),
+        'bwt' => N__('wagner tuba'),
+        'bzz' => N__('brass - other'),
+    };
+}
+
+sub strings_bowed {
+    return {
+        'sar' => N__('arpeggione'),
+        'sba' => N__('baryton'),
+        'sbt' => N__('bassett'),
+        'sbu' => N__('bumbass'),
+        'scr' => N__('crwth'),
+        'sdb' => N__('double bass'),
+        'sdf' => N__('five-string double bass'),
+        'sfi' => N__('fiddle, viol (family)'),
+        'sli' => N__('lira da braccio'),
+        'sln' => N__('lirone'),
+        'sny' => N__('keyed fiddle'),
+        'sob' => N__('octobass'),
+        'spo' => N__('kit'),
+        'sps' => N__('psalmodicon'),
+        'sre' => N__('rebec'),
+        'stm' => N__('trumpet marine'),
+        'sun' => N__('strings, bowed - unspecified'),
+        'sva' => N__('viola'),
+        'svc' => N__('cello'),
+        'sve' => N__('violone'),
+        'svg' => N__('viol'),
+        'svl' => N__('violin'),
+        'szz' => N__('strings, bowed - other'),
+    };
+}
+
+sub strings_plucked {
+    return {
+        'tal' => N__('archlute'),
+        'tat' => N__('harp-psaltery'),
+        'tbb' => N__('barbitos'),
+        'tbi' => N__('biwa'),
+        'tbj' => N__('banjo'),
+        'tbl' => N__('balalaika'),
+        'tbo' => N__('bouzouki'),
+        'tci' => N__('cittern'),
+        'tct' => N__('citole'),
+        'tcz' => N__('cobza'),
+        'tgu' => N__('guitar'),
+        'tha' => N__('harp'),
+        'thg' => N__('hawaiian guitar'),
+        'tih' => N__('Irish harp'),
+        'tkh' => N__('kithara'),
+        'tko' => N__('kora'),
+        'tkt' => N__('koto'),
+        'tlf' => N__('lute (family)'),
+        'tlg' => N__('lyre-guitar'),
+        'tlu' => N__('lute'),
+        'tma' => N__('mandolin'),
+        'tmd' => N__('mandore'),
+        'tpi' => N__('pipa'),
+        'tps' => N__('psaltery'),
+        'tpx' => N__('phorminx'),
+        'tqa' => N__('qānūn'),
+        'tsh' => N__('shamisen'),
+        'tsi' => N__('sitār'),
+        'tth' => N__('theorbo'),
+        'ttn' => N__('tanbur'),
+        'tud' => N__('oud'),
+        'tuk' => N__('ukulele'),
+        'tun' => N__('strings, plucked - unspecified'),
+        'tzi' => N__('zither'),
+        'tzz' => N__('strings, plucked - other'),
+    };
+}
+
+sub keyboard {
+    return {
+        'kac' => N__('accordion'),
+        'kce' => N__('celesta'),
+        'kcl' => N__('clavichord'),
+        'kco' => N__('claviorgan'),
+        'kcy' => N__('clavicytherium'),
+        'kfp' => N__('fortepiano'),
+        'kgl' => N__('glockenspiel'),
+        'khm' => N__('harmonium'),
+        'khp' => N__('harpsichord'),
+        'kmp' => N__('melopiano'),
+        'kor' => N__('organ'),
+        'kpf' => N__('piano'),
+        'kps' => N__('plucked string keyboard'),
+        'kre' => N__('regals'),
+        'ksi' => N__('sirenion'),
+        'ksp' => N__('sostenente piano'),
+        'kst' => N__('spinet'),
+        'kun' => N__('keyboard - unspecified'),
+        'kvg' => N__('virginal'),
+        'kzz' => N__('keyboard - other'),
+    };
+}
+
+sub percussion {
+    return {
+        'pab' => N__('aeolian bells'),
+        'pad' => N__('arabian drum'),
+        'pag' => N__('agogo'),
+        'pan' => N__('anvil'),
+        'pbb' => N__('boobams'),
+        'pbd' => N__('bass drum'),
+        'pbl' => N__('bells'),
+        'pbo' => N__('bongos'),
+        'pbp' => N__('metal bells plate'),
+        'pca' => N__('castanets'),
+        'pcb' => N__('cabaca'),
+        'pcc' => N__('chinese cymbals'),
+        'pcg' => N__('conga'),
+        'pch' => N__('chains'),
+        'pci' => N__('dulcimer'),
+        'pcr' => N__('crash cymbal'),
+        'pct' => N__('crotales'),
+        'pcv' => N__('claves'),
+        'pcw' => N__('cowbell'),
+        'pcy' => N__('cymbal'),
+        'pdr' => N__('drum'),
+        'pds' => N__('drums'),
+        'pfc' => N__('finger cymbals'),
+        'pfd' => N__('friction drum'),
+        'pfl' => N__('flexatone'),
+        'pgn' => N__('gun'),
+        'pgo' => N__('gong'),
+        'pgu' => N__('güiro'),
+        'pha' => N__('hammer'),
+        'phb' => N__('handbell'),
+        'phh' => N__('hi-hat'),
+        'pje' => N__('jembe'),
+        'pji' => N__('jingles'),
+        'pli' => N__('lithophone'),
+        'plj' => N__('lujon'),
+        'pmb' => N__('marimba'),
+        'pmd' => N__('military drum'),
+        'pme' => N__('metallophone'),
+        'pnv' => N__('nail violin'),
+        'pra' => N__('ratchet'),
+        'prs' => N__('rain stick'),
+        'prt' => N__('roto-toms'),
+        'psc' => N__('sizzle cymbals'),
+        'pse' => N__('sound-effect instrument'),
+        'psl' => N__('slit-drum'),
+        'psm' => N__('sistrum'),
+        'psn' => N__('siren'),
+        'psp' => N__('sandpaper'),
+        'pss' => N__('sound sculpture'),
+        'pst' => N__('steel drum'),
+        'psw' => N__('switch whip'),
+        'ptb' => N__('tabor'),
+        'ptc' => N__('turkish crescent'),
+        'pte' => N__('temple block'),
+        'ptg' => N__('tuned gong'),
+        'pti' => N__('timpani'),
+        'ptl' => N__('triangle'),
+        'ptm' => N__('thunder machine'),
+        'pto' => N__('tarol'),
+        'ptr' => N__('tambourine'),
+        'ptt' => N__('tom-tom'),
+        'pun' => N__('percussion - unspecified'),
+        'pvi' => N__('vibraphone'),
+        'pvs' => N__('vibra-slap'),
+        'pwh' => N__('whip'),
+        'pwm' => N__('wind machine'),
+        'pwo' => N__('woodblocks'),
+        'pxr' => N__('xylorimba'),
+        'pxy' => N__('xylophone'),
+        'pzz' => N__('percussion - other'),
+    };
+}
+
+sub electronic {
+    return {
+        'eco' => N__('computer'),
+        'ecs' => N__('computerized musical station'),
+        'ect' => N__('computerized tape'),
+        'eds' => N__('digital space device'),
+        'eea' => N__('electro-acoustic device'),
+        'eli' => N__('live electronic'),
+        'ely' => N__('lyricon'),
+        'eme' => N__('meta-instrument'),
+        'emu' => N__('multimedial device'),
+        'eos' => N__('oscillator'),
+        'esp' => N__('space device'),
+        'esy' => N__('synthesizer'),
+        'eta' => N__('tape'),
+        'eth' => N__('theremin'),
+        'eun' => N__('electronic - non specified'),
+        'ezz' => N__('electronic - other'),
+    };
+}
+
+sub misc {
+    return {
+        'mah' => N__('aeolian harp'),
+        'mbo' => N__('barrel organ'),
+        'mbr' => N__('bullroarer'),
+        'mbs' => N__('bass'),
+        'mbw' => N__('musical bow'),
+        'mbx' => N__('musical box'),
+        'mck' => N__('chekker'),
+        'mcl' => N__('musical clock'),
+        'mco' => N__('continuo'),
+        'mgh' => N__('glassharmonika'),
+        'mgt' => N__('glass trumpet'),
+        'mha' => N__('harmonica'),
+        'mhg' => N__('hurdy-gurdy'),
+        'mjh' => N__('jew\'s harp'),
+        'mla' => N__('lamellaphone'),
+        'mmc' => N__('monochord'),
+        'mme' => N__('melodica'),
+        'mmi' => N__('mirliton'),
+        'mml' => N__('melodic instrument'),
+        'mms' => N__('musical saw'),
+        'moc' => N__('ocarina'),
+        'mpo' => N__('polyphonic instrument'),
+        'mpp' => N__('player piano'),
+        'mra' => N__('rabāb'),
+        'mss' => N__('sound sculpture'),
+        'msw' => N__('swanee whistle'),
+        'mtf' => N__('tuning-fork'),
+        'mui' => N__('instrument - non specified'),
+        'mun' => N__('instrument or voice - non specified'),
+        'mwd' => N__('wind instrument'),
+        'mwh' => N__('whistle'),
+        'mzz' => N__('other'),
+    };
+}
+
+sub choruses {
+    return {
+        'cch' => N__('children\'s choir'),
+        'cme' => N__('men\'s choir'),
+        'cmi' => N__('mixed choir'),
+        'cre' => N__('reciting choir'),
+        'cun' => N__('choir - unspecified'),
+        'cve' => N__('vocal ensemble'),
+        'cwo' => N__('women\'s choir'),
+        'czz' => N__('choir - other'),
+    };
+}
+
+sub orchestras {
+    return {
+        'oba' => N__('band'),
+        'obi' => N__('big band'),
+        'obr' => N__('brass band'),
+        'och' => N__('chamber orchestra'),
+        'oco' => N__('combo'),
+        'odo' => N__('dance orchestra'),
+        'ofu' => N__('full orchestra'),
+        'oga' => N__('gamelan'),
+        'oie' => N__('instrumental ensemble'),
+        'oiv' => N__('vocal and instrumental ensemble'),
+        'oja' => N__('jazz band'),
+        'ope' => N__('percussion orchestra'),
+        'orb' => N__('ragtime band'),
+        'osb' => N__('steel band'),
+        'ost' => N__('string orchestra'),
+        'oun' => N__('orchestra - unspecified'),
+        'owi' => N__('wind orchestra'),
+        'ozz' => N__('orchestra - other'),
+    };
+}
+
+sub conductors {
+    return {
+        'qce' => N__('live electronic conductor'),
+        'qch' => N__('choir conductor, chorus master'),
+        'qco' => N__('conductor'),
+        'qlc' => N__('light conductor'),
+        'qzz' => N__('conductor - other'),
+    };
+}
+
+sub other_performers {
+    return {
+        'zab' => N__('acrobat'),
+        'zac' => N__('child actor'),
+        'zas' => N__('silent actor'),
+        'zat' => N__('actor'),
+        'zaw' => N__('actress'),
+        'zda' => N__('dancer'),
+        'zel' => N__('light engineer'),
+        'zes' => N__('sound engineer'),
+        'zju' => N__('juggler'),
+        'zmi' => N__('mime'),
+        'zwp' => N__('walk-on part'),
+        'zzz' => N__('performer - other'),
+    };
+}
+
+sub tessitura {
+    return {
+        'a' => N__p('tessitura', 'sopranino'),
+        'b' => N__p('tessitura', 'soprano'),
+        'c' => N__p('tessitura', 'alto'),
+        'd' => N__p('tessitura', 'tenor'),
+        'e' => N__p('tessitura', 'baritone'),
+        'f' => N__p('tessitura', 'bass'),
+        'g' => N__p('tessitura', 'contrabass'),
+        'h' => N__p('tessitura', 'sub-contrabass'),
+        'i' => N__p('tessitura', 'sopracute'),
+        'j' => N__p('tessitura', 'high'),
+        'k' => N__p('tessitura', 'medium'),
+        'l' => N__p('tessitura', 'low'),
+        'm' => N__p('tessitura', 'prepared'),
+    };
+}
+
+sub number_of_hands_or_keys {
+    return {
+        '1' => N__p('music', 'one hand'),
+        '2' => N__p('music', 'two players on one instrument'),
+        '3' => N__p('music', 'three hands'),
+        '4' => N__p('music', 'four hands'),
+        '6' => N__p('music', 'six hands'),
+        '8' => N__p('music', 'eight hands'),
+        'a' => N__p('music', 'A'),
+        'b' => N__p('music', 'B flat'),
+        'c' => N__p('music', 'C'),
+        'd' => N__p('music', 'D'),
+        'e' => N__p('music', 'E'),
+        'f' => N__p('music', 'F'),
+        'g' => N__p('music', 'G'),
+        'h' => N__p('music', 'B'),
+        'i' => N__p('music', 'E flat'),
+        'j' => N__p('music', 'A flat'),
+        'k' => N__p('music', 'D flat'),
+        'l' => N__p('music', 'F sharp'),
+        'n' => N__p('music', 'Instrument played in non standard way'),
+        's' => N__p('music', 'non standard string number'),
+    };
+}
+
+sub other {
+    return {
+        'r' => N__('electric'),
+        's' => N__('electronic'),
+        't' => N__('midi'),
+        'v' => N__('amplified'),
+        'w' => N__('recorded'),
+        'q' => N__('antiquity'),
+        'y' => N__('ethnic, traditional'),
+    };
+}
+
+sub other2 {
+    return {
+        'b' => N__('ad libitum'),
+        'c' => N__('may take place of the preceding code / alternative'),
+        'd' => N__('used by the same player as the preceding code'),
+    };
+}
+
+1;
index 464911c..3f09673 100644 (file)
@@ -168,19 +168,19 @@ sub __npx {
 }
 
 sub N__ {
-    return @_;
+    return $_[0];
 }
 
 sub N__n {
-    return @_;
+    return $_[0];
 }
 
 sub N__p {
-    return @_;
+    return $_[1];
 }
 
 sub N__np {
-    return @_;
+    return $_[1];
 }
 
 sub _base_directory {
diff --git a/cataloguing/value_builder/unimarc_field_146b.pl b/cataloguing/value_builder/unimarc_field_146b.pl
new file mode 100644 (file)
index 0000000..a507d17
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Scalar::Util;
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::I18N;
+use Koha::CodeList::Unimarc::MediumOfPerformance;
+
+my $builder = sub {
+    my $params = shift;
+    my $id = $params->{id};
+
+    return qq|
+<script>
+function Click$id (event) {
+    event.preventDefault();
+    const value = document.getElementById(event.data.id).value;
+    const url = new URL('/cgi-bin/koha/cataloguing/plugin_launcher.pl', location);
+    url.searchParams.set('plugin_name', 'unimarc_field_146b.pl');
+    url.searchParams.set('id', event.data.id);
+    url.searchParams.set('value', value);
+    window.open(url.toString(), 'tag_editor', 'width=700,height=700,toolbar=false,scrollbars=yes');
+}
+</script>|;
+};
+
+my $launcher = sub {
+    my $params = shift;
+    my $cgi = $params->{cgi};
+    my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+        template_name => "cataloguing/value_builder/unimarc_field_146b.tt",
+        query => $cgi,
+        type => 'intranet',
+        flagsrequired => { editcatalogue => '*' },
+    });
+
+    my @category_optgroups = (
+        { label => __('Voices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->voices() },
+        { label => __('Woodwinds'), values => Koha::CodeList::Unimarc::MediumOfPerformance->woodwinds() },
+        { label => __('Brass instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->brass() },
+        { label => __('Strings, bowed'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_bowed() },
+        { label => __('Strings, plucked'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_plucked() },
+        { label => __('Keyboard'), values => Koha::CodeList::Unimarc::MediumOfPerformance->keyboard() },
+        { label => __('Percussion'), values => Koha::CodeList::Unimarc::MediumOfPerformance->percussion() },
+        { label => __('Electric / electronic instruments and devices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->electronic() },
+        { label => __('Miscellaneous, other, unspecified instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->misc() },
+        { label => __('Other performers'), values => Koha::CodeList::Unimarc::MediumOfPerformance->other_performers() },
+    );
+
+    foreach my $optgroup (@category_optgroups) {
+        my $values = delete $optgroup->{values};
+        $optgroup->{options} = [
+            map {
+                { value => $_, label => __( $values->{$_} ) }
+            } sort keys %$values
+        ];
+    }
+
+    my $tessitura_hash = Koha::CodeList::Unimarc::MediumOfPerformance->tessitura();
+    my @tessitura_options = map {
+        { value => $_, label => __p('tessitura', $tessitura_hash->{$_}) }
+    } sort keys %$tessitura_hash;
+
+    my $number_of_hands_or_keys_hash = Koha::CodeList::Unimarc::MediumOfPerformance->number_of_hands_or_keys();
+    my @number_of_hands_or_keys_options = map {
+        { value => $_, label => __p('music', $number_of_hands_or_keys_hash->{$_}) }
+    } sort keys %$number_of_hands_or_keys_hash;
+
+    my $other_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other();
+    my @other_options = map {
+        { value => $_, label => __($other_hash->{$_}) }
+    } sort keys %$other_hash;
+
+    my $other2_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other2();
+    my @other2_options = map {
+        { value => $_, label => __($other2_hash->{$_}) }
+    } sort keys %$other2_hash;
+
+    my $value = $cgi->param('value');
+    my $number = substr($value, 0, 2);
+    unless (Scalar::Util::looks_like_number($number)) {
+        $number = '';
+    }
+    my $category = substr($value, 2, 3);
+    my $tessitura = substr($value, 5, 1);
+    my $number_of_hands_or_keys = substr($value, 6, 1);
+    my $other = substr($value, 7, 1);
+    my $other2 = substr($value, 8, 1);
+
+    $template->param(
+        id => scalar $cgi->param('id'),
+        number => $number,
+        category => $category,
+        tessitura => $tessitura,
+        number_of_hands_or_keys => $number_of_hands_or_keys,
+        other => $other,
+        other2 => $other2,
+        category_optgroups => \@category_optgroups,
+        tessitura_options => \@tessitura_options,
+        number_of_hands_or_keys_options => \@number_of_hands_or_keys_options,
+        other_options => \@other_options,
+        other2_options => \@other2_options,
+    );
+    output_html_with_http_headers $cgi, $cookie, $template->output;
+};
+
+return { builder => $builder, launcher => $launcher };
diff --git a/cataloguing/value_builder/unimarc_field_146c.pl b/cataloguing/value_builder/unimarc_field_146c.pl
new file mode 100644 (file)
index 0000000..0d44b3f
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Scalar::Util;
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::I18N;
+use Koha::CodeList::Unimarc::MediumOfPerformance;
+
+my $builder = sub {
+    my $params = shift;
+    my $id = $params->{id};
+
+    return qq|
+<script>
+function Click$id (event) {
+    event.preventDefault();
+    const value = document.getElementById(event.data.id).value;
+    const url = new URL('/cgi-bin/koha/cataloguing/plugin_launcher.pl', location);
+    url.searchParams.set('plugin_name', 'unimarc_field_146c.pl');
+    url.searchParams.set('id', event.data.id);
+    url.searchParams.set('value', value);
+    window.open(url.toString(), 'tag_editor', 'width=700,height=700,toolbar=false,scrollbars=yes');
+}
+</script>|;
+};
+
+my $launcher = sub {
+    my $params = shift;
+    my $cgi = $params->{cgi};
+    my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+        template_name => "cataloguing/value_builder/unimarc_field_146c.tt",
+        query => $cgi,
+        type => 'intranet',
+        flagsrequired => { editcatalogue => '*' },
+    });
+
+    my @category_optgroups = (
+        { label => __('Voices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->voices() },
+        { label => __('Woodwinds'), values => Koha::CodeList::Unimarc::MediumOfPerformance->woodwinds() },
+        { label => __('Brass instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->brass() },
+        { label => __('Strings, bowed'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_bowed() },
+        { label => __('Strings, plucked'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_plucked() },
+        { label => __('Keyboard'), values => Koha::CodeList::Unimarc::MediumOfPerformance->keyboard() },
+        { label => __('Percussion'), values => Koha::CodeList::Unimarc::MediumOfPerformance->percussion() },
+        { label => __('Electric / electronic instruments and devices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->electronic() },
+        { label => __('Miscellaneous, other, unspecified instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->misc() },
+        { label => __('Conductors'), values => Koha::CodeList::Unimarc::MediumOfPerformance->conductors() },
+        { label => __('Other performers'), values => Koha::CodeList::Unimarc::MediumOfPerformance->other_performers() },
+    );
+
+    foreach my $optgroup (@category_optgroups) {
+        my $values = delete $optgroup->{values};
+        $optgroup->{options} = [
+            map {
+                { value => $_, label => __( $values->{$_} ) }
+            } sort keys %$values
+        ];
+    }
+
+    my $tessitura_hash = Koha::CodeList::Unimarc::MediumOfPerformance->tessitura();
+    my @tessitura_options = map {
+        { value => $_, label => __p('tessitura', $tessitura_hash->{$_}) }
+    } sort keys %$tessitura_hash;
+
+    my $number_of_hands_or_keys_hash = Koha::CodeList::Unimarc::MediumOfPerformance->number_of_hands_or_keys();
+    my @number_of_hands_or_keys_options = map {
+        { value => $_, label => __p('music', $number_of_hands_or_keys_hash->{$_}) }
+    } sort keys %$number_of_hands_or_keys_hash;
+
+    my $other_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other();
+    my @other_options = map {
+        { value => $_, label => __($other_hash->{$_}) }
+    } sort keys %$other_hash;
+
+    my $other2_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other2();
+    my @other2_options = map {
+        { value => $_, label => __($other2_hash->{$_}) }
+    } sort keys %$other2_hash;
+
+    my $value = $cgi->param('value');
+    my $number = substr($value, 0, 2);
+    unless (Scalar::Util::looks_like_number($number)) {
+        $number = '';
+    }
+    my $category = substr($value, 2, 3);
+    my $tessitura = substr($value, 5, 1);
+    my $number_of_hands_or_keys = substr($value, 6, 1);
+    my $other = substr($value, 7, 1);
+    my $other2 = substr($value, 8, 1);
+
+    $template->param(
+        id => scalar $cgi->param('id'),
+        number => $number,
+        category => $category,
+        tessitura => $tessitura,
+        number_of_hands_or_keys => $number_of_hands_or_keys,
+        other => $other,
+        other2 => $other2,
+        category_optgroups => \@category_optgroups,
+        tessitura_options => \@tessitura_options,
+        number_of_hands_or_keys_options => \@number_of_hands_or_keys_options,
+        other_options => \@other_options,
+        other2_options => \@other2_options,
+    );
+    output_html_with_http_headers $cgi, $cookie, $template->output;
+};
+
+return { builder => $builder, launcher => $launcher };
diff --git a/cataloguing/value_builder/unimarc_field_146d.pl b/cataloguing/value_builder/unimarc_field_146d.pl
new file mode 100644 (file)
index 0000000..ee4a3ed
--- /dev/null
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Scalar::Util;
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::I18N;
+use Koha::CodeList::Unimarc::MediumOfPerformance;
+
+my $builder = sub {
+    my $params = shift;
+    my $id = $params->{id};
+
+    return qq|
+<script>
+function Click$id (event) {
+    event.preventDefault();
+    const value = document.getElementById(event.data.id).value;
+    const url = new URL('/cgi-bin/koha/cataloguing/plugin_launcher.pl', location);
+    url.searchParams.set('plugin_name', 'unimarc_field_146d.pl');
+    url.searchParams.set('id', event.data.id);
+    url.searchParams.set('value', value);
+    window.open(url.toString(), 'tag_editor', 'width=700,height=700,toolbar=false,scrollbars=yes');
+}
+</script>|;
+};
+
+my $launcher = sub {
+    my $params = shift;
+    my $cgi = $params->{cgi};
+    my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+        template_name => "cataloguing/value_builder/unimarc_field_146d.tt",
+        query => $cgi,
+        type => 'intranet',
+        flagsrequired => { editcatalogue => '*' },
+    });
+
+    my @category_optgroups = (
+        { label => __('Choruses'), values => Koha::CodeList::Unimarc::MediumOfPerformance->choruses() },
+        { label => __('Orchestras, ensembles'), values => Koha::CodeList::Unimarc::MediumOfPerformance->orchestras() },
+    );
+
+    foreach my $optgroup (@category_optgroups) {
+        my $values = delete $optgroup->{values};
+        $optgroup->{options} = [
+            map {
+                { value => $_, label => __( $values->{$_} ) }
+            } sort keys %$values
+        ];
+    }
+
+    my $other_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other();
+    my @other_options = map {
+        { value => $_, label => __($other_hash->{$_}) }
+    } sort keys %$other_hash;
+
+    my $other2_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other2();
+    my @other2_options = map {
+        { value => $_, label => __($other2_hash->{$_}) }
+    } sort keys %$other2_hash;
+
+    my $value = $cgi->param('value');
+    my $number = substr($value, 0, 2);
+    unless (Scalar::Util::looks_like_number($number)) {
+        $number = '';
+    }
+    my $category = substr($value, 2, 3);
+    my $number_of_real_parts = substr($value, 5, 2);
+    unless (Scalar::Util::looks_like_number($number_of_real_parts)) {
+        $number_of_real_parts = '';
+    }
+    my $other = substr($value, 7, 1);
+    my $other2 = substr($value, 8, 1);
+
+    $template->param(
+        id => scalar $cgi->param('id'),
+        number => $number,
+        category => $category,
+        number_of_real_parts => $number_of_real_parts,
+        other => $other,
+        other2 => $other2,
+        category_optgroups => \@category_optgroups,
+        other_options => \@other_options,
+        other2_options => \@other2_options,
+    );
+    output_html_with_http_headers $cgi, $cookie, $template->output;
+};
+
+return { builder => $builder, launcher => $launcher };
diff --git a/cataloguing/value_builder/unimarc_field_146e.pl b/cataloguing/value_builder/unimarc_field_146e.pl
new file mode 100644 (file)
index 0000000..9a36a9b
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Scalar::Util;
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::I18N;
+use Koha::CodeList::Unimarc::MediumOfPerformance;
+
+my $builder = sub {
+    my $params = shift;
+    my $id = $params->{id};
+
+    return qq|
+<script>
+function Click$id (event) {
+    event.preventDefault();
+    const value = document.getElementById(event.data.id).value;
+    const url = new URL('/cgi-bin/koha/cataloguing/plugin_launcher.pl', location);
+    url.searchParams.set('plugin_name', 'unimarc_field_146e.pl');
+    url.searchParams.set('id', event.data.id);
+    url.searchParams.set('value', value);
+    window.open(url.toString(), 'tag_editor', 'width=700,height=700,toolbar=false,scrollbars=yes');
+}
+</script>|;
+};
+
+my $launcher = sub {
+    my $params = shift;
+    my $cgi = $params->{cgi};
+    my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+        template_name => "cataloguing/value_builder/unimarc_field_146e.tt",
+        query => $cgi,
+        type => 'intranet',
+        flagsrequired => { editcatalogue => '*' },
+    });
+
+    my @category_optgroups = (
+        { label => __('Voices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->voices() },
+        { label => __('Woodwinds'), values => Koha::CodeList::Unimarc::MediumOfPerformance->woodwinds() },
+        { label => __('Brass instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->brass() },
+        { label => __('Strings, bowed'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_bowed() },
+        { label => __('Strings, plucked'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_plucked() },
+        { label => __('Keyboard'), values => Koha::CodeList::Unimarc::MediumOfPerformance->keyboard() },
+        { label => __('Percussion'), values => Koha::CodeList::Unimarc::MediumOfPerformance->percussion() },
+        { label => __('Electric / electronic instruments and devices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->electronic() },
+        { label => __('Miscellaneous, other, unspecified instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->misc() },
+        { label => __('Conductors'), values => Koha::CodeList::Unimarc::MediumOfPerformance->conductors() },
+        { label => __('Other performers'), values => Koha::CodeList::Unimarc::MediumOfPerformance->other_performers() },
+    );
+
+    foreach my $optgroup (@category_optgroups) {
+        my $values = delete $optgroup->{values};
+        $optgroup->{options} = [
+            map {
+                { value => $_, label => __( $values->{$_} ) }
+            } sort keys %$values
+        ];
+    }
+
+    my $tessitura_hash = Koha::CodeList::Unimarc::MediumOfPerformance->tessitura();
+    my @tessitura_options = map {
+        { value => $_, label => __p('tessitura', $tessitura_hash->{$_}) }
+    } sort keys %$tessitura_hash;
+
+    my $number_of_hands_or_keys_hash = Koha::CodeList::Unimarc::MediumOfPerformance->number_of_hands_or_keys();
+    my @number_of_hands_or_keys_options = map {
+        { value => $_, label => __p('music', $number_of_hands_or_keys_hash->{$_}) }
+    } sort keys %$number_of_hands_or_keys_hash;
+
+    my $other_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other();
+    my @other_options = map {
+        { value => $_, label => __($other_hash->{$_}) }
+    } sort keys %$other_hash;
+
+    my $other2_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other2();
+    my @other2_options = map {
+        { value => $_, label => __($other2_hash->{$_}) }
+    } sort keys %$other2_hash;
+
+    my $value = $cgi->param('value');
+    my $number = substr($value, 0, 2);
+    unless (Scalar::Util::looks_like_number($number)) {
+        $number = '';
+    }
+    my $category = substr($value, 2, 3);
+    my $tessitura = substr($value, 5, 1);
+    my $number_of_hands_or_keys = substr($value, 6, 1);
+    my $other = substr($value, 7, 1);
+    my $other2 = substr($value, 8, 1);
+
+    $template->param(
+        id => scalar $cgi->param('id'),
+        number => $number,
+        category => $category,
+        tessitura => $tessitura,
+        number_of_hands_or_keys => $number_of_hands_or_keys,
+        other => $other,
+        other2 => $other2,
+        category_optgroups => \@category_optgroups,
+        tessitura_options => \@tessitura_options,
+        number_of_hands_or_keys_options => \@number_of_hands_or_keys_options,
+        other_options => \@other_options,
+        other2_options => \@other2_options,
+    );
+    output_html_with_http_headers $cgi, $cookie, $template->output;
+};
+
+return { builder => $builder, launcher => $launcher };
diff --git a/cataloguing/value_builder/unimarc_field_146f.pl b/cataloguing/value_builder/unimarc_field_146f.pl
new file mode 100644 (file)
index 0000000..d74967b
--- /dev/null
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Scalar::Util;
+
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::I18N;
+use Koha::CodeList::Unimarc::MediumOfPerformance;
+
+my $builder = sub {
+    my $params = shift;
+    my $id = $params->{id};
+
+    return qq|
+<script>
+function Click$id (event) {
+    event.preventDefault();
+    const value = document.getElementById(event.data.id).value;
+    const url = new URL('/cgi-bin/koha/cataloguing/plugin_launcher.pl', location);
+    url.searchParams.set('plugin_name', 'unimarc_field_146f.pl');
+    url.searchParams.set('id', event.data.id);
+    url.searchParams.set('value', value);
+    window.open(url.toString(), 'tag_editor', 'width=700,height=700,toolbar=false,scrollbars=yes');
+}
+</script>|;
+};
+
+my $launcher = sub {
+    my $params = shift;
+    my $cgi = $params->{cgi};
+    my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+        template_name => "cataloguing/value_builder/unimarc_field_146f.tt",
+        query => $cgi,
+        type => 'intranet',
+        flagsrequired => { editcatalogue => '*' },
+    });
+
+    my @category_optgroups = (
+        { label => __('Woodwinds'), values => Koha::CodeList::Unimarc::MediumOfPerformance->woodwinds() },
+        { label => __('Brass instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->brass() },
+        { label => __('Strings, bowed'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_bowed() },
+        { label => __('Strings, plucked'), values => Koha::CodeList::Unimarc::MediumOfPerformance->strings_plucked() },
+        { label => __('Keyboard'), values => Koha::CodeList::Unimarc::MediumOfPerformance->keyboard() },
+        { label => __('Percussion'), values => Koha::CodeList::Unimarc::MediumOfPerformance->percussion() },
+        { label => __('Electric / electronic instruments and devices'), values => Koha::CodeList::Unimarc::MediumOfPerformance->electronic() },
+        { label => __('Miscellaneous, other, unspecified instruments'), values => Koha::CodeList::Unimarc::MediumOfPerformance->misc() },
+    );
+
+    foreach my $optgroup (@category_optgroups) {
+        my $values = delete $optgroup->{values};
+        $optgroup->{options} = [
+            map {
+                { value => $_, label => __( $values->{$_} ) }
+            } sort keys %$values
+        ];
+    }
+
+    my $tessitura_hash = Koha::CodeList::Unimarc::MediumOfPerformance->tessitura();
+    my @tessitura_options = map {
+        { value => $_, label => __p('tessitura', $tessitura_hash->{$_}) }
+    } sort keys %$tessitura_hash;
+
+    my $number_of_hands_or_keys_hash = Koha::CodeList::Unimarc::MediumOfPerformance->number_of_hands_or_keys();
+    my @number_of_hands_or_keys_options = map {
+        { value => $_, label => __p('music', $number_of_hands_or_keys_hash->{$_}) }
+    } sort keys %$number_of_hands_or_keys_hash;
+
+    my $other_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other();
+    my @other_options = map {
+        { value => $_, label => __($other_hash->{$_}) }
+    } sort keys %$other_hash;
+
+    my $other2_hash = Koha::CodeList::Unimarc::MediumOfPerformance->other2();
+    my @other2_options = map {
+        { value => $_, label => __($other2_hash->{$_}) }
+    } sort keys %$other2_hash;
+
+    my $value = $cgi->param('value');
+    my $number = substr($value, 0, 2);
+    unless (Scalar::Util::looks_like_number($number)) {
+        $number = '';
+    }
+    my $category = substr($value, 2, 3);
+    my $tessitura = substr($value, 5, 1);
+    my $number_of_hands_or_keys = substr($value, 6, 1);
+    my $other = substr($value, 7, 1);
+    my $other2 = substr($value, 8, 1);
+
+    $template->param(
+        id => scalar $cgi->param('id'),
+        number => $number,
+        category => $category,
+        tessitura => $tessitura,
+        number_of_hands_or_keys => $number_of_hands_or_keys,
+        other => $other,
+        other2 => $other2,
+        category_optgroups => \@category_optgroups,
+        tessitura_options => \@tessitura_options,
+        number_of_hands_or_keys_options => \@number_of_hands_or_keys_options,
+        other_options => \@other_options,
+        other2_options => \@other2_options,
+    );
+    output_html_with_http_headers $cgi, $cookie, $template->output;
+};
+
+return { builder => $builder, launcher => $launcher };
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146b.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146b.tt
new file mode 100644 (file)
index 0000000..c2339c5
--- /dev/null
@@ -0,0 +1,141 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Framework plugin unimarc_field_146b &rsaquo; Cataloguing &rsaquo; Koha</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="unimarc_field_146b" class="cat">
+    <div class="container-fluid">
+        <h1>Framework plugin for UNIMARC 146$b</h1>
+
+        <form class="form-horizontal" id="form">
+            <input type="hidden" id="id" name="id" value="[% id | html %]">
+
+            <div class="form-group">
+                <label for="number" class="col-sm-3 control-label">Number of instruments or voices</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number" name="number" value="[% number | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="category" class="col-sm-3 control-label">Category of instrument or voice</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="category">
+                        <option value=""></option>
+                        [% FOREACH optgroup IN category_optgroups %]
+                            <optgroup label="[% optgroup.label | html %]">
+                                [% FOREACH option IN optgroup.options %]
+                                    [% IF option.value == category %]
+                                        <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% ELSE %]
+                                        <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% END %]
+                                [% END %]
+                            </optgroup>
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="tessitura" class="col-sm-3 control-label">Tessitura</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="tessitura">
+                        <option value=""></option>
+                        [% FOREACH option IN tessitura_options %]
+                            [% IF option.value == tessitura %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="number_of_hands_or_keys" class="col-sm-3 control-label">Number of hands / players; keys of pitched instruments</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="number_of_hands_or_keys">
+                        <option value=""></option>
+                        [% FOREACH option IN number_of_hands_or_keys_options %]
+                            [% IF option.value == number_of_hands_or_keys %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="other" class="col-sm-3 control-label">Other (position 7)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other">
+                        <option value=""></option>
+                        [% FOREACH option IN other_options %]
+                            [% IF option.value == other %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="other2" class="col-sm-3 control-label">Other (position 8)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other2">
+                        <option value=""></option>
+                        [% FOREACH option IN other2_options %]
+                            [% IF option.value == other2 %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="col-sm-offset-3 col-sm-9">
+                    <button type="submit">OK</button>
+                    <a href="#" class="cancel close">Cancel</a>
+                </div>
+            </div>
+        </form>
+    </div>
+
+    [% INCLUDE 'select2.inc' %]
+    <script>
+        $(document).ready(function () {
+            $('#category').select2();
+        });
+    </script>
+
+    <script>
+        document.getElementById('form').addEventListener('submit', function (ev) {
+            ev.preventDefault();
+            const id = document.getElementById('id').value;
+            const number = document.getElementById('number').value;
+            const category = document.getElementById('category').value;
+            const tessitura = document.getElementById('tessitura').value;
+            const number_of_hands_or_keys = document.getElementById('number_of_hands_or_keys').value;
+            const other = document.getElementById('other').value;
+            const other2 = document.getElementById('other2').value;
+            const value =
+                (number ? number.toString().padStart(2, '0') : 'uu') +
+                category.padStart(3, ' ') +
+                tessitura.padStart(1, ' ') +
+                number_of_hands_or_keys.padStart(1, ' ') +
+                other.padStart(1, ' ') +
+                other2.padStart(1, ' ');
+            opener.document.getElementById(id).value = value;
+            window.close();
+        });
+    </script>
+
+[% INCLUDE 'popup-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146c.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146c.tt
new file mode 100644 (file)
index 0000000..36e77d4
--- /dev/null
@@ -0,0 +1,141 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Framework plugin unimarc_field_146c &rsaquo; Cataloguing &rsaquo; Koha</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="unimarc_field_146c" class="cat">
+    <div class="container-fluid">
+        <h1>Framework plugin for UNIMARC 146$c</h1>
+
+        <form class="form-horizontal" id="form">
+            <input type="hidden" id="id" name="id" value="[% id | html %]">
+
+            <div class="form-group">
+                <label for="number" class="col-sm-3 control-label">Number of instruments or voices</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number" name="number" value="[% number | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="category" class="col-sm-3 control-label">Category of instrument or voice</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="category">
+                        <option value=""></option>
+                        [% FOREACH optgroup IN category_optgroups %]
+                            <optgroup label="[% optgroup.label | html %]">
+                                [% FOREACH option IN optgroup.options %]
+                                    [% IF option.value == category %]
+                                        <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% ELSE %]
+                                        <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% END %]
+                                [% END %]
+                            </optgroup>
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="tessitura" class="col-sm-3 control-label">Tessitura</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="tessitura">
+                        <option value=""></option>
+                        [% FOREACH option IN tessitura_options %]
+                            [% IF option.value == tessitura %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="number_of_hands_or_keys" class="col-sm-3 control-label">Number of hands / players; keys of pitched instruments</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="number_of_hands_or_keys">
+                        <option value=""></option>
+                        [% FOREACH option IN number_of_hands_or_keys_options %]
+                            [% IF option.value == number_of_hands_or_keys %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="other" class="col-sm-3 control-label">Other (position 7)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other">
+                        <option value=""></option>
+                        [% FOREACH option IN other_options %]
+                            [% IF option.value == other %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="other2" class="col-sm-3 control-label">Other (position 8)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other2">
+                        <option value=""></option>
+                        [% FOREACH option IN other2_options %]
+                            [% IF option.value == other2 %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="col-sm-offset-3 col-sm-9">
+                    <button type="submit">OK</button>
+                    <a href="#" class="cancel close">Cancel</a>
+                </div>
+            </div>
+        </form>
+    </div>
+
+    [% INCLUDE 'select2.inc' %]
+    <script>
+        $(document).ready(function () {
+            $('#category').select2();
+        });
+    </script>
+
+    <script>
+        document.getElementById('form').addEventListener('submit', function (ev) {
+            ev.preventDefault();
+            const id = document.getElementById('id').value;
+            const number = document.getElementById('number').value;
+            const category = document.getElementById('category').value;
+            const tessitura = document.getElementById('tessitura').value;
+            const number_of_hands_or_keys = document.getElementById('number_of_hands_or_keys').value;
+            const other = document.getElementById('other').value;
+            const other2 = document.getElementById('other2').value;
+            const value =
+                (number ? number.toString().padStart(2, '0') : 'uu') +
+                category.padStart(3, ' ') +
+                tessitura.padStart(1, ' ') +
+                number_of_hands_or_keys.padStart(1, ' ') +
+                other.padStart(1, ' ') +
+                other2.padStart(1, ' ');
+            opener.document.getElementById(id).value = value;
+            window.close();
+        });
+    </script>
+
+[% INCLUDE 'popup-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146d.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146d.tt
new file mode 100644 (file)
index 0000000..382589a
--- /dev/null
@@ -0,0 +1,116 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Framework plugin unimarc_field_146d &rsaquo; Cataloguing &rsaquo; Koha</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="unimarc_field_146d" class="cat">
+    <div class="container-fluid">
+        <h1>Framework plugin for UNIMARC 146$d</h1>
+
+        <form class="form-horizontal" id="form">
+            <input type="hidden" id="id" name="id" value="[% id | html %]">
+
+            <div class="form-group">
+                <label for="number" class="col-sm-3 control-label">Number of ensembles</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number" name="number" value="[% number | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="category" class="col-sm-3 control-label">Category of ensemble</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="category">
+                        <option value=""></option>
+                        [% FOREACH optgroup IN category_optgroups %]
+                            <optgroup label="[% optgroup.label | html %]">
+                                [% FOREACH option IN optgroup.options %]
+                                    [% IF option.value == category %]
+                                        <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% ELSE %]
+                                        <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% END %]
+                                [% END %]
+                            </optgroup>
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="number_of_real_parts" class="col-sm-3 control-label">Number of real parts</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number_of_real_parts" value="[% number_of_real_parts | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="other" class="col-sm-3 control-label">Other (position 7)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other">
+                        <option value=""></option>
+                        [% FOREACH option IN other_options %]
+                            [% IF option.value == other %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="other2" class="col-sm-3 control-label">Other (position 8)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other2">
+                        <option value=""></option>
+                        [% FOREACH option IN other2_options %]
+                            [% IF option.value == other2 %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="col-sm-offset-3 col-sm-9">
+                    <button type="submit">OK</button>
+                    <a href="#" class="cancel close">Cancel</a>
+                </div>
+            </div>
+        </form>
+    </div>
+
+    [% INCLUDE 'select2.inc' %]
+    <script>
+        $(document).ready(function () {
+            $('#category').select2();
+        });
+    </script>
+
+    <script>
+        document.getElementById('form').addEventListener('submit', function (ev) {
+            ev.preventDefault();
+            const id = document.getElementById('id').value;
+            const number = document.getElementById('number').value;
+            const category = document.getElementById('category').value;
+            const number_of_real_parts = document.getElementById('number_of_real_parts').value;
+            const other = document.getElementById('other').value;
+            const other2 = document.getElementById('other2').value;
+            const value =
+                (number ? number.toString().padStart(2, '0') : 'uu') +
+                category.padStart(3, ' ') +
+                (number_of_real_parts ? number_of_real_parts.toString().padStart(2, '0') : '##') +
+                other.padStart(1, ' ') +
+                other2.padStart(1, ' ');
+            opener.document.getElementById(id).value = value;
+            window.close();
+        });
+    </script>
+
+[% INCLUDE 'popup-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146e.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146e.tt
new file mode 100644 (file)
index 0000000..a87485e
--- /dev/null
@@ -0,0 +1,141 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Framework plugin unimarc_field_146e &rsaquo; Cataloguing &rsaquo; Koha</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="unimarc_field_146e" class="cat">
+    <div class="container-fluid">
+        <h1>Framework plugin for UNIMARC 146$e</h1>
+
+        <form class="form-horizontal" id="form">
+            <input type="hidden" id="id" name="id" value="[% id | html %]">
+
+            <div class="form-group">
+                <label for="number" class="col-sm-3 control-label">Number of instruments or voices</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number" name="number" value="[% number | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="category" class="col-sm-3 control-label">Category of instrument or voice</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="category">
+                        <option value=""></option>
+                        [% FOREACH optgroup IN category_optgroups %]
+                            <optgroup label="[% optgroup.label | html %]">
+                                [% FOREACH option IN optgroup.options %]
+                                    [% IF option.value == category %]
+                                        <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% ELSE %]
+                                        <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% END %]
+                                [% END %]
+                            </optgroup>
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="tessitura" class="col-sm-3 control-label">Tessitura</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="tessitura">
+                        <option value=""></option>
+                        [% FOREACH option IN tessitura_options %]
+                            [% IF option.value == tessitura %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="number_of_hands_or_keys" class="col-sm-3 control-label">Number of hands / players; keys of pitched instruments</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="number_of_hands_or_keys">
+                        <option value=""></option>
+                        [% FOREACH option IN number_of_hands_or_keys_options %]
+                            [% IF option.value == number_of_hands_or_keys %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="other" class="col-sm-3 control-label">Other (position 7)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other">
+                        <option value=""></option>
+                        [% FOREACH option IN other_options %]
+                            [% IF option.value == other %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="other2" class="col-sm-3 control-label">Other (position 8)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other2">
+                        <option value=""></option>
+                        [% FOREACH option IN other2_options %]
+                            [% IF option.value == other2 %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="col-sm-offset-3 col-sm-9">
+                    <button type="submit">OK</button>
+                    <a href="#" class="cancel close">Cancel</a>
+                </div>
+            </div>
+        </form>
+    </div>
+
+    [% INCLUDE 'select2.inc' %]
+    <script>
+        $(document).ready(function () {
+            $('#category').select2();
+        });
+    </script>
+
+    <script>
+        document.getElementById('form').addEventListener('submit', function (ev) {
+            ev.preventDefault();
+            const id = document.getElementById('id').value;
+            const number = document.getElementById('number').value;
+            const category = document.getElementById('category').value;
+            const tessitura = document.getElementById('tessitura').value;
+            const number_of_hands_or_keys = document.getElementById('number_of_hands_or_keys').value;
+            const other = document.getElementById('other').value;
+            const other2 = document.getElementById('other2').value;
+            const value =
+                (number ? number.toString().padStart(2, '0') : 'uu') +
+                category.padStart(3, ' ') +
+                tessitura.padStart(1, ' ') +
+                number_of_hands_or_keys.padStart(1, ' ') +
+                other.padStart(1, ' ') +
+                other2.padStart(1, ' ');
+            opener.document.getElementById(id).value = value;
+            window.close();
+        });
+    </script>
+
+[% INCLUDE 'popup-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146f.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_146f.tt
new file mode 100644 (file)
index 0000000..d80ba2b
--- /dev/null
@@ -0,0 +1,141 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Framework plugin unimarc_field_146e &rsaquo; Cataloguing &rsaquo; Koha</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+
+<body id="unimarc_field_146f" class="cat">
+    <div class="container-fluid">
+        <h1>Framework plugin for UNIMARC 146$f</h1>
+
+        <form class="form-horizontal" id="form">
+            <input type="hidden" id="id" name="id" value="[% id | html %]">
+
+            <div class="form-group">
+                <label for="number" class="col-sm-3 control-label">Number of instruments</label>
+                <div class="col-sm-9">
+                    <input inputmode="numeric" pattern="^[0-9]{0,2}$" title="a number between 0 and 99 (inclusive)" id="number" name="number" value="[% number | html %]">
+                    <p class="help-block">A number between 0 and 99 (inclusive)</p>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="category" class="col-sm-3 control-label">Category of instrument</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="category">
+                        <option value=""></option>
+                        [% FOREACH optgroup IN category_optgroups %]
+                            <optgroup label="[% optgroup.label | html %]">
+                                [% FOREACH option IN optgroup.options %]
+                                    [% IF option.value == category %]
+                                        <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% ELSE %]
+                                        <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %] ([% optgroup.label | html %])</option>
+                                    [% END %]
+                                [% END %]
+                            </optgroup>
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="tessitura" class="col-sm-3 control-label">Tessitura</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="tessitura">
+                        <option value=""></option>
+                        [% FOREACH option IN tessitura_options %]
+                            [% IF option.value == tessitura %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="number_of_hands_or_keys" class="col-sm-3 control-label">Number of hands / players; keys of pitched instruments</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="number_of_hands_or_keys">
+                        <option value=""></option>
+                        [% FOREACH option IN number_of_hands_or_keys_options %]
+                            [% IF option.value == number_of_hands_or_keys %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <label for="other" class="col-sm-3 control-label">Other (position 7)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other">
+                        <option value=""></option>
+                        [% FOREACH option IN other_options %]
+                            [% IF option.value == other %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+            <div class="form-group">
+                <label for="other2" class="col-sm-3 control-label">Other (position 8)</label>
+                <div class="col-sm-9">
+                    <select class="form-control" id="other2">
+                        <option value=""></option>
+                        [% FOREACH option IN other2_options %]
+                            [% IF option.value == other2 %]
+                                <option value="[% option.value | html %]" selected>[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% ELSE %]
+                                <option value="[% option.value | html %]">[% option.value | html %] &ndash; [% option.label | html %]</option>
+                            [% END %]
+                        [% END %]
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="col-sm-offset-3 col-sm-9">
+                    <button type="submit">OK</button>
+                    <a href="#" class="cancel close">Cancel</a>
+                </div>
+            </div>
+        </form>
+    </div>
+
+    [% INCLUDE 'select2.inc' %]
+    <script>
+        $(document).ready(function () {
+            $('#category').select2();
+        });
+    </script>
+
+    <script>
+        document.getElementById('form').addEventListener('submit', function (ev) {
+            ev.preventDefault();
+            const id = document.getElementById('id').value;
+            const number = document.getElementById('number').value;
+            const category = document.getElementById('category').value;
+            const tessitura = document.getElementById('tessitura').value;
+            const number_of_hands_or_keys = document.getElementById('number_of_hands_or_keys').value;
+            const other = document.getElementById('other').value;
+            const other2 = document.getElementById('other2').value;
+            const value =
+                (number ? number.toString().padStart(2, '0') : 'uu') +
+                category.padStart(3, ' ') +
+                tessitura.padStart(1, ' ') +
+                number_of_hands_or_keys.padStart(1, ' ') +
+                other.padStart(1, ' ') +
+                other2.padStart(1, ' ');
+            opener.document.getElementById(id).value = value;
+            window.close();
+        });
+    </script>
+
+[% INCLUDE 'popup-bottom.inc' %]