This patch set replaces and extends Koha's current sound options.
This is implemented be removing the existing sound system, and
re-engineering using a table of selector/sound combinations such that
the highest precedence selector that is found in the DOM will trigger
and audio alert. The existing audio behaviors are implemented as a set
of default audio alerts.
Test Plan:
1) Apply this patch set
2) Run updatedatabase.pl
3) Enable the AudioAlerts system preference
4) Test existing sounds
5) Enter the new alerts editor in the admin section
6) Add a new audo alert with the following selector:
"body:contains('Check in message')",
choose any sound alert you wish, make sure it's not one of the 3
sounds already used! Make this selector precedence 1
4) Browse to the checkins page, you should hear the default sound
5) Attempt to return an invalid barcode, you should hear your custom sound!
Signed-off-by: Nick Clemens <nick@quecheelibrary.org>
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
--- /dev/null
+package Koha::AudioAlert;
+
+# Copyright ByWater Solutions 2014
+#
+# 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Modern::Perl;
+
+use Carp;
+
+use Koha::Database;
+
+use base qw(Koha::Object);
+
+=head1 NAME
+
+Koha::AudioAlert - Koha Borrower Object class
+
+=head1 API
+
+=head2 Class Methods
+
+=head3 store
+
+Override base store to set default precedence
+if there is not one set already.
+
+=cut
+
+sub store {
+ my ($self) = @_;
+
+ $self->precedence( Koha::AudioAlerts->get_next_precedence() ) unless defined $self->precedence();
+
+ return $self->SUPER::store();
+}
+
+=head3 move
+
+$alert->move('up');
+
+Changes the alert's precedence up, down, top, or bottom
+
+=cut
+
+sub move {
+ my ( $self, $where ) = @_;
+
+ return Koha::AudioAlerts->move( { audio_alert => $self, where => $where } );
+}
+
+=head3 type
+
+=cut
+
+sub type {
+ return 'AudioAlert';
+}
+
+=head1 AUTHOR
+
+Kyle M Hall <kyle@bywatersolutions.com>
+
+=cut
+
+1;
--- /dev/null
+package Koha::AudioAlerts;
+
+# Copyright ByWater Solutions 2014
+#
+# 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Modern::Perl;
+
+use Carp;
+
+use Koha::Database;
+
+use Koha::AudioAlert;
+
+use base qw(Koha::Objects);
+
+=head1 NAME
+
+Koha::AudioAlert - Koha Borrower Object class
+
+=head1 API
+
+=head2 Class Methods
+
+=head3 search
+
+Overrides default search such that
+the default ordering is by precedence
+
+=cut
+
+sub search {
+ my ( $self, $params, $attributes ) = @_;
+
+ $attributes->{order_by} ||= 'precedence';
+
+ return $self->SUPER::search( $params, $attributes );
+}
+
+=head3 get_next_precedence
+
+Gets the next precedence value for audio alerts
+
+=cut
+
+sub get_next_precedence {
+ my ($self) = @_;
+
+ return $self->get_last_precedence() + 1;
+}
+
+=head3 get_last_precedence
+
+Gets the last precedence value for audio alerts
+
+=cut
+
+sub get_last_precedence {
+ my ($self) = @_;
+
+ return $self->_resultset()->get_column('precedence')->max();
+}
+
+=head3 move
+
+Koha::AudioAlerts->move( { audio_alert => $audio_alert, where => $where } );
+
+Moves the given alert precedence 'up', 'down', 'top' or 'bottom'
+
+=cut
+
+sub move {
+ my ( $self, $params ) = @_;
+
+ my $alert = $params->{audio_alert};
+ my $where = $params->{where};
+
+ return unless ( $alert && $where );
+
+ if ( $where eq 'up' ) {
+ unless ( $alert->precedence() == 1 ) {
+ my ($other) = $self->search( { precedence => $alert->precedence() - 1 } );
+ $other->precedence( $alert->precedence() )->store();
+ $alert->precedence( $alert->precedence() - 1 )->store();
+ }
+ }
+ elsif ( $where eq 'down' ) {
+ unless ( $alert->precedence() == $self->get_last_precedence() ) {
+ my ($other) = $self->search( { precedence => $alert->precedence() + 1 } );
+ $other->precedence( $alert->precedence() )->store();
+ $alert->precedence( $alert->precedence() + 1 )->store();
+ }
+ }
+ elsif ( $where eq 'top' ) {
+ $alert->precedence(0)->store();
+ $self->fix_precedences();
+ }
+ elsif ( $where eq 'bottom' ) {
+ $alert->precedence( $self->get_next_precedence() )->store();
+ $self->fix_precedences();
+ }
+}
+
+=head3 fix_precedences
+
+Koha::AudioAlerts->fix_precedences();
+
+Updates precedence numbers to start with 1
+and to have no gaps
+
+=cut
+
+sub fix_precedences {
+ my ($self) = @_;
+
+ my @alerts = $self->search();
+
+ my $i = 1;
+ map { $_->precedence( $i++ )->store() } @alerts;
+}
+
+=head3 type
+
+=cut
+
+sub type {
+ return 'AudioAlert';
+}
+
+=head3 object_class
+
+=cut
+
+sub object_class {
+ return 'Koha::AudioAlert';
+}
+
+=head1 AUTHOR
+
+Kyle M Hall <kyle@bywatersolutions.com>
+
+=cut
+
+1;
# Using direct setter/getter like $item->barcode() or $item->barcode($barcode);
if ( grep {/^$method$/} @columns ) {
if ( @_ ) {
- return $self->_result()->set_column( $method, @_ );
+ $self->_result()->set_column( $method, @_ );
+ return $self;
} else {
my $value = $self->_result()->get_column( $method );
return $value;
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
+use Encode qw( encode );
+use JSON;
use base qw( Template::Plugin );
sub Version {
my $version_string = Koha::version();
- my ($major,$minor,$maintenance,$development) = split('\.',$version_string);
+ my ( $major, $minor, $maintenance, $development ) = split( '\.', $version_string );
return {
major => $major,
release => $major . "." . $minor,
maintenance => $major . "." . $minor . "." . $maintenance,
- development => ( $development ne '000' )
- ? $development
- : undef
+ development => ( $development ne '000' ) ? $development : undef,
};
}
+sub AudioAlerts {
+ my $dbh = C4::Context->dbh;
+ my $audio_alerts = $dbh->selectall_arrayref( 'SELECT * FROM audio_alerts ORDER BY precedence', { Slice => {} } );
+ return encode_json($audio_alerts);
+}
+
1;
--- /dev/null
+#!/usr/bin/perl
+
+# Copyright 2014 ByWater Solutions
+#
+# 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Modern::Perl;
+
+use CGI;
+use C4::Auth;
+use C4::Output;
+use Koha::AudioAlert;
+use Koha::AudioAlerts;
+
+my $cgi = new CGI;
+
+my $selector = $cgi->param('selector');
+my $sound = $cgi->param('sound');
+my $id = $cgi->param('id');
+my $action = $cgi->param('action');
+my $where = $cgi->param('where');
+my @delete = $cgi->param('delete');
+
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
+ {
+ template_name => "admin/audio_alerts.tt",
+ query => $cgi,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { parameters => 'parameters_remaining_permissions' },
+ debug => 1,
+ }
+);
+
+if ( $selector && $sound ) {
+ Koha::AudioAlert->new( { selector => $selector, sound => $sound } )->store();
+}
+
+map { Koha::AudioAlerts->find($_)->delete() } @delete;
+
+if ( $id && $action && $where && $action eq 'move' ) {
+ Koha::AudioAlerts->find($id)->move($where);
+}
+
+$template->param( audio_alerts => scalar Koha::AudioAlerts->search() );
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
is_child => ($borrowernumber && $borrower->{'category_type'} eq 'C'),
$view => 1,
batch_allowed => $batch_allowed,
- soundon => C4::Context->preference("SoundOn"),
+ AudioAlerts => C4::Context->preference("AudioAlerts"),
fast_cataloging => $fast_cataloging,
CircAutoPrintQuickSlip => C4::Context->preference("CircAutoPrintQuickSlip"),
activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
dropboxdate => output_pref($dropboxdate),
forgivemanualholdsexpire => $forgivemanualholdsexpire,
overduecharges => $overduecharges,
- soundon => C4::Context->preference("SoundOn"),
+ AudioAlerts => C4::Context->preference("AudioAlerts"),
BlockReturnOfWithdrawnItems => C4::Context->preference("BlockReturnOfWithdrawnItems"),
);
<li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li>
<li><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></li>
<li><a href="/cgi-bin/koha/admin/columns_settings.pl">Columns settings</a></li>
+ <li><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></li>
</ul>
</div>
</div>
+[% USE Koha %]
+[% USE String %]
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% interface %]/[% theme %]/img/favicon.ico[% END %]" type="image/x-icon" />
+
<link rel="stylesheet" type="text/css" href="[% interface %]/lib/jquery/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="[% interface %]/lib/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="[% interface %]/lib/font-awesome/css/font-awesome.min.css" />
<link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" />
[% INCLUDE intranetstylesheet.inc %]
-[% IF ( bidi ) %]
- <link rel="stylesheet" type="text/css" href="[% themelang %]/css/right-to-left.css" />
-[% END %]
+[% IF ( bidi ) %]<link rel="stylesheet" type="text/css" href="[% themelang %]/css/right-to-left.css" />[% END %]
[% IF ( IntranetUserCSS ) %]<style type="text/css">[% IntranetUserCSS %]</style>[% END %]
+
<script type="text/javascript" src="[% interface %]/lib/jquery/jquery.js"></script>
<script type="text/javascript" src="[% interface %]/lib/jquery/jquery-ui.js"></script>
<script type="text/javascript" src="[% interface %]/lib/shortcut/shortcut.js"></script>
<!-- koha core js -->
<script type="text/javascript" src="[% themelang %]/js/staff-global.js"></script>
+
[% INCLUDE 'validator-strings.inc' %]
[% IF ( IntranetUserJS ) %]
<script type="text/javascript">
//]]>
</script>
[% END %]
+
[% IF ( virtualshelves || intranetbookbag ) %]
<script type="text/javascript">
//<![CDATA[
var MSG_NON_RESERVES_SELECTED = _("One or more selected items cannot be reserved.");
//]]>
</script>
-<script type="text/javascript" src="[% themelang %]/js/basket.js"></script>
+
+ <script type="text/javascript" src="[% themelang %]/js/basket.js"></script>
[% END %]
+
[% IF LocalCoverImages %]
-<script type="text/javascript" src="[% themelang %]/js/localcovers.js"></script>
-<script type="text/javascript">
-//<![CDATA[
-var NO_LOCAL_JACKET = _("No cover image available");
-//]]>
-</script>
+ <script type="text/javascript" src="[% themelang %]/js/localcovers.js"></script>
+ <script type="text/javascript">
+ //<![CDATA[
+ var NO_LOCAL_JACKET = _("No cover image available");
+ //]]>
+ </script>
+[% END %]
+
+[% IF Koha.Preference('AudioAlerts') %]
+ <script type="text/javascript">
+ //<![CDATA[
+ var AUDIO_ALERT_PATH = '[% interface %]/[% theme %]/sound/';
+ var AUDIO_ALERTS = JSON.parse( '[% Koha.AudioAlerts | replace( "'", "\\'" ) %]' );
+ //]]>
+
+ $( document ).ready(function() {
+ if ( AUDIO_ALERTS ) {
+ for ( var k in AUDIO_ALERTS ) {
+ var alert = AUDIO_ALERTS[k];
+ if ( $( alert.selector ).length ) {
+ playSound( alert.sound );
+ break;
+ }
+ }
+ }
+ });
+ </script>
[% END %]
<!-- For keeping the text when navigating the search tabs -->
</div>
[% END %]
[% END %]
+ <span id="audio-alert"></span>
</body>
</html>
function confirmDelete(message) {
return (confirm(message) ? true : false);
}
+
+function playSound( sound ) {
+ // This is way faster than substring
+ if ( ! ( sound.charAt(4) == ':' && sound.charAt(5) == '/' && sound.charAt(6) == '/' ) ) {
+ sound = AUDIO_ALERT_PATH + sound;
+ }
+ document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
+}
<dd>Choose which plugins to use to suggest searches to patrons and staff.</dd>
<dt><a href="/cgi-bin/koha/admin/columns_settings.pl">Configure columns</a></dt>
<dd>Hide or show columns for tables.</dd>
+ <dt><a href="/cgi-bin/koha/admin/audio_alerts.pl">Audio alerts</a></dt>
+ <dd>Define which events trigger which sounds</dd>
</dl>
</div>
--- /dev/null
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha › Administration › Audio alerts</title>
+[% INCLUDE 'doc-head-close.inc' %]
+
+<script type="text/javascript">
+$( document ).ready(function() {
+ $.ajax({
+ //This will retrieve the contents of the folder if the folder is configured as 'browsable'
+ url: AUDIO_ALERT_PATH,
+ success: function (data) {
+ $("#fileNames").html('<ul>');
+ //List all png or jpg or gif file names in the page
+ $(data).find('a:contains("ogg")').each(function () {
+ var filename = this.href.split('/').pop();
+ $('#koha-sounds').append($('<option>', { value : filename }).text(filename));
+ });
+ }
+ });
+
+ $('#koha-sounds').on('change', function() {
+ $('#sound').val( this.value );
+ });
+
+ $('#koha-sounds').on('change', function() {
+ $('#sound').val( this.value );
+ });
+
+ $('#play-sound').on('click', function() {
+ playSound( $('#sound').val() );
+ return false;
+ });
+
+ $('#new-alert-form').on('submit', function() {
+ if ( ! $('#selector').val() ) {
+ alert(_("You must enter a selector!"));
+ return false;
+ } else if ( ! $('#sound').val() ) {
+ alert(_("You must choose a sound!"));
+ return false;
+ } else {
+ return true;
+ }
+ });
+
+ $('#delete-alert-form').on('submit', function() {
+ return confirm(_("Are you sure you want to delete the selected audio alerts?"));
+ });
+});
+</script>
+
+</head>
+<body id="admin_audio_alerts" class="admin">
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'patrons-admin-search.inc' %]
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › Audio alerts</div>
+
+<div id="doc3" class="yui-t2">
+ <div id="bd">
+ <div id="yui-main">
+ <div class="yui-b">
+ <form id="new-alert-form" action="audio_alerts.pl" method="post">
+ <fieldset class="form-inline">
+ <legend>Add new alert</legend>
+
+ <input id="selector" name="selector" type="text" class="input-large" placeholder="selector" />
+ <input id="sound" name="sound" type="text" class="input-large" placeholder="sound" />
+
+ <button id="play-sound" class="btn"><i class="icon-play"></i> Play sound</button>
+
+ <br/>
+
+ <select id="koha-sounds">
+ <option value="">Select built-in sound</option>
+ </select>
+
+ <button id="save-alert" type="submit" class="btn"><i class="icon-hdd"></i> Save alert</button>
+ </fieldset>
+ </form>
+
+ <form id="delete-alert-form" action="audio_alerts.pl" method="post">
+ <table>
+ <thead>
+ <tr>
+ <th> </th>
+ <th>Precedence</th>
+ <th> </th>
+ <th>Selector</th>
+ <th>Sound</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ [% FOREACH a IN audio_alerts %]
+ <tr>
+ <td><input type="checkbox" name="delete" value="[% a.id %]" /></td>
+ <td>[% a.precedence %]</td>
+ <td style="white-space:nowrap;">
+ <a title="Move alert up" href="audio_alerts.pl?action=move&where=up&id=[% a.id %]">
+ <img src="[% interface %]/[% theme %]/img/go-up.png" border="0" alt="Go up" />
+ </a>
+
+ <a title="Move alert to top" href="audio_alerts.pl?action=move&where=top&id=[% a.id %]">
+ <img src="[% interface %]/[% theme %]/img/go-top.png" border="0" alt="Go top" />
+ </a>
+
+ <a title="Move alert to bottom" href="audio_alerts.pl?action=move&where=bottom&id=[% a.id %]">
+ <img src="[% interface %]/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" />
+ </a>
+
+ <a title="Move alert down" href="audio_alerts.pl?action=move&where=down&id=[% a.id %]">
+ <img src="[% interface %]/[% theme %]/img/go-down.png" border="0" alt="Go down" />
+ </a>
+ </td>
+ <td>[% a.selector %]</td>
+ <td>[% a.sound %]</td>
+ </tr>
+ [% END %]
+ </tbody>
+ </table>
+
+ <p/>
+ <button id="delete-alerts" type="submit" class="btn"><i class="icon-trash"></i> Delete selected alerts</button>
+ </form>
+ </div>
+ </div>
+ <div class="yui-b">
+[% INCLUDE 'admin-menu.inc' %]
+</div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
desc: latest to earliest
- due date.
-
- - pref: soundon
- choices:
- yes: "Enable"
- no: "Don't enable"
- - circulation sounds during checkin and checkout in the staff interface. Not supported by all web browsers yet.
- -
- pref: SpecifyDueDate
choices:
yes: Allow
yes: Show
no: "Don't show"
- "the print receipt popup dialog when self checkout is finished"
-
Course Reserves:
-
- pref: UseCourseReserves
yes: Show
no: "Don't show"
- WYSIWYG editor when editing certain HTML system preferences.
+ -
+ - pref: AudioAlerts
+ choices:
+ yes: "Enable"
+ no: "Don't enable"
+ - audio alerts for events defined in the audio alerts section of administration.
[% IF ( NEEDSCONFIRMATION ) %]
<div class="yui-g">
-<div id="circ_needsconfirmation" class="dialog alert">
+<div id="circ_needsconfirmation" class="dialog alert audio-alert-action">
[% IF CAN_user_circulate_force_checkout %]
<h3>Please confirm checkout</h3>
[% ELSE %]
[% IF ( IMPOSSIBLE ) %]
-[% IF ( soundon ) %]
-<audio src="[% interface %]/[% theme %]/sound/critical.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
-[% END %]
-
<div class="yui-g">
-<div id="circ_impossible" class="dialog alert">
+<div id="circ_impossible" class="dialog alert audio-alert-warning">
<!-- RESULT OF ISSUING REQUEST -->
<ul>
[% IF ( STATS ) %]
</div></div>
[% ELSE %]
-[% IF ( soundon ) %]
-<audio src="[% interface %]/[% theme %]/sound/beep.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
-[% END %]
-
[% IF (forceallow) %]
<div id="overridden_debarment" class="dialog alert">Restriction overridden temporarily</div>
[% END %]
+[% END %] <!-- /impossible -->
- [% END %] <!-- /impossible -->
+<span class="audio-alert-success"></span>
[% IF ( issued ) %]
<p>Item checked out</p>
</script>
</head>
<body id="circ_returns" class="circ">
+<span class="audio-alert-success"></span>
[% INCLUDE 'header.inc' %]
[% INCLUDE 'checkin-search.inc' %]
[% IF ( waiting ) %]
<!-- waiting -->
-[% IF ( soundon ) %]
-<audio src="[% interface %]/[% theme %]/sound/ending.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
-[% END %]
-
-<div id="hold-found1" class="dialog message">
+ <div id="hold-found1" class="dialog message audio-alert-action">
<h3>Hold found (item is already waiting): <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% itembiblionumber %]">[% title |html %]</a></h3>
[% IF ( reservenotes ) %]<h4>Notes: [% reservenotes %]</h4>[% END %]
<h4>Hold for:</h4>
[% IF ( diffbranch ) %]
<!-- diffbranch -->
- [% IF ( soundon ) %]
- <audio src="[% interface %]/[% theme %]/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
- [% END %]
- <div id="transfer-needed" class="dialog message">
+ <div id="transfer-needed" class="dialog message audio-alert-action">
<h3>Hold needing transfer found: <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% itembiblionumber %]">[% title |html %]</a></h3>
<h4>Hold for: </h4>
<ul>
[% IF ( transfer ) %]
<!-- transfer: item with no reservation, must be returned according to home library circulation rules -->
- <div id="return1" class="dialog message">
+ <div id="return1" class="dialog message audio-alert-action">
<h3>Please return <a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=[% itembiblionumber %]">[% title or "item" |html %]</a> to [% Branches.GetName( returnbranch ) %]<br/>( <a href="#" onclick="Dopop('transfer-slip.pl?transferitem=[% itemnumber %]&branchcode=[% returnbranch %]&op=slip'); return true;">Print slip</a> )</h3>
</div>
- [% IF ( soundon ) %]
- <audio src="[% interface %]/[% theme %]/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
- [% END %]
[% END %]
[% IF ( needstransfer ) %]
<!-- needstransfer -->
- [% IF ( soundon ) %]
- <audio src="[% interface %]/[% theme %]/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
- [% END %]
- <div id="item-transfer" class="dialog message"><h3> This item needs to be transferred to [% Branches.GetName( returnbranch ) %]</h3>
+ <div id="item-transfer" class="dialog message audio-alert-action"><h3> This item needs to be transferred to [% Branches.GetName( returnbranch ) %]</h3>
Transfer now?<br />
<form method="post" action="returns.pl" name="mainform" id="mainform">
[% IF itemnumber %]
[% IF ( diffbranch ) %]
<!-- diffbranch -->
- [% IF ( soundon ) %]
- <audio src="[% interface %]/[% theme %]/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
- [% END %]
- <h3>Item consigned:</h3>
+ <h3 class="audio-alert-action">Item consigned:</h3>
<table>
<caption><a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=[% itembiblionumber %]">[% title |html %]</a></caption>
<tr>
[% IF ( reserved ) %]
<!-- reserved -->
- [% IF ( soundon ) %]
- <audio src="[% interface %]/[% theme %]/sound/opening.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
- [% END %]
-
- <div id="hold-found2" class="dialog message">
+ <div id="hold-found2" class="dialog message audio-alert-action">
<h3>Hold found: <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% itembiblionumber %]">[% title |html %]</a></h3>
[% IF ( reservenotes ) %]<h4>Notes: [% reservenotes %]</h4>[% END %]
<h5>Hold for:</h5>
[% END %]
[% IF ( errmsgloop ) %]
- <div class="dialog alert">
+ <div class="dialog alert audio-alert-warning">
<h3>Check in message</h3>
[% FOREACH errmsgloo IN errmsgloop %]
[% IF ( errmsgloo.NotForLoanStatusUpdated ) %]
[% END %]
[% END %]
-[% IF ( soundon ) %]
-<audio src="[% interface %]/[% theme %]/sound/critical.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
-[% END %]
[% ELSE %]
-[% IF ( soundon ) %]
-<audio src="[% interface %]/[% theme %]/sound/beep.ogg" autoplay="autoplay" autobuffer="autobuffer"></audio>
-[% END %]
[% END %]
</div>
--- /dev/null
+[% INCLUDE 'help-top.inc' %]
+
+<h1>Audio alerts</h1>
+
+<p>This section of Koha lets you specify a given sound to play when a given jQuery selector is matched.</p>
+
+<h2>Adding a new alert</h2>
+
+<p>To add a new alert:</p>
+
+<ul>
+ <li>Locate the "Add new alert" form.</li>
+ <li>Enter a selector in the "selector" input, you can see documentation on jQuery selectors <a href="http://api.jquery.com/category/selectors/">here</a>.
+ <li>Enter a sound to be played, you can either select a built-in Koha sound using the pulldown selector, or you can enter a full URL to a sound file on another server</li>
+ <li>At this point, you can preview your sound by clicking the "Play sound" button</li>
+ <li>Click "Save alert" and your done!</li>
+</ul>
+
+<h2>Sound precedence</h2>
+
+<p>Sounds will be played in order from top to bottom. That is, the first select that finds a match will have its sound played.</p>
+
+<p>To change the precedence of a given alert, use the four arrows to move it up, down, or to the top or bottom of the list.</o>
+
+<h2>Deleting alerts</h2>
+
+<p>To delete one or more alerts, check the checkboxes for those alerts you wish to delete, then click the "Delete selected alerts" button and confirm you want to delete those alerts.
+
+[% INCLUDE 'help-bottom.inc' %]