X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/e1f26f013c4ee3a9ce54f62889ead084998e5e9a11e79ddeb7fe33235cfde1b0..b28ebe4e6fd448dc280c91f4fbde53d347f7e51680ba3c5becd7a213896d65a0:/gitweb.js diff --git a/gitweb.js b/gitweb.js index d462a0e..d1b64b2 100644 --- a/gitweb.js +++ b/gitweb.js @@ -7,6 +7,39 @@ * @license GPLv2 or later */ +/* ============================================================ */ +/* functions for generic gitweb actions and views */ + +/** + * used to check if link has 'js' query parameter already (at end), + * and other reasons to not add 'js=1' param at the end of link + * @constant + */ +var jsExceptionsRe = /[;?]js=[01]$/; + +/** + * Add '?js=1' or ';js=1' to the end of every link in the document + * that doesn't have 'js' query parameter set already. + * + * Links with 'js=1' lead to JavaScript version of given action, if it + * exists (currently there is only 'blame_incremental' for 'blame') + * + * @globals jsExceptionsRe + */ +function fixLinks() { + var allLinks = document.getElementsByTagName("a") || document.links; + for (var i = 0, len = allLinks.length; i < len; i++) { + var link = allLinks[i]; + if (!jsExceptionsRe.test(link)) { // =~ /[;?]js=[01]$/; + link.href += + (link.href.indexOf('?') === -1 ? '?' : ';') + 'js=1'; + } + } +} + + +/* ============================================================ */ + /* * This code uses DOM methods instead of (nonstandard) innerHTML * to modify page. @@ -89,6 +122,7 @@ function createRequestObject() { return null; } + /* ============================================================ */ /* utility/helper functions (and variables) */ @@ -210,6 +244,101 @@ function errorInfo(str) { } } +/* ............................................................ */ +/* coloring rows during blame_data (git blame --incremental) run */ + +/** + * used to extract N from 'colorN', where N is a number, + * @constant + */ +var colorRe = /\bcolor([0-9]*)\b/; + +/** + * return N if , otherwise return null + * (some browsers require CSS class names to begin with letter) + * + * @param {HTMLElement} tr: table row element to check + * @param {String} tr.className: 'class' attribute of tr element + * @returns {Number|null} N if tr.className == 'colorN', otherwise null + * + * @globals colorRe + */ +function getColorNo(tr) { + if (!tr) { + return null; + } + var className = tr.className; + if (className) { + var match = colorRe.exec(className); + if (match) { + return parseInt(match[1], 10); + } + } + return null; +} + +var colorsFreq = [0, 0, 0]; +/** + * return one of given possible colors (curently least used one) + * example: chooseColorNoFrom(2, 3) returns 2 or 3 + * + * @param {Number[]} arguments: one or more numbers + * assumes that 1 <= arguments[i] <= colorsFreq.length + * @returns {Number} Least used color number from arguments + * @globals colorsFreq + */ +function chooseColorNoFrom() { + // choose the color which is least used + var colorNo = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + if (colorsFreq[arguments[i]-1] < colorsFreq[colorNo-1]) { + colorNo = arguments[i]; + } + } + colorsFreq[colorNo-1]++; + return colorNo; +} + +/** + * given two neigbour elements, find color which would be different + * from color of both of neighbours; used to 3-color blame table + * + * @param {HTMLElement} tr_prev + * @param {HTMLElement} tr_next + * @returns {Number} color number N such that + * colorN != tr_prev.className && colorN != tr_next.className + */ +function findColorNo(tr_prev, tr_next) { + var color_prev = getColorNo(tr_prev); + var color_next = getColorNo(tr_next); + + + // neither of neighbours has color set + // THEN we can use any of 3 possible colors + if (!color_prev && !color_next) { + return chooseColorNoFrom(1,2,3); + } + + // either both neighbours have the same color, + // or only one of neighbours have color set + // THEN we can use any color except given + var color; + if (color_prev === color_next) { + color = color_prev; // = color_next; + } else if (!color_prev) { + color = color_next; + } else if (!color_next) { + color = color_prev; + } + if (color) { + return chooseColorNoFrom((color % 3) + 1, ((color+1) % 3) + 1); + } + + // neighbours have different colors + // THEN there is only one color left + return (3 - ((color_prev + color_next) % 3)); +} + /* ............................................................ */ /* coloring rows like 'blame' after 'blame_data' finishes */ @@ -224,8 +353,6 @@ function isStartOfGroup(tr) { return tr.firstChild.className === 'sha1'; } -var colorRe = /(?:light|dark)/; - /** * change colors to use zebra coloring (2 colors) instead of 3 colors * concatenate neighbour commit groups belonging to the same commit @@ -391,6 +518,12 @@ function handleLine(commit, group) { formatDateISOLocal(commit.authorTime, commit.authorTimezone); } + // color depends on group of lines, not only on blamed commit + var colorNo = findColorNo( + document.getElementById('l'+(resline-1)), + document.getElementById('l'+(resline+group.numlines)) + ); + // loop over lines in commit group for (var i = 0; i < group.numlines; i++, resline++) { var tr = document.getElementById('l'+resline); @@ -409,7 +542,10 @@ function handleLine(commit, group) { var a_linenr = td_sha1.nextSibling.firstChild; /* */ - var tr_class = 'light'; // or tr.className + var tr_class = ''; + if (colorNo !== null) { + tr_class = 'color'+colorNo; + } if (commit.boundary) { tr_class += ' boundary'; }