slitaz-dev-tools rev 282
Import mercurial.js to have a working copy on pangolin (hg host)
author | Christophe Lincoln <pankso@slitaz.org> |
---|---|
date | Wed Mar 01 22:39:32 2017 +0100 (2017-03-01) |
parents | 3749e19b9a23 |
children | 8a5d1dfcf3c0 |
files | slitaz-mercurial-style/templates/static/mercurial.js |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/slitaz-mercurial-style/templates/static/mercurial.js Wed Mar 01 22:39:32 2017 +0100 1.3 @@ -0,0 +1,443 @@ 1.4 +// mercurial.js - JavaScript utility functions 1.5 +// 1.6 +// Rendering of branch DAGs on the client side 1.7 +// Display of elapsed time 1.8 +// Show or hide diffstat 1.9 +// 1.10 +// Copyright 2008 Dirkjan Ochtman <dirkjan AT ochtman DOT nl> 1.11 +// Copyright 2006 Alexander Schremmer <alex AT alexanderweb DOT de> 1.12 +// 1.13 +// derived from code written by Scott James Remnant <scott@ubuntu.com> 1.14 +// Copyright 2005 Canonical Ltd. 1.15 +// 1.16 +// This software may be used and distributed according to the terms 1.17 +// of the GNU General Public License, incorporated herein by reference. 1.18 + 1.19 +var colors = [ 1.20 + [ 1.0, 0.0, 0.0 ], 1.21 + [ 1.0, 1.0, 0.0 ], 1.22 + [ 0.0, 1.0, 0.0 ], 1.23 + [ 0.0, 1.0, 1.0 ], 1.24 + [ 0.0, 0.0, 1.0 ], 1.25 + [ 1.0, 0.0, 1.0 ] 1.26 +]; 1.27 + 1.28 +function Graph() { 1.29 + 1.30 + this.canvas = document.getElementById('graph'); 1.31 + if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas); 1.32 + this.ctx = this.canvas.getContext('2d'); 1.33 + this.ctx.strokeStyle = 'rgb(0, 0, 0)'; 1.34 + this.ctx.fillStyle = 'rgb(0, 0, 0)'; 1.35 + this.cur = [0, 0]; 1.36 + this.line_width = 3; 1.37 + this.bg = [0, 4]; 1.38 + this.cell = [2, 0]; 1.39 + this.columns = 0; 1.40 + this.revlink = ''; 1.41 + 1.42 + this.reset = function() { 1.43 + this.bg = [0, 4]; 1.44 + this.cell = [2, 0]; 1.45 + this.columns = 0; 1.46 + document.getElementById('nodebgs').innerHTML = ''; 1.47 + document.getElementById('graphnodes').innerHTML = ''; 1.48 + } 1.49 + 1.50 + this.scale = function(height) { 1.51 + this.bg_height = height; 1.52 + this.box_size = Math.floor(this.bg_height / 1.2); 1.53 + this.cell_height = this.box_size; 1.54 + } 1.55 + 1.56 + function colorPart(num) { 1.57 + num *= 255 1.58 + num = num < 0 ? 0 : num; 1.59 + num = num > 255 ? 255 : num; 1.60 + var digits = Math.round(num).toString(16); 1.61 + if (num < 16) { 1.62 + return '0' + digits; 1.63 + } else { 1.64 + return digits; 1.65 + } 1.66 + } 1.67 + 1.68 + this.setColor = function(color, bg, fg) { 1.69 + 1.70 + // Set the colour. 1.71 + // 1.72 + // If color is a string, expect an hexadecimal RGB 1.73 + // value and apply it unchanged. If color is a number, 1.74 + // pick a distinct colour based on an internal wheel; 1.75 + // the bg parameter provides the value that should be 1.76 + // assigned to the 'zero' colours and the fg parameter 1.77 + // provides the multiplier that should be applied to 1.78 + // the foreground colours. 1.79 + var s; 1.80 + if(typeof color == "string") { 1.81 + s = "#" + color; 1.82 + } else { //typeof color == "number" 1.83 + color %= colors.length; 1.84 + var red = (colors[color][0] * fg) || bg; 1.85 + var green = (colors[color][1] * fg) || bg; 1.86 + var blue = (colors[color][2] * fg) || bg; 1.87 + red = Math.round(red * 255); 1.88 + green = Math.round(green * 255); 1.89 + blue = Math.round(blue * 255); 1.90 + s = 'rgb(' + red + ', ' + green + ', ' + blue + ')'; 1.91 + } 1.92 + this.ctx.strokeStyle = s; 1.93 + this.ctx.fillStyle = s; 1.94 + return s; 1.95 + 1.96 + } 1.97 + 1.98 + this.edge = function(x0, y0, x1, y1, color, width) { 1.99 + 1.100 + this.setColor(color, 0.0, 0.65); 1.101 + if(width >= 0) 1.102 + this.ctx.lineWidth = width; 1.103 + this.ctx.beginPath(); 1.104 + this.ctx.moveTo(x0, y0); 1.105 + this.ctx.lineTo(x1, y1); 1.106 + this.ctx.stroke(); 1.107 + 1.108 + } 1.109 + 1.110 + this.render = function(data) { 1.111 + 1.112 + var backgrounds = ''; 1.113 + var nodedata = ''; 1.114 + 1.115 + for (var i in data) { 1.116 + 1.117 + var parity = i % 2; 1.118 + this.cell[1] += this.bg_height; 1.119 + this.bg[1] += this.bg_height; 1.120 + 1.121 + var cur = data[i]; 1.122 + var node = cur[1]; 1.123 + var edges = cur[2]; 1.124 + var fold = false; 1.125 + 1.126 + var prevWidth = this.ctx.lineWidth; 1.127 + for (var j in edges) { 1.128 + 1.129 + line = edges[j]; 1.130 + start = line[0]; 1.131 + end = line[1]; 1.132 + color = line[2]; 1.133 + var width = line[3]; 1.134 + if(width < 0) 1.135 + width = prevWidth; 1.136 + var branchcolor = line[4]; 1.137 + if(branchcolor) 1.138 + color = branchcolor; 1.139 + 1.140 + if (end > this.columns || start > this.columns) { 1.141 + this.columns += 1; 1.142 + } 1.143 + 1.144 + if (start == this.columns && start > end) { 1.145 + var fold = true; 1.146 + } 1.147 + 1.148 + x0 = this.cell[0] + this.box_size * start + this.box_size / 2; 1.149 + y0 = this.bg[1] - this.bg_height / 2; 1.150 + x1 = this.cell[0] + this.box_size * end + this.box_size / 2; 1.151 + y1 = this.bg[1] + this.bg_height / 2; 1.152 + 1.153 + this.edge(x0, y0, x1, y1, color, width); 1.154 + 1.155 + } 1.156 + this.ctx.lineWidth = prevWidth; 1.157 + 1.158 + // Draw the revision node in the right column 1.159 + 1.160 + column = node[0] 1.161 + color = node[1] 1.162 + 1.163 + radius = this.box_size / 8; 1.164 + x = this.cell[0] + this.box_size * column + this.box_size / 2; 1.165 + y = this.bg[1] - this.bg_height / 2; 1.166 + var add = this.vertex(x, y, color, parity, cur); 1.167 + backgrounds += add[0]; 1.168 + nodedata += add[1]; 1.169 + 1.170 + if (fold) this.columns -= 1; 1.171 + 1.172 + } 1.173 + 1.174 + document.getElementById('nodebgs').innerHTML += backgrounds; 1.175 + document.getElementById('graphnodes').innerHTML += nodedata; 1.176 + 1.177 + } 1.178 + 1.179 +} 1.180 + 1.181 + 1.182 +function process_dates(parentSelector){ 1.183 + 1.184 + // derived from code from mercurial/templatefilter.py 1.185 + 1.186 + var scales = { 1.187 + 'year': 365 * 24 * 60 * 60, 1.188 + 'month': 30 * 24 * 60 * 60, 1.189 + 'week': 7 * 24 * 60 * 60, 1.190 + 'day': 24 * 60 * 60, 1.191 + 'hour': 60 * 60, 1.192 + 'minute': 60, 1.193 + 'second': 1 1.194 + }; 1.195 + 1.196 + function format(count, string){ 1.197 + var ret = count + ' ' + string; 1.198 + if (count > 1){ 1.199 + ret = ret + 's'; 1.200 + } 1.201 + return ret; 1.202 + } 1.203 + 1.204 + function shortdate(date){ 1.205 + var ret = date.getFullYear() + '-'; 1.206 + // getMonth() gives a 0-11 result 1.207 + var month = date.getMonth() + 1; 1.208 + if (month <= 9){ 1.209 + ret += '0' + month; 1.210 + } else { 1.211 + ret += month; 1.212 + } 1.213 + ret += '-'; 1.214 + var day = date.getDate(); 1.215 + if (day <= 9){ 1.216 + ret += '0' + day; 1.217 + } else { 1.218 + ret += day; 1.219 + } 1.220 + return ret; 1.221 + } 1.222 + 1.223 + function age(datestr){ 1.224 + var now = new Date(); 1.225 + var once = new Date(datestr); 1.226 + if (isNaN(once.getTime())){ 1.227 + // parsing error 1.228 + return datestr; 1.229 + } 1.230 + 1.231 + var delta = Math.floor((now.getTime() - once.getTime()) / 1000); 1.232 + 1.233 + var future = false; 1.234 + if (delta < 0){ 1.235 + future = true; 1.236 + delta = -delta; 1.237 + if (delta > (30 * scales.year)){ 1.238 + return "in the distant future"; 1.239 + } 1.240 + } 1.241 + 1.242 + if (delta > (2 * scales.year)){ 1.243 + return shortdate(once); 1.244 + } 1.245 + 1.246 + for (unit in scales){ 1.247 + var s = scales[unit]; 1.248 + var n = Math.floor(delta / s); 1.249 + if ((n >= 2) || (s == 1)){ 1.250 + if (future){ 1.251 + return format(n, unit) + ' from now'; 1.252 + } else { 1.253 + return format(n, unit) + ' ago'; 1.254 + } 1.255 + } 1.256 + } 1.257 + } 1.258 + 1.259 + var nodes = document.querySelectorAll((parentSelector || '') + ' .age'); 1.260 + var dateclass = new RegExp('\\bdate\\b'); 1.261 + for (var i=0; i<nodes.length; ++i){ 1.262 + var node = nodes[i]; 1.263 + var classes = node.className; 1.264 + var agevalue = age(node.textContent); 1.265 + if (dateclass.test(classes)){ 1.266 + // We want both: date + (age) 1.267 + node.textContent += ' ('+agevalue+')'; 1.268 + } else { 1.269 + node.title = node.textContent; 1.270 + node.textContent = agevalue; 1.271 + } 1.272 + } 1.273 +} 1.274 + 1.275 +function toggleDiffstat() { 1.276 + var curdetails = document.getElementById('diffstatdetails').style.display; 1.277 + var curexpand = curdetails == 'none' ? 'inline' : 'none'; 1.278 + document.getElementById('diffstatdetails').style.display = curexpand; 1.279 + document.getElementById('diffstatexpand').style.display = curdetails; 1.280 +} 1.281 + 1.282 +function toggleLinewrap() { 1.283 + function getLinewrap() { 1.284 + var nodes = document.getElementsByClassName('sourcelines'); 1.285 + // if there are no such nodes, error is thrown here 1.286 + return nodes[0].classList.contains('wrap'); 1.287 + } 1.288 + 1.289 + function setLinewrap(enable) { 1.290 + var nodes = document.getElementsByClassName('sourcelines'); 1.291 + for (var i = 0; i < nodes.length; i++) { 1.292 + if (enable) { 1.293 + nodes[i].classList.add('wrap'); 1.294 + } else { 1.295 + nodes[i].classList.remove('wrap'); 1.296 + } 1.297 + } 1.298 + 1.299 + var links = document.getElementsByClassName('linewraplink'); 1.300 + for (var i = 0; i < links.length; i++) { 1.301 + links[i].innerHTML = enable ? 'on' : 'off'; 1.302 + } 1.303 + } 1.304 + 1.305 + setLinewrap(!getLinewrap()); 1.306 +} 1.307 + 1.308 +function format(str, replacements) { 1.309 + return str.replace(/%(\w+)%/g, function(match, p1) { 1.310 + return String(replacements[p1]); 1.311 + }); 1.312 +} 1.313 + 1.314 +function makeRequest(url, method, onstart, onsuccess, onerror, oncomplete) { 1.315 + xfr = new XMLHttpRequest(); 1.316 + xfr.onreadystatechange = function() { 1.317 + if (xfr.readyState === 4) { 1.318 + try { 1.319 + if (xfr.status === 200) { 1.320 + onsuccess(xfr.responseText); 1.321 + } else { 1.322 + throw 'server error'; 1.323 + } 1.324 + } catch (e) { 1.325 + onerror(e); 1.326 + } finally { 1.327 + oncomplete(); 1.328 + } 1.329 + } 1.330 + }; 1.331 + 1.332 + xfr.open(method, url); 1.333 + xfr.overrideMimeType("text/xhtml; charset=" + document.characterSet.toLowerCase()); 1.334 + xfr.send(); 1.335 + onstart(); 1.336 + return xfr; 1.337 +} 1.338 + 1.339 +function removeByClassName(className) { 1.340 + var nodes = document.getElementsByClassName(className); 1.341 + while (nodes.length) { 1.342 + nodes[0].parentNode.removeChild(nodes[0]); 1.343 + } 1.344 +} 1.345 + 1.346 +function docFromHTML(html) { 1.347 + var doc = document.implementation.createHTMLDocument(''); 1.348 + doc.documentElement.innerHTML = html; 1.349 + return doc; 1.350 +} 1.351 + 1.352 +function appendFormatHTML(element, formatStr, replacements) { 1.353 + element.insertAdjacentHTML('beforeend', format(formatStr, replacements)); 1.354 +} 1.355 + 1.356 +function ajaxScrollInit(urlFormat, 1.357 + nextPageVar, 1.358 + nextPageVarGet, 1.359 + containerSelector, 1.360 + messageFormat, 1.361 + mode) { 1.362 + updateInitiated = false; 1.363 + container = document.querySelector(containerSelector); 1.364 + 1.365 + function scrollHandler() { 1.366 + if (updateInitiated) { 1.367 + return; 1.368 + } 1.369 + 1.370 + var scrollHeight = document.documentElement.scrollHeight; 1.371 + var clientHeight = document.documentElement.clientHeight; 1.372 + var scrollTop = document.body.scrollTop 1.373 + || document.documentElement.scrollTop; 1.374 + 1.375 + if (scrollHeight - (scrollTop + clientHeight) < 50) { 1.376 + updateInitiated = true; 1.377 + removeByClassName('scroll-loading-error'); 1.378 + container.lastElementChild.classList.add('scroll-separator'); 1.379 + 1.380 + if (!nextPageVar) { 1.381 + var message = { 1.382 + class: 'scroll-loading-info', 1.383 + text: 'No more entries' 1.384 + }; 1.385 + appendFormatHTML(container, messageFormat, message); 1.386 + return; 1.387 + } 1.388 + 1.389 + makeRequest( 1.390 + format(urlFormat, {next: nextPageVar}), 1.391 + 'GET', 1.392 + function onstart() { 1.393 + var message = { 1.394 + class: 'scroll-loading', 1.395 + text: 'Loading...' 1.396 + }; 1.397 + appendFormatHTML(container, messageFormat, message); 1.398 + }, 1.399 + function onsuccess(htmlText) { 1.400 + if (mode == 'graph') { 1.401 + var addHeight = htmlText.match(/^\s*<canvas id="graph".*height="(\d+)"><\/canvas>$/m)[1]; 1.402 + addHeight = parseInt(addHeight); 1.403 + graph.canvas.height = addHeight; 1.404 + 1.405 + var dataStr = htmlText.match(/^\s*var data = (.*);$/m)[1]; 1.406 + var data = JSON.parse(dataStr); 1.407 + if (data.length < nextPageVar) { 1.408 + nextPageVar = undefined; 1.409 + } 1.410 + graph.reset(); 1.411 + graph.render(data); 1.412 + } else { 1.413 + var doc = docFromHTML(htmlText); 1.414 + var nodes = doc.querySelector(containerSelector).children; 1.415 + var curClass = 'c' + Date.now(); 1.416 + while (nodes.length) { 1.417 + var node = nodes[0]; 1.418 + node = document.adoptNode(node); 1.419 + node.classList.add(curClass); 1.420 + container.appendChild(node); 1.421 + } 1.422 + process_dates('.' + curClass); 1.423 + } 1.424 + 1.425 + nextPageVar = nextPageVarGet(htmlText, nextPageVar); 1.426 + }, 1.427 + function onerror(errorText) { 1.428 + var message = { 1.429 + class: 'scroll-loading-error', 1.430 + text: 'Error: ' + errorText 1.431 + }; 1.432 + appendFormatHTML(container, messageFormat, message); 1.433 + }, 1.434 + function oncomplete() { 1.435 + removeByClassName('scroll-loading'); 1.436 + updateInitiated = false; 1.437 + scrollHandler(); 1.438 + } 1.439 + ); 1.440 + } 1.441 + } 1.442 + 1.443 + window.addEventListener('scroll', scrollHandler); 1.444 + window.addEventListener('resize', scrollHandler); 1.445 + scrollHandler(); 1.446 +}