Bugzilla – Attachment 175432 Details for
Bug 30975
Use event delegation for framework plugins to avoid using private jQuery method _data
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 30975: Fix framework plugins not working on cloned fields/subfields
Bug-30975-Fix-framework-plugins-not-working-on-clo.patch (text/plain), 28.44 KB, created by
Julian Maurice
on 2024-12-13 08:25:25 UTC
(
hide
)
Description:
Bug 30975: Fix framework plugins not working on cloned fields/subfields
Filename:
MIME Type:
Creator:
Julian Maurice
Created:
2024-12-13 08:25:25 UTC
Size:
28.44 KB
patch
obsolete
>From 4b60b0fddfbae63efef4c783e41022fee84378f1 Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Fri, 3 Feb 2023 12:00:39 +0100 >Subject: [PATCH] Bug 30975: Fix framework plugins not working on cloned > fields/subfields > >Since bug 29155 (Upgrade jquery version to 3.6.0) framework plugins do >not work on a cloned field/subfield. >That is because we rely on jQuery's `.data('events')` to clone event >handlers to the cloned elements, and that was removed in jQuery 1.8.0 >(I did not confirm but it's possible it continued to work after that >thanks to jQuery Migrate) > >It is apparently still possible to access these event handlers by using >`jQuery._data(element, "events")` but here's what jQuery 1.8.0 release >notes says about it: >"this is not a supported public interface; the actual data structures >may change incompatibly from version to version." >So we should not rely on it. > >Instead, what this patch does is use event delegation [1]. >Events are bound to a parent container, so when elements are added >dynamically inside that container, we don't need to re-attach event >handlers manually > >This patch also comes with a bit of cleanup, and introduce "breaking >changes" (they are breaking changes only if you happen to have custom >framework plugins): >1) 'mouseover', 'mousemove', 'keypress' events are no longer listened to > 'mouseover' and 'mousemove' are not used and would trigger too much > events. > 'keypress' is also not used, and is deprecated >2) Event handlers now takes a single parameter that is an Event object > It just makes the code a lot less complicated. >3) Event handlers do not pollute the global scope anymore > >[1] https://learn.jquery.com/events/event-delegation/ > >Test plan: >- Go to every page that has a MARC editor and verify that plugins still > work. This includes addbiblio.pl, additem.pl, authorities.pl, > neworderempty.pl, orderreceive.pl >- Test plugins that use 'focus' event (for instance barcode.pl), 'blur' > event (callnumber.pl) and 'click' event (almost all the others) >- Test that plugins work on cloned fields/subfields > >Rebased-by: Victor Grousset/tuxayo <victor@tuxayo.net> >--- > C4/Items.pm | 2 +- > Koha/FrameworkPlugin.pm | 84 ++------------- > Koha/UI/Form/Builder/Item.pm | 1 + > authorities/authorities.pl | 1 + > cataloguing/value_builder/EXAMPLE.pl | 26 +---- > .../prog/en/includes/html_helpers.inc | 6 +- > .../prog/en/modules/acqui/neworderempty.tt | 2 +- > .../prog/en/modules/acqui/orderreceive.tt | 2 +- > .../en/modules/authorities/authorities.tt | 4 +- > .../prog/en/modules/cataloguing/addbiblio.tt | 8 +- > .../prog/en/modules/cataloguing/additem.tt | 2 +- > koha-tmpl/intranet-tmpl/prog/js/additem.js | 14 --- > koha-tmpl/intranet-tmpl/prog/js/cataloging.js | 101 ++++++++---------- > 13 files changed, 72 insertions(+), 181 deletions(-) > >diff --git a/C4/Items.pm b/C4/Items.pm >index 920b6c77f3..d29ff1d20e 100644 >--- a/C4/Items.pm >+++ b/C4/Items.pm >@@ -1557,7 +1557,7 @@ sub PrepareItemrecordDisplay { > my $tab= $plugin->noclick? '-1': ''; > my $class= $plugin->noclick? ' disabled': ''; > my $title= $plugin->noclick? 'No popup': 'Tag editor'; >- $subfield_data{marc_value} = qq[<input type="text" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="$maxlength" value="$defaultvalue" /><a href="#" id="buttonDot_$subfield_data{id}" class="buttonDot $class" title="$title">...</a>\n].$plugin->javascript; >+ $subfield_data{marc_value} = qq[<input type="text" id="$subfield_data{id}" name="field_value" class="input_marceditor framework_plugin" size="50" maxlength="$maxlength" value="$defaultvalue" data-plugin="$plugin->{name}" /><a href="#" id="buttonDot_$subfield_data{id}" class="buttonDot $class" title="$title" data-plugin="$plugin->{name}">...</a>\n].$plugin->javascript; > } else { > warn $plugin->errstr; > $subfield_data{marc_value} = qq(<input type="text" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="$maxlength" value="$defaultvalue" />); # supply default input form >diff --git a/Koha/FrameworkPlugin.pm b/Koha/FrameworkPlugin.pm >index dab6c4f471..96a5945bf5 100644 >--- a/Koha/FrameworkPlugin.pm >+++ b/Koha/FrameworkPlugin.pm >@@ -307,94 +307,24 @@ sub _process_javascript { > $script =~ s/\<script[^>]*\>\s*(\/\/\<!\[CDATA\[)?\s*//s; > $script =~ s/(\/\/\]\]\>\s*)?\<\/script\>//s; > >- my $id = $params->{id}//''; >- my $bind = ''; > my $clickfound = 0; >- my @events = qw|click focus blur change mouseover mouseout mousedown >- mouseup mousemove keydown keypress keyup|; >+ my @events = qw|click focus blur change mousedown mouseup keydown keyup|; > foreach my $ev ( @events ) { > my $scan = $ev eq 'click' && $self->{oldschool}? 'clic': $ev; >- if( $script =~ /function\s+($scan\w+)\s*\(([^\)]*)\)/is ) { >- my ( $bl, $sl ) = $self->_add_binding( $1, $2, $ev, $id ); >- $script .= $sl; >- $bind .= $bl; >+ if( $script =~ /function\s+($scan\w+)\s*\(/is ) { >+ my $function_name = $1; >+ $script .= sprintf('registerFrameworkPluginHandler("%s", "%s", %s);', $self->name, $ev, $function_name); > $clickfound = 1 if $ev eq 'click'; > } > } >- if( !$clickfound ) { # make buttonDot do nothing >- my ( $bl ) = $self->_add_binding( 'noclick', '', 'click', $id ); >- $bind .= $bl; >- } > $self->{noclick} = !$clickfound; >- $self->{javascript}= _merge_script( $id, $script, $bind ); >-} >- >-sub _add_binding { >-# adds some jQuery code for event binding: >-# $bind contains lines for the actual event binding: .click, .focus, etc. >-# $script contains function definitions (if needed) >- my ( $self, $fname, $pars, $ev, $id ) = @_; >- my ( $bind, $script ); >- my $ctl= $ev eq 'click'? 'buttonDot_'.$id: $id; >- #click event applies to buttonDot >- >- if( $pars =~ /^(e|ev|event)$/i ) { # new style event handler assumed >- $bind = qq| \$("#$ctl").off('$ev').on('$ev', \{id: '$id'\}, $fname);\n|; # remove old handler if any >- $script = q{}; >- } elsif( $fname eq 'noclick' ) { # no click: return false, no scroll >- $bind = qq| \$("#$ctl").$ev(function () { return false; });\n|; >- $script = q{}; >- } else { # add real event handler calling the function found >- $bind = qq| \$("#$ctl").off('$ev').on('$ev', \{id: '$id'\}, ${fname}_handler);\n|; >- $script = $self->_add_handler( $ev, $fname ); >- } >- return ( $bind, $script ); >-} >- >-sub _add_handler { >-# adds a handler with event parameter >-# event.data.id is passed to the plugin function in parameters >-# for the click event we always return false to prevent scrolling >- my ( $self, $ev, $fname ) = @_; >- my $first= $self->_first_item_par( $ev ); >- my $prefix= $ev eq 'click'? '': 'return '; >- my $suffix= $ev eq 'click'? "\n return false;": ''; >- return <<HERE; >-function ${fname}_handler(event) { >- $prefix$fname(${first}event.data.id);$suffix >-} >-HERE >-} >- >-sub _first_item_par { >- my ( $self, $event ) = @_; >- # needed for backward compatibility >- # js event functions in old style item plugins have an extra parameter >- # BUT.. not for all events (exceptions provide employment :) >- if( $self->{item_style} && $self->{oldschool} && >- $event=~/focus|blur|change/ ) { >- return qq/'0',/; >- } >- return ''; >-} >- >-sub _merge_script { >-# Combine script and event bindings, enclosed in script tags. >-# The BindEvents function is added to easily repeat event binding; >-# this is used in additem.js for dynamically created item blocks. >- my ( $id, $script, $bind ) = @_; >- chomp ($script, $bind); >- return <<HERE; >+ $self->{javascript} = <<JS; > <script> >+\$(document).ready(function () { > $script >-function BindEvents$id() { >-$bind >-} >-\$(document).ready(function() { >- BindEvents$id(); > }); > </script> >-HERE >+JS > } > > =head1 AUTHOR >diff --git a/Koha/UI/Form/Builder/Item.pm b/Koha/UI/Form/Builder/Item.pm >index 228ba982e6..f6125cd97c 100644 >--- a/Koha/UI/Form/Builder/Item.pm >+++ b/Koha/UI/Form/Builder/Item.pm >@@ -342,6 +342,7 @@ sub generate_subfield_form { > class => $class, > nopopup => $plugin->noclick, > javascript => $plugin->javascript, >+ plugin => $plugin->name, > }; > } > else { >diff --git a/authorities/authorities.pl b/authorities/authorities.pl >index 2133008f4f..8f99777b41 100755 >--- a/authorities/authorities.pl >+++ b/authorities/authorities.pl >@@ -200,6 +200,7 @@ sub create_input { > maxlength => $max_length, > javascript => $plugin->javascript, > noclick => $plugin->noclick, >+ plugin => $plugin->name, > }; > } else { # warn and supply default field > warn $plugin->errstr; >diff --git a/cataloguing/value_builder/EXAMPLE.pl b/cataloguing/value_builder/EXAMPLE.pl >index 691e69f8e2..31319494e1 100755 >--- a/cataloguing/value_builder/EXAMPLE.pl >+++ b/cataloguing/value_builder/EXAMPLE.pl >@@ -65,37 +65,19 @@ my $builder= sub { > <script> > function Focus$id(event) { > if( \$('#'+event.data.id).val()=='' ) { >- \$('#'+event.data.id).val('EXAMPLE:'); >+ \$('#'+event.data.id).val('Focus'); > } > } > >-function MouseOver$id(event) { >- return Focus$id(event); >- /* just redirecting it to Focus for the same effect */ >-} >- >-function KeyPress$id(event) { >- if( event.which == 64 ) { /* at character */ >- var f= \$('#'+event.data.id).val(); >- \$('#'+event.data.id).val( f + 'AT' ); >- return false; /* prevents getting the @ character back too */ >- } >-} >- >-function Change$id(event) { >- var colors= [ 'rgb(0, 0, 255)', 'rgb(0, 128, 0)', 'rgb(255, 0, 0)' ]; >- var curcol= \$('#'+event.data.id).css('color'); >- var i= Math.floor( Math.random() * 3 ); >- if( colors[i]==curcol ) { >- i= (i + 1)%3; >+function Blur$id(event) { >+ if( \$('#'+event.data.id).val()=='' ) { >+ \$('#'+event.data.id).val('Blur'); > } >- var f= \$('#'+event.data.id).css('color',colors[i]); > } > > function Click$id(event) { > var fieldvalue=\$('#'+event.data.id).val(); > window.open(\"../cataloguing/plugin_launcher.pl?plugin_name=EXAMPLE.pl&index=\"+event.data.id+\"&result=\"+fieldvalue,\"tag_editor\",'width=700,height=700,toolbar=false,scrollbars=yes'); >- return false; /* prevents scrolling */ > } > </script>|; > }; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >index d5af13c7dc..88244006a7 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >@@ -144,11 +144,11 @@ > [% IF mv.readonly %] > <input type="text" id="[%- mv.id | html -%]" name="[% kohafield | html %]" class="input_marceditor [% kohafield | html %]" maxlength="[%- mv.maxlength | html -%]" value="[%- mv.value | html -%]" readonly="readonly" /> > [% ELSE %] >- <input type="text" id="[%- mv.id | html -%]" name="[% kohafield | html %]" class="input_marceditor [% kohafield | html %]" maxlength="[%- mv.maxlength | html -%]" value="[%- mv.value | html -%]" /> >+ <input type="text" id="[%- mv.id | html -%]" name="[% kohafield | html %]" class="input_marceditor framework_plugin [% kohafield | html %]" maxlength="[%- mv.maxlength | html -%]" value="[%- mv.value | html -%]" data-plugin="[% mv.plugin | html %]" /> > [% IF ( mv.nopopup ) %] >- <a href="#" id="buttonDot_[%- mv.id | html -%]" class="[%- mv.class | html -%]" title="No popup">...</a> >+ <a href="#" id="buttonDot_[%- mv.id | html -%]" class="[%- mv.class | html -%]" title="No popup" data-plugin="[% mv.plugin | html %]">...</a> > [% ELSE %] >- <a href="#" id="buttonDot_[%- mv.id | html -%]" class="[%- mv.class | html -%]" title="Tag editor">...</a> >+ <a href="#" id="buttonDot_[%- mv.id | html -%]" class="[%- mv.class | html -%]" title="Tag editor" data-plugin="[% mv.plugin | html %]">...</a> > [% END %] > [% UNLESS no_plugin %][%# FIXME - from batchMod-edit, jQuery is included at the end of the template and cataloguing plugins are not working in this situation %] > [%- mv.javascript | $raw -%] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >index 72433c41ef..59e611f3cc 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt >@@ -546,7 +546,7 @@ > <div class="alert alert-info">The autoBarcode system preference is set to [% Koha.Preference('autoBarcode') | html %] and items with blank barcodes will have barcodes generated upon save to database</div> > [% END %] > >- <div id="outeritemblock"></div> >+ <div id="outeritemblock" class="marc_editor"></div> > > </fieldset> > [% END %][%# | html UNLESS subscriptionid %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >index 4ac0cbc33c..cb5fa7bf23 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt >@@ -248,7 +248,7 @@ > used > </p> > [% END %] >- <div id="outeritemblock"></div> >+ <div id="outeritemblock" class="marc_editor"></div> > </div> > </div> > <div id="acq-create-ordering"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt >index 48e0984df2..75357488a5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt >@@ -463,7 +463,7 @@ > </div> > [% END # /IF duplicateauthid %] > >- <form method="post" id="f" name="f" action="/cgi-bin/koha/authorities/authorities.pl"> >+ <form method="post" id="f" name="f" action="/cgi-bin/koha/authorities/authorities.pl" class="marc_editor"> > [% INCLUDE 'csrf-token.inc' %] > <input type="hidden" name="op" value="cud-add" /> > <input type="hidden" name="original_op" value="[% op | html %]" /> >@@ -757,7 +757,7 @@ > [% IF mv.noclick %] > <a href="#" class="buttonDot tag_editor disabled" tabindex="-1" title="No popup">...</a> > [% ELSE %] >- <a href="#" id="buttonDot_[% mv.id | html %]" class="buttonDot tag_editor" title="Tag editor">...</a> >+ <a href="#" id="buttonDot_[% mv.id | html %]" class="buttonDot tag_editor" title="Tag editor" data-plugin="[% mv.plugin | html %]">...</a> > [% END %] > [% mv.javascript | $raw %] > [% END #/IF ( mv.type == 'text1' ) %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt >index 799a26e6c8..b50df1dad9 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt >@@ -834,7 +834,7 @@ $(document).ready(function(){ > > <div class="main container-fluid"> > <div class="row"> >- <div class="col-md-10 offset-md-1"> >+ <div class="col-md-10 offset-md-1 marc_editor"> > [% INCLUDE 'messages.inc' %] > [% IF ( INVALID_METADATA ) %] > <div class="page-section bg-danger"> >@@ -1179,7 +1179,7 @@ $(document).ready(function(){ > [% END %] > > [% ELSIF ( mv.type == 'text_complex' ) %] >- <input type="text" id="[%- mv.id | html -%]" name="[%- mv.name | html -%]" value="[%- mv.value | html -%]" class="input_marceditor framework_plugin" tabindex="1" size="[%- mv.size | html -%]" maxlength="[%- mv.maxlength | html -%]" /> >+ <input type="text" id="[%- mv.id | html -%]" name="[%- mv.name | html -%]" value="[%- mv.value | html -%]" class="input_marceditor framework_plugin" tabindex="1" size="[%- mv.size | html -%]" maxlength="[%- mv.maxlength | html -%]" data-plugin="[% mv.plugin | html %]" /> > [% mv.javascript | $raw %] > [% ELSIF ( mv.type == 'hidden' ) %] > <input tabindex="1" type="hidden" id="[%- mv.id | html -%]" name="[%- mv.name | html -%]" size="[%- mv.size | html -%]" maxlength="[%- mv.maxlength | html -%]" value="[%- mv.value | html -%]" /> >@@ -1231,9 +1231,9 @@ $(document).ready(function(){ > <span class="buttonDot tag_editor disabled" tabindex="-1" title="Field autofilled by plugin"></span> > [% ELSE %] > [% IF mv.plugin == "upload.pl" %] >- <a href="#" id="buttonDot_[% mv.id | html %]" class="tag_editor upload framework_plugin" tabindex="1"><i class="fa fa-upload" aria-hidden="true"></i> Upload</a> >+ <a href="#" id="buttonDot_[% mv.id | html %]" class="tag_editor upload framework_plugin" tabindex="1" data-plugin="[% mv.plugin | html %]"><i class="fa fa-upload" aria-hidden="true"></i> Upload</a> > [% ELSE %] >- <a href="#" id="buttonDot_[% mv.id | html %]" class="buttonDot tag_editor framework_plugin" tabindex="1" title="Tag editor">Tag editor</a> >+ <a href="#" id="buttonDot_[% mv.id | html %]" class="buttonDot tag_editor framework_plugin" tabindex="1" title="Tag editor" data-plugin="[% mv.plugin | html %]">Tag editor</a> > [% END %] > [% END %] > </span> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt >index 7d966bee25..9c73135826 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt >@@ -189,7 +189,7 @@ > </div> > <div class="col-md-10 order-md-2 order-sm-1"> > >-<div id="cataloguing_additem_newitem" class="item_edit_form page-section"> >+<div id="cataloguing_additem_newitem" class="item_edit_form page-section marc_editor"> > <form id="f" method="post" action="/cgi-bin/koha/cataloguing/additem.pl?biblionumber=[% biblio.biblionumber | html %]" name="f"> > [% INCLUDE 'csrf-token.inc' %] > <input type="hidden" name="op" value="[% op | html %]" /> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/additem.js b/koha-tmpl/intranet-tmpl/prog/js/additem.js >index 5bad33ba4f..63aaae8c03 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/additem.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/additem.js >@@ -227,24 +227,10 @@ function cloneItemBlock(index, unique_item_fields, callback) { > var cloneIndex = "itemblock"+random; > callback(cloneIndex); > } >- BindPluginEvents(data); > } > }); > } > >-function BindPluginEvents(data) { >-// the script tag in data for plugins contains a document ready that binds >-// the events for the plugin >-// when we append, this code does not get executed anymore; so we do it here >- var events= data.match(/BindEventstag_\d+_subfield_._\d+/g); >- if ( events == null ) return; >- for(var i=0; i<events.length; i++) { >- window[events[i]](); >- if( i<events.length-1 && events[i]==events[i+1] ) { i++; } >- // normally we find the function name twice >- } >-} >- > function clearItemBlock(node) { > var index = $(node).closest("div").attr('id'); > var block = $("#"+index); >diff --git a/koha-tmpl/intranet-tmpl/prog/js/cataloging.js b/koha-tmpl/intranet-tmpl/prog/js/cataloging.js >index 2cb734ef6e..1e6b87a4d3 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/cataloging.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/cataloging.js >@@ -1,5 +1,5 @@ > /* global __ */ >-/* exported openAuth ExpandField CloneField CloneSubfield UnCloneField CloneItemSubfield CheckMandatorySubfields */ >+/* exported openAuth ExpandField CloneField CloneSubfield UnCloneField CloneItemSubfield CheckMandatorySubfields registerFrameworkPluginHandler */ > > /* > * Unified file for catalogue edition >@@ -185,8 +185,6 @@ function CloneField(index, hideMarc, advancedMARCEditor) { > > var inputs = divs[i].getElementsByTagName('input'); > var id_input = ""; >- var olddiv; >- var oldcontrol; > > for( j = 0 ; j < inputs.length ; j++ ) { > if(inputs[j].getAttribute("id") && inputs[j].getAttribute("id").match(/^tag_/) ){ >@@ -228,11 +226,6 @@ function CloneField(index, hideMarc, advancedMARCEditor) { > } > } > } >- if( $(inputs[1]).hasClass('framework_plugin') ) { >- olddiv= original.getElementsByTagName('li')[i]; >- oldcontrol= olddiv.getElementsByTagName('input')[1]; >- AddEventHandlers( oldcontrol,inputs[1],id_input ); >- } > } > // when cloning a subfield, re set its label too. > try { >@@ -270,22 +263,12 @@ function CloneField(index, hideMarc, advancedMARCEditor) { > if(!CloneButtonPlus){ // it s impossible to have + ... (buttonDot AND buttonPlus) > buttonDot = spans[0]; > if(buttonDot){ >- // 2 possibilities : >- try{ >- if( $(buttonDot).hasClass('framework_plugin') ) { >- olddiv= original.getElementsByTagName('li')[i]; >- oldcontrol= olddiv.getElementsByTagName('a')[0]; >- AddEventHandlers(oldcontrol,buttonDot,id_input); >- } >- try { >- // do not copy the script section. >- var script = spans[0].getElementsByTagName('script')[0]; >- spans[0].removeChild(script); >- } catch(e) { >- // do nothing if there is no script >- } >- } catch(e){ >- // >+ try { >+ // do not copy the script section. >+ var script = spans[0].getElementsByTagName('script')[0]; >+ spans[0].removeChild(script); >+ } catch(e) { >+ // do nothing if there is no script > } > } > } >@@ -353,7 +336,6 @@ function CloneSubfield(index, advancedMARCEditor){ > var selects = clone.getElementsByTagName('select'); > var textareas = clone.getElementsByTagName('textarea'); > var linkid; >- var oldcontrol; > > // input > var id_input = ""; >@@ -367,12 +349,6 @@ function CloneSubfield(index, advancedMARCEditor){ > linkid = id_input; > } > >- // Plugin input >- if( $(inputs[1]).hasClass('framework_plugin') ) { >- oldcontrol= original.getElementsByTagName('input')[1]; >- AddEventHandlers( oldcontrol, inputs[1], linkid ); >- } >- > // select > for(i=0,len=selects.length; i<len ; i++ ){ > id_input = selects[i].getAttribute('id')+new_key; >@@ -393,13 +369,6 @@ function CloneSubfield(index, advancedMARCEditor){ > linkid = id_input; > } > >- // Handle click event on buttonDot for plugin >- var links = clone.getElementsByTagName('a'); >- if( $(links[0]).hasClass('framework_plugin') ) { >- oldcontrol= original.getElementsByTagName('a')[0]; >- AddEventHandlers( oldcontrol, links[0], linkid ); >- } >- > if(advancedMARCEditor == '0') { > // when cloning a subfield, reset its label too. > var label = clone.getElementsByTagName('label')[0]; >@@ -438,23 +407,6 @@ function CloneSubfield(index, advancedMARCEditor){ > clone.querySelectorAll('input.input_marceditor').value = ""; > } > >-function AddEventHandlers (oldcontrol, newcontrol, newinputid ) { >-// This function is a helper for CloneField and CloneSubfield. >-// It adds the event handlers from oldcontrol to newcontrol. >-// newinputid is the id attribute of the cloned controlling input field >-// Note: This code depends on the jQuery data for events; this structure >-// is moved to _data as of jQuery 1.8. >- var ev = $._data(oldcontrol, "events"); >- if(typeof ev != 'undefined') { >- $.each(ev, function(prop,val) { >- $.each(val, function(prop2,val2) { >- $(newcontrol).off( val2.type ); >- $(newcontrol).on( val2.type, {id: newinputid}, val2.handler ); >- }); >- }); >- } >-} >- > /** > * This function removes or clears unwanted subfields > */ >@@ -654,3 +606,42 @@ $(document).ready(function() { > }); > > }); >+ >+Koha.frameworkPlugins ||= {}; >+function registerFrameworkPluginHandler(name, eventType, handler) { >+ // 'focus' and 'blur' events do not bubble, >+ // so we have to use 'focusin' and 'focusout' instead >+ if (eventType === 'focus') eventType = 'focusin'; >+ else if (eventType === 'blur') eventType = 'focusout'; >+ >+ Koha.frameworkPlugins[name] ||= {}; >+ Koha.frameworkPlugins[name][eventType] ||= handler; >+} >+$(document).ready(function() { >+ function callClickPluginEventHandler (event) { >+ event.preventDefault(); >+ callPluginEventHandler.call(this, event); >+ } >+ >+ function callPluginEventHandler (event) { >+ event.stopPropagation(); >+ >+ const plugin = event.target.getAttribute('data-plugin'); >+ if (plugin && plugin in Koha.frameworkPlugins && event.type in Koha.frameworkPlugins[plugin]) { >+ event.data = {}; >+ if (event.target.classList.contains('buttonDot')) { >+ event.data.id = event.target.closest('.subfield_line').querySelector('input.input_marceditor').id; >+ } else { >+ event.data.id = event.target.id; >+ } >+ >+ Koha.frameworkPlugins[plugin][event.type].call(this, event); >+ } >+ } >+ >+ // We use delegated event handlers here so that dynamically added elements >+ // (like when cloning a field or a subfield) respond to these events >+ // without having to re-attach events manually >+ $('.marc_editor').on('click', '.buttonDot', callClickPluginEventHandler); >+ $('.marc_editor').on('focusin focusout change mousedown mouseup keydown keyup', 'input.input_marceditor.framework_plugin', callPluginEventHandler); >+}); >-- >2.39.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 30975
:
136135
|
138318
|
140763
|
140810
|
146146
|
146817
|
158064
|
170499
|
170500
|
171513
|
171514
|
175432
|
175433
|
175434
|
175435
|
175436
|
175437
|
177612
|
177613
|
177614
|
177615
|
177616
|
177719
|
177720
|
177721
|
177722
|
177723