Index: /extensions/GrumPluginClasses/language/fr_FR/rbuilder.lang.php
===================================================================
--- /extensions/GrumPluginClasses/language/fr_FR/rbuilder.lang.php	(revision 6174)
+++ /extensions/GrumPluginClasses/language/fr_FR/rbuilder.lang.php	(revision 6174)
@@ -0,0 +1,13 @@
+<?php
+
+$lang['gpc_rb_search_criterion']='Critères de recherche';
+$lang['gpc_rb_do_modify_request']='Modifier la recherche';
+$lang['gpc_rb_result_query']='Résultat de la recherche';
+$lang['gpc_rb_number_of_item_found']='Nombre d\'images trouvées';
+$lang['gpc_rb_add_criterions']='Critères';
+$lang['gpc_rb_clear_criterions']='Réinitialiser les critères';
+$lang['gpc_rb_search']='Rechercher';
+$lang['gpc_rb_textAND']='Tous les critères doivent être vérifiés';
+$lang['gpc_rb_textOR']='Au moins un critère doit être vérifié';
+
+?>
Index: /extensions/GrumPluginClasses/css/rbuilder.css
===================================================================
--- /extensions/GrumPluginClasses/css/rbuilder.css	(revision 6106)
+++ /extensions/GrumPluginClasses/css/rbuilder.css	(revision 6174)
@@ -19,2 +19,95 @@
   margin-left:0px;
 }
+
+.cPnActive, .cPnDisabled, .cPnInactive { margin:2px; padding:2px;  min-width:20px; text-align:center; }
+.pnInactiveclear, .pnInactiveroma { cursor:pointer; }
+.pnInactiveclear:hover { background:#F1F1F1; }
+.pnActiveclear { background:#F1F1F1; font-weight:bold; }
+.pnInactiveroma:hover { background:#999999; color:#444444; }
+.pnActiveroma { background:#999999; color:#444444; font-weight:bold; }
+#iPagesNavigator ul { margin:0px; }
+
+
+.cbGroup { border-width:1px; border-style:solid; padding:0px; margin:2px; min-height:30px; list-style:none; }
+.cbItem {   padding:2px; margin:8px; min-height:34px; list-style:none; }
+
+#iListSelectedCriterions { padding:0px; }
+
+#dragHelper ul li.cbItem { padding:2px; }
+#dragHelper ul li {
+  clear:both;
+  min-height:32px;
+  list-style-image:none;
+  list-style-position:outside;
+  list-style-type:none;
+  margin:4px;
+  padding:0px;
+}
+
+.cbItemButtons { padding:2px; }
+.cbItem img { cursor: pointer; }
+
+.cbSortHandle { cursor:move; }
+
+
+.helper {
+ border:2px dashed #777777;
+}
+
+div.cbOperator {
+ cursor:pointer;
+ padding:4px;
+ text-align:left;
+ font-weight:bold;
+}
+
+div.cbOperatorBgroma {
+ background:#333333;
+}
+
+div.cbOperatorBgclear {
+ background:#dbe8f3;
+}
+
+.cbButtons {
+  float:left;
+  margin:2px;
+  padding:8px;
+  height:15px;
+}
+
+
+div#iMenuCriterions div#iMenuCItems {
+  display:none;
+  list-style-type:none;
+  max-height:30px;
+  position:absolute;
+  padding:0px;
+  margin:36px 2px 2px;
+}
+
+
+div#iMenuCriterions ul {
+  padding:2px;
+}
+
+div#iMenuCriterions ul li {
+  list-style-type:none;
+  padding:4px;
+}
+
+div#iMenuCriterions:hover  div#iMenuCItems
+{
+  cursor:pointer;
+  display:block;
+}
+
+div#iMenuCriterions:hover div#iMenuCTitle
+{
+  margin-bottom:0px;
+  padding-bottom:11px;
+}
+
+div#iMenuCriterions div#iMenuCTitle
+{
+  margin-bottom:3px;
Index: /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php	(revision 6106)
+++ /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php	(revision 6174)
@@ -100,4 +100,49 @@
 
 
+  /**
+   * this function is called by the request builder to make the search page, and
+   * must return the HTML & JS code of the dialogbox used to select criterion
+   *
+   * Notes :
+   *  - the dialogbox is a JS object with a public method 'show'
+   *  - when the method show is called, one parameter is given by the request
+   *    builder ; the parameter is an object defined as this :
+   *      {
+   *        cBuilder: an instance of the criteriaBuilder object used in the page,
+   *      }
+   *
+   *
+   *
+   *
+   * @param String $mode : can take 'admin' or 'public' values, allowing to
+   *                       return different interface if needed
+   * @return String : HTML formatted value
+   */
+  static public function getInterfaceContent($mode='admin')
+  {
+    return("");
+  }
+
+  /**
+   * this function returns the label displayed in the criterion menu
+   *
+   * @return String : label displayed in the criterions menu
+   */
+  static public function getInterfaceLabel()
+  {
+    return(l10n('gpc_rb_unknown_interface'));
+  }
+
+  /**
+   * this function returns the name of the dialog box class
+   *
+   * @return String : name of the dialogbox class
+   */
+  static public function getInterfaceDBClass()
+  {
+    return('');
+  }
+
+
 }
 
@@ -119,5 +164,5 @@
    * @return Boolean : true if registering is Ok, otherwise false
    */
-  static public function register($pluginName, $fileName)
+  static public function register($pluginName, $fileName, $dialogBoxObject)
   {
     $config=Array();
@@ -127,4 +172,5 @@
         'name' => $pluginName,
         'fileName' => $fileName,
+        'dialogBox' => $dialogBoxObject,
         'date' => date("Y-m-d H:i:s"),
         'version' => self::$version,
@@ -880,4 +926,47 @@
 
 
+
+  /**
+   * display search page
+   */
+  static public function displaySearchPage()
+  {
+    global $template, $lang;
+
+    load_language('rbuilder.lang', GPC_PATH);
+
+    $template->set_filename('gpc_search_page',
+                dirname(dirname(__FILE__)).'/templates/GPCRequestBuilder_search.tpl');
+
+    $registeredPlugin=self::getRegistered();
+    $dialogBox=Array();
+    foreach($registeredPlugin as $key=>$val)
+    {
+      if(array_key_exists($key, $registeredPlugin))
+      {
+        if(file_exists($registeredPlugin[$key]['fileName']))
+        {
+          include_once($registeredPlugin[$key]['fileName']);
+
+          $dialogBox[]=Array(
+            'handle' => $val['name'].'DB',
+            'dialogBoxClass' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceDBClass')),
+            'label' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceLabel')),
+            'content' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceContent')),
+          );
+        }
+      }
+    }
+
+    $datas=Array(
+      'dialogBox' => $dialogBox,
+      'themeName' => $template->get_themeconf('name'),
+    );
+
+    $template->assign('datas', $datas);
+
+    return($template->parse('gpc_search_page', true));
+  } //displaySearchPage
+
 }
 
Index: /extensions/GrumPluginClasses/classes/GPCTabSheet.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCTabSheet.class.inc.php	(revision 5918)
+++ /extensions/GrumPluginClasses/classes/GPCTabSheet.class.inc.php	(revision 6174)
@@ -62,4 +62,14 @@
   }
 
+
+  function add($name, $caption, $url, $selected = false, $onClick='')
+  {
+    if(parent::add($name,$caption,$url,$selected))
+    {
+      $this->sheets[$name]['onClick'] = $onClick;
+      return(true);
+    }
+    return(false);
+  }
 
   public function setClasses($classes)
Index: /extensions/GrumPluginClasses/templates/GPCTabSheet.tpl
===================================================================
--- /extensions/GrumPluginClasses/templates/GPCTabSheet.tpl	(revision 5918)
+++ /extensions/GrumPluginClasses/templates/GPCTabSheet.tpl	(revision 6174)
@@ -1,9 +1,25 @@
 {if isset($tabsheet) and count($tabsheet)}
 <ul {if isset($tabsheet_classes)}class="{$tabsheet_classes}"{/if} {if isset($tabsheet_id)}id="{$tabsheet_id}"{/if} >
-{foreach from=$tabsheet key=name item=sheet}
-  <li class="{if ($name == $tabsheet_selected)}selected_tab{else}normal_tab{/if}">
-    <a href="{$sheet.url}"><span>{$sheet.caption}</span></a>
+{foreach from=$tabsheet key=name item=sheet name=tabs}
+  <li {if isset($tabsheet_id)}id="{$tabsheet_id}{$smarty.foreach.tabs.index}"{/if} class="{if ($name == $tabsheet_selected)}selected_tab{else}normal_tab{/if}">
+    <a {if $sheet.url!=''}href="{$sheet.url}"{/if} {if $sheet.onClick!=''}onclick="{$sheet.onClick}"{/if} ><span>{$sheet.caption}</span></a>
   </li>
 {/foreach}
 </ul>
+
+  {if isset($tabsheet_id)}
+  {literal}
+  <script type="text/javascript">
+    $('#{/literal}{$tabsheet_id}{literal} li').bind('click',
+      function ()
+      {
+        $('#{/literal}{$tabsheet_id}{literal} li').removeClass('selected_tab').addClass('normal_tab');
+        $(this).removeClass('normal_tab').addClass('selected_tab');
+      }
+    );
+  {/literal}
+  </script>
+
+  {/if}
+
 {/if}
Index: /extensions/GrumPluginClasses/templates/GPCRequestBuilder_search.tpl
===================================================================
--- /extensions/GrumPluginClasses/templates/GPCRequestBuilder_search.tpl	(revision 6174)
+++ /extensions/GrumPluginClasses/templates/GPCRequestBuilder_search.tpl	(revision 6174)
@@ -0,0 +1,298 @@
+{known_script id="jquery.ui" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.core.packed.js"}
+{known_script id="jquery.ui.dialog" src=$ROOT_URL|@cat:"themes/default/js/ui/packed/ui.dialog.packed.js"}
+{known_script id="jquery.tipTip" src=$ROOT_URL|@cat:"themes/default/js/plugins/jquery.tipTip.minified.js"}
+
+{known_script id="gpc.pagesNavigator" src=$ROOT_URL|@cat:"plugins/GrumPluginClasses/js/pagesNavigator.js"}
+
+
+{literal}
+<script type="text/javascript">
+var cb=null;
+
+  interfaceManager = function(optionsToSet)
+  {
+    var pn=null;
+    var requestNumber=0;
+
+    options =
+      {
+        requestCriterionsVisible:'',
+        requestCriterionsHidden:'',
+        requestResult:'',
+        requestResultContent:'',
+        requestResultNfo:'',
+        requestResultPagesNavigator:'',
+        requestResultRequestNumber:0,
+        onPageChange:null,
+        numberPerPage:30,
+      };
+
+    /**
+     *
+     */
+    this.doAction = function(fct)
+    {
+      switch(fct)
+      {
+        case 'queryResult':
+          /* function 'queryResult' : when query is executed, prepare the interface
+           */
+          if(arguments.length==3)
+          {
+            displayQueryResult(arguments[1], arguments[2]);
+          }
+          break;
+        case 'queryPage':
+          /* function 'queryPage' : display returned page
+           */
+          if(arguments.length==3)
+          {
+            displayQueryPage(arguments[1], arguments[2]);
+          }
+          break;
+        case 'show':
+          /* function 'show' : show/hide the query/result
+           */
+          if(arguments.length==2)
+          {
+            show(arguments[1]);
+          }
+          break;
+        case 'setOptions':
+          /* function 'setOptions' : allows to set options after the object was
+           *                         created
+           */
+          if(arguments.length==2)
+          {
+            setOptions(arguments[1]);
+          }
+          break;
+      }
+    }
+
+    /**
+     * returns the current request number
+     */
+    this.getRequestNumber = function ()
+    {
+      return(requestNumber);
+    }
+
+    /**
+     * returns the number of items per page
+     */
+    this.getNumberPerPage = function ()
+    {
+      return(options.numberPerPage);
+    }
+
+    /**
+     * this function show/hide the different panels
+     *  'buildQuery'  : hide the result panel and display the panel to build query
+     *  'resultQuery' : hide the panel to build query and display the result panel
+     */
+    var show = function(mode)
+    {
+      switch(mode)
+      {
+        case 'buildQuery':
+          $('.'+options.requestCriterionsVisible).css('display', 'block');
+          $('.'+options.requestCriterionsHidden).css('display', 'none');
+          $('.'+options.requestResult).css('display', 'none');
+          break;
+        case 'resultQuery':
+          $('#iResultQueryContent').html("<br><img src='./plugins/GrumPluginClasses/icons/processing.gif'>");
+          $('.'+options.requestCriterionsVisible).css('display', 'none');
+          $('.'+options.requestCriterionsHidden).css('display', 'block');
+          $('.'+options.requestResult).css('display', 'block');
+          break;
+      }
+    }
+
+    /**
+     * this function display the number of items found and prepare the page
+     * navigator
+     *
+     * @param String nfo : 2 information separated with a semi-colon ';'
+     *                      requestNumber;numberOfItems
+     */
+    var displayQueryResult = function (isSuccess, nfo)
+    {
+      if(isSuccess)
+      {
+        nfo=nfo.split(';');
+
+        requestNumber=nfo[0];
+        $('#iResultQueryNfo').html(nfo[1]);
+        pn.doAction('setOptions', { numberItem:nfo[1], defaultPage:1 } );
+        show('resultQuery');
+      }
+      else
+      {
+        //$('#'+options.requestResultContent).html("");
+        show('buildQuery');
+        alert('Something is wrong on the server-side !');
+      }
+    }
+
+
+    /**
+     * this function display the number of items found and prepare the page
+     * navigator
+     *
+     * @param String nfo : 2 information separated with a semi-colon ';'
+     *                      requestNumber;numberOfItems
+     */
+    var displayQueryPage = function (isSuccess, nfo)
+    {
+      if(isSuccess)
+      {
+        $('#iResultQueryContent').html(nfo);
+      }
+      else
+      {
+        alert('Something is wrong on the server-side !');
+      }
+    }
+
+
+    /**
+     *
+     * @param Object optionsToSet : set the given options
+     */
+    var setOptions = function(optionsToSet)
+    {
+      if(typeof optionsToSet=='object')
+      {
+        options = jQuery.extend(options, optionsToSet);
+      }
+    }
+
+    /**
+     * initialize the object
+     */
+    var init = function (optionsToSet)
+    {
+      setOptions(optionsToSet);
+
+      pn = new pagesNavigator(options.requestResultPagesNavigator,
+        {
+          itemPerPage:options.numberPerPage,
+          displayNumPage:9,
+          classActive:'pnActive{/literal}{$datas.themeName}{literal}',
+          classInactive:'pnInactive{/literal}{$datas.themeName}{literal}',
+          onPageChange: function (page)
+            {
+              if(options.onPageChange!=null && jQuery.isFunction(options.onPageChange))
+              {
+                options.onPageChange(requestNumber, page, options.numberPerPage);
+              }
+            },
+        }
+      );
+
+      requestNumber=options.requestResultRequestNumber;
+    }
+
+    init(optionsToSet);
+  }
+
+
+  function init()
+  {
+    im = new interfaceManager(
+      {
+        requestCriterionsVisible:'cRequestCriterions',
+        requestCriterionsHidden:'cModifyRequest',
+        requestResult:'cResultQuery',
+        requestResultContent:'iResultQueryContent',
+        requestResultNfo:'iResultQueryNfo',
+        requestResultPagesNavigator:'iPagesNavigator',
+      }
+    );
+
+    requestBuilderOptions.imgEditUrl='{/literal}{$ROOT_URL}{$themeconf.admin_icon_dir}{literal}/edit_s.png';
+    requestBuilderOptions.imgDeleteUrl='{/literal}{$ROOT_URL}{$themeconf.admin_icon_dir}{literal}/delete.png';
+    requestBuilderOptions.classGroup='gcBorderInput gcTextInput';
+    requestBuilderOptions.classItem='gcBgInput gcTextInput';
+    requestBuilderOptions.classOperator='cbOperator cbOperatorBg{/literal}{$datas.themeName}{literal} gcLinkHover';
+    requestBuilderOptions.onRequestSuccess = function (msg) { im.doAction('queryResult', true, msg); cb.doAction('getPage', im.getRequestNumber(), 1, im.getNumberPerPage()); };
+    requestBuilderOptions.onRequestError = function (msg) { im.doAction('queryResult', false, msg); };
+    requestBuilderOptions.onGetPageSuccess = function (msg) { im.doAction('queryPage', true, msg); };
+    requestBuilderOptions.onGetPageError = function (msg) { im.doAction('queryPage', false, msg); };
+
+    cb = new criteriaBuilder('iListSelectedCriterions', requestBuilderOptions);
+
+    im.doAction('setOptions',
+      {
+        onPageChange:
+          function (requestNumber, page, numberPerPage)
+          {
+            $('#iResultQueryContent').html("<br><img src='./plugins/GrumPluginClasses/icons/processing.gif'>");
+            cb.doAction('getPage', requestNumber, page, numberPerPage);
+          }
+      }
+    );
+  }
+
+
+
+</script>
+{/literal}
+
+{foreach from=$datas.dialogBox item=dialogBox}
+  {$dialogBox.content}
+{/foreach}
+
+<form>
+  <fieldset>
+    <legend>{'gpc_rb_search_criterion'|@translate}</legend>
+
+    <div id='iRequestCriterions' class='cRequestCriterions'>
+      <div style='width:100%;min-height:250px;margin-bottom:8px;'>
+        <ul id='iListSelectedCriterions'>
+        </ul>
+      </div>
+
+      <div id='iMenuCriterions' >
+        <div id='iMenuCTitle' class='gcLink gcBgInput cbButtons'>{'gpc_rb_add_criterions'|@translate}</div>
+        <div id='iMenuCItems'>
+          <ul class='gcBgInput'>
+            {foreach from=$datas.dialogBox item=dialogBox}
+              <li class='gcBgInput'><a onclick="{$dialogBox.handle}.show({literal}{cBuilder:cb}{/literal});">{$dialogBox.label}</a></li>
+            {/foreach}
+          </ul>
+        </div>
+      </div>
+
+      <div class='gcBgInput cbButtons'>{literal}<a onclick="cb.doAction('clear');">{/literal}{'gpc_rb_clear_criterions'|@translate}</a></div>
+    </div>
+    <div class='cModifyRequest' style='display:none;'>
+      <div class='gcBgInput cbButtons'>{literal}<a onclick="im.doAction('show', 'buildQuery');">{/literal}{'gpc_rb_do_modify_request'|@translate}</a></div>
+    </div>
+
+  </fieldset>
+
+  <input type="button" class='cRequestCriterions' style="margin-left:1em;" onclick="cb.doAction('send');" value="{'gpc_rb_search'|@translate}">
+</form>
+
+  <fieldset id='iResultQuery' style='display:none;' class='cResultQuery'>
+    <legend>{'gpc_rb_result_query'|@translate}</legend>
+
+    <div id='iResultQueryContent' style='width:100%;min-height:250px;max-height:450px;overflow:auto;margin-bottom:8px;'></div>
+
+    <div class='gcBgInput gcTextInput'>
+      <div id='iPagesNavigator' style='float:right;'></div>
+      <div style='text-align:left;padding:4px;'>{'gpc_rb_number_of_item_found'|@translate}&nbsp;:&nbsp;<span id='iResultQueryNfo'></span></div>
+    </div>
+
+  </fieldset>
+
+
+<script type="text/javascript">
+  {foreach from=$datas.dialogBox item=dialogBox}
+  var {$dialogBox.handle}=new {$dialogBox.dialogBoxClass}();
+  {/foreach}
+
+  init();
+</script>
