github.com/kvattikuti/drone@v0.2.1-0.20140603034306-d400229a327a/cmd/droned/assets/js/main.js (about) 1 ;// Live commit updates 2 3 if(typeof(Drone) === 'undefined') { Drone = {}; } 4 5 (function () { 6 Drone.CommitUpdates = function(socket) { 7 if(typeof(socket) === "string") { 8 var url = [(window.location.protocol == 'https:' ? 'wss' : 'ws'), 9 '://', 10 window.location.host, 11 socket].join('') 12 this.socket = new WebSocket(url); 13 } else { 14 this.socket = socket; 15 } 16 17 this.lineFormatter = new Drone.LineFormatter(); 18 this.attach(); 19 } 20 21 Drone.CommitUpdates.prototype = { 22 lineBuffer: "", 23 autoFollow: false, 24 25 startOutput: function(el) { 26 if(typeof(el) === 'string') { 27 this.el = document.getElementById(el); 28 } else { 29 this.el = el; 30 } 31 32 if(!this.reqId) { 33 this.updateScreen(); 34 } 35 }, 36 37 stopOutput: function() { 38 this.stoppingRefresh = true; 39 }, 40 41 attach: function() { 42 this.socket.onopen = this.onOpen; 43 this.socket.onerror = this.onError; 44 this.socket.onmessage = this.onMessage.bind(this); 45 this.socket.onclose = this.onClose; 46 }, 47 48 updateScreen: function() { 49 if(this.lineBuffer.length > 0) { 50 this.el.innerHTML += this.lineBuffer; 51 this.lineBuffer = ''; 52 53 if (this.autoFollow) { 54 window.scrollTo(0, document.body.scrollHeight); 55 } 56 } 57 58 if(this.stoppingRefresh) { 59 this.stoppingRefresh = false; 60 } else { 61 window.requestAnimationFrame(this.updateScreen.bind(this)); 62 } 63 }, 64 65 onOpen: function() { 66 console.log('output websocket open'); 67 }, 68 69 onError: function(e) { 70 console.log('websocket error: ' + e); 71 }, 72 73 onMessage: function(e) { 74 this.lineBuffer += this.lineFormatter.format(e.data); 75 }, 76 77 onClose: function(e) { 78 console.log('output websocket closed: ' + JSON.stringify(e)); 79 window.location.reload(); 80 } 81 }; 82 83 // Polyfill rAF for older browsers 84 window.requestAnimationFrame = window.requestAnimationFrame || 85 window.webkitRequestAnimationFrame || 86 function(callback, element) { 87 return window.setTimeout(function() { 88 callback(+new Date()); 89 }, 1000 / 60); 90 }; 91 92 window.cancelRequestAnimationFrame = window.cancelRequestAnimationFrame || 93 window.cancelWebkitRequestAnimationFrame || 94 function(fn) { 95 window.clearTimeout(fn); 96 }; 97 98 })(); 99 ;// Format ANSI to HTML 100 101 if(typeof(Drone) === 'undefined') { Drone = {}; } 102 103 (function() { 104 Drone.LineFormatter = function() {}; 105 106 Drone.LineFormatter.prototype = { 107 regex: /\u001B\[([0-9]+;?)*[Km]/g, 108 styles: [], 109 110 format: function(s) { 111 // Check for newline and early exit? 112 s = s.replace(/</g, "<"); 113 s = s.replace(/>/g, ">"); 114 115 var output = ""; 116 var current = 0; 117 while (m = this.regex.exec(s)) { 118 var part = s.substring(current, m.index); 119 current = this.regex.lastIndex; 120 121 var token = s.substr(m.index, this.regex.lastIndex - m.index); 122 var code = token.substr(2, token.length-2); 123 124 var pre = ""; 125 var post = ""; 126 127 switch (code) { 128 case 'm': 129 case '0m': 130 var len = this.styles.length; 131 for (var i=0; i < len; i++) { 132 this.styles.pop(); 133 post += "</span>" 134 } 135 break; 136 case '30;42m': pre = '<span style="color:black;background:lime">'; break; 137 case '36m': 138 case '36;1m': pre = '<span style="color:cyan;">'; break; 139 case '31m': 140 case '31;31m': pre = '<span style="color:red;">'; break; 141 case '33m': 142 case '33;33m': pre = '<span style="color:yellow;">'; break; 143 case '32m': 144 case '0;32m': pre = '<span style="color:lime;">'; break; 145 case '90m': pre = '<span style="color:gray;">'; break; 146 case 'K': 147 case '0K': 148 case '1K': 149 case '2K': break; 150 } 151 152 if (pre !== "") { 153 this.styles.push(pre); 154 } 155 156 output += part + pre + post; 157 } 158 159 var part = s.substring(current, s.length); 160 output += part; 161 return output; 162 } 163 }; 164 })();