diff options
author | Jesse Luehrs <doy@tozt.net> | 2013-02-28 19:31:58 -0600 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2013-02-28 19:31:58 -0600 |
commit | c26b0869a2b68d349eeb4baed11eaa2013b11f83 (patch) | |
tree | 5dd7515e164b0e4da6f85bb43b36b1008afedf94 /lib/diagrams.js | |
download | scala-test-more-c26b0869a2b68d349eeb4baed11eaa2013b11f83.tar.gz scala-test-more-c26b0869a2b68d349eeb4baed11eaa2013b11f83.zip |
docs
Diffstat (limited to 'lib/diagrams.js')
-rw-r--r-- | lib/diagrams.js | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/lib/diagrams.js b/lib/diagrams.js new file mode 100644 index 0000000..478f2e3 --- /dev/null +++ b/lib/diagrams.js @@ -0,0 +1,324 @@ +/** + * JavaScript functions enhancing the SVG diagrams. + * + * @author Damien Obrist + */ + +var diagrams = {}; + +/** + * Initializes the diagrams in the main window. + */ +$(document).ready(function() +{ + // hide diagrams in browsers not supporting SVG + if(Modernizr && !Modernizr.inlinesvg) + return; + + // only execute this in the main window + if(diagrams.isPopup) + return; + + if($("#content-diagram").length) + $("#inheritance-diagram").css("padding-bottom", "20px"); + + $(".diagram-container").css("display", "block"); + + $(".diagram").each(function() { + // store inital dimensions + $(this).data("width", $("svg", $(this)).width()); + $(this).data("height", $("svg", $(this)).height()); + // store unscaled clone of SVG element + $(this).data("svg", $(this).get(0).childNodes[0].cloneNode(true)); + }); + + // make diagram visible, hide container + $(".diagram").css("display", "none"); + $(".diagram svg").css({ + "position": "static", + "visibility": "visible", + "z-index": "auto" + }); + + // enable linking to diagrams + if($(location).attr("hash") == "#inheritance-diagram") { + diagrams.toggle($("#inheritance-diagram-container"), true); + } else if($(location).attr("hash") == "#content-diagram") { + diagrams.toggle($("#content-diagram-container"), true); + } + + $(".diagram-link").click(function() { + diagrams.toggle($(this).parent()); + }); + + // register resize function + $(window).resize(diagrams.resize); + + // don't bubble event to parent div + // when clicking on a node of a resized + // diagram + $("svg a").click(function(e) { + e.stopPropagation(); + }); + + diagrams.initHighlighting(); +}); + +/** + * Initializes the diagrams in the popup. + */ +diagrams.initPopup = function(id) +{ + // copy diagram from main window + if(!jQuery.browser.msie) + $("body").append(opener.$("#" + id).data("svg")); + + // positioning + $("svg").css("position", "absolute"); + $(window).resize(function() + { + var svg_w = $("svg").css("width").replace("px", ""); + var svg_h = $("svg").css("height").replace("px", ""); + var x = $(window).width() / 2 - svg_w / 2; + if(x < 0) x = 0; + var y = $(window).height() / 2 - svg_h / 2; + if(y < 0) y = 0; + $("svg").css("left", x + "px"); + $("svg").css("top", y + "px"); + }); + $(window).resize(); + + diagrams.initHighlighting(); + $("svg a").click(function(e) { + opener.diagrams.redirectFromPopup(this.href.baseVal); + window.close(); + }); + $(document).keyup(function(e) { + if (e.keyCode == 27) window.close(); + }); +} + +/** + * Initializes highlighting for nodes and edges. + */ +diagrams.initHighlighting = function() +{ + // helper function since $.hover doesn't work in IE + + function hover(elements, fn) + { + elements.mouseover(fn); + elements.mouseout(fn); + } + + // inheritance edges + + hover($("svg .edge.inheritance"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + var parts = $(this).attr("id").split("_"); + toggleClass($("#" + parts[0] + "_" + parts[1])); + toggleClass($("#" + parts[0] + "_" + parts[2])); + toggleClass($(this)); + }); + + // nodes + + hover($("svg .node"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + toggleClass($(this)); + var parts = $(this).attr("id").split("_"); + var index = parts[1]; + $("svg#" + parts[0] + " .edge.inheritance").each(function(){ + var parts2 = $(this).attr("id").split("_"); + if(parts2[1] == index) + { + toggleClass($("#" + parts2[0] + "_" + parts2[2])); + toggleClass($(this)); + } else if(parts2[2] == index) + { + toggleClass($("#" + parts2[0] + "_" + parts2[1])); + toggleClass($(this)); + } + }); + }); + + // incoming implicits + + hover($("svg .node.implicit-incoming"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + toggleClass($(this)); + toggleClass($("svg .edge.implicit-incoming")); + toggleClass($("svg .node.this")); + }); + + hover($("svg .edge.implicit-incoming"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + toggleClass($(this)); + toggleClass($("svg .node.this")); + $("svg .node.implicit-incoming").each(function(){ + toggleClass($(this)); + }); + }); + + // implicit outgoing nodes + + hover($("svg .node.implicit-outgoing"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + toggleClass($(this)); + toggleClass($("svg .edge.implicit-outgoing")); + toggleClass($("svg .node.this")); + }); + + hover($("svg .edge.implicit-outgoing"), function(evt){ + var toggleClass = evt.type == "mouseout" ? diagrams.removeClass : diagrams.addClass; + toggleClass($(this)); + toggleClass($("svg .node.this")); + $("svg .node.implicit-outgoing").each(function(){ + toggleClass($(this)); + }); + }); +}; + +/** + * Resizes the diagrams according to the available width. + */ +diagrams.resize = function() +{ + // available width + var availableWidth = $("body").width() - 20; + + $(".diagram-container").each(function() { + // unregister click event on whole div + $(".diagram", this).unbind("click"); + var diagramWidth = $(".diagram", this).data("width"); + var diagramHeight = $(".diagram", this).data("height"); + + if(diagramWidth > availableWidth) + { + // resize diagram + var height = diagramHeight / diagramWidth * availableWidth; + $(".diagram svg", this).width(availableWidth); + $(".diagram svg", this).height(height); + + // register click event on whole div + $(".diagram", this).click(function() { + diagrams.popup($(this)); + }); + $(".diagram", this).addClass("magnifying"); + } + else + { + // restore full size of diagram + $(".diagram svg", this).width(diagramWidth); + $(".diagram svg", this).height(diagramHeight); + // don't show custom cursor any more + $(".diagram", this).removeClass("magnifying"); + } + }); +}; + +/** + * Shows or hides a diagram depending on its current state. + */ +diagrams.toggle = function(container, dontAnimate) +{ + // change class of link + $(".diagram-link", container).toggleClass("open"); + // get element to show / hide + var div = $(".diagram", container); + if (div.is(':visible')) + { + $(".diagram-help", container).hide(); + div.unbind("click"); + div.removeClass("magnifying"); + div.slideUp(100); + } + else + { + diagrams.resize(); + if(dontAnimate) + div.show(); + else + div.slideDown(100); + $(".diagram-help", container).show(); + } +}; + +/** + * Opens a popup containing a copy of a diagram. + */ +diagrams.windows = {}; +diagrams.popup = function(diagram) +{ + var id = diagram.attr("id"); + if(!diagrams.windows[id] || diagrams.windows[id].closed) { + var title = $(".symbol .name", $("#signature")).text(); + // cloning from parent window to popup somehow doesn't work in IE + // therefore include the SVG as a string into the HTML + var svgIE = jQuery.browser.msie ? $("<div />").append(diagram.data("svg")).html() : ""; + var html = '' + + '<?xml version="1.0" encoding="UTF-8"?>\n' + + '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' + + '<html>\n' + + ' <head>\n' + + ' <title>' + title + '</title>\n' + + ' <link href="' + $("#diagrams-css").attr("href") + '" media="screen" type="text/css" rel="stylesheet" />\n' + + ' <script type="text/javascript" src="' + $("#jquery-js").attr("src") + '"></script>\n' + + ' <script type="text/javascript" src="' + $("#diagrams-js").attr("src") + '"></script>\n' + + ' <script type="text/javascript">\n' + + ' diagrams.isPopup = true;\n' + + ' </script>\n' + + ' </head>\n' + + ' <body onload="diagrams.initPopup(\'' + id + '\');">\n' + + ' <a href="#" onclick="window.close();" id="close-link">Close this window</a>\n' + + ' ' + svgIE + '\n' + + ' </body>\n' + + '</html>'; + + var padding = 30; + var screenHeight = screen.availHeight; + var screenWidth = screen.availWidth; + var w = Math.min(screenWidth, diagram.data("width") + 2 * padding); + var h = Math.min(screenHeight, diagram.data("height") + 2 * padding); + var left = (screenWidth - w) / 2; + var top = (screenHeight - h) / 2; + var parameters = "height=" + h + ", width=" + w + ", left=" + left + ", top=" + top + ", scrollbars=yes, location=no, resizable=yes"; + var win = window.open("about:blank", "_blank", parameters); + win.document.open(); + win.document.write(html); + win.document.close(); + diagrams.windows[id] = win; + } + win.focus(); +}; + +/** + * This method is called from within the popup when a node is clicked. + */ +diagrams.redirectFromPopup = function(url) +{ + window.location = url; +}; + +/** + * Helper method that adds a class to a SVG element. + */ +diagrams.addClass = function(svgElem, newClass) { + newClass = newClass || "over"; + var classes = svgElem.attr("class"); + if ($.inArray(newClass, classes.split(/\s+/)) == -1) { + classes += (classes ? ' ' : '') + newClass; + svgElem.attr("class", classes); + } +}; + +/** + * Helper method that removes a class from a SVG element. + */ +diagrams.removeClass = function(svgElem, oldClass) { + oldClass = oldClass || "over"; + var classes = svgElem.attr("class"); + classes = $.grep(classes.split(/\s+/), function(n, i) { return n != oldClass; }).join(' '); + svgElem.attr("class", classes); +}; + |