diff --git a/application/modules/opac/controllers/BibController.php b/application/modules/opac/controllers/BibController.php
index b444b8d60f11ec268a1b0dc34b57489aa55d5229..4496366df18c89f940e340bb98c07a673b785a4e 100644
--- a/application/modules/opac/controllers/BibController.php
+++ b/application/modules/opac/controllers/BibController.php
@@ -194,26 +194,45 @@ class BibController extends ZendAfi_Controller_Action {
 
   function bibviewAction() {
     $id_bib = (int)$this->_request->getParam('id');
-    if(!$id_bib || $id_bib==0) {
+
+    if (!$id_bib || $id_bib == 0) {
+      $this->_redirect('opac/bib/index');
+      return;
+    }
+
+    if (!($bib = Class_Bib::getLoader()->find($id_bib))) {
       $this->_redirect('opac/bib/index');
       return;
     }
 
-    $bib = Class_Bib::getLoader()->find($id_bib);
     $zone = $bib->getZone();
+    $this->view->url_retour = ($zone)
+      ? $this->view->url(['action' => 'zoneview', 'id' => $zone->getId()])
+      : $this->_request->getServer('HTTP_REFERER');
 
-    $this->view->url_retour = $this->view->url(array('action' => 'zoneview',
-                                                     'id' => $zone->getId()));
     if (3 == count($specs = explode(' ', $this->_getParam('retour')))) {
-      $this->view->url_retour = $this->view->url(array('controller' => $specs[0],
-                                                       'action' => $specs[1],
-                                                       'id' => $specs[2]));
+      $this->view->url_retour = $this->view->url(['controller' => $specs[0],
+                                                  'action' => $specs[1],
+                                                  'id' => $specs[2]]);
     }
 
     $this->view->bib = $bib;
-    $this->view->zone_name = $zone->getLibelle();
     $this->view->id_bib = $bib->getId();
-    $this->view->id_zone = $zone->getId();
+
+    $this->view->zone_name = ($zone) ? $zone->getLibelle() : '';
+    $this->view->id_zone = ($zone) ? $zone->getId() : 0;
+
+    $this->view->form =
+      ZendAfi_Form::newWithOptions([])
+      ->setAttribs(['action' => $this->view->url(['controller' => 'recherche',
+                                                  'action' => 'simple',
+                                                  'geo_bib' => $bib->getId()]),
+                    'id' => 'recherche',
+                    'class' => 'bibview_find'])
+
+      ->addElement('text', 'expressionRecherche', ['id' => 'expressionRecherche'])
+
+      ->addElement('submit', 'Rechercher', ['class' => 'submit']);
   }
 
 
diff --git a/application/modules/opac/views/scripts/bib/bibview.phtml b/application/modules/opac/views/scripts/bib/bibview.phtml
index 8f8fb48ee40e1077efbc2584caf2f182ebd8db07..90abed64513060934d62f6e38a3a37467441b8f9 100644
--- a/application/modules/opac/views/scripts/bib/bibview.phtml
+++ b/application/modules/opac/views/scripts/bib/bibview.phtml
@@ -1,137 +1,21 @@
 <?php
 $this->openBoite($this->_("Rechercher un livre, un disque, une vidéo"));
 
-if(!$_SESSION["selection_bib"]["nb_notices"]) print($this->_("Le catalogue de cette bibliothèque n'est pas encore intégré au portail"));
-else
-{
-?>
-
-
-<form id="recherche" style="text-align: left;" name="recherche" method="post" action="<?php echo $this->url(['controller'=>'recherche',
-                                                                                                             'action'=>'simple',
-                                                                                                             'geo_bib'=>$this->id_bib]); ?>">
-  <input type="field" style="width: 250px;" value="" name="expressionRecherche" id="expressionRecherche" />
-  <input class="submit" type="submit" value="" name="button"/>
-  <?php echo $this->_('La bibliothèque contient %s notices.', $_SESSION["selection_bib"]["nb_notices"]) ?>
-  <br/>
-  <?php echo $this->_('Dans cette bibliothèque.') ?>
-</form>
-
-<?php
+if (!$_SESSION["selection_bib"]["nb_notices"])
+  print($this->_("Le catalogue de cette bibliothèque n'est pas encore intégré au portail"));
+else {
+  echo $this->renderForm($this->form);
+
+  echo $this->tag('p',
+                  $this->_('La bibliothèque contient %s notices.',
+                           $_SESSION["selection_bib"]["nb_notices"]) .
+                           '<br/>' .
+                           $this->_('Dans cette bibliothèque.'));
 }
-$this->closeBoite();
-?>
-
-<table class="bibview" width="635px" border="0" cellpadding="0" cellspacing="0">
-  <tr>
-    <td valign="top">
-      <table width="460" border="0" cellpadding="3" cellspacing="1">
-        <tr>
-          <td colspan="2"><h1><?php echo $this->_('Fiche de la bibliothèque :') ?><br /></h1></td>
-        </tr>
-        <tr>
-          <td width="120" style="text-align:right;padding-right:5px;" valign="top"><?php echo $this->_('Nom :') ?></td>
-          <td width="346"><h2><?php echo $this->bib->LIBELLE ;?></h2></td>
-       </tr>
-
-<?php
-if ( strlen($this->bib->ADRESSE) > 0 || strlen($this->bib->CP) > 0 || strlen($this->bib->VILLE) > 0) echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Adresse : ') ?></td>
-      <td valign="top"><h2>
-<?php if (strlen($this->bib->ADRESSE) > 0) echo $this->bib->ADRESSE .'<br />' . $this->bib->CP .'&nbsp;'. $this->bib->VILLE ;
-else echo $this->bib->CP .'&nbsp;'. $this->bib->VILLE ;?>
-      </h2></td>
-      </tr>
-<?php if (strlen($this->bib->TELEPHONE) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Tel. :') ?> </td>
-      <td><h2><?php echo $this->bib->TELEPHONE ;?></h2></td>
-      </tr>
-<?php if (strlen($this->bib->MAIL) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Mail : ') ?></td>
-      <td><a href="mailto:<?php echo $this->bib->MAIL ;?>"><?php echo $this->_('Mail') ?></a></td>
-      </tr>
-<?php if (strlen($this->bib->URL_WEB) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Site internet :') ?> </td>
-      <td><a href="<?php echo $this->bib->URL_WEB ;?>" target="_blank"><?php echo $this->_('Site') ?></a></td>
-      </tr>
-<?php if (strlen($this->bib->LIEN_CARTO) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Lien cartographique :') ?> </td>
-      <td><a href="<?php echo $this->bib->LIEN_CARTO ;?>" target="_blank"><?php echo $this->_('Carte') ?></a></td>
-      </tr>
-<?php if (strlen($this->bib->HORAIRE) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Horaires :') ?> </td>
-      <td><h2><?php $horaire = str_replace('%0D%0A','BR',$this->bib->HORAIRE);
-      echo  str_replace ('BR','<br />',urldecode($horaire));?></h2></td>
-      </tr>
-<?php if (strlen($this->bib->INSCRIPTION) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Conditions inscription :') ?></td>
-      <td><h2><?php $inscr = str_replace('%0D%0A','BR',$this->bib->INSCRIPTION);
-      echo str_replace ('BR','<br />',urldecode($inscr)) ;?></h2></td>
-      </tr>
-<?php if (strlen($this->bib->PRET) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Prêts et réservations :') ?> </td>
-      <td><h2><?php $pret = str_replace('%0D%0A','BR',$this->bib->PRET);
-      echo str_replace ('BR','<br />',urldecode($pret));?></h2></td>
-      </tr>
-<?php if (strlen($this->bib->ANNEXE) > 0)echo ('<tr>');
-else echo ('<tr style="display:none;">'); ?>
-      <td style="text-align:right;padding-right:5px;width:117px;" valign="top"><?php echo $this->_('Annexe :') ?> </td>
-      <td><h2><?php $annexe = str_replace('%0D%0A','BR',$this->bib->ANNEXE) ;
-      echo str_replace ('BR','<br />',urldecode($annexe));?></h2></td>
-      </tr>
-    </td>
-    </tr>
-  </table>
-</td>
-    <td valign="top">
-      <table border="0" cellspacing="0" cellpadding="0" >
-          <tr>
-            <td align="right"></td>
-          </tr>
-          <tr>
-            <td>
-              <br /><center><div align="center">
-              <?php
-                if (trim($this->bib->PHOTO) !="") $img_bib = '<img src="'.BASE_URL.'/bib/photobib?id_bib='.$this->bib->ID_SITE.'" border="0" width="180" height="140"/>';
-                else $img_bib = '';
-                 print($img_bib);
-if(trim($this->bib->GOOGLE_MAP) !="") print('<br /> <a href="'.$this->url(['module'=>'opac',
-                                                                           'controller'=>'bib',
-                                                                           'action'=>'mapview',
-                                                                           'id_bib'=>$this->bib->ID_SITE]).'">'.$this->_('Voir le plan').'</a>');
-                 ?>
-              </div> </center>
-            </td>
-          </tr>
-        </table>
-    </td>
-  </tr>
-  <tr>
-    <td colspan="20" style="background:transparent url(<?php echo URL_IMG; ?>box/menu/separ.gif) repeat-x scroll center bottom">&nbsp;</td>
-  </tr>
-  <tr>
-    <td style="text-align:left"><a href="<?php echo $this->url_retour ?>"><?php echo $this->_('Retour') ?></a></td>
-    <td style="text-align:right"><a href="#Top">Haut</a></td>
-  </tr>
- </table>
-
-<?php
 
+$this->closeBoite();
 
-foreach(Class_CustomField_Model::getModel('Bib')->find($this->bib->getId())->getFieldValues() as $value) {
-  echo $value->getLabel() . ': ' . $value->getValue() . '<br>';
-}
+echo $this->bibView($this->bib, $this->url_retour);
 
+echo $this->newsBibHelper($this->bib->ID_SITE);
 ?>
-
-
-
-<?php echo $this->newsBibHelper($this->bib->ID_SITE);?>
diff --git a/library/Class/Bib.php b/library/Class/Bib.php
index e85b4753b1206046c604f4bcfebd931329501077..8af06263811c2eed6709bf6945e977abb4f532cc 100644
--- a/library/Class/Bib.php
+++ b/library/Class/Bib.php
@@ -154,6 +154,7 @@ class BibLoader extends Storm_Model_Loader {
 class Class_Bib extends Storm_Model_Abstract {
   use Trait_PermissionTargetable;
   use Trait_UploadFile;
+  use Trait_CustomFields;
   const V_INVISIBLE = 0;
   const V_NODATA = 1;
   const V_DATA = 2;
@@ -237,7 +238,14 @@ class Class_Bib extends Storm_Model_Abstract {
                                           'photo' => '',
                                           'redmine_login' => '',
                                           'redmine_password' => '',
-                                          'redmine_api_key' => ''];
+                                          'redmine_api_key' => '',
+                                          'cp' => '',
+                                          'lien_carto' => '',
+                                          'horaire' => '',
+                                          'inscription' => '',
+                                          'pret' => '',
+                                          'annexe' => ''];
+
 
   protected $_translate;
   protected $_fixed_id = true;
diff --git a/library/Class/CustomField/Model.php b/library/Class/CustomField/Model.php
index 08696278d28538d4af45e264f3df9ec3c7819a18..390c16666baabcd7c0c9c3478f9c03d6272621d8 100644
--- a/library/Class/CustomField/Model.php
+++ b/library/Class/CustomField/Model.php
@@ -21,8 +21,7 @@
 
 
 class Class_CustomField_Model {
-  use Trait_TreeViewableCategorie;
-
+  use Trait_TreeViewableCategorie, Trait_Translator;
   const CLASS_PREFIX = 'Class_';
 
   protected static $_models = [];
@@ -41,6 +40,32 @@ class Class_CustomField_Model {
   }
 
 
+  public static function registerDefault() {
+    $translator = new self(0);
+
+    $array_of_models_configuration =
+      [
+       new Class_CustomField_ModelConfiguration_Article(),
+       new Class_CustomField_ModelConfiguration_Formation(),
+       new Class_CustomField_ModelConfiguration_UserGroup(),
+       new Class_CustomField_ModelConfiguration_Sitotheque(),
+       new Class_CustomField_ModelConfiguration('SessionFormation',
+                                                $translator->_('Session'),
+                                                ['module' => 'admin',
+                                                 'controller' => 'formation',
+                                                 'action' => 'session_edit']),
+       new Class_CustomField_ModelConfiguration('Bib',
+                                                $translator->_('Bibliothèque'),
+                                                ['module' => 'admin',
+                                                 'controller' => 'bib',
+                                                 'action' => 'edit'])
+      ];
+
+    static::$_models = [];
+    foreach ($array_of_models_configuration as $configuration)
+      static::register($configuration);
+  }
+
   public static function isRegistered($name) {
     return array_key_exists(static::sanitizeName($name), static::$_models);
   }
diff --git a/library/Class/CustomField/Value.php b/library/Class/CustomField/Value.php
index 8bd29280d432ca959fc4c9193097561dfda8ea03..60c5107632a81abe845e4756613e44b97bdff25a 100644
--- a/library/Class/CustomField/Value.php
+++ b/library/Class/CustomField/Value.php
@@ -66,5 +66,13 @@ class Class_CustomField_Value extends Storm_Model_Abstract {
   public function getOptionsListAsArray() {
     return $this->getField()->getOptionsListAsArray();
   }
+
+
+  public function getSelectedOptionsList() {
+    if (empty($this->getOptionsListAsArray()))
+      return [];
+
+    return explode(';', $this->getValue());
+  }
 }
 ?>
diff --git a/library/Trait/CustomFields.php b/library/Trait/CustomFields.php
index 94aa29c2d375f3d92f7a0f0c3a7a04cad0eda8d3..3dcd68c267f2dbd0a2c5adfaece1f7121b85fb41 100644
--- a/library/Trait/CustomFields.php
+++ b/library/Trait/CustomFields.php
@@ -53,6 +53,11 @@ trait Trait_CustomFields {
   }
 
 
+  public function getAllCustomFields() {
+    return Class_CustomField_Model::getModel($this->getModelName())->find($this->getId());
+  }
+
+
   public function setCustomField($field,$value) {
     $this->custom_fields[$field]=$value;
     return $this;
diff --git a/library/ZendAfi/Controller/Plugin/CustomFields.php b/library/ZendAfi/Controller/Plugin/CustomFields.php
index 9ff5d94260c6e256ed84b02c0149a858303977af..649b8d4e022cda46e0cac7117f59eb68a41b20db 100644
--- a/library/ZendAfi/Controller/Plugin/CustomFields.php
+++ b/library/ZendAfi/Controller/Plugin/CustomFields.php
@@ -25,22 +25,7 @@ class ZendAfi_Controller_Plugin_CustomFields extends Zend_Controller_Plugin_Abst
 
 
   public function preDispatch(Zend_Controller_Request_Abstract $request) {
-    Class_CustomField_Model::registerAll([
-            new Class_CustomField_ModelConfiguration_Article(),
-            new Class_CustomField_ModelConfiguration_Formation(),
-            new Class_CustomField_ModelConfiguration_UserGroup(),
-            new Class_CustomField_ModelConfiguration_Sitotheque(),
-            new Class_CustomField_ModelConfiguration('SessionFormation',
-                                                     $this->_('Session'),
-                                                     ['module' => 'admin',
-                                                      'controller' => 'formation',
-                                                      'action' => 'session_edit']),
-            new Class_CustomField_ModelConfiguration('Bib',
-                                                     $this->_('Bibliothèque'),
-                                                     ['module' => 'admin',
-                                                      'controller' => 'bib',
-                                                      'action' => 'edit'])
-                                           ]);
+    Class_CustomField_Model::registerDefault();
   }
 }
 ?>
diff --git a/library/ZendAfi/Form/ContactForm.php b/library/ZendAfi/Form/ContactForm.php
index bc11a3c0d06573a7e9b8a0e0cd246c426534b6c8..0d14149bf32e4f4d7cdb912450b76906696f45d7 100644
--- a/library/ZendAfi/Form/ContactForm.php
+++ b/library/ZendAfi/Form/ContactForm.php
@@ -24,7 +24,7 @@ class ZendAfi_Form_ContactForm extends ZendAfi_Form {
 
   public function init() {
     parent::init();
-    $this->setAttrib('class', 'zend_form')
+    $this->setAttrib('class', 'zend_form form')
          ->addAllElements()
          ->addAllGroups();
   }
diff --git a/library/ZendAfi/Form/Login.php b/library/ZendAfi/Form/Login.php
index 00a80e7bb2d5f006fb3efc9e90b87f05af3e5873..94dce2dd7a5bdd3596a0d456213c5e87eea930d0 100644
--- a/library/ZendAfi/Form/Login.php
+++ b/library/ZendAfi/Form/Login.php
@@ -38,7 +38,7 @@ class ZendAfi_Form_Login extends ZendAfi_Form {
 
     $this->setMethod(Zend_Form::METHOD_POST)
          ->setAttrib('autocomplete', $this->_data['autocomplete_off'] ? 'off' : 'on')
-         ->setAttrib('class', 'login')
+         ->setAttrib('class', 'login form')
          ->addElement('text',
                       'username',
                       ['label' => $this->_data['identifiant'],
diff --git a/library/ZendAfi/View/Helper/BibView.php b/library/ZendAfi/View/Helper/BibView.php
new file mode 100644
index 0000000000000000000000000000000000000000..c04645639061339f8b51e539accc4dd19c7e593a
--- /dev/null
+++ b/library/ZendAfi/View/Helper/BibView.php
@@ -0,0 +1,205 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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_View_Helper_BibView extends ZendAfi_View_Helper_BaseHelper {
+  protected $bib;
+
+  public function bibView($bib, $back_url) {
+    $this->bib = $bib;
+
+    return
+      $this->_tag('h1', $this->_('Fiche de la bibliothèque :')) .
+      $this->_renderTable() .
+      $this->_renderPicture() .
+      $this->_renderBackLink($back_url);
+  }
+
+
+  protected function _renderTable() {
+    return '<table class="bibview">' .
+      $this->_renderName() .
+      $this->_renderAdress() .
+      $this->_renderPhone() .
+      $this->_renderMail() .
+      $this->_renderUrlWeb() .
+      $this->_renderLienCarto() .
+      $this->_renderHoraire() .
+      $this->_renderInscription() .
+      $this->_renderPret() .
+      $this->_renderAnnexe() .
+      $this->_renderCustomFields() .
+      '</table>';
+  }
+
+
+  protected function _renderBackLink($back_url) {
+    return $this->_tag('div', $this->view->tagAnchor($back_url, $this->_('Retour')),
+                       ['class' => 'back_link']);
+  }
+
+
+  protected function _renderPicture() {
+    $img = (trim($this->bib->getPhoto()) !== '') ? $this->_getImage() : '';
+    $map = (trim($this->bib->getGoogleMap()) !== '') ? $this->_getMap() : '';
+
+    return $img . $map;
+  }
+
+
+  protected function _getImage() {
+    $url = $this->view->url(['controller' => 'bib',
+                             'action' => 'photobib',
+                             'id_bib' => $this->bib->getIdSite()], null, true);
+
+    return $this->view->tagImg($url, ['class' => 'bibview_image']);
+  }
+
+
+  protected function _getMap() {
+    $url = $this->view->url(['module' => 'opac',
+                             'controller' => 'bib',
+                             'action' => 'mapview',
+                             'id_bib' => $this->bib->getIdSite()], null, true);
+
+    return $this->view->tagAnchor($url, $this->_('Voir le plan'));
+  }
+
+
+  protected function _renderName() {
+    $content = $this->_tag('td', $this->_('Nom :')) .
+      $this->_tag('td', $this->_tag('h2', $this->bib->getLibelle()), ['width' => '346']);
+
+    return $this->_tag('tr', $content);
+  }
+
+
+  protected function _renderAdress() {
+    $display = (strlen($this->bib->getAdresse()) > 0
+                || strlen($this->bib->getCp()) > 0
+                || strlen($this->bib->getVille()) > 0) ? true : false;
+
+    $content = (strlen($this->bib->getAdresse()) > 0)
+      ? $this->bib->getAdresse() . '<br />' . $this->bib->getCp() . ' ' . $this->bib->getVille()
+      : $this->bib->getCp()  . ' ' . $this->bib->getVille();
+
+    return $this->_renderInfo($content, $this->_('Adresse : '), $display);
+  }
+
+
+  protected function _renderPhone() {
+    $display = (strlen($this->bib->getTelephone()) > 0) ? true : false;
+
+    return $this->_renderInfo($this->bib->getTelephone(), $this->_('Tel : '), $display);
+  }
+
+
+  protected function _renderMail() {
+    $display = (strlen($this->bib->getMail()) > 0) ? true : false;
+    $content = $this->view->tagAnchor('mailto:' . $this->bib->getMail(), $this->bib->getMail());
+
+    return $this->_renderInfo($content, $this->_('Mail : '), $display);
+  }
+
+
+  protected function _renderUrlWeb() {
+    $display = (strlen($this->bib->getUrlWeb()) > 0) ? true : false;
+    $content = $this->view->tagAnchor($this->bib->getUrlWeb(),
+                                      $this->_('Site'),
+                                      ['target' => '_blank']);
+
+    return $this->_renderInfo($content, $this->_('Site internet : '), $display);
+  }
+
+
+  protected function _renderLienCarto() {
+    $display = (strlen($this->bib->getLienCarto()) > 0) ? true : false;
+    $content = $this->view->tagAnchor($this->bib->getLienCarto(),
+                                      $this->_('Carte'),
+                                      ['target' => '_blank']);
+
+    return $this->_renderInfo($content, $this->_('Lien cartographique : '), $display);
+  }
+
+
+  protected function _renderHoraire() {
+    $display = (strlen($this->bib->getHoraire()) > 0) ? true : false;
+
+    return $this->_renderInfo($this->_escapeInfo($this->bib->getHoraire()),
+                              $this->_('Horaires : '), $display);
+  }
+
+
+  protected function _renderInscription() {
+    $display = (strlen($this->bib->getInscription()) > 0) ? true : false;
+
+    return $this->_renderInfo($this->_escapeInfo($this->bib->getInscription()),
+                              $this->_('Conditions inscription : '), $display);
+  }
+
+
+  protected function _renderPret() {
+    $display = (strlen($this->bib->getPret()) > 0) ? true : false;
+
+    return $this->_renderInfo($this->_escapeInfo($this->bib->getPret()),
+                              $this->_('Prêts et réservations :'), $display);
+  }
+
+
+  protected function _renderAnnexe() {
+    $display = (strlen($this->bib->getAnnexe()) > 0) ? true : false;
+
+    return $this->_renderInfo($this->_escapeInfo($this->bib->getAnnexe()),
+                              $this->_('Annexe : '), $display);
+  }
+
+
+  protected function _renderCustomFields() {
+    foreach($this->bib->getAllCustomFields()->getFieldValues() as $field) {
+      if ($field->getValue() === '')
+        continue;
+
+      $options = $field->getSelectedOptionsList();
+      if (empty($options))
+        return $this->_renderInfo($field->getValue(),
+                                  $field->getLabel() . ' : ');
+
+      return $this->_renderInfo(implode('<br>', $options),
+                                $field->getLabel() . ' : ');
+    }
+  }
+
+
+  protected function _escapeInfo($info) {
+    return str_replace('BR', '<br />', urldecode(str_replace('%0D%0A','BR', $info)));
+  }
+
+
+  protected function _renderInfo($value, $label, $display = true) {
+    $content = $this->_tag('td', $label) .
+      $this->_tag('td', $this->_tag('h2', $value));
+
+    return $this->_tag('tr',
+                       $content,
+                       ($display) ? [] : ['style' => 'display:none;']);
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/RenderForm.php b/library/ZendAfi/View/Helper/RenderForm.php
index 999e83afa077bb557c741f6c163fe74624c3f638..2bb72af6417e5685acfa131aaa3e2b5ff272ce1c 100644
--- a/library/ZendAfi/View/Helper/RenderForm.php
+++ b/library/ZendAfi/View/Helper/RenderForm.php
@@ -27,7 +27,10 @@ class ZendAfi_View_Helper_RenderForm extends ZendAfi_View_Helper_BaseHelper {
     if (!$form)
       return;
 
-    $form->setAttrib('class', trim($form->getAttrib('class').' form'));
+    if (($class = $form->getAttrib('class')) === null)
+        $class = 'form';
+
+    $form->setAttrib('class', trim($class));
 
     // compatibilité avec les tables admin standard
     $this->setupTableDecoratorsForForm($form);
diff --git a/public/opac/css/global.css b/public/opac/css/global.css
index 245f5cbec693bd9d7f6d489d0a127e6c837ade28..d7b0cbc4333f6a2dc28afc07ef0f4ceccc1eba3c 100644
--- a/public/opac/css/global.css
+++ b/public/opac/css/global.css
@@ -833,7 +833,40 @@ li.notice_liste {
     white-space:nowrap;
 }
 
+table.bibview {
+    width: 460px;
+    border: 0;
+    cellpadding: 0;
+    cellspacing: 0;
+    float: left;
+    margin: 20px;
+}
+
+
+table.bibview td:first-child {
+    text-align: right;
+    padding-right: 5px;
+    width: 125px;
+    vertical-align: text-top;
+}
 
+.back_link {
+    clear: both;
+}
+
+.bibview_image {
+    border: 0;
+    width: 180px;
+    height: 140px;
+}
+
+.bibview_find {
+    text-align: left;
+}
+
+.bibview_find input[type="text"] {
+    width: 250px;
+}
 
 /** selecteur de langue */
 .country_flag {
diff --git a/public/opac/skins/modele/css/global.css b/public/opac/skins/modele/css/global.css
index de3818f476dc307d9e4c05a167811874da6b2082..6f7329bbbe25a0af1d990484efcb70683c7b173f 100644
--- a/public/opac/skins/modele/css/global.css
+++ b/public/opac/skins/modele/css/global.css
@@ -169,6 +169,7 @@ a:hover {color:#D44100;}
 .form td.saisie{text-align:left;}
 .submit {background:transparent url(../images/bouton/btn_ok.gif) no-repeat scroll 0 0;border:0 none;cursor:pointer;height:18px;width:18px;}
 .panier_index .submit {font-size: 0px;}
+.bibview_find .submit {font-size: 0px;}
 /* Tableau de liste */
 .listeTitre{border-bottom:1px solid #CACFD5;border-top:1px solid #CACFD5;color:#666666;font-weight:bold;}
 .listePaire{background-color:#F4F4EF;}
diff --git a/public/opac/skins/original/css/global.css b/public/opac/skins/original/css/global.css
index 62984b81b48242e5f53457c62c2075184e4e63fe..cd24db1dcfcb0e86c418f3658d00fc1b40693068 100644
--- a/public/opac/skins/original/css/global.css
+++ b/public/opac/skins/original/css/global.css
@@ -191,6 +191,7 @@ a:visited{color:#0058A5; text-decoration:none;}
 .form td.saisie{text-align:left;font-size:8pt}
 .submit {background:transparent url(../images/bouton/btn_ok.gif) no-repeat scroll 0 0;border:0 none;cursor:pointer;height:18px;width:18px;}
 .panier_index .submit {font-size: 0px;}
+.bibview_find .submit {font-size: 0px;}
 /* Tableau de liste */
 .listeTitre{border-bottom:1px solid #CACFD5;border-top:1px solid #CACFD5;color:#666666;font-weight:bold;}
 .listePaire{background-color:#F4F4EF;}
diff --git a/tests/application/modules/admin/controllers/BibControllerTest.php b/tests/application/modules/admin/controllers/BibControllerTest.php
index ce023d58c2b35881cd786e1be6f0220d4e652106..b914380785b2d809f7712b1607d6d479f73c8df6 100644
--- a/tests/application/modules/admin/controllers/BibControllerTest.php
+++ b/tests/application/modules/admin/controllers/BibControllerTest.php
@@ -236,7 +236,7 @@ class BibControllerWithAdminBibEditAnnecyTest extends BibControllerWithAdminBibT
 
     $this->fixture('Class_Zone',
                    ['id' => 1,
-                    'libelle' => 'Territoire']);
+                    'libelle' => 'Zone 1']);
 
     $this->dispatch('admin/bib/edit/id/2');
   }
@@ -293,8 +293,8 @@ class BibControllerWithAdminBibEditAnnecyTest extends BibControllerWithAdminBibT
 
 
   /** @test */
-  public function zoneTerritoireShouldBeDisplayed() {
-    $this->assertXPathContentContains('//select[@name="id_zone"][@id="id_zone"]//option[@value="1"]','Territoire',$this->_response->getBody());
+  public function zoneZone1ShouldBeDisplayed() {
+    $this->assertXPathContentContains('//select[@name="id_zone"][@id="id_zone"]//option[@value="1"]','Zone 1',$this->_response->getBody());
   }
 
 
diff --git a/tests/application/modules/opac/controllers/BibControllerTest.php b/tests/application/modules/opac/controllers/BibControllerTest.php
index 8d62fa98f2e0d2572123842d6258381eeb94e68e..b1be77c0aab4964226ee5dfd2fc1ab6b4173609d 100644
--- a/tests/application/modules/opac/controllers/BibControllerTest.php
+++ b/tests/application/modules/opac/controllers/BibControllerTest.php
@@ -21,54 +21,67 @@
 require_once 'AbstractControllerTestCase.php';
 
 abstract class BibControllerWithZoneTestCase extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
+
+    Class_CustomField_Model::registerDefault();
+
     unset($_REQUEST['geo_zone']);
-    $_SESSION['selection_bib'] = ['nb_notices' => 12345,
-                                  'id_bibs' => null];
-
-    $this->bib_annecy = Class_Bib::getLoader()
-      ->newInstanceWithId(4)
-      ->setIdZone(1)
-      ->setLibelle('Annecy')
-      ->setAffZone('')
-      ->setVille('Annecy')
-      ->setUrlWeb('http://www.annecy.fr')
-      ->setMail('jp@annecy.com')
-      ->setTelephone('04 50 51 32 12')
-      ->setAdresse('1 rue Jean Jaures')
-      ->setVisibilite(Class_Bib::V_DATA);
-
-    $this->haute_savoie = Class_Zone::getLoader()
-      ->newInstanceWithId(1)
-      ->setCouleurTexte('#059')
-      ->setCouleurOmbre('#234')
-      ->setTailleFonte('14')
-      ->setImage('carte_moulins.jpg')
-      ->setBibs(array($this->bib_annecy));
-
-    $ecrivez_des_tests = Class_Article::getLoader()
-      ->newInstanceWithId(2)
-      ->setIdSite(0)
-      ->setTitre('Ecrivez des tests !')
-      ->setContenu('Ça fera le plus grand bien')
-      ->setCategorie(Class_ArticleCategorie::getLoader()
-                     ->newInstanceWithId(5)
-                     ->setLibelle('Bonnes pratiques'));
+    $_SESSION['selection_bib'] = ['nb_notices' => 12345, 'id_bibs' => null];
+
+
+    $this->bib_annecy = $this->fixture('Class_Bib', ['id' => 4,
+                                                     'id_zone' => 1,
+                                                     'libelle' => 'Annecy',
+                                                     'aff_zone' => '',
+                                                     'ville' => 'Annecy',
+                                                     'url_web' => 'http://www.annecy.fr',
+                                                     'mail' => 'jp@annecy.com',
+                                                     'telephone' => '04 50 51 32 12',
+                                                     'adresse' => '1 rue Jean Jaures',
+                                                     'visibilite' => Class_Bib::V_DATA]);
+
+    $this->bib_nozone = $this->fixture('Class_Bib', ['id' => 22,
+                                                     'id_zone' => 100,
+                                                     'libelle' => 'NoZone',
+                                                     'aff_zone' => '',
+                                                     'ville' => 'No Zone',
+                                                     'url_web' => 'http://www.nozone.fr',
+                                                     'mail' => 'mail@nozone.com',
+                                                     'telephone' => '04 50 51 32 12',
+                                                     'adresse' => '1 rue Jean Jaures',
+                                                     'visibilite' => Class_Bib::V_DATA]);
+
+
+    $this->haute_savoie = $this->fixture('Class_Zone', ['id' => 1,
+                                                        'libelle' => 'moulins',
+                                                        'couleur_texte' => '#059',
+                                                        'couleur_ombre' => '#234',
+                                                        'taille_fonte' => '14',
+                                                        'image' => 'carte_moulins.png',
+                                                        'bibs' => [$this->bib_annecy]]);
+
+    $ecrivez_des_tests = $this->fixture('Class_Article', ['id' => 2,
+                                                          'id_site' => 0,
+                                                          'titre' => 'Ecrivez des tests !',
+                                                          'contenu' => 'Ça fera le plus grand bien',
+                                                          'categorie' => $this->fixture('Class_ArticleCategorie', ['id' => 5,
+                                                                                                                   'libelle' => 'Bonnes pratiques'])]);
 
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Article')
       ->whenCalled('getArticlesByPreferences')
-      ->with(array('id_bib' => '4'))
-      ->answers(array($ecrivez_des_tests))
-
-      ->whenCalled('filterByLocaleAndWorkflow')
-      ->with(array($ecrivez_des_tests))
-      ->answers(array($ecrivez_des_tests));
+      ->with(['id_bib' => '4'])
+      ->answers([$ecrivez_des_tests])
 
+      ->whenCalled('getArticlesByPreferences')
+      ->with(['id_bib' => '22'])
+      ->answers([$ecrivez_des_tests])
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Zone')
-      ->whenCalled('findAll')
-      ->answers(array($this->haute_savoie));
+      ->whenCalled('filterByLocaleAndWorkflow')
+      ->with([$ecrivez_des_tests])
+      ->answers([$ecrivez_des_tests]);
   }
 }
 
@@ -126,6 +139,8 @@ class BibControllerZoneViewOneTest extends BibControllerWithZoneTestCase {
 }
 
 
+
+
 class BibControllerZoneViewOneWithHideNewsTest extends BibControllerWithZoneTestCase {
   public function setUp() {
     parent::setUp();
@@ -278,7 +293,7 @@ class BibControllerMapViewWithoutProfilTest extends BibControllerMapViewTest {
 
 
 
-class BibControllerBibViewAnnecyTest extends BibControllerWithZoneTestCase {
+abstract class BibControllerBibViewTestCase extends BibControllerWithZoneTestCase {
   protected $_mock_sql;
 
   public function setUp() {
@@ -291,11 +306,24 @@ class BibControllerBibViewAnnecyTest extends BibControllerWithZoneTestCase {
       ->whenCalled('countBy')
       ->with(['model' => $this->bib_annecy, 'role' => 'bib'])
       ->answers(20)
+
+      ->whenCalled('countBy')
+      ->with(['model' => $this->bib_nozone, 'role' => 'bib'])
+      ->answers(20)
       ->beStrict();
 
     $this->_mock_sql
       ->whenCalled('fetchOne')
       ->answers('');
+  }
+}
+
+
+
+class BibControllerBibViewAnnecyTest extends BibControllerBibViewTestCase {
+
+  public function setUp() {
+    parent::setUp();
 
     $this->dispatch('bib/bibview/id/4', true);
   }
@@ -318,11 +346,13 @@ class BibControllerBibViewAnnecyTest extends BibControllerWithZoneTestCase {
     $this->assertXPathContentContains('//h2', 'Ecrivez des tests !');
   }
 
+
   /** @test */
   function libelleCatBonnesPratiquesShouldBeVisible() {
     $this->assertXPathContentContains('//h1', 'Bonnes pratiques');
   }
 
+
   /** @test */
   public function urlRetourShouldBeZoneViewIdOne() {
     $this->assertXPathContentContains('//a[contains(@href, "/bib/zoneview/id/1")]',
@@ -331,6 +361,139 @@ class BibControllerBibViewAnnecyTest extends BibControllerWithZoneTestCase {
 }
 
 
+
+class BibControllerBackUrlTest extends BibControllerBibViewTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $_SERVER['HTTP_REFERER'] = '/link/to/referer';
+  }
+
+
+  /** @test */
+  public function backUrlShouldBeZoneView() {
+    $this->dispatch('bib/bibview/id/4', true);
+    $this->assertXPathContentContains('//div[@class="back_link"]/a[contains(@href, "zoneview/id/1")]', 'Retour');
+  }
+
+
+  /** @test */
+  public function backUrlShouldBeReferer() {
+    $this->dispatch('bib/bibview/id/22', true);
+    $this->assertXPathContentContains('//div[@class="back_link"]/a[contains(@href, "/link/to/referer")]', 'Retour');
+  }
+
+}
+
+
+
+class BibControllerTextCustomFieldsTest extends BibControllerBibViewTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    $meta = $this->fixture('Class_CustomField_Meta',
+                   ['id' => 3,
+                    'label' => 'Lieu',
+                    'field_type' => Class_CustomField_Meta::TEXT_INPUT,
+                    'indexable' => 1]);
+
+
+    $this->custom_field = $this->fixture('Class_CustomField',
+                                          ['id' => 5,
+                                           'priority' => 3,
+                                           'meta_id' => 3,
+                                           'model' => 'Bib']);
+  }
+
+
+  /** @test */
+  public function customFieldLieuShouldBeDisplayed() {
+    $this->bib_annecy->setCustomField('Lieu', 'Far Far Away');
+    $this->bib_annecy->saveWithCustomFields();
+    $this->dispatch('bib/bibview/id/4', true);
+    $this->assertXPathContentContains("//table//td", "Lieu :", $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function customFieldValueShouldBeFarFarAway() {
+    $this->bib_annecy->setCustomField('Lieu', 'Far Far Away');
+    $this->bib_annecy->saveWithCustomFields();
+    $this->dispatch('bib/bibview/id/4', true);
+    $this->assertXPathContentContains("//table//td", "Far Far Away", $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function customFieldLieuShouldNotBeDisplayed() {
+    $this->bib_annecy->setCustomField('Lieu', '');
+    $this->bib_annecy->saveWithCustomFields();
+    $this->dispatch('bib/bibview/id/4', true);
+    $this->assertNotXPathContentContains("//table//td", "Lieu :", $this->_response->getBody());
+  }
+}
+
+
+
+
+class BibControllerMultiCheckBoxCustomFieldsTest extends BibControllerBibViewTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    $meta = $this->fixture('Class_CustomField_Meta',
+                   ['id' => 22,
+                    'label' => 'Services',
+                    'options_list' => 'Wifi;Projection;Restauration',
+                    'field_type' => Class_CustomField_Meta::MULTI_CHECKBOX,
+                    'indexable' => 1]);
+
+
+    $this->custom_field = $this->fixture('Class_CustomField',
+                                          ['id' => 12,
+                                           'priority' => 3,
+                                           'meta_id' => 22,
+                                           'model' => 'Bib']);
+
+    $this->bib_annecy->setCustomField('Services', ['Wifi', 'Restauration']);
+    $this->bib_annecy->saveWithCustomFields();
+    $this->dispatch('bib/bibview/id/4', true);
+
+  }
+
+
+  /** @test */
+  public function customFieldLieuShouldBeDisplayed() {
+    $this->assertXPathContentContains("//table//td", "Services :");
+  }
+
+
+  /** @test */
+  public function servicesShouldContainsWifi() {
+    $this->assertXPathContentContains('//table//td', 'Wifi');
+  }
+
+
+  /** @test */
+  public function servicesShouldContainsRestauration() {
+    $this->assertXPathContentContains('//table//td', 'Restauration');
+  }
+
+
+  /** @test */
+  public function servicesShouldNotContainsProjection() {
+    $this->assertNotXPathContentContains('//table//td', 'Projection');
+  }
+
+
+  /** @test */
+  public function servicesShouldNotContainsSeparator() {
+    $this->assertNotXPathContentContains('//table//td', 'Wifi;Restauration');
+  }
+}
+
+
+
 class BibControllerBibViewAnnecyWithParamRetourHistoriqueTest extends BibControllerWithZoneTestCase {
   /** @test */
   public function withUrlRetourCmsArticleViewFiveShouldBeAccepted() {
diff --git a/tests/library/ZendAfi/View/Helper/BibViewTest.php b/tests/library/ZendAfi/View/Helper/BibViewTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..21e7276add4311ccb0096bc5b31f595c39158ac9
--- /dev/null
+++ b/tests/library/ZendAfi/View/Helper/BibViewTest.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 BibViewTest extends ViewHelpertestCase {
+  protected
+    $_storm_default_to_volatile = true;
+
+  public function setup() {
+    parent::setup();
+
+    $this->bib_annecy = $this->fixture('Class_Bib', ['id' => 4,
+                                                     'id_zone' => 1,
+                                                     'libelle' => 'Annecy',
+                                                     'aff_zone' => '',
+                                                     'ville' => 'Annecy',
+                                                     'url_web' => 'http://www.annecy.fr',
+                                                     'mail' => 'jp@annecy.com',
+                                                     'telephone' => '04 50 51 32 12',
+                                                     'adresse' => '1 rue Jean Jaures',
+                                                     'visibilite' => Class_Bib::V_DATA]);
+
+
+    $helper = new ZendAfi_View_Helper_BibView();
+    $helper->setView(new ZendAfi_Controller_Action_Helper_View());
+
+    $this->html = $helper->bibView(Class_Bib::find(4), '/back');
+  }
+
+
+  /** @test */
+  public function adressShouldBeDisplayed() {
+    $this->assertXPathContentContains($this->html, '//tr[2]//h2', '1 rue Jean Jaures');
+    $this->assertXPathContentContains($this->html, '//tr[2]//h2', 'Annecy');
+  }
+
+
+  /** @test */
+  public function telephoneShouldBeDisplayed() {
+    $this->assertXPathContentContains($this->html, '//tr[3]//h2', '04 50 51 32 12');
+  }
+
+
+  /** @test */
+  public function mailShouldBeDisplayed() {
+    $this->assertXPathContentContains($this->html, '//tr[4]//h2/a[contains(@href, "mailto:jp@annecy.com")]', 'jp@annecy.com');
+  }
+
+
+  /** @test */
+  public function backLinkShouldBeDisplayed() {
+    $this->assertXPathContentContains($this->html, '//div/a[contains(@href, "/back")]', 'Retour');
+  }
+}
+?>
\ No newline at end of file