1/* eslint-disable */ 2var billboardDemo = { 3 replacer: { 4 plugin: "__PLUGIN__" 5 }, 6 timer: { 7 code: null, 8 btn: null 9 }, 10 11 /** 12 * Initializer 13 */ 14 init: function() { 15 this.$wrapper = document.getElementById("wrapper"); 16 this.$chartArea = document.querySelector(".chart_area"); 17 this.$list = document.querySelector(".sidebar-nav"); 18 this.$title = document.getElementById("title"); 19 this.$description = document.getElementById("description"); 20 this.$codeArea = document.querySelector(".code"); 21 this.$launch = document.getElementById("launch"); 22 23 this.$html = document.querySelector("code.html"); 24 this.$code = document.querySelector("code.javascript"); 25 26 this.$clipboardBtn = this.$codeArea.querySelector(".button.clipboard"); 27 28 this.WIDTH = 768; 29 this.selectedClass = "selected"; 30 31 this._bindEvents(); 32 this._createList(); 33 34 location.hash && this.showDemo(location.hash); 35 }, 36 37 _bindEvents: function() { 38 var $wrapper = this.$wrapper; 39 var WIDTH = this.WIDTH; 40 var ctx = this; 41 42 document.getElementById("menu-toggle").addEventListener("click", function(e) { 43 $wrapper.className = $wrapper.className ? "" : "toggled"; 44 e.preventDefault(); 45 }, false); 46 47 this.$codeArea.addEventListener("click", function(e) { 48 var el = e.target; 49 50 if (el.tagName === "BUTTON") { 51 if (el.className.indexOf("clipboard") > -1) { 52 var pos = document.documentElement.scrollTop; 53 54 ctx.copyToClipboard(); 55 document.documentElement.scrollTop = pos; 56 } else { 57 ctx.editor(ctx.$code.textContent, el.innerHTML, e.altKey); 58 } 59 } 60 }); 61 62 window.addEventListener("resize", function() { 63 if (window.innerWidth > WIDTH) { 64 $wrapper && ($wrapper.className = ""); 65 } 66 }); 67 68 window.addEventListener("hashchange", function() { 69 ctx.showDemo(location.hash); 70 }); 71 72 this.$code.addEventListener("keydown", function(e) { 73 if (/^(9|13|3[27-9]|40)$/.test(e.keyCode)) { 74 if (e.keyCode === 9) { 75 document.execCommand("insertHTML", false, "	"); 76 e.preventDefault(); 77 } 78 79 return; 80 } 81 82 ctx.timer.code && clearTimeout(ctx.timer.code); 83 ctx.timer.code = setTimeout(function() { 84 try { 85 eval(e.target.textContent); 86 } catch(e) {} 87 }, 700); 88 }, false); 89 90 this.$code.addEventListener("focus", function(e) { 91 e.target.classList.add("focus"); 92 }); 93 94 this.$code.addEventListener("blur", function(e) { 95 e.target.classList.remove("focus"); 96 }); 97 98 this.$launch.addEventListener("click", function(e) { 99 var el = e.target; 100 101 if (el.tagName === "BUTTON") { 102 ctx.editor(null, el.innerHTML, e.altKey); 103 } 104 }) 105 }, 106 107 /** 108 * Create left menu list 109 * @private 110 */ 111 _createList: function() { 112 var html = []; 113 114 Object.keys(demos).forEach(function(key) { 115 html.push("<li><h4>" + key + "</h4>"); 116 117 Object.keys(demos[key]).sort().forEach(function (v, i) { 118 i === 0 && html.push("<ul>"); 119 html.push("<li><a href='#"+ [key, v].join(".") + "'>" + v + "</a></li>"); 120 }); 121 122 html.push("</ul></li>"); 123 }); 124 125 this.$chartArea.querySelector(".item_count").innerHTML = (html.length - 2); 126 this.$list.innerHTML = html.join(""); 127 }, 128 129 /** 130 * Click handler 131 * @param {String} type 132 */ 133 showDemo: function(type) { 134 if (!type) { 135 return; 136 } 137 138 // remove legend 139 var $legend = document.querySelector(".legend"); 140 $legend && $legend.parentNode.removeChild($legend); 141 142 if (window.innerWidth <= this.WIDTH) { 143 this.$wrapper.className = ""; 144 } 145 146 type = type.replace("#", "").split("."); 147 148 this.generate(type[0], type[1]); 149 150 this.$title.innerHTML = type[1] 151 .replace(/([A-Z][a-z])/g, " $1") 152 .replace(/([A-Z]+)/g, " $1"); 153 154 // set description 155 this.$description.innerHTML = demos[type[0]][type[1]].description || ""; 156 this.$codeArea.style.display = "block"; 157 158 // remove selected class 159 var $selected = this.$list.querySelector("[class="+ this.selectedClass +"]"); 160 $selected && ($selected.className = $selected.className.replace(this.selectedClass,"")); 161 162 // add selected class 163 $selected = this.$list.querySelector("[href='#"+ type.join(".") +"']"); 164 $selected.className += this.selectedClass; 165 166 window.scrollTo(0, 0); 167 }, 168 169 /** 170 * Generate chart demo 171 * @param {String} type 172 * @param {String} key 173 * @returns {boolean} 174 */ 175 generate: function(type, key) { 176 var inst = bb.instance; 177 var typeData = demos[type][key]; 178 var isArray = typeData && typeData.constructor === Array; 179 var camelize = function(s) { 180 return s.replace(/-./g, function(x) { return x.toUpperCase()[1] }); 181 } 182 var self = this; 183 184 inst.length && inst.forEach(function (c) { 185 var timer = c.timer; 186 var el = c.$.chart; 187 188 try { 189 timer && timer.forEach(function (v) { 190 clearTimeout(v); 191 }); 192 } finally { 193 el.parentNode && el.parentNode.removeChild(el); 194 c.destroy(); 195 } 196 }); 197 198 var code = { 199 markup: [], 200 data: [], 201 esm: [] 202 }; 203 204 key = type +"."+ key; 205 206 // generate chart 207 isArray ? typeData.forEach(function(t, i) { 208 self._addChartInstance(t, key, i + 1, code); 209 }
209) : this._addChartInstance(typeData, key, undefined, code); 210 211 this.$html.innerHTML = code.markup.join(""); 212 213 // UMD 214 code.data = code.data.join("") 215 .replace(/"(area|area-line-range|area-spline|area-spline-range|area-step|bar|bubble|candlestick|donut|gauge|line|pie|radar|scatter|spline|step|selection|subchart|zoom)(\(\))?",?/g, function(match, p1, p2, p3, offset, string) { 216 var module = camelize(p1); 217 218 code.esm.indexOf(module) === -1 && 219 code.esm.push(module); 220 221 return ( 222 /(selection|subchart|zoom)/.test(module) ? "true" : '"'+ p1 +'"' 223 ) + ", // for ESM specify as: " + module +"()"; 224 }); 225 226 this.$code.innerHTML = '// for ESM environment, need to import modules as:\r\n' + 227'// import bb, {'+ code.esm.join(", ") +'} from "billboard.js"\r\n\r\n' + 228code.data; 229 230 this.$code.scrollTop = 0; 231 232 hljs.highlightBlock(this.$html); 233 hljs.highlightBlock(this.$code); 234 235 return false; 236 }, 237 copyToClipboard: function() { 238 var text = this.$code.textContent; 239 var errMsg = false; 240 var ctx = this; 241 242 if (navigator.clipboard) { 243 navigator.clipboard.writeText(text) 244 .then(function() { 245 ctx.showCopyMsg(); 246 }, function(e) { 247 console.error("An error occured:", errMsg); 248 }); 249 } else { 250 var textArea = document.createElement("textarea"); 251 252 textArea.value = text; 253 textArea.style.cssText = "width:0;height:0"; 254 document.body.appendChild(textArea); 255 256 textArea.focus(); 257 258 if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { 259 var editable = textArea.contentEditable; 260 var readOnly = textArea.readOnly; 261 262 textArea.contentEditable = true; 263 textArea.readOnly = true; 264 265 var range = document.createRange(); 266 range.selectNodeContents(textArea); 267 268 var selection = window.getSelection(); 269 selection.removeAllRanges(); 270 selection.addRange(range); 271 textArea.setSelectionRange(0, 999999); 272 273 textArea.contentEditable = editable; 274 textArea.readOnly = readOnly; 275 } else { 276 textArea.select(); 277 } 278 279 try { 280 document.execCommand("copy"); 281 ctx.showCopyMsg(); 282 } catch (e) { 283 console.error("An error occured:", errMsg); 284 } 285 286 document.body.removeChild(textArea); 287 } 288 }, 289 showCopyMsg: function() { 290 if (this.timer.btn) { 291 return; 292 } 293 294 var btn = this.$clipboardBtn; 295 var ctx = this; 296 var origText = btn.innerHTML; 297 298 btn.innerHTML = "Copied!"; 299 300 this.timer.btn = setTimeout(function() { 301 btn.innerHTML = origText; 302 ctx.timer.btn = null; 303 }, 1000); 304 }, 305 getLowerFirstCase: function(str) { 306 return /^(JSON)/.test(str) ? 307 str : str.charAt(0).toLowerCase() + str.slice(1); 308 }, 309 310 getReplaced: function(str) { 311 return str.replace(/\"?(function|})\"?/g, "$1") 312 .replace(/\\"/g, "\"") 313 .replace(/</g, "<") 314 .replace(/\\t/g, "\t") 315 .replace(/\t{5}/g, "") 316 .replace(/\\r/g, "\r") 317 .replace(/"(\w+)":/g, "$1:"); 318 }, 319 320 getPluginsCodeStr: function(val) { 321 var key = this.replacer.plugin; 322 var plugins = key; 323 324 val.forEach(function(p) { 325 Object.keys(p).forEach(function(key) { 326 plugins += "new bb.plugin."+ key +"("; 327 plugins += JSON.stringify(p[key], function(k, v) { 328 return typeof v === "function" ? v.toString() : v; 329 }
329, 5).replace(/\\n/g, "\n").replace(/}$/, " }"); 330 plugins += "),"; 331 }) 332 }); 333 334 335 return this.getReplaced(plugins) + key; 336 }, 337 338 getCodeStr: function(options, index) { 339 var self = this; 340 var codeStr = "var chart"+ (index > 1 ? index : "") +" = bb.generate(" + 341 this.getReplaced(JSON.stringify(options, function(k, v) { 342 if (typeof v === "function") { 343 return v.toString().replace(/\t+}$/, Array(/(format|data)/.test(k) ? 8 : 4).join(" ") + "}"); 344 } else if (/(columns|rows|json)/.test(k)) { 345 var str = JSON.stringify(v) 346 .replace(/\[\[/g, "[\r\n\t[") 347 .replace(/\]\]/g, "]\r\n ]") 348 .replace(/(],)/g, "$1\r\n\t") 349 .replace(/(\"|\d),/g, "$1, "); 350 351 return k === "json" ? 352 str.replace(/{/, "{\r\n\t").replace(/}/, "\r\n }") : str; 353 } else if (k === "_plugins") { 354 return [self.getPluginsCodeStr(v)]; 355 } 356 357 return v; 358 }, 2)) 359 .replace("_plugins", "plugins") 360 .replace(new RegExp('"?'+ this.replacer.plugin +'"?', "g"), ""); 361 362 if (/multiline/i.test(options.bindto)) { 363 codeStr = codeStr.replace(/\\n(?=(\t|\s+))/g, "") 364 .replace(/\\\\n(?=[a-zA-Z0-9])/g, "\\n"); 365 } else { 366 codeStr = codeStr.replace(/\\n(?!T)/g, "\n") 367 .replace(/\\(u)/g, "\$1"); 368 } 369 370 codeStr += ");"; 371 372 return codeStr; 373 }, 374 375 _addChartInstance: function(type, typeKey, index, code) { 376 typeKey = typeKey.split("."); 377 378 var key = this.getLowerFirstCase(typeKey[1]); 379 380 if (index) { 381 key += "_"+ index; 382 } 383 384 var $el = document.getElementById(key); 385 var template; 386 var plugins; 387 388 if (!$el) { 389 $el = document.createElement("div"); 390 $el.id = key; 391 392 if ((index && index === 1) || !index) { 393 this.$chartArea.innerHTML = ""; 394 } 395 396 this.$chartArea.appendChild($el); 397 398 if (/^(legend|tooltip)Template/.test(key) || /(sparkline)/.test(key)) { 399 const name = RegExp.$1; 400 let attrName = "id"; 401 402 template = document.createElement("div"); 403 404 if (key === "sparkline") { 405 attrName = "className"; 406 } 407 408 template[attrName] = this.getLowerFirstCase(RegExp.$1); 409 template.style.textAlign = "center"; 410 411 this.$chartArea.appendChild(template); 412 template = "<div "+ attrName.replace(/name/i, "") +"=\""+ template[attrName] +"\"></div>"; 413 } 414 415 if (typeKey[0] === "Plugins") { 416 type.options._plugins.forEach(function(v) { 417 plugins = Object.keys(v).map(function(p) { 418 return new bb.plugin[p](v[p]); 419 }); 420 }); 421 } 422 } 423 424 var func = type.func; 425 var style = type.style; 426 var options = type.options; 427 428 options.bindto = "#" + key; 429 430 if (plugins) { 431 options.plugins = plugins; 432 } 433 434 var inst = bb.generate(options); 435 436 delete options.plugins; 437 inst.timer = []; 438 439 var codeStr = this.getCodeStr(options, index); 440 441 // markup 442 if ((index && index === 1) || !index) { 443 code.markup.push("<!-- Markup -->\r\n<div id=\"" + key + "\"></div>\r\n" + (template ? template + "\r\n" : "")); 444 } else if (index && index > 1) { 445 code.markup.push("<div id=\"" + key + "\"></div>\r\n" + (template ? template + "\r\n" : "")); 446 } 447 448 if (index && index > 1) { 449 code.data.push("\r\n\r\n"); 450 } 451 452 // script this.$code.innerHTML 453 code.data.push(codeStr.replace(/"(\[|{)/, "$1").replace(/(\]|})"/, "$1")); 454 455 try { 456 if (func) { 457 code.data.push("\r\n\r\n" + func.toString() 458 .replace(/[\t\s]*function\s*\(chart[\d+]?\) \{[\r\n\t\s]*/, "") 459 .replace(/}$/, "") 460 .replace(/chart.timer = \[[\r\n\t\s]*/, "") 461 .replace(/\t{5}/g, "") 462 .replace(/[\r\n\t\s]*\];?[\r\n\t\s]*$/, "") 463 .replace(/(\d)\),?/g, "$1);")); 464 465 func(inst); 466 } 467 } catch(e) {} 468 469 // style 470 if (style) { 471 code.markup.unshift("<style>\r\n"+ style.join("\r\n") +"\r\n</style>\r\n\r\n"); 472 } 473 }, 474 475 /** 476 * Open online editor 477 * @param {String} bodyCode Code string 478 * @param {String} type "JS" | "TS" 479 * @param {Boolean} isOpen true: open as new window, false: Embed 480 */ 481 editor: function(bodyCode, type, isOpen) { 482 var id = (bodyCode && bodyCode.match(/bindto: \"#(.*)\"/) || [,"chart"])[1]; 483 var html = "<div id='"+ id +"'></div>"; 484 var code = { 485 import: [ 486 '// base css', 487 'import "billboard.js/dist/theme/insight.css";', 488 'import bb from "billboard.js";', 489 ].join("\r\n"), 490 body: bodyCode || [ 491 'bb.generate({', 492 ' data: {', 493 ' columns: [', 494 ' ["data1", 500, 350, 300, 0, 0, 0],', 495 ' ["data2", 230, 100, 140, 200, 150, 50]', 496 ' ]', 497 ' }', 498 '});' 499 ].join("\r\n") 500 }; 501 502 // Create the project payload. 503 var project = { 504 files: { 505 "index.html": html 506 }, 507 title: "billboard.js: Playground!", 508 description: "Simple billboard.js project", 509 template: type === "JS" ? "javascript" : "typescript", 510 tags: ["chart", "billborad.js", "d3", "data visualization"] , 511 dependencies: { 512 "billboard.js": "*" 513 } 514 }; 515 516 project.files["index."+ type.toLowerCase()] = code.import +"\r\n\r\n"+ code.body; 517 518 this.$wrapper.className = ""; 519 520 if (isOpen) { 521 StackBlitzSDK.openProject(project); 522 } else { 523 this.$title.innerHTML = "Code Editor ("+ type +")"; 524 this.$codeArea.style.display = "none"; 525 location.hash = ""; 526 527 if (!this.$chartArea.querySelector("#editor")) { 528 this.$chartArea.innerHTML = "<div id='editor'></div>"; 529 } 530 531 StackBlitzSDK.embedProject("editor", project, { 532 height: "80%", 533 forceEmbedLayout: true 534 }); 535 } 536 } 537};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.