diff --git a/application/modules/admin/controllers/UsersController.php b/application/modules/admin/controllers/UsersController.php
index 8632b41cf19098c6d792d6251201d993966f2fee..ab5107f3e711a95ad95f076a4de36cdd5b41e9f4 100644
--- a/application/modules/admin/controllers/UsersController.php
+++ b/application/modules/admin/controllers/UsersController.php
@@ -100,10 +100,7 @@ class Admin_UsersController extends ZendAfi_Controller_Action {
 
     $done = $total - $db_double_finder->countDouble();
 
-    return $this->_helper->json(['total' => $total,
-                                 'done' => $done,
-                                 'cursor' => $new_cursor,
-                                 'run' => $continue]);
+    return $this->_helper->progressbar($total, $done, $new_cursor, $continue);
   }
 
 
diff --git a/application/modules/admin/views/scripts/users/manage-double.phtml b/application/modules/admin/views/scripts/users/manage-double.phtml
index 60f031b2d21f6c28cf2422fec00aa61ae65b7df8..1f238cbf74bcac64c9ceed4e36f9333cb8238ba1 100644
--- a/application/modules/admin/views/scripts/users/manage-double.phtml
+++ b/application/modules/admin/views/scripts/users/manage-double.phtml
@@ -16,19 +16,10 @@ echo $this->button((new Class_Entity())
                                             ['style' => 'filter: invert();']))
                    ->setText($this->_('Retour à la gestion des utilisateurs')));
 
-echo $this->button((new Class_Entity())
-                   ->setAttribs([
-  'id' => 'dedupe-users-button',
-  'onclick' => sprintf('dedupeUsers(\'%s\', %d);',
-                       Class_Url::relative('/admin/users/delete-double'),
-                       $this->double_manager->countDouble())])
-                   ->setImage($this->tagImg(Class_Admin_Skin::current()
-                                        ->getIconUrl('actions',
-                                                     'test'),
-                                            ['style' => 'filter: invert();']))
-
-                   ->setText($this->_('Lancer le dédoublonnage automatique')
-                             . $this->tag('span', '')));
+echo $this->button((new Class_ButtonDescription())
+                   ->beProgressbar($this, Class_Url::relative('/admin/users/delete-double'),
+                                   $this->double_manager->countDouble(),
+                                   $this->_('Lancer le dédoublonnage automatique')));
 
 
 echo $this->button((new Class_Entity())
diff --git a/library/Class/ButtonDescription.php b/library/Class/ButtonDescription.php
new file mode 100644
index 0000000000000000000000000000000000000000..c55089245620a6a5ece5d93cc4b541b3910a7faf
--- /dev/null
+++ b/library/Class/ButtonDescription.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, 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 Class_ButtonDescription extends Class_Entity {
+  public function beProgressbar($view, $url, $total, $text) {
+
+    Class_ScriptLoader::getInstance()->addAdminScript('progressbar.js');
+    $id = md5(implode(',',$this->_attribs));
+    $this->setAttribs([
+                       'id' => $id,
+                       'onclick' => sprintf('progressbar(\'%s\',\'%s\', %d);',
+                                            $id, $url,$total)
+                       ])
+         ->setImage($view->tagImg(Class_Admin_Skin::current()
+                                  ->getIconUrl('actions',
+                                               'test'),
+                                  ['style' => 'filter: invert();']))
+         ->setText($text.$view->tag('span', ''));
+    return $this;
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/Controller/Action/Helper/Progressbar.php b/library/ZendAfi/Controller/Action/Helper/Progressbar.php
new file mode 100644
index 0000000000000000000000000000000000000000..df7391cc8f97f5869cd47d4323cae4d87ef28bd4
--- /dev/null
+++ b/library/ZendAfi/Controller/Action/Helper/Progressbar.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, 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_Action_Helper_Progressbar extends Zend_Controller_Action_Helper_Abstract {
+  public function progressbar($total, $done, $cursor, $run) {
+    $this->getActionController()
+         ->getHelper('json')
+         ->direct( ['total' => $total,
+                    'done' => $done,
+                    'cursor' => $cursor,
+                    'run' => $run]);
+
+  }
+
+
+  public function direct($total, $done, $cursor, $run) {
+    return $this->progressbar($total, $done, $cursor, $run);
+  }
+}
diff --git a/library/ZendAfi/View/Helper/Admin/Button.php b/library/ZendAfi/View/Helper/Admin/Button.php
index 36a1f80ce700e3ad56c2f9d7132d7d192fb46aec..0724251acc6db3a3dc7e6cad8d1c93859510cde2 100644
--- a/library/ZendAfi/View/Helper/Admin/Button.php
+++ b/library/ZendAfi/View/Helper/Admin/Button.php
@@ -71,4 +71,5 @@ class ZendAfi_View_Helper_Admin_Button extends ZendAfi_View_Helper_Button {
 
     return $button->getElement();
   }
+
 }
\ No newline at end of file
diff --git a/public/admin/js/onload_utils.js b/public/admin/js/onload_utils.js
index a3de1bfb84a8c3ff60cab76f89e301be68644838..d11eacdfc50612ff8f94b153ffe14b80afc66aea 100644
--- a/public/admin/js/onload_utils.js
+++ b/public/admin/js/onload_utils.js
@@ -152,33 +152,3 @@ var updateSelectWidget = function(element) {
 }
 
 
-var dedupeUsers = function(url, total, cursor = 0) {
-  var run;
-  
-  $.ajax({
-    type: 'GET',
-    url: url,
-    data: {'total': total,
-	   'cursor': cursor},
-    success: function(data)
-    {
-      var percent = data.done * 100 / total;
-      var new_cursor = data.cursor;
-      run = data.run;
-      percent = percent ? percent : 1;
-      $("#dedupe-users-button span")
-	.progressbar({value: percent});
-
-      if(run)
-	dedupeUsers(url, total, new_cursor);
-
-    },
-    complete: function(event, ui) {
-      if(run)
-	return;
-      $("#dedupe-users-button span")
-	.progressbar({value: 100});
-
-	location.reload();      
-    }});
-}
diff --git a/public/admin/js/progressbar.js b/public/admin/js/progressbar.js
new file mode 100644
index 0000000000000000000000000000000000000000..da9f9b1f2ead58adbfedec0c0d135e14876ecc86
--- /dev/null
+++ b/public/admin/js/progressbar.js
@@ -0,0 +1,28 @@
+var progressbar = function(id, url, total, cursor = 0) {
+  var run;
+  var tag = $("#" + id + " span");
+  $.ajax({
+    type: 'GET',
+    url: url,
+    data: {'total': total,
+	   'cursor': cursor},
+    success: function(data)
+    {
+      var percent = data.done * 100 / total;
+      var new_cursor = data.cursor;
+      run = data.run;
+      percent = percent ? percent : 1;
+      tag.progressbar({value: percent});
+
+      if(run)
+	progressbar(id, url, total, new_cursor);
+
+    },
+    complete: function(event, ui) {
+      if(run)
+	return;
+      tag.progressbar({value: 100});
+
+	location.reload();      
+    }});
+}