Index: tests/functional/fixtures/form_media_disabled.html
===================================================================
--- tests/functional/fixtures/form_media_disabled.html	(revision 1724)
+++ tests/functional/fixtures/form_media_disabled.html	(revision 1724)
@@ -0,0 +1,37 @@
+<div>
+  <h4>Add files</h4>
+
+  <form id="fileupload" action="media.php?popup=0&amp;post_id=" method="post" enctype="multipart/form-data" aria-disabled="false">
+    <p>
+      <input type="hidden" name="MAX_FILE_SIZE" value="2097152"  />
+      <input type="hidden" name="xd_check" value="7a87b8c0d60e38a05b1b8cf524d08a5594222763"  />
+    </p>
+    <div class="fileupload-ctrl">
+      <p class="queue-message"></p>
+      <ul class="files"></ul>
+    </div>
+    <div class="fileupload-buttonbar clear">
+      <p>
+	<label for="upfile"><span class="add-label one-file">Choose file</span></label>
+	<button class="button add">Choose files</button>
+	<input type="file" id="upfile" name="upfile[]" data-url="media.php?popup=0&amp;post_id=" />
+      </p>
+      <p class="one-file">
+	<label for="upfiletitle">Title:</label>
+	<input type="text" size="35" name="upfiletitle" id="upfiletitle" maxlength="255"  />
+      </p>
+      <p class="one-file">
+	<label for="upfilepriv" class="classic">Private</label>
+	<input type="checkbox" name="upfilepriv" value="1" id="upfilepriv"  />
+      </p>
+      <p class="clear">
+	<button class="button clean">Refresh</button>
+	<input class="button cancel one-file" type="reset" value="Clear All"/>
+	<input class="button start" type="submit" value="Upload"/>
+      </p>
+    </div>
+    <p style="clear:both;">
+      <input type="hidden" name="d" value="."  />
+    </p>
+  </form>
+</div>
Index: tests/functional/fixtures/form_media_enabled.html
===================================================================
--- tests/functional/fixtures/form_media_enabled.html	(revision 1724)
+++ tests/functional/fixtures/form_media_enabled.html	(revision 1724)
@@ -0,0 +1,37 @@
+<div class="enhanced_uploader">
+  <h4>Add files</h4>
+
+  <form id="fileupload" action="media.php?popup=0&amp;post_id=" method="post" enctype="multipart/form-data" aria-disabled="false">
+    <p>
+      <input type="hidden" name="MAX_FILE_SIZE" value="2097152"  />
+      <input type="hidden" name="xd_check" value="7a87b8c0d60e38a05b1b8cf524d08a5594222763"  />
+    </p>
+    <div class="fileupload-ctrl">
+      <p class="queue-message"></p>
+      <ul class="files"></ul>
+    </div>
+    <div class="fileupload-buttonbar clear">
+      <p>
+	<label for="upfile"><span class="add-label one-file">Choose file</span></label>
+	<button class="button add">Choose files</button>
+	<input type="file" id="upfile" name="upfile[]" multiple="mutiple" data-url="media.php?popup=0&amp;post_id=" />
+      </p>
+      <p class="one-file">
+	<label for="upfiletitle">Title:</label>
+	<input type="text" size="35" name="upfiletitle" id="upfiletitle" maxlength="255"  />
+      </p>
+      <p class="one-file">
+	<label for="upfilepriv" class="classic">Private</label>
+	<input type="checkbox" name="upfilepriv" value="1" id="upfilepriv"  />
+      </p>
+      <p class="clear">
+	<button class="button clean">Refresh</button>
+	<input class="button cancel one-file" type="reset" value="Clear All"/>
+	<input class="button start" type="submit" value="Upload"/>
+      </p>
+    </div>
+    <p style="clear:both;">
+      <input type="hidden" name="d" value="."  />
+    </p>
+  </form>
+</div>
Index: tests/functional/index.html
===================================================================
--- tests/functional/index.html	(revision 1703)
+++ tests/functional/index.html	(revision 1724)
@@ -7,5 +7,6 @@
     <script type="text/javascript" src="lib/jasmine.js"></script>
     <script type="text/javascript" src="lib/jasmine-html.js"></script>
-    <script type="text/javascript" src="lib/jquery.js"></script>
+    <!-- use same jquery -->
+    <script type="text/javascript" src="../../admin/js/jquery/jquery.js"></script>
     <script type="text/javascript" src="lib/jasmine-jquery.js"></script>
     <script type="text/javascript" src="lib/jasmine-jquery-bootstrap.js"></script>
@@ -13,10 +14,24 @@
     <script type="text/javascript" src="../../admin/js/_users_actions.js"></script>
     <script type="text/javascript" src="../../admin/js/common.js"></script>
+
     <script type="text/javascript" src="js/fix_include.js"></script>
 
-    <script type="text/javascript" src="spec/users_actions.js"></script>
+    <!-- jsUpload -->
+    <script type="text/javascript" src="../../admin/js/jsUpload/vendor/jquery.ui.widget.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/tmpl.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/template-upload.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/template-download.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/load-image.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/jquery.iframe-transport.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/jquery.fileupload.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/jquery.fileupload-process.js"></script>
+    <script type="text/javascript" src="../../admin/js/jsUpload/jquery.fileupload-resize.js"></script> 
+    <script type="text/javascript" src="../../admin/js/jsUpload/jquery.fileupload-ui.js"></script>
+    <script type="text/javascript" src="../../admin/js/_media.js"></script>    
+
+    <!-- <script type="text/javascript" src="spec/users_actions.js"></script> -->
     <script type="text/javascript" src="spec/toggle_with_legend.js"></script>
-
     <script type="text/javascript" src="spec/common.js"></script>
+    <script type="text/javascript" src="spec/media_manager.js"></script>
   </head>
   <body>
Index: tests/functional/js/fix_include.js
===================================================================
--- tests/functional/js/fix_include.js	(revision 1703)
+++ tests/functional/js/fix_include.js	(revision 1724)
@@ -10,2 +10,12 @@
 dotclear.msg.confirm_delete_posts = 'confirm %s delete';
 dotclear.msg.confirm_delete_comments = 'confirm %s delete';
+
+dotclear.jsUpload = {msg:{}};
+dotclear.jsUpload.msg.cancel = 'cancel';
+dotclear.jsUpload.msg.send = 'send';
+dotclear.jsUpload.msg.error = 'error';
+dotclear.jsUpload.msg.file_successfully_uploaded = 'file succesfully uploaded';
+
+dotclear.msg.enhanced_uploader_activate = 'Temporarily activate enhanced uploader';
+dotclear.msg.enhanced_uploader_disable = 'Temporarily disable enhanced uploader';
+
Index: tests/functional/lib/jasmine-jquery-bootstrap.js
===================================================================
--- tests/functional/lib/jasmine-jquery-bootstrap.js	(revision 1602)
+++ tests/functional/lib/jasmine-jquery-bootstrap.js	(revision 1724)
@@ -1,28 +1,29 @@
 (function() {
-    jasmine.getFixtures().fixturesPath = 'fixtures';
+	jasmine.getFixtures().fixturesPath = 'fixtures';
+	jasmine.getStyleFixtures().fixturesPath = '../../admin/style';
 
-    var jasmineEnv = jasmine.getEnv();
-    jasmineEnv.updateInterval = 1000;
+	var jasmineEnv = jasmine.getEnv();
+	jasmineEnv.updateInterval = 1000;
 
-    var htmlReporter = new jasmine.HtmlReporter();
+	var htmlReporter = new jasmine.HtmlReporter();
 
-    jasmineEnv.addReporter(htmlReporter);
+	jasmineEnv.addReporter(htmlReporter);
 
-    jasmineEnv.specFilter = function(spec) {
-	return htmlReporter.specFilter(spec);
-    };
+	jasmineEnv.specFilter = function(spec) {
+		return htmlReporter.specFilter(spec);
+	};
 
-    var currentWindowOnload = window.onload;
+	var currentWindowOnload = window.onload;
 
-    window.onload = function() {
-	if (currentWindowOnload) {
-	    currentWindowOnload();
+	window.onload = function() {
+		if (currentWindowOnload) {
+			currentWindowOnload();
+		}
+		execJasmine();
+	};
+
+	function execJasmine() {
+		jasmineEnv.execute();
 	}
-	execJasmine();
-    };
-
-    function execJasmine() {
-	jasmineEnv.execute();
-    }
 
 })();
Index: tests/functional/spec/common.js
===================================================================
--- tests/functional/spec/common.js	(revision 1703)
+++ tests/functional/spec/common.js	(revision 1724)
@@ -1,83 +1,83 @@
 describe("Others common methods (admin/js/common.js)", function() {
-    describe("postsActionsHelper", function() {
-	it("A confirm popup must appear if action is \"delete\" and at least on checkbox is checked", function() {
-	    loadFixtures('posts_list.html');
-	    dotclear.postsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-entries').submit(submitCallback);
+	describe("postsActionsHelper", function() {
+		it("A confirm popup must appear if action is \"delete\" and at least on checkbox is checked", function() {
+			loadFixtures('posts_list.html');
+			dotclear.postsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-entries').submit(submitCallback);
 
-	    $('select[name="action"] option[value="delete"]').attr('selected', 'selected');
-	    $('input[type="checkbox"][name="entries[]"][value="2"]').attr('checked', 'checked');
+			$('select[name="action"] option[value="delete"]').attr('selected', 'selected');
+			$('input[type="checkbox"][name="entries[]"][value="2"]').attr('checked', 'checked');
 
-	    $('#form-entries').trigger('submit');
-	    expect(window.confirm).toHaveBeenCalled();
+			$('#form-entries').trigger('submit');
+			expect(window.confirm).toHaveBeenCalled();
+		});
+		it("Confirm popup doesn't appear if action is \"delete\" but no checkbox is checked", function() {
+			loadFixtures('posts_list.html');
+			dotclear.postsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-entries').submit(submitCallback);
+
+			$('select[name="action"] option[value="delete"]').attr('selected', 'selected');
+			$('#form-entries').trigger('submit');
+			expect(window.confirm).not.toHaveBeenCalled();
+		});
+		it("Others actions don't show confirm popup", function() {
+			loadFixtures('posts_list.html');
+			dotclear.postsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-entries').submit(submitCallback);
+
+			$('select[name="action"] option[value="publish"]').attr('selected', 'selected');
+			$('#form-entries').trigger('submit');
+			expect(window.confirm).not.toHaveBeenCalled();
+		});
 	});
-	it("Confirm popup doesn't appear if action is \"delete\" but no checkbox is checked", function() {
-	    loadFixtures('posts_list.html');
-	    dotclear.postsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-entries').submit(submitCallback);
 
-	    $('select[name="action"] option[value="delete"]').attr('selected', 'selected');
-	    $('#form-entries').trigger('submit');
-	    expect(window.confirm).not.toHaveBeenCalled();
+	describe("commentsActionsHelper", function() {
+		it("A confirm popup must appear if action is \"delete\" and at least on checkbox is checked", function() {
+			loadFixtures('comments_list.html');
+			dotclear.commentsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-comments').submit(submitCallback);
+
+			$('select[name="action"] option[value="delete"]').attr('selected', 'selected');
+			$('input[type="checkbox"][name="comments[]"][value="2"]').attr('checked', 'checked');
+
+			$('#form-comments').trigger('submit');
+			expect(window.confirm).toHaveBeenCalled();
+		});
+		it("Confirm popup doesn't appear if action is \"delete\" but no checkbox is checked", function() {
+			loadFixtures('comments_list.html');
+			dotclear.commentsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-comments').submit(submitCallback);
+
+			$('select[name="action"] option[value="delete"]').attr('selected', 'selected');
+			$('#form-comments').trigger('submit');
+			expect(window.confirm).not.toHaveBeenCalled();
+		});
+		it("Others actions don't show confirm popup", function() {
+			loadFixtures('comments_list.html');
+			dotclear.commentsActionsHelper();
+			
+			spyOn(window, 'confirm').andReturn(false);
+			var submitCallback = jasmine.createSpy().andReturn(false);
+			$('#form-comments').submit(submitCallback);
+
+			$('select[name="action"] option[value="publish"]').attr('selected', 'selected');
+			$('#form-comments').trigger('submit');
+			expect(window.confirm).not.toHaveBeenCalled();
+		});
 	});
-	it("Others actions don't show confirm popup", function() {
-	    loadFixtures('posts_list.html');
-	    dotclear.postsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-entries').submit(submitCallback);
-
-	    $('select[name="action"] option[value="publish"]').attr('selected', 'selected');
-	    $('#form-entries').trigger('submit');
-	    expect(window.confirm).not.toHaveBeenCalled();
-	});
-    });
-
-    describe("commentsActionsHelper", function() {
-	it("A confirm popup must appear if action is \"delete\" and at least on checkbox is checked", function() {
-	    loadFixtures('comments_list.html');
-	    dotclear.commentsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-comments').submit(submitCallback);
-
-	    $('select[name="action"] option[value="delete"]').attr('selected', 'selected');
-	    $('input[type="checkbox"][name="comments[]"][value="2"]').attr('checked', 'checked');
-
-	    $('#form-comments').trigger('submit');
-	    expect(window.confirm).toHaveBeenCalled();
-	});
-	it("Confirm popup doesn't appear if action is \"delete\" but no checkbox is checked", function() {
-	    loadFixtures('comments_list.html');
-	    dotclear.commentsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-comments').submit(submitCallback);
-
-	    $('select[name="action"] option[value="delete"]').attr('selected', 'selected');
-	    $('#form-comments').trigger('submit');
-	    expect(window.confirm).not.toHaveBeenCalled();
-	});
-	it("Others actions don't show confirm popup", function() {
-	    loadFixtures('comments_list.html');
-	    dotclear.commentsActionsHelper();
-	    
-	    spyOn(window, 'confirm').andReturn(false);
-	    var submitCallback = jasmine.createSpy().andReturn(false);
-	    $('#form-comments').submit(submitCallback);
-
-	    $('select[name="action"] option[value="publish"]').attr('selected', 'selected');
-	    $('#form-comments').trigger('submit');
-	    expect(window.confirm).not.toHaveBeenCalled();
-	});
-    });
 });
Index: tests/functional/spec/media_manager.js
===================================================================
--- tests/functional/spec/media_manager.js	(revision 1724)
+++ tests/functional/spec/media_manager.js	(revision 1724)
@@ -0,0 +1,31 @@
+describe("Enhanced Media Manager", function() {
+	describe("Starting with media manager enhanced disabled", function() {
+		it("Enhanced uploader can be temporarily enabled", function() {
+			loadFixtures('form_media_disabled.html');
+			loadStyleFixtures('jsUpload/style.css');
+			
+			$('#fileupload').enhancedUploader();
+			expect($('p.clear a.enhanced-toggle').text()).toBe(dotclear.msg.enhanced_uploader_activate);
+			expect($('#fileupload .button.start')).not.toBeDisabled();
+
+			$('p.clear a.enhanced-toggle').click();
+			expect($('p.clear a.enhanced-toggle').text()).toBe(dotclear.msg.enhanced_uploader_disable);			
+			expect($('.button.start')).toBeDisabled();
+		});
+	});
+
+	describe("Starting with media manager enhanced enabled", function() {
+		it("Enhanced uploader can be temporarily disabled", function() {
+			loadFixtures('form_media_enabled.html');
+			loadStyleFixtures('jsUpload/style.css');
+
+			$('#fileupload').enhancedUploader();
+			expect($('p.clear a.enhanced-toggle').text()).toBe(dotclear.msg.enhanced_uploader_disable);
+			expect($('.button.start')).toBeDisabled();
+
+			$('p.clear a.enhanced-toggle').click();
+			expect($('p.clear a.enhanced-toggle').text()).toBe(dotclear.msg.enhanced_uploader_activate);
+			expect($('#fileupload .button.start')).not.toBeDisabled();
+		});
+	});
+});
Index: tests/functional/spec/toggle_with_legend.js
===================================================================
--- tests/functional/spec/toggle_with_legend.js	(revision 1703)
+++ tests/functional/spec/toggle_with_legend.js	(revision 1724)
@@ -1,47 +1,47 @@
 describe("toggleWithLegend method (admin/js/common.js)", function() {
-    it("Click arrow must make target visible", function() {
-	loadFixtures('menu.html');
-	$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
+	it("Click arrow must make target visible", function() {
+		loadFixtures('menu.html');
+		$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
 
-	var $arrow = $('#post_status').parent().find('img');
-	$arrow.click();
-	expect($('#post_status')).toBeVisible();
-    });
-    it("Click arrow twice,must make target visible and after second click hidden", function() {
-	loadFixtures('menu.html');
-	$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
+		var $arrow = $('#post_status').parent().find('img');
+		$arrow.click();
+		expect($('#post_status')).toBeVisible();
+	});
+	it("Click arrow twice,must make target visible and after second click hidden", function() {
+		loadFixtures('menu.html');
+		$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
 
-	var $arrow = $('#post_status').parent().find('img');
-	$arrow.click();
-	expect($('#post_status')).toBeVisible();
+		var $arrow = $('#post_status').parent().find('img');
+		$arrow.click();
+		expect($('#post_status')).toBeVisible();
 
-	$arrow.click();
-	expect($('#post_status')).toBeHidden();
-    });
-    it("Chick target must not hide target", function() {
-	loadFixtures('menu.html');
-	$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
+		$arrow.click();
+		expect($('#post_status')).toBeHidden();
+	});
+	it("Chick target must not hide target", function() {
+		loadFixtures('menu.html');
+		$('#post_status').parent().toggleWithLegend($('#post_status'),{	});
 
-	var $arrow = $('#post_status').parent().find('img');
-	$arrow.click();
-	expect($('#post_status')).toBeVisible();
+		var $arrow = $('#post_status').parent().find('img');
+		$arrow.click();
+		expect($('#post_status')).toBeVisible();
 
-	$('#post_status option[value="-2"]').attr('selected', 'selected');
-	expect($('#post_status')).toBeVisible();
-    });
-    it("Chick target must not hide target, when legend_click is true", function() {
-	loadFixtures('menu.html');
-	var $label = $('#post_status').parent().children('label');
-	$label.toggleWithLegend($('#post_status'),{'legend_click':true, a_container:false});
+		$('#post_status option[value="-2"]').attr('selected', 'selected');
+		expect($('#post_status')).toBeVisible();
+	});
+	it("Chick target must not hide target, when legend_click is true", function() {
+		loadFixtures('menu.html');
+		var $label = $('#post_status').parent().children('label');
+		$label.toggleWithLegend($('#post_status'),{'legend_click':true, a_container:false});
 
-	$label.click();
-	expect($('#post_status')).toBeVisible();
+		$label.click();
+		expect($('#post_status')).toBeVisible();
 
-	var $arrow = $('#post_status').parent().find('img');
-	$arrow.click();
-	expect($('#post_status')).toBeVisible();
+		var $arrow = $('#post_status').parent().find('img');
+		$arrow.click();
+		expect($('#post_status')).toBeVisible();
 
-	$('#post_status').val(-2).trigger('change');
-	expect($('#post_status')).toBeVisible();
-    });
+		$('#post_status').val(-2).trigger('change');
+		expect($('#post_status')).toBeVisible();
+	});
 });
Index: tests/functional/spec/users_actions.js
===================================================================
--- tests/functional/spec/users_actions.js	(revision 1703)
+++ tests/functional/spec/users_actions.js	(revision 1724)
@@ -1,25 +1,25 @@
 describe("updatePermissionsForm method (admin/js/_users_actions.js)", function() {
-    it("Click admin persmission must checked all associated permissions", function() {
-	loadFixtures('normal.html');
-	$('#permissions-form').updatePermissionsForm();
-	var permissions = ['usage','publish','delete','contentadmin','categories'];
+	it("Click admin persmission must checked all associated permissions", function() {
+		loadFixtures('normal.html');
+		$('#permissions-form').updatePermissionsForm();
+		var permissions = ['usage','publish','delete','contentadmin','categories'];
 
-	$('input[name="perm[default][admin]"]').click();
-	for (var _i=0,_len=permissions.length;_i<_len;_i++) {
-	    expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeChecked();
-	    expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeDisabled();
-	}
-    });
+		$('input[name="perm[default][admin]"]').click();
+		for (var _i=0,_len=permissions.length;_i<_len;_i++) {
+			expect($('input[name="perm\\[default\\]\\['+permissions[_i]+'\\]"]')).toBeChecked();
+			expect($('input[name="perm\\[default\\]\\['+permissions[_i]+'\\]"]')).toBeDisabled();
+		}
+	});
 
-    it("Click contentadmin persmission must checked all associated permissions", function() {
-	loadFixtures('normal.html');
-	$('#permissions-form').updatePermissionsForm();
-	var permissions = ['usage','publish','delete'];
+	it("Click contentadmin persmission must checked all associated permissions", function() {
+		loadFixtures('normal.html');
+		$('#permissions-form').updatePermissionsForm();
+		var permissions = ['usage','publish','delete'];
 
-	$('input[name="perm[default][contentadmin]"]').click();
-	for (var _i=0,_len=permissions.length;_i<_len;_i++) {
-	    expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeChecked();
-	    expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeDisabled();
-	}
-    });
+		$('input[name="perm[default][contentadmin]"]').click();
+		for (var _i=0,_len=permissions.length;_i<_len;_i++) {
+			expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeChecked();
+			expect($('input[name="perm[default]['+permissions[_i]+']"]')).toBeDisabled();
+		}
+	});
 });
