jQuery custom accordion widget

jquery ui accordions with auto scrolling and expanding on print

by jmeile

HTML

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<div id="my-accordion">
  <h5>Anreise vom Flughafen Zürich (ZRH)</h5>
  <div>
    <p>Nachdem Sie Ihr Gepäck abgeholt haben, können Sie ein Billett entweder direkt an den roten SBB-Billettautomaten vor dem Ausgang aus den Zollhallen 1 und 2 oder an den Automaten in der Nähe des SBB Reisebüros/Travel Agency kaufen, das sich unter dem Airport Center Bereich Checking 3 befindet (folgen Sie den Schildern <strong>&#8220;Bahn/Train&#8221;</strong> und <strong>&#8220;Bahnreisezentrum / Railway Center&#8221;</strong>).</p>
    <p>Um den roten SBB-Billettautomaten zu benutzen, gehen Sie wie folgt vor:</p>
    <ol>
      <li>Um das Menü zu aktivieren, berühren Sie den Bildschirm.</li>
      <li>Wählen Sie &#8220;<strong>Zürich HB</strong>&#8221; (HB steht für Hauptbahnhof).</li>
      <li>Unter &#8220;<strong>Route</strong>&#8220;, wählen Sie: “via direkt – 3 ZONEN“.</li>
      <li>Drücken Sie <strong>&#8220;Abfahrt sofort&#8221;</strong>.</li>
      <li>Wählen Sie: <strong>&#8220;ZVV Einzelbillet&#8221;</strong>.</li>
      <li>Unter <strong>&#8220;Klasse&#8221;</strong> wählen Sie <strong>&#8220;2. Klasse&#8221;</strong>. In der <strong>&#8220;1. Klasse&#8221;</strong> sitzen Sie viel bequemer, aber Sie müssen zusätzlich CHF 4.40 bezahlen. Bitte beachten Sie, dass die erste Klasse nicht für Fahrten mit Tram oder Bus zur Verfügung steht.</li>
      <li>Unter <strong>&#8220;Erwachsene (ohne Halbtax)&#8221;</strong>, wählen Sie die Anzahl Billette aus, die Sie kaufen möchten, d.h. <strong>&#8220;1x&#8221;</strong> (für eine Person), <strong>&#8220;2x&#8221;</strong> (wenn Sie Billette für zwei Personen kaufen), usw.</li>
      <li>Bezahlen Sie den auf dem Display angezeigten Ticketpreis mit einer Kredit-/Debitkarte, mit Münzen oder mit...

CSS

/* The following styles are optional */

/* jquery ui Accordion Widget */
.jm-accordion .ui-accordion-content {
  padding-left: 0.5em;
  padding-right: 0.5em;
  padding-top: 0em;
  padding-bottom: 0em;
}

.jm-accordion .ui-accordion-header {
  padding-left: 0.1em;
  padding-right: 0.1em;
}

.jm-accordion-2 .ui-accordion-header {
  font-weight: bold;
}

.jm-accordion-2 .ui-state-active {
  background: #ff0000;
  border-color: #dd0000;
}

JavaScript

/* I used the following as a refference while implementing an extension of the
 * jQuery ui accordion Widget:
 * - Extending Widgets with the Widget Factory
 *   https://learn.jquery.com/jquery-ui/widget-factory/extending-widgets/
 * - Chapter 9. Extending widgets with the widget factory
 *   https://livebook.manning.com/book/jquery-ui-in-action/chapter-9/17
 * - Widget Factory (Example)
 *   https://jqueryui.com/widget/#default
 * - Widget Factory (Methods and properties)
 *   https://api.jqueryui.com/jQuery.widget/
 *
 */
 
/* Here I'm saying that my widget is inside the "custom" namespace, which is
 * useful in order to avoid breaking the jQuery .ui namespace. Then I give it
 * the name "jmAccordion" and finally, it will extend the jQuery ui accordion
 * Widget, which is inside the .ui namespace
 */
$.widget("custom.jmAccordion", $.ui.accordion, {

  // Here I added the options for the Widget
  options: {
    // Indicates wether or not to scroll to the top when opening a section
    topScrolling: true,
    
    // Indicates wether or not to keep sections opened, when clicking others
    keepOpen: true,
    
    // Indicates whatever to open all the accordion section on print or not
    // If it is false, then only the opened accordions will be printed
    openOnPrint: true,

    /* The following option is the css class for styling the widget. It
     * basically works the same as the accordion jQuery ui Widget, but you will
     * have to preffix the classes with the one defined here, for example:
     * .jm-accordion .ui-accordion-content { your styles }
     * The styles that you don't set, will be inherited from the accordion
     * Widget of jQuery ui
     */
    containerClass: "jm-accordion",
  },
   
  // Constructor method
  _create: function() {

    /* Since the Widget can be called several times, only one print css class
     * named as containerClass + '-styles' will be added to the head element,
     * so we only have to check that it doesn't...