diff --git a/VERSIONS_HOTLINE/135970 b/VERSIONS_HOTLINE/135970
new file mode 100644
index 0000000000000000000000000000000000000000..684967d311116be3b1f1c05366864c8b5a8de70f
--- /dev/null
+++ b/VERSIONS_HOTLINE/135970
@@ -0,0 +1 @@
+ - ticket #135970 : Magasin de thèmes : Amélioration des performances d'affichage des pages mon compte, notice, bibliothèque et auteur.
\ No newline at end of file
diff --git a/application/modules/opac/controllers/AbonneController.php b/application/modules/opac/controllers/AbonneController.php
index e3e2965b7adb007df49d47ac18b6ae3d0e19259f..e4728c0c9f4996ad7e68d80caeaebb4533cb864f 100644
--- a/application/modules/opac/controllers/AbonneController.php
+++ b/application/modules/opac/controllers/AbonneController.php
@@ -24,9 +24,10 @@ class AbonneController extends ZendAfi_Controller_Action {
 
 
   public function getPlugins() {
-    return ['ZendAfi_Controller_Plugin_Printer_Loans',
-            'ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity',
-            'ZendAfi_Controller_Plugin_Template_Borrower'];
+    return [ZendAfi_Controller_Plugin_Printer_Loans::class,
+            ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity::class,
+            ZendAfi_Controller_Plugin_Template_Borrower::class,
+            ZendAfi_Controller_Plugin_Template_Jumbotron::class];
   }
 
 
diff --git a/application/modules/opac/controllers/NoticeajaxController.php b/application/modules/opac/controllers/NoticeajaxController.php
index 808576747fc41d49f964533a3a2021e9a16f449f..ba2f54863554488171605cfac10a1c08657d3b0f 100644
--- a/application/modules/opac/controllers/NoticeajaxController.php
+++ b/application/modules/opac/controllers/NoticeajaxController.php
@@ -26,16 +26,23 @@ class NoticeAjaxController extends ZendAfi_Controller_Action {
   private $service_afi;           // Web service afi actif ou pas
 
 
+  public function getPlugins() {
+    return ['ZendAfi_Controller_Plugin_Template_Jumbotron'];
+  }
+
+
   public function init() {
+    parent::init();
+    $this->notice = $this->extractNoticeFromRequest();
+    $this->id_notice = $this->notice->getId();
     $this->notice_html = new Class_NoticeHtml();
     $this->service_afi = Class_CosmoVar::get('url_services');
   }
 
 
-  public function preDispatch() {
-    parent::preDispatch();
-    $this->notice = $this->extractNoticeFromRequest();
-    $this->id_notice = $this->notice->getId();
+  public function acceptVisitor($plugin) {
+    parent::acceptVisitor($plugin);
+    $plugin->visitRecord($this->notice);
   }
 
 
diff --git a/application/modules/opac/views/scripts/record/items.phtml b/application/modules/opac/views/scripts/record/items.phtml
index b09d70a4d3abba9838a2ab87ad26874e4026c47b..75a0911e0926ec284fde2545a8c7bfe0fbcfcd91 100644
--- a/application/modules/opac/views/scripts/record/items.phtml
+++ b/application/modules/opac/views/scripts/record/items.phtml
@@ -1,2 +1,2 @@
 <?php
-echo $this->renderRecord_Items($this->record);
\ No newline at end of file
+echo $this->renderRecord_Items($this->record);
diff --git a/library/ZendAfi/Controller/Plugin/Template/Jumbotron.php b/library/ZendAfi/Controller/Plugin/Template/Jumbotron.php
new file mode 100644
index 0000000000000000000000000000000000000000..beea58bff2f9eb554f65d662be6650a54ba6f253
--- /dev/null
+++ b/library/ZendAfi/Controller/Plugin/Template/Jumbotron.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+
+class ZendAfi_Controller_Plugin_Template_Jumbotron extends ZendAfi_Controller_Plugin_Abstract {
+
+  protected
+    $_record,
+    $_user;
+
+
+  public function visitRecord($record) {
+    $this->_record = $record;
+    return $this;
+  }
+
+
+  public function visitUser($user) {
+    $this->_user = $user;
+    return $this;
+  }
+
+
+  public function hasMediaAction() {
+    return $this->_withRecordDo(function()
+                                {
+                                  return (new Intonation_Library_Record_MediaHelper($this->_record))->hasMedia();
+                                });
+  }
+
+
+  public function hasAuthorAction() {
+    return $this->_withRecordDo(function()
+                                {
+                                  return Class_CodifAuteur::findWithFullName($this->_record->getAuteurPrincipal());
+                                });
+  }
+
+
+  public function hasLoanAction() {
+    return $this->_withUserDo(function()
+                              {
+                                $cards = new Class_User_Cards($this->_user);
+                                return $cards->getLoansCount();
+                              });
+  }
+
+
+  protected function _withUserDo($callback) {
+    return $this->_withModelDo($this->_user, $callback);
+  }
+
+
+  protected function _withRecordDo($callback) {
+    return $this->_withModelDo($this->_record, $callback);
+  }
+
+
+  protected function _withModelDo($model, $callback) {
+    $helper = $this->_helper->getHelper('HTMLAjaxResponse');
+
+    if ( ! $model)
+      return $helper->direct('');
+
+    return $callback()
+      ? $helper->htmlAjaxResponseWithScript($this->_view->tag('span', '', ['class' => 'success']))
+      : $helper->direct('');
+  }
+}
\ No newline at end of file
diff --git a/library/templates/Intonation/Library/LastFm.php b/library/templates/Intonation/Library/LastFm.php
index 2bb0b1c5fcd3ff398ec157108c66403bed91b9a6..238e1ea7c7c8419bca06087564b883dcfc90d545 100644
--- a/library/templates/Intonation/Library/LastFm.php
+++ b/library/templates/Intonation/Library/LastFm.php
@@ -30,13 +30,53 @@ class Intonation_Library_LastFm extends Class_Entity {
     LAST_FM = 'https://www.last.fm/music/';
 
 
+  protected $_author_cache;
+
+
+  protected function _getAuthor() {
+    if ( $this->_author_cache)
+      return $this->_author_cache;
+
+    return $this->_author_cache = $this->getModel()->getMainAuthorFromCodif();
+  }
+
+
   public function getAlbumPictures() {
-    return $this->_getPictures($this->getModel()->getMainAuthorFromCodif());
+    return $this->_getPictures($this->_getAuthor());
   }
 
 
   public function getAlbumTracks() {
-    return $this->_getTracks($this->getModel()->getMainAuthorFromCodif(), $this->getModel()->getTitrePrincipal(' '));
+    return $this->_getTracks($this->_getAuthor(), $this->getModel()->getTitrePrincipal(' '));
+  }
+
+
+  public function hasTracks() {
+    if ( ! $author = $this->_getAuthor())
+      return false;
+
+    if ( ! $album = $this->getModel()->getTitrePrincipal(' '))
+      return false;
+
+    return $this->_tryUrl(static::LAST_FM . urlencode($author) . '/' . urlencode($album));
+  }
+
+
+  public function hasPictures() {
+    if (! $this->_getAuthor())
+      return false;
+
+    return $this->_tryUrl(static::LAST_FM . urlencode($this->_getAuthor()) . static::LAST_FM_IMGS);
+  }
+
+
+  protected function _tryUrl($url) {
+    if (!$response = static::getWebClient()->getResponse($url))
+      return '';
+
+    return $response->isSuccessful()
+      ? $response->getBody()
+      : '';
   }
 
 
@@ -57,13 +97,7 @@ class Intonation_Library_LastFm extends Class_Entity {
 
 
   protected function _withUrlDo($url, $callback) {
-    if (!$response = static::getWebClient()->getResponse($url))
-      return [];
-
-    if (!$response->isSuccessful())
-      return [];
-
-    return ($body = $response->getBody())
+    return ($body = $this->_tryUrl($url))
       ? $callback($body)
       : [];
   }
diff --git a/library/templates/Intonation/Library/Pictures.php b/library/templates/Intonation/Library/Pictures.php
index aff294dab20ca7ce14299b77d5218e4fde01d762..3370db8d99d9f971b4b871bed5fa384da75e4c08 100644
--- a/library/templates/Intonation/Library/Pictures.php
+++ b/library/templates/Intonation/Library/Pictures.php
@@ -49,6 +49,13 @@ class Intonation_Library_Pictures {
   }
 
 
+  public function hasContent() {
+    return ((new Intonation_Library_LastFm)
+            ->setModel($this->_model)
+            ->hasPictures());
+  }
+
+
   protected function _canGetPicturesFronLastFm() {
     return $this->_model->isDisc()
       || $this->_model->isDVD()
diff --git a/library/templates/Intonation/Library/Record/MediaHelper.php b/library/templates/Intonation/Library/Record/MediaHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ed6611a426a884405548250e04c0effe29d6ada
--- /dev/null
+++ b/library/templates/Intonation/Library/Record/MediaHelper.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Intonation_Library_Record_MediaHelper {
+
+
+  protected $_record;
+
+
+  public function __construct($record) {
+    $this->_record = $record;
+  }
+
+
+  public function hasMedia() {
+    if ($this->_record->hasAlbum())
+      return true;
+
+    if (Class_FRBR_Link::countAlbumsFromNotice($this->_record))
+      return true;
+
+    if ( (new Class_Notice_Numel($this->_record))->shouldRender())
+      return true;
+
+    if ( (new Class_Notice_Gallica($this->_record))->getViewer())
+      return true;
+
+    if ((new Intonation_Library_Trailers)
+        ->setModel($this->_record)
+        ->hasContent())
+      return true;
+
+    if ((new Intonation_Library_Tracks)
+        ->setModel($this->_record)
+        ->hasContent())
+      return true;
+
+    return (bool) (new Intonation_Library_Pictures)
+      ->setModel($this->_record)
+      ->hasContent();
+  }
+}
diff --git a/library/templates/Intonation/Library/Tracks.php b/library/templates/Intonation/Library/Tracks.php
index a17c0d942afcfa3034ed8c09742926f19e0ad297..8dfac27abf6757f1af73113193d8ddc69b236163 100644
--- a/library/templates/Intonation/Library/Tracks.php
+++ b/library/templates/Intonation/Library/Tracks.php
@@ -36,6 +36,30 @@ class Intonation_Library_Tracks {
   }
 
 
+  public function hasContent() {
+    if (!$this->_model->isTypeDocSonore())
+      return false;
+
+    if ($this->_hasTracks())
+      return true;
+
+    return (new Intonation_Library_LastFm)
+      ->setModel($this->_model)
+      ->hasTracks();
+  }
+
+
+  protected function _hasTracks() {
+    return $this->_model->isGam()
+      ? ((new Intonation_Library_TracksGam)
+         ->setModel($this->_model)
+         ->hasContent())
+      : ((new Intonation_Library_TracksBase)
+         ->setModel($this->_model)
+         ->hasContent());
+  }
+
+
   public function tracks() {
     if (!$this->_model->isTypeDocSonore())
       return [];
@@ -77,6 +101,13 @@ abstract class Intonation_Library_TracksAbstract {
 
 
 class Intonation_Library_TracksBase extends Intonation_Library_TracksAbstract {
+
+
+  public function hasContent() {
+    return ! empty($this->_model->get_subfield('464'));
+  }
+
+
   public function getTracks() {
     $tracks = [];
     $unimarc = $this->_model->get_subfield('464');
@@ -113,6 +144,11 @@ class Intonation_Library_TracksBase extends Intonation_Library_TracksAbstract {
 
 
 class Intonation_Library_TracksGam extends Intonation_Library_TracksAbstract {
+  public function hasContent() {
+    return ! empty($this->_model->get_subfield('856'));
+  }
+
+
   public function getTracks() {
     $tracks = [];
     $unimarc = $this->_model->get_subfield('856');
diff --git a/library/templates/Intonation/Library/Trailers.php b/library/templates/Intonation/Library/Trailers.php
index 8dd4f19ad148a02307917f045604047e1dac9498..e7b816ed7bfc0f47cb6ef3aa2b524daf1995851e 100644
--- a/library/templates/Intonation/Library/Trailers.php
+++ b/library/templates/Intonation/Library/Trailers.php
@@ -38,7 +38,40 @@ class Intonation_Library_Trailers {
   }
 
 
-  public function trailers() {
+  public function hasContent() {
+    return ! empty($this->_getData());
+  }
+
+
+  protected function _getData() {
+    if ( ! $data = $this->_getResponse())
+      return [];
+
+    if ( $disabled = $this->_getDisabledTrailer($data))
+      return $disabled;
+
+    return ($player = $this->_getPlayer($data))
+      ? $player
+      : [];
+  }
+
+
+  protected function _getPlayer($data) {
+    return (isset($data['player']) && ($html = $data['player']))
+      ? $html
+      : [];
+  }
+
+
+  protected function _getDisabledTrailer($data) {
+    return Class_WebService_AllServices::isTrailerDisabled($data)
+      ? [new Intonation_Library_Trailer(['Model' => $this->_model,
+                                         'Disabled' => true])]
+      : [];
+  }
+
+
+  protected function _getResponse() {
     $args = ['titre' => $this->_model->getRecordTitle(),
              'auteur' => $this->_model->getMainAuthorFromCodif(),
              'clef_oeuvre' => $this->_model->getClefOeuvre(),
@@ -46,21 +79,25 @@ class Intonation_Library_Trailers {
 
     $trailer_service = (new Class_WebService_AllServices);
 
-    $data = $trailer_service->runServiceAfi($trailer_service::SVC_GET_TRAILER, $args);
+    return ($data = $trailer_service->runServiceAfi($trailer_service::SVC_GET_TRAILER, $args))
+      ? $data
+      : [];
+  }
+
 
-    if ( empty($data) )
+  public function trailers() {
+    if ( ! $data = $this->_getResponse())
       return [];
 
-    if (Class_WebService_AllServices::isTrailerDisabled($data))
-      return [new Intonation_Library_Trailer(['Model' => $this->_model,
-                                              'Disabled' => true])];
+    if ( $disabled = $this->_getDisabledTrailer($data))
+      return $disabled;
 
-    if ( !isset($data['player']) || (!$html = $data['player']))
+    if ( ! $player = $this->_getPlayer($data))
       return [];
 
     $source = isset($data['source']) ? $data['source'] : $this->_('source inconnue');
 
-    preg_match('/src="([^"]+)"/', $html, $match);
+    preg_match('/src="([^"]+)"/', $player, $match);
 
     if ( !$url = $match[1])
       return [];
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Author.php b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Author.php
index e18013dab1517a983af817fa941eb2f1bb1bcf0f..8aab66e34e64e2fefb3478d637cc345ef5c1a967 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Author.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Author.php
@@ -39,6 +39,12 @@ class Intonation_Library_View_Wrapper_Record_RichContent_Author extends Intonati
   }
 
 
+  protected function _getEnableTabAjaxUrl() {
+    return $this->_view->url(['controller' => 'noticeajax',
+                              'action' => 'has-author']);
+  }
+
+
   public function getClass() {
     return 'document_author';
   }
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Home.php b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Home.php
index 68ec0a6b9eedf40e1c5ed5cb883962a0fcaf93b2..015102e91cb0b14cbb3253c047ae508368b299c9 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Home.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Home.php
@@ -32,6 +32,11 @@ class Intonation_Library_View_Wrapper_Record_RichContent_Home extends Intonation
   }
 
 
+  public function hasContent() {
+    return true;
+  }
+
+
   public function getClass() {
     return 'all_record_data';
   }
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Items.php b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Items.php
index 99604307d61f2fc0f53bbcfeef11e23a2412cfba..6aeb155f42d9562ce366fa86bd9a91a76181a072 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Items.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Items.php
@@ -41,6 +41,11 @@ class Intonation_Library_View_Wrapper_Record_RichContent_Items extends Intonatio
   }
 
 
+  public function shouldDisableTab() {
+    return false;
+  }
+
+
   public function renderSettingsAction() {
     $current_profile = Class_Profil::getCurrentProfil();
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Media.php b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Media.php
index ae7e3f8bdbaff6c5a45b67195429503f3437206a..9afefe5506dab9a11c59656305dead740a1ac4ad 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Media.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent/Media.php
@@ -40,6 +40,12 @@ class Intonation_Library_View_Wrapper_Record_RichContent_Media extends Intonatio
   }
 
 
+  protected function _getEnableTabAjaxUrl() {
+    return $this->_view->url(['controller' => 'noticeajax',
+                              'action' => 'has-media']);
+  }
+
+
   public function getClass() {
     return 'document_media';
   }
diff --git a/library/templates/Intonation/Library/View/Wrapper/RichContent/Section.php b/library/templates/Intonation/Library/View/Wrapper/RichContent/Section.php
index 6434126e2bfa09d24c6367470f0d552881d3b6cb..f67c28889b00fcaf607330cc4def3be5f26960ed 100644
--- a/library/templates/Intonation/Library/View/Wrapper/RichContent/Section.php
+++ b/library/templates/Intonation/Library/View/Wrapper/RichContent/Section.php
@@ -71,7 +71,7 @@ abstract class Intonation_Library_View_Wrapper_RichContent_Section {
 
 
   public function isVisible() {
-    return $this->_visible && $this->getContent();
+    return $this->_visible;
   }
 
 
@@ -103,6 +103,11 @@ abstract class Intonation_Library_View_Wrapper_RichContent_Section {
   }
 
 
+  public function isActive() {
+    return $this->_is_active;
+  }
+
+
   public function getActiveClass() {
     return $this->_is_active ? 'active' : '';
   }
@@ -158,12 +163,29 @@ abstract class Intonation_Library_View_Wrapper_RichContent_Section {
   }
 
 
+  public function addJsEnableTab($id) {
+    if ( ! $url =  $this->_getEnableTabAjaxUrl())
+      return;
+
+    Class_ScriptLoader::getInstance()
+      ->addJQueryReady(sprintf('$("#%s").load("%s", function() {%s});',
+                               $id,
+                               $url,
+                               $this->_getJsCallback()));
+
+    return $this->_div(['id' => $id,
+                        'data-ajax-content' => 1,
+                        'class' => 'd-none'],
+                       '');
+  }
+
+
   protected function _getJsCallback($html = '') {
     $js = '';
     if ($class = $this->getClass())
       $js =
         sprintf('$(\'.loading_icon\').parent().remove();
-                 if ($(\'.%1$s .jumbotron_section_content [data-ajax-content] > *\').length)
+                 if ($(\'.%1$s [data-ajax-content] > *\').length)
                    return $(\'.%1$s\').removeClass(\'d-none text-black-50 disabled\');',
                 $class);
 
@@ -176,6 +198,16 @@ abstract class Intonation_Library_View_Wrapper_RichContent_Section {
   }
 
 
+  protected function _getEnableTabAjaxUrl() {
+    return '';
+  }
+
+
+  public function shouldDisableTab() {
+    return $this->isAjax();
+  }
+
+
   abstract public function getTitle();
   abstract public function getContent();
   abstract public function getClass();
diff --git a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Holds.php b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Holds.php
index 059b24e05060216b60ed52102731bca762fa7ebb..a15112b25be41d7dd7aa6fcee16c821bb299a040 100644
--- a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Holds.php
+++ b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Holds.php
@@ -22,6 +22,7 @@
 
 class Intonation_Library_View_Wrapper_User_RichContent_Holds extends Intonation_Library_View_Wrapper_User_RichContent_Section {
 
+
   public function getTitle() {
     return $this->_('Mes réservations');
   }
@@ -41,7 +42,12 @@ class Intonation_Library_View_Wrapper_User_RichContent_Holds extends Intonation_
       $html [] = $this->_view->div(['class' => 'col-12'],
                                    $this->_view->abonne_PNBHolds($pnb_holds));
 
-    return $this->_view->grid($html);
+    return $html
+      ? $this->_view->grid($html)
+      :  $this->_('Vous n\'avez pas encore fait de réservation. %s !',
+                      $this->_view->tagAnchor(['controller' => 'recherche',
+                                               'action' => 'simple'],
+                                              $this->_('Commencer maintenant')));
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php
index 6763d7fe1f8758ffcebe0d93a6e6e0f5305bffd5..83a436af4f8793cd975031e476d8cbf76ef19ac8 100644
--- a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php
+++ b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php
@@ -25,6 +25,12 @@ class Intonation_Library_View_Wrapper_User_RichContent_Loans extends Intonation_
   protected $_ajax = true;
 
 
+  protected function _getEnableTabAjaxUrl() {
+    return $this->_view->url(['controller' => 'abonne',
+                              'action' => 'has-loan']);
+  }
+
+
   public function getTitle() {
     return $this->_('Mes prêts');
   }
diff --git a/library/templates/Intonation/Library/View/Wrapper/Work/RichContent/Items.php b/library/templates/Intonation/Library/View/Wrapper/Work/RichContent/Items.php
index 34d8f7a1688198d995632231cca823eb634bf0a4..41417ac3c0464c52e6363ce97d560460f796fea3 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Work/RichContent/Items.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Work/RichContent/Items.php
@@ -26,6 +26,11 @@ class Intonation_Library_View_Wrapper_Work_RichContent_Items
   protected $_ajax = true;
 
 
+  public function shouldDisableTab() {
+    return false;
+  }
+
+
   public function getTitle() {
     return $this->_('Exemplaires');
   }
diff --git a/library/templates/Intonation/View/Jumbotron.php b/library/templates/Intonation/View/Jumbotron.php
index 8e76178ebc7c3ca92df478388f176f125a9b0e94..b4aef538a70ea22bab9e47e4b7afce2b4ae1748a 100644
--- a/library/templates/Intonation/View/Jumbotron.php
+++ b/library/templates/Intonation/View/Jumbotron.php
@@ -127,22 +127,38 @@ class Intonation_View_Jumbotron extends ZendAfi_View_Helper_BaseHelper {
 
   protected function _renderNavItem($item) {
     $id = $item->getModel()->getId();
+    $active_class = $item->getActiveClass();
+    $classes = $item->getClass();
+
+    $html = [Class_Template::current()->getIco($this->view, $item->getDBNavIco()),
+             $this->view->div(['class' => 'button_text jumbotron_nav_tab_text'], $item->getDBTitle())];
 
     $params = ['title' => $item->getDBNavTitle(),
-               'class' => 'jumbotron_nav_link nav-link p-1 p-xl-0 ' . $item->getClass() . ' ' . $item->getActiveClass()];
+               'class' => 'jumbotron_nav_link nav-link p-1 p-xl-0 ' . $classes . ' ' . $active_class];
 
-    if ($item->isAjax() || (!$item->getContent()))
+    if ($item->shouldDisableTab()) {
       $params ['class'] .= ' text-black-50 disabled';
+      $html = $this->_addJsEnableTabToHTML($item, $id, $html);
+    }
 
     return
       $this->_tag('li',
                   $this->view->tagAnchor(array_merge($item->getNavUrl(),
                                                      ['id' => $id]),
-                                         Class_Template::current()->getIco($this->view, $item->getDBNavIco()). $this->view->div(['class' => 'button_text jumbotron_nav_tab_text'], $item->getDBTitle()),
+                                         implode($html),
                                          $params),
                   ['class' => sprintf('nav-item wrapper_%s wrapper_%s',
-                                      $item->getClass(),
-                                      $item->getActiveClass())]);
+                                      $classes,
+                                      $active_class)]);
+  }
+
+
+  protected function _addJsEnableTabToHTML($item, $id, $html) {
+    if ( $item->isVisible())
+      return $html;
+
+    $html [] = $item->addJsEnableTab('nav_tab_ajax_' . $item->getClass());
+    return $html;
   }
 
 
@@ -162,10 +178,12 @@ class Intonation_View_Jumbotron extends ZendAfi_View_Helper_BaseHelper {
 
 
   protected function _renderSection($element) {
-    if (!$element->handleSection())
+    if ( ! $element->handleSection())
       return '';
 
-    if (!$element->isVisible() && !$element->isAjax())
+    $visible = $element->isVisible();
+
+    if ( ! $visible)
       return '';
 
     $classes = 'rich_content jumbotron_rich_content ';
@@ -173,9 +191,6 @@ class Intonation_View_Jumbotron extends ZendAfi_View_Helper_BaseHelper {
     if ($element->isAjax())
       $classes .= ' d-none';
 
-    if ($element->isAjax() && !$element->isVisible())
-      $classes .= ' hidde_content';
-
     if ($class = $element->getClass())
       $classes .= sprintf(' %s wrapper_%s wrapper_%s',
                           $class,
@@ -192,7 +207,7 @@ class Intonation_View_Jumbotron extends ZendAfi_View_Helper_BaseHelper {
                                          ['class' => 'jumbotron_section_title'])
                            . $this->view->div(['class' => 'jumbotron_section_content'],
                                               $element->getContent()));
-    return ($element->isAjax() && $element->isvisible())
+    return ($element->isAjax() && $visible)
       ? ($this->_renderLoadingIcon() . $content)
       : $content;
   }
diff --git a/scripts/emacs/yasnippet/snippets/text-mode/php-mode/fixture b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/fixture
index f7a8407634f36b2aa2fad5c65931f7b049e74696..6e96baae4ff5d7e47505465444edbf50a759b7c2 100644
--- a/scripts/emacs/yasnippet/snippets/text-mode/php-mode/fixture
+++ b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/fixture
@@ -1,5 +1,6 @@
 #contributor : Patrick Barroca <pbarroca@afi-sa.fr>
+#contributor : Ghislain Loas <gloas@afi-sa.fr>
 # --
-$this->fixture('${class_name}',
-								['id' => ${id},
-								 $0]);
\ No newline at end of file
+$this->fixture(${class_name}::class,
+  ['id' => ${id},
+  $0]);
\ No newline at end of file
diff --git a/tests/scenarios/Templates/TemplatesAbonneTest.php b/tests/scenarios/Templates/TemplatesAbonneTest.php
index f38dc17ae8cd67d3581b5b27d710b3eac4770ed0..dd858f8c3c85653edd9452d94965ea0e9d703fc4 100644
--- a/tests/scenarios/Templates/TemplatesAbonneTest.php
+++ b/tests/scenarios/Templates/TemplatesAbonneTest.php
@@ -1749,4 +1749,15 @@ class TemplatesAbonneAgendaDisabledTest extends AbstractControllerTestCase {
   public function agendaTabShouldNotBePresent() {
     $this->assertNotXPath('//div//a[contains(@class, "user_agenda")]');
   }
+}
+
+
+
+
+class TemplatesAbonneJumbotronLoansTest extends TemplatesIntonationAccountTestCase {
+  /** @test */
+  public function abonneHasLoanShouldRenderScript() {
+    $this->dispatch('/abonne/has-loan/id_profil/72');
+    $this->assertXPath('//span[@class="success"]');
+  }
 }
\ No newline at end of file
diff --git a/tests/scenarios/Templates/TemplatesJumbotronTest.php b/tests/scenarios/Templates/TemplatesJumbotronTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..49b4036dbd240a157a125ff15fbe9458d406be02
--- /dev/null
+++ b/tests/scenarios/Templates/TemplatesJumbotronTest.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class TemplatesRecordsDispatchItemsTest extends AbstractControllerTestCase {
+
+  protected $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+    $this->_buildTemplateProfil(['id' => 2]);
+
+    $this->fixture(Class_Notice::class,
+                   ['id' => 1,
+                    'type_doc' => Class_TypeDoc::DISQUE,
+                    'titre_principal' => 'Thérapie de groupe',
+                    'resume' => 'Une bonne BD de Manu']);
+  }
+
+
+  /** @test */
+  public function shouldJsLoadItemsWithInitializePopupAndSetupAnchorTarget() {
+    $this->dispatch('/record/items/id/1');
+    $this->assertXPathContentContains('//script', '.load("/noticeajax/resources/id/1", function() {$(\'.loading_icon\').parent().remove();
+                 if ($(\'.document_items [data-ajax-content] > *\').length)
+                   return $(\'.document_items\').removeClass(\'d-none text-black-50 disabled\');initializePopups();setupAnchorsTarget();});}, 5);');
+  }
+
+
+  /** @test */
+  public function shouldJsLoadHasAuthor() {
+    $this->dispatch('/record/items/id/1');
+    $this->assertXPathContentContains('//script', '.load("/noticeajax/has-author/id/1", function() {$(\'.loading_icon\').parent().remove();
+                 if ($(\'.document_author [data-ajax-content] > *\').length)
+                   return $(\'.document_author\').removeClass(\'d-none text-black-50 disabled\');});}, 5);');
+  }
+
+
+  /** @test */
+  public function shouldJsLoadHasMedia() {
+    $this->dispatch('/record/items/id/1');
+    $this->assertXPathContentContains('//script', '.load("/noticeajax/has-media/id/1", function() {$(\'.loading_icon\').parent().remove();
+                 if ($(\'.document_media [data-ajax-content] > *\').length)
+                   return $(\'.document_media\').removeClass(\'d-none text-black-50 disabled\');});}, 5);');
+  }
+
+
+  /** @test */
+  public function shouldNotJsLoadResources() {
+    $this->dispatch('/record/media/id/1');
+    $this->assertNotXPathContentContains('//script', '.resources/id/1');
+  }
+
+
+  /** @test */
+  public function noticeAjaxHasMediaShouldRenderScript() {
+    $unimarc = (new Class_NoticeUnimarc_Fluent)
+      ->zoneWithContent('001', '12345')
+      ->zoneWithChildren('200', ['f' => 'Loow'])
+      ->zoneWithChildren('464', ['t' => 'Lotus out of water',
+                                 '3' => 'https://my-super-sound/lotus_out_of_water.mp3'])
+      ->zoneWithChildren('464', ['t' => 'Milking song',
+                                 '3' => 'https://my-super-sound/milking_song.mp3'])
+      ->zoneWithChildren('464', ['t' => 'Boisson Divine',
+                                 '3' => 'https://youtube.com/watch?v=12341513O'])
+      ->zoneWithChildren('464', ['t' => 'Spirits From Tuva',
+                                 '3' => 'https://ma-discotheque.org/Hunn-Huur-Tu/song']);
+
+    Class_Notice::find(1)->setUnimarc($unimarc->render());
+
+    $this->dispatch('/noticeajax/has-media/id/1');
+    $this->assertXPath('//script');
+  }
+
+
+  /** @test */
+  public function noticeAjaxHasAuthorShouldRenderJsCallback() {
+    $this->fixture('Class_CodifAuteur',
+                   ['id' => 2408,
+                    'libelle' => 'Victor Hugo',
+                    'thumbnail_url' => 'http://wp/hugo.jpg']);
+
+    Class_Notice::find(1)->setAuteurPrincipal('Victor Hugo');
+
+    $this->dispatch('/noticeajax/has-author/id/1');
+    $this->assertXPath('//script');
+  }
+
+
+
+  /** @test */
+  public function shouldJsLoadBorrowerLoans() {
+    $pierre = $this->fixture(Class_Users::class,
+                             ['id' => 2,
+                              'login' => 'Pierre',
+                              'password' => '.com']);
+
+    ZendAfi_Auth::getInstance()->logUser($pierre);
+
+    $this->dispatch('/abonne/selections/id/2');
+    $this->assertXPathContentContains('//script', 'load("/abonne/has-loan/id/2", function() {$(\'.loading_icon\').parent().remove();
+                 if ($(\'.user_loans [data-ajax-content] > *\').length)
+                   return $(\'.user_loans\').removeClass(\'d-none text-black-50 disabled\');});});');
+  }
+
+
+  /** @test */
+  public function withNoTracksNoticeAjaxHasMediaResponseShouldBeEmpty() {
+    $this->dispatch('/noticeajax/has-media/id/1');
+    $this->assertEmpty($this->_response->getBody());
+  }
+}
\ No newline at end of file
diff --git a/tests/scenarios/Templates/TemplatesRecordsTest.php b/tests/scenarios/Templates/TemplatesRecordsTest.php
index 35de31fb24348b4ed17e40c0a18da86ea019a1f2..d4965092501f0e7d0b4e1522f932791e6cdce55b 100644
--- a/tests/scenarios/Templates/TemplatesRecordsTest.php
+++ b/tests/scenarios/Templates/TemplatesRecordsTest.php
@@ -465,19 +465,6 @@ class TemplatesRecordsViewnoticeModeratedReviewsValidatedBadgesTest
 
 
 
-class TemplatesRecordsDispatchItemsTest extends TemplatesRecordsWidgetTestCase {
-  /** @test */
-  public function shouldRenderAjaxLoadWithInitializePopupAndSetupAnchorTarget() {
-    $this->dispatch('/record/items/id/1/id_profil/1');
-    $this->assertXPathContentContains('//script', '.load("/noticeajax/author/id/1/id_profil/1", function() {$(\'.loading_icon\').parent().remove();
-                 if ($(\'.document_author .jumbotron_section_content [data-ajax-content] > *\').length)
-                   return $(\'.document_author\').removeClass(\'d-none text-black-50 disabled\');initializePopups();setupAnchorsTarget();});}, 5);');
-  }
-}
-
-
-
-
 class TemplatesRecordsCollectionBadgesTest extends AbstractControllerTestCase {
   protected $_storm_default_to_volatile = true;