What if I don't want events I've already seen to take up so much space when I view a case? - FogBugz Knowledge Exchange most recent 30 from http://fogbugz.stackexchange.com 2013-05-24T16:37:03Z http://fogbugz.stackexchange.com/feeds/question/3242 http://www.creativecommons.org/licenses/by-nc/2.5/rdf http://fogbugz.stackexchange.com/questions/3242/what-if-i-dont-want-events-ive-already-seen-to-take-up-so-much-space-when-i-vie What if I don't want events I've already seen to take up so much space when I view a case? Daniel LeCheminant 2010-06-04T00:57:10Z 2013-04-12T07:27:13Z <p>When I look at a case with a lot of events, it can be overwhelming.</p> <p>Is there a way to make it so that events that I've already seen are hidden (or at least truncated)?</p> http://fogbugz.stackexchange.com/questions/3242/what-if-i-dont-want-events-ive-already-seen-to-take-up-so-much-space-when-i-vie/3243#3243 Answer by Daniel LeCheminant for What if I don't want events I've already seen to take up so much space when I view a case? Daniel LeCheminant 2010-06-04T01:10:02Z 2011-09-27T11:28:45Z <p>The following <a href="http://fogbugz.stackexchange.com/questions/3183/bugmonkey-how-do-i-get-started" rel="nofollow">BugMonkey</a> script shows one way to have more control over which/how case events are displayed:</p> <pre><code>// Provide a menu on case view that allows you to do one of the following: // View all events // Show all events as one-line summaries // Show seen events as one-line summaries // Hide seen events $(document).ready(function() { // Don't do anything unless we're looking at a single bug if (!window.goBug || !$("#bugviewContainer").length || $("#miniBugList").length) return; // The text displayed in the display menu var modes = { showAll: { text: "Show All", label: "Showing all events", show: ".bugevent" }, summarizeAll: { text: "Summarize All", label: "Summarizing all events", show: ".small-summary" }, summarizeSeen: { text: "Summarize Seen", label: "Summarizing #seen events", show: ".bugevent:not(.seen),.small-summary.seen" }, hideSeen: { text: "Hide Seen", label: "Hiding #seen events", show: ".bugevent:not(.seen)" } }; // The name of the cookie used to save settings var sCookie = "sSeenEventMode"; // Read the user's current settings. Default is to show all var sSeenMode = getCookie(sCookie) || "showAll"; // Determine the last event the user saw var ixLastView = goBug.ixBugEventLastView; // A table describing the translation from a standard bug event // to its summary var summTrans = [ { sel: ".action", color: "#000", css: { "font-weight": "bold"} }, { sel: ".date a", color: "#68615e" }, { fnHtml: function(ev) { return (ev.find(".emailBody").html() || ev.find(".body").html() || ""). replace(/&lt;[^&gt;]*&gt;/g, " "); }, color: "#888" }, { sel: ".changes", color: "#aaa" } ]; var jAllEvents = $("#BugEvents .bugevent"); // Process bug events we've already seen var numSeen = jAllEvents // Filter out events we haven't seen .filter(function() { return /\d+/.exec($(this).attr("id")) &lt;= ixLastView; }) .addClass("seen") .length; // Process all visible bug events jAllEvents .each(function() { var ev = $(this); // Create the event summary var divSummary = $("&lt;div&gt;") .addClass("small-summary") .css({ "white-space": "nowrap", overflow: "hidden", "text-overflow": "ellipsis", "font-size": "10px", "margin-bottom": "4px", "cursor": "pointer" }) .insertBefore(this) .click(function() { // Clicking anywhere on the summary hides it // and displays the full bug event $(this).hide().next(".bugevent").show(); }); if (ev.hasClass("seen")) divSummary.addClass("seen"); // Convert the bug event into a summary $.each(summTrans, function(ix, tbl) { var entry = $("&lt;span&gt;") .css(tbl.css) .css({ color: tbl.color, "margin-right": "4px" }) .appendTo(divSummary); if (tbl.fnHtml) entry.html(tbl.fnHtml(ev)); else entry.text(ev.find(tbl.sel).text()) }); }); var divMenu = $("&lt;div&gt;") .css({ "margin-bottom": "1em", border: "1px dotted #888", padding: "4px", "background-color": "#f4f4f4" }) .insertBefore("#BugEvents"); var spanLabel = $("&lt;span&gt;") .css({ "font-weight": "bold", "float": "right" }) .appendTo(divMenu); // Set the display mode var setMode = function(ev, sMode) { // If this is being used as an event handler, // get the mode from the link that was clicked sMode = sMode || $(this).attr("mode"); // Don't underline the link that represents the current display mode divMenu.find("a") .css("text-decoration", function() { return $(this).attr("mode") == sMode ? "none" : "underline"; }); // Only show the events/summaries allowed by the user's selection $("#BugEvents").find(".bugevent,.small-summary") .hide() .filter(modes[sMode].show) .show(); // Update the label spanLabel.html(modes[sMode].label.replace(/#seen/g, numSeen)); // Remember the user's selection setCookie(sCookie, sMode); }; // Add the display modes to the menu for (var mode in modes) { $("&lt;a&gt;") .text(modes[mode].text) .css("margin", ".5em") .attr({ href: "javascript:void(0)", mode: mode }) .appendTo(divMenu) .click(setMode); } // Apply the user's saved mode setMode(null, sSeenMode); }); </code></pre> <p>If you'd like to use the code as is, you can use the <a href="http://closure-compiler.appspot.com/home" rel="nofollow">Closure</a> compiled version:</p> <pre><code>$(document).ready(function(){if(!(!window.goBug||!$("#bugviewContainer").length||$("#miniBugList").length)){var e={showAll:{text:"Show All",label:"Showing all events",show:".bugevent"},summarizeAll:{text:"Summarize All",label:"Summarizing all events",show:".small-summary"},summarizeSeen:{text:"Summarize Seen",label:"Summarizing #seen events",show:".bugevent:not(.seen),.small-summary.seen"},hideSeen:{text:"Hide Seen",label:"Hiding #seen events",show:".bugevent:not(.seen)"}},i=getCookie("sSeenEventMode")|| "showAll",j=goBug.ixBugEventLastView,k=[{sel:".action",color:"#000",css:{"font-weight":"bold"}},{sel:".date a",color:"#68615e"},{fnHtml:function(b){return(b.find(".emailBody").html()||b.find(".body").html()||"").replace(/&lt;[^&gt;]*&gt;/g," ")},color:"#888"},{sel:".changes",color:"#aaa"}],c=$("#BugEvents .bugevent"),l=c.filter(function(){return/\d+/.exec($(this).attr("id"))&lt;=j}).addClass("seen").length;c.each(function(){var b=$(this),a=$("&lt;div&gt;").addClass("small-summary").css({"white-space":"nowrap",overflow:"hidden", "text-overflow":"ellipsis","font-size":"10px","margin-bottom":"4px",cursor:"pointer"}).insertBefore(this).click(function(){$(this).hide().next(".bugevent").show()});b.hasClass("seen")&amp;&amp;a.addClass("seen");$.each(k,function(n,d){var g=$("&lt;span&gt;").css(d.css).css({color:d.color,"margin-right":"4px"}).appendTo(a);d.fnHtml?g.html(d.fnHtml(b)):g.text(b.find(d.sel).text())})});var f=$("&lt;div&gt;").css({"margin-bottom":"1em",border:"1px dotted #888",padding:"4px","background-color":"#f4f4f4"}).insertBefore("#BugEvents"), m=$("&lt;span&gt;").css({"font-weight":"bold","float":"right"}).appendTo(f);c=function(b,a){a=a||$(this).attr("mode");f.find("a").css("text-decoration",function(){return $(this).attr("mode")==a?"none":"underline"});$("#BugEvents").find(".bugevent,.small-summary").hide().filter(e[a].show).show();m.html(e[a].label.replace(/#seen/g,l));setCookie("sSeenEventMode",a)};for(var h in e)$("&lt;a&gt;").text(e[h].text).css("margin",".5em").attr({href:"javascript:void(0)",mode:h}).appendTo(f).click(c);c(null,i)}}); </code></pre> http://fogbugz.stackexchange.com/questions/3242/what-if-i-dont-want-events-ive-already-seen-to-take-up-so-much-space-when-i-vie/10112#10112 Answer by Michel de Ruiter for What if I don't want events I've already seen to take up so much space when I view a case? Michel de Ruiter 2012-03-14T09:21:47Z 2013-04-12T07:27:13Z <p>I took Daniel's version and tried to improve on it over time.</p> <p>Major new features:</p> <ul> <li>summary tooltips</li> <li>easily expand, collapse or hide individual events</li> <li>integrated <a href="http://fogbugz.stackexchange.com/questions/6302/how-to-show-all-quoted-texts/6303#6303" rel="nofollow">Toggle quoted texts</a> link</li> <li>border color makes unseen events stand out</li> </ul> <p>Minor improvements and fixes:</p> <ul> <li>changed to BugMonkey 2 format</li> <li>compatible with Tidy Case Events and Case Event Merge plugins</li> <li>works with recent FogBugz (.summary, jQuery version)</li> <li>compatible with minor, pseudo and borrowed events</li> <li>updates on edits</li> <li>added extra counts</li> <li>changed Summarize All position</li> </ul> <p>I tested it with recent versions of FogBugz: I might have broken older versions.</p> <p>Hope this helps. At least I find it <strong>very</strong> useful!</p> <p>Screen shot: <img src="http://d.sentient.nl/Files/fogbugz.4.112428.1/SummarizeEvents.png" alt="alt text"></p> <pre><code>name: Summarize Events description: Add menu to case to summarize/hide seen events or summarize/show all events author: Daniel LeCheminant, Michel de Ruiter version: 1.2.7.0 js: if (!window.goBug || !$("#bugviewContainer").length || $("#miniBugList").length) return; // Don't do anything unless we're looking at a single bug :-( var modes = { // The text displayed in the display menu showAll: { text: "Show All", label: "Showing all #all (seen #seen)", show: ".bugevent:not(.minor),.pseudobugevent,.small-summary.minor" }, summarizeSeen: { text: "Summarize Seen", label: "Summarizing #seen of #all", show: ".bugevent:not(.seen),.small-summary.seen:not(.minor,.SOcollapsed)" }, hideSeen: { text: "Hide Seen", label: "Hiding #seen of #all", show: ".bugevent:not(.seen)" }, space1: { text: "" }, summarizeAll: { text: "Summarize All", label: "Summarizing all #alls (seen #seen)", show: ".small-summary:not(.SOcollapsed)" }, space2: { text: "" } }; var summTrans = [ // A table describing the translation from a standard bug event to its summary { sel: ".action", color: "#000", css: { "font-weight": "bold"} }, { sel: ".date a", color: "#68615e" }, { fnHtml: function(ev) { return (ev.find(".emailBody").html() || ev.find(".body").html() || "").replace(/&lt;[^&gt;]*&gt;/g, " "); }, color: "#888" }, { sel: ".changes", color: "#aaa" } ]; $.fn.textNodes = function() { var ret = []; (function(el) { if (el === undefined) // Necessary when "Not showing ... additional events" return; if (el.nodeType == 3) ret.push(el.innerHTML || el.textContent || ""); else for (var i = 0; i &lt; el.childNodes.length; ++i) arguments.callee(el.childNodes[i]); })(this[0]); return ret; } var sCookie = "sSeenEventMode"; // Name of the cookie used to save settings $("#BugEvents &gt; .bugevent:hidden").addClass("minor"); // Initially hidden events are 'minor' ones. function doIt(sCommand) { var sSeenMode = getCookie(sCookie) || "showAll"; // Default to all var jAllEvents = $("#BugEvents .summary").parent(); var numAll = jAllEvents.length; var ixLastView = goBug.ixBugEventLastView; // Determine the last event the user saw. var jSeen = jAllEvents.filter(function() { // Process bug events we've already seen. return /\d+/.exec($(this).attr("id") || "0") &lt;= ixLastView; // Pseudo events are always 'seen', }); if (jSeen.length &lt; numAll) jSeen = jSeen.add('.borrowed .bugevent'); // as are old events 'borrowed' from duplicates. var numSeen = jSeen.addClass("seen").length; var numHidden = $("#BugEvents .bugevent.minor:not(.seen)").length; $('div.small-summary').remove(); // Remove any existing ones jAllEvents.each(function() { // Process all visible bug events var ev = $(this); // Create the event summary: var txt = ev.find(".body").clone(); txt.find("script,.showQuote,pre.linenos,.emailActionsMore").remove(); txt.find(".emailHeaderName").each(function(i) { $(this).replaceWith($(this).text() + " " + $(this).next().remove().text()); }); txt.find(".codesnippet").each(function(i) { $(this).find("br").replaceWith("\n"); $(this).replaceWith($(this).find(".prettyprint").text()); }); txt.find("br").remove(); txt = txt.textNodes(); $.each(txt, function(i, v) { txt[i] = v.replace(/^\n/, ""); }); txt = $.makeArray(txt); txt = txt.join("\n"); txt = txt.replace(/\s+$/g, ""); txt = txt.replace(/^\s+/g, ""); txt = txt.replace(/[ \t\xA0]+$/mg, ""); txt = txt.replace(/\n\n+$/mg, "\n"); var divSummary = $("&lt;div&gt;").addClass("small-summary").attr("title", txt).css({ "white-space": "nowrap", "overflow": "hidden", "text-overflow": "ellipsis", "font-size": "10px", "margin-bottom": "3px", "cursor": "pointer" }).insertBefore(this) .click(function() { // Clicking the summary hides it and displays the full bug event $(this).hide().next(".bugevent,.pseudobugevent").show(); }); if (ev.hasClass("minor")) divSummary.addClass("minor"); if (ev.hasClass("seen")) divSummary.addClass("seen"); if (ev.has('input.scratchedOutFlagScratch').length &gt; 0) divSummary.addClass("SOcollapsed"); $.each(summTrans, function(ix, tbl) { // Convert the bug event into a summary var entry = $("&lt;span&gt;").css({ "color": tbl.color, "margin-right": "4px" }).appendTo(divSummary); if (tbl.css) entry.css(tbl.css); if (tbl.fnHtml) entry.html(tbl.fnHtml(ev)); else entry.text(ev.find(tbl.sel).text()); }); }); $("#BugEvents .summary").filter(":not(:has(.topright))").prepend($("&lt;div&gt;").addClass("topright") .append($("&lt;a&gt;").text("\u2014").attr("title", "Summarize").click(function() { $(this).closest(".summary").parent().hide().prev(".small-summary").show(); })) .append($("&lt;a&gt;").text("\xD7").attr("title", "Hide").click(function() { $(this).closest(".summary").parent().hide(); }))); $('div#summarize').remove(); // Remove any existing one var divMenu = $("&lt;div&gt;").attr("id", "summarize").css({ "margin-bottom": "6px", "border": "1px dotted #888", "padding": "4px", "background-color": "#f4f4f4" }).insertBefore("#BugEvents"); var spanLabel = $("&lt;span&gt;").css({ "font-weight": "bold", "float": "right" }).appendTo(divMenu); var setMode = function(ev, sMode) { // Set the display mode // If this is being used as an event handler, get the mode from the link that was clicked sMode = sMode || $(this).attr("mode"); // Don't underline the link that represents the current display mode divMenu.find("a").css("text-decoration", function() { return $(this).attr("mode") == sMode ? "none" : "underline"; }); // Only show the events/summaries allowed by the user's selection $("#BugEvents").find(".bugevent,.pseudobugevent,.small-summary") .hide().filter(modes[sMode].show).show(); spanLabel.html(modes[sMode].label .replace(/#seen/g, numSeen) .replace(/#all/g, numAll) .replace(/#hidden/g, numHidden)); setCookie(sCookie, sMode); // Remember the user's selection }; for (var mode in modes) { // Add the display modes to the menu $("&lt;a&gt;").text(modes[mode].text).css("margin", ".5em") .attr({ href: "javascript:void(0)", mode: mode }) .appendTo(divMenu).click(setMode); } var quotedTexts = $(".showQuote &gt; a[href='#'][onclick]"); if (quotedTexts.length &gt; 0) { $("&lt;a&gt;").text("Toggle quoted texts").css("margin", ".5em") .attr("title", quotedTexts.length) .attr("href", "javascript:void(0)").appendTo(divMenu) .click(function() { $(".showQuote &gt; a[href='#'][onclick]").each(function(){ this.onclick(); }); }); } if (sCommand == 'load') setMode(null, sSeenMode); // Apply the user's saved mode } doIt($("#sEventEdit").length &gt; 0 ? "new" : "load"); $(window).on("BugViewChange", function(e, data) { doIt(data.sCommand); }); // Work around ListBrowser skipping hidden elements: var originalFlipAttachDeleteIcons = TabManager.flipAttachDeleteIcons; TabManager.flipAttachDeleteIcons = function(sCommand) { var hidden = $("#BugEvents").find(".bugevent:hidden,.pseudobugevent:hidden").show(); originalFlipAttachDeleteIcons(sCommand); hidden.hide(); }; css: /* The Case Event Merge plugin makes this "none" by default. */ #bugviewContainer #BugEvents .borrowed .bugevent.brief { display: block; } #bugviewContainer .bugevents .borrowed .bugevent em.borrowed { font-size: 10px; line-height: 10px; } #bugviewContainer .bugevents .bugevent { border: 1px solid #808080 !important; } #bugviewContainer .bugevents .pseudobugevent, #bugviewContainer .bugevents .bugevent.seen { border: 1px solid #C0C0C0 !important; } #bugviewContainer .bugevents .pseudobugevent.minor, #bugviewContainer .bugevents .bugevent.minor { border: 1px solid yellow !important; } #BugEvents .summary div.topright { float: right; } #BugEvents .summary div.topright a { font-size: 9px; margin-left: 6px; cursor: pointer; } #bugviewContainerTop { margin-bottom: 2px; } </code></pre>