Rework js tree drilldown to just directly insert new rows instead of using nested tables, to fix issues with uneven table widths
[gitphp.git] / js / tree.js
blob:a/js/tree.js -> blob:b/js/tree.js
--- a/js/tree.js
+++ b/js/tree.js
@@ -9,12 +9,29 @@
  * @subpackage Javascript
  */
 
+function expanderLink(href, text) {
+	var a = jQuery(document.createElement('a'));
+	a.attr('href', href);
+	a.text(text);
+	a.addClass('jsTree');
+	a.addClass('expander');
+	return a;
+};
+
 function initTree() {
-	var project = window.location.href.match(/p=([^&]+)/);
-	if (!project) {
+	var url = window.location.href.match(/^([^\?]+\/)/);
+	if (!url) {
 		return;
 	}
-	project = unescape(project[1]);
+	url = url[1];
+
+	var collapsed = '[+]';
+	var expanded = '[–]';
+	var indent = '—';
+
+	$('a.treeLink').each(function() {
+		$(this).parent().parent().find('td.expander').append(expanderLink($(this).attr('href'), collapsed));
+	});
 
 	$('a.jsTree').live('click', function() {
 		var treeHash = $(this).attr('href').match(/h=([0-9a-fA-F]{40}|HEAD)/);
@@ -24,21 +41,39 @@
 
 		treeHash = treeHash[1];
 
+		var cell = $(this).parent();
+		var row = cell.parent();
+
 		var treeRows = $('.' + treeHash);
 		if (treeRows && treeRows.size() > 0) {
-			if (treeRows.is(':visible'))
+			if (treeRows.is(':visible')) {
 				treeRows.hide();
-			else
-				treeRows.show();
+				treeRows.each(function() {
+					if ($(this).data('parent') == treeHash) {
+						$(this).data('expanded', false);
+					}
+				});
+				row.find('a.expander').text(collapsed);
+			} else {
+				treeRows.each(function() {
+					if (($(this).data('parent') == treeHash) || ($(this).data('expanded') == true)) {
+						$(this).show();
+						$(this).data('expanded', true);
+					}
+				});
+				row.find('a.expander').text(expanded);
+			}
 		} else {
-			var cell = $(this).parent();
-			var row = cell.parent();
-			var indent = cell.html().match(/^(—+)/);
-			if (indent)
-				indent = indent[1];
-			else
-				indent = '';
-			indent += '—';
+			var depth = row.data('depth');
+			if (depth == null)
+				depth = 0;
+			depth++;
+
+			var img = jQuery(document.createElement('img'));
+			img.attr('src', url + "images/tree-loader.gif");
+			img.attr('alt', GITPHP_RES_LOADING);
+			img.addClass('treeSpinner');
+			row.find('a.treeLink').after(img);
 
 			$.get($(this).attr('href'), { o: 'js' },
 			function(data) {
@@ -53,15 +88,35 @@
 					}
 				});
 
-				subRows.find('td.fileName').prepend(indent);
+				subRows.each(function() {
+
+					$(this).data('parent', treeHash);
+					$(this).data('expanded', true);
+					$(this).data('depth', depth);
+
+					var fileCell = $(this).find('td.fileName');
+					var treeLink = $(this).find('a.treeLink');
+					if (treeLink && (treeLink.size() > 0)) {
+						fileCell.prepend(expanderLink(treeLink.attr('href'), collapsed));
+					} else {
+						fileCell.prepend(indent);
+					}
+
+					for (var i = 1; i < depth; i++) {
+						fileCell.prepend(indent);
+					}
+				});
 
 				row.after(subRows);
+
+				row.find('a.expander').text(expanded);
+				row.find('img.treeSpinner').remove();
 			});
 		}
 
 		return false;
 	});
-}
+};
 
 $(document).ready(function() {
 	initTree();

comments