src/pyams_zodbbrowser/zmi/resources/js/zodbbrowser.js
changeset 0 a02202f95e2c
child 10 ae56cae68d91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_zodbbrowser/zmi/resources/js/zodbbrowser.js	Wed Mar 11 12:27:00 2015 +0100
@@ -0,0 +1,221 @@
+(function($) {
+
+	window.PyAMS_zodbbrowser = {
+
+		filterAll: function () {
+			$('.filter').attr('checked', true);
+			PyAMS_zodbbrowser.filterHistory(true);
+		},
+
+		filterNone: function () {
+			$('.filter').attr('checked', false);
+			PyAMS_zodbbrowser.filterHistory();
+		},
+
+		filterHistory: function (showAll) {
+			var transactions = $('div.transaction');
+			var filters = $('.filter');
+			var filterMap = Array();
+			var MAPPING_PREFIX = "map";
+
+			for (var i = 0; i < filters.length; i++) {
+				var filter = filters[i];
+				if (filter.checked) {
+					filterMap[MAPPING_PREFIX + filter.name] = filter.checked;
+				}
+			}
+
+			for (i = 0; i < transactions.length; i++) {
+				var transaction = transactions[i];
+				var diffs = $(transaction).children('div.diff').children('div.diffitem');
+				var n_hidden = 0;
+				for (var j = 0; j < diffs.length; j++) {
+					var id = $($(diffs[j]).children()[0]).text();
+					if (MAPPING_PREFIX + id in filterMap || showAll) {
+						$(diffs[j]).show();
+					} else {
+						$(diffs[j]).hide();
+						n_hidden += 1;
+					}
+				}
+				var hidden_text = null;
+				if (n_hidden == 1) {
+					hidden_text = '1 item hidden';
+				} else if (n_hidden) {
+					hidden_text = n_hidden + ' items hidden';
+				}
+				$(transaction).children('.filtered').remove();
+				if (hidden_text) {
+					$(transaction).append('<div class="filtered">' + hidden_text + '</div>');
+				}
+			}
+		},
+
+		collapseOrExpand: function () {
+			// this is <div class="extender">
+			// the following element is <div class="collapsible">
+			var content = $(this).next();
+			var icon = $(this).children('img');
+			if (content.is(':hidden')) {
+				$(icon).attr('src', $('#collapseImg').attr('src'));
+				content.slideDown();
+			} else {
+				$(icon).attr('src', $('#expandImg').attr('src'));
+				content.slideUp();
+			}
+		},
+
+		hideItemsIfTooMany: function () {
+			$('.items').each(function () {
+				var expander = $(this).children('.expander')[0];
+				var content = $(this).children('.collapsible')[0];
+				// items are formatted using <br /> so the heuristic is very
+				// approximate.
+				if (content.childNodes.length > 100 && !$(content).is(':hidden')) {
+					var icon = $(expander).children('img');
+					$(icon).attr('src', $('#expandImg').attr('src'));
+					$(content).hide();
+				}
+			});
+		},
+
+		showGoTo: function () {
+			$('#path').hide();
+			$('#goto').show();
+			$('#gotoInput').focus();
+		},
+
+		hideGoTo: function () {
+			$('#goto').hide();
+			$('#path').show();
+			// Don't hide #pathError right away, this blur event might have been the
+			// result of the user clicking on a link inside the #pathError text and
+			// hiding it will prevent that link from getting activated.
+			setTimeout(function () {
+				$('#pathError').slideUp();
+			}, 50);
+		},
+
+		ajaxErrorHandler: function (XMLHttpRequest, textStatus, errorThrown) {
+			errorMessage = "";
+			if (textStatus == "parsererror") {
+				errorMessage = "Server returned malformed data";
+			} else if (textStatus == "error") {
+				errorMessage = "Unknown error (maybe server is offline?)";
+			} else if (textStatus == "timeout") {
+				errorMessage = "Server timeout";
+			} else if (textStatus == "notmodified") {
+				errorMessage = "Server error (says resource not modified)";
+			} else {
+				errorMessage = "Unknown error";
+			}
+
+			errorMessage = '<span class="error"> ' + errorMessage + '</strong>';
+			$('#pathError').html(errorMessage);
+		},
+
+		ajaxSuccessHandler: function (data, status) {
+			if (data.url) {
+				window.location = data.url;
+				$('#pathError').text("Found.").slideDown().slideUp();
+			} else if (data.error) {
+				$('#pathError').text(data.error).show();
+				if (data.partial_url) {
+					$('#pathError').append(', would you like to ' +
+										   '<a href="' + data.partial_url + '">' +
+										   'go to ' + data.partial_path +
+										   '</a>' +
+										   ' instead?');
+				}
+			} else {
+				$('#pathError').text(status).show();
+			}
+		},
+
+		activateGoTo: function () {
+			var path = $('#gotoInput').val();
+			var api_url = 'zodbbrowser_path_to_oid';
+			$('#pathError').text("Loading...").slideDown();
+			$.ajax({
+				url: api_url,
+				dataType: 'json',
+				data: "path=" + path,
+				timeout: 7000,
+				success: PyAMS_zodbbrowser.ajaxSuccessHandler,
+				error: PyAMS_zodbbrowser.ajaxErrorHandler
+			});
+		},
+
+		cancelRollback: function (e) {
+			$('#confirmation').remove();
+			$('div.transaction').removeClass('focus');
+			$('input.rollbackbtn').show();
+		},
+
+		pressRollback: function (e) {
+			e.preventDefault();
+			PyAMS_zodbbrowser.cancelRollback();
+			$(e.target).hide();
+			var transaction_div = $(e.target).closest('div.transaction');
+			transaction_div.addClass('focus');
+			$('<div id="confirmation">' +
+			  '<form action="" method="post">' +
+			  '<div class="message">' +
+			  'This is a dangerous operation that may break data integrity.' +
+			  ' Are you really sure you want to do this?' +
+			  '</div>' +
+			  '<input type="BUTTON" value="Really revert to this state" onclick="PyAMS_zodbbrowser.doRollback()">' +
+			  '<input type="BUTTON" value="Cancel" onclick="PyAMS_zodbbrowser.cancelRollback()">' +
+			  '</form>' +
+			  '</div>').appendTo(transaction_div);
+		},
+
+		doRollback: function () {
+			var transaction_div = $('#confirmation').closest('div.transaction');
+			var rollback_form = transaction_div.find('form.rollback');
+			rollback_form.find('input[name="confirmed"]').val('1');
+			rollback_form.submit();
+		},
+
+		init: function(element) {
+			$('.expander', element).click(PyAMS_zodbbrowser.collapseOrExpand);
+			PyAMS_zodbbrowser.hideItemsIfTooMany();
+			$('#path a', element).click(function (event) {
+				event.stopPropagation();
+			});
+			$('#path', element).click(PyAMS_zodbbrowser.showGoTo);
+			$('#gotoInput', element).blur(PyAMS_zodbbrowser.hideGoTo);
+			$('#gotoInput', element).keypress(function (event) {
+				if (event.which == 13) { // enter
+					PyAMS_zodbbrowser.activateGoTo();
+				}
+			});
+			$('#gotoInput', element).keydown(function (event) {
+				if (event.keyCode == 27) { // escape
+					PyAMS_zodbbrowser.hideGoTo();
+				}
+			});
+			$(document).keypress(function (event) {
+				if (event.which == 103) { // lowercase g
+					if ($('#goto', element).is(':hidden')) {
+						PyAMS_zodbbrowser.showGoTo();
+						event.preventDefault();
+					}
+				}
+			});
+			$('input.rollbackbtn', element).click(PyAMS_zodbbrowser.pressRollback);
+			$('span.truncated', element).click(function (event) {
+				event.preventDefault();
+				var placeholder = $(this);
+				var id = placeholder.attr('id');
+				$.ajax({
+					url: 'zodbbrowser_truncated', data: 'id=' + id,
+					success: function (data, status) {
+						placeholder.replaceWith(data);
+					}
+				});
+			});
+		}
+	}
+
+})(jQuery);