-
Notifications
You must be signed in to change notification settings - Fork 524
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
InheritanceDiagram: cleanup code; avoid iframe hack; use single param…
…eter (#5056) * Cleanup code; avoid iframe hack * feedback * Prevent cutoffs when xpos is negative * No inheritance diagram when there is no inheritance chain
- Loading branch information
Showing
1 changed file
with
94 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,129 @@ | ||
<% | ||
/* | ||
Draws an responsive SVG diagram for the inheritance chain (inverted in rtl) | ||
Draws an SVG diagram to display an interface's inheritance chain | ||
$0 - width - defaults to 600 | ||
$1 - height - defaults to 70 | ||
$2 - offset - defaults to 50 | ||
$3 - Interface name | ||
$0 - Interface name (defaults to the interface page the macro is called on) | ||
Test pages | ||
- http://localhost:3000/en-US/docs/Web/API/SVGTextPositioningElement | ||
- http://localhost:3000/en-US/docs/Web/API/WheelEvent | ||
- http://localhost:3000/en-US/docs/Web/API/USB/connect_event | ||
*/ | ||
var data = web.getJSONData("InterfaceData"); | ||
var slug = env.slug; | ||
var result = ""; | ||
// slug is not available in preview mode. | ||
if (slug) { | ||
var locale = env.locale; | ||
var href = 'https://developer.mozilla.org/' + locale + '/docs/Web/API/'; | ||
var mainIF = $3 || slug.replace('Web/API/','').split('/')[0]; | ||
var rtlLocales = ['ar', 'he', 'fa']; | ||
var inheritanceChain = [mainIF]; | ||
var inh = data[0][mainIF] != undefined ? data[0][mainIF].inh : ''; | ||
var width = $0 || 600; | ||
var height = $1 || 70; | ||
var offset = $2 || 50; | ||
var rtl = false; | ||
if (rtlLocales.indexOf(locale) != -1) { | ||
rtl = true; | ||
} | ||
const data = web.getJSONData("InterfaceData")[0]; | ||
const href = `/${env.locale}/docs/Web/API/`; | ||
const mainInterfaceName = $0 || env.slug.replace('Web/API/','').split('/')[0]; | ||
let height = 40; | ||
let offset = 0; | ||
let xpos = 1; | ||
let ypos = 1; | ||
let inheritanceChain = [mainInterfaceName]; | ||
let inh = data[mainInterfaceName] != undefined ? data[mainInterfaceName].inh : ''; | ||
function getInheritance(inh) { | ||
if (inh.length > 0) { | ||
if (inh !== '') { | ||
inheritanceChain.unshift(inh); | ||
if (Object.prototype.hasOwnProperty.call(data[0], inh)) { | ||
var inh = data[0][inh].inh; | ||
if (data[inh]) { | ||
inh = data[inh].inh; | ||
getInheritance(inh); | ||
} | ||
} | ||
} | ||
getInheritance(inh); | ||
var l = 0; | ||
function rectWithText(x, y, fill, interface, reverse) { | ||
var flip = rtl ? 'transform="scale(-1 1)"' : ''; | ||
var inv = rtl ? '-' : ''; | ||
l = interface.length * 10 < 75 ? 75 : interface.length * 10; | ||
function rectWithText(x, y, fill, interfaceName, reverse) { | ||
const rectWidth = interfaceName.length * 8 < 75 ? 75 : interfaceName.length * 8; | ||
if (reverse) { | ||
xpos -= l; | ||
xpos -= rectWidth; | ||
x = xpos; | ||
} else { | ||
xpos += rectWidth; | ||
} | ||
if (!reverse) { | ||
xpos += l; | ||
} | ||
return '<a xlink:href="' + href + interface + '" target="_top">' + | ||
'<rect x="'+x+'" y="'+y+'" width="'+l+'" height="50" fill="'+fill+'" stroke="#D4DDE4" stroke-width="2px" />' + | ||
'<text '+flip+' x="'+inv+(x+l/2)+'" y="'+(y+29)+'" font-size="12px" font-family="Consolas,Monaco,Andale Mono,monospace"' + | ||
' fill="#4D4E53" text-anchor="middle" alignment-baseline="middle">'+interface+'</text>' + | ||
'</a>'; | ||
return ` | ||
<a style="text-decoration: none;" xlink:href="${href+interfaceName}"> | ||
<rect x="${x}" y="${y}" width="${rectWidth}" height="25" fill="${fill}" stroke="#D4DDE4" stroke-width="2px" /> | ||
<text x="${x+rectWidth/2}" y="${y+16}" font-size="10px" fill="#4D4E53" text-anchor="middle"> | ||
${interfaceName} | ||
</text> | ||
</a>`; | ||
} | ||
function lineWithTriangle(x, y, reverse) { | ||
var str = ''; | ||
let str = ''; | ||
let polylinePoints = `${x},${y+14} ${x+10},${y+9} ${x+10},${y+19} ${x},${y+14}`; | ||
let linePoints = `x1="${x+10}" y1="${y+14}" x2="${x+30}" y2="${y+14}"`; | ||
if (reverse) { | ||
str += '<polyline points="'+x+','+(y+24)+' '+(x-10)+','+(y+19)+' '+(x-10)+','+(y+29)+' '+x+','+(y+24)+'" stroke="#D4DDE4" fill="none"/>'; | ||
x -= 10; | ||
str += '<line x1="'+x+'" y1="'+(y+24)+'" x2="'+(x-30)+'" y2="'+(y+24)+'" stroke="#D4DDE4"/>'; | ||
} else { | ||
str += '<polyline points="'+x+','+(y+24)+' '+(x+10)+','+(y+19)+' '+(x+10)+','+(y+29)+' '+x+','+(y+24)+'" stroke="#D4DDE4" fill="none"/>'; | ||
x += 10; | ||
str += '<line x1="'+x+'" y1="'+(y+24)+'" x2="'+(x+30)+'" y2="'+(y+24)+'" stroke="#D4DDE4"/>'; | ||
polylinePoints = `${x},${y+14} ${x-10},${y+9} ${x-10},${y+19} ${x},${y+14}`; | ||
linePoints = `x1="${x-10}" y1="${y+14}" x2="${x-30}" y2="${y+14}"`; | ||
} | ||
str += `<polyline points="${polylinePoints}" stroke="#D4DDE4" fill="none"/>`; | ||
x -= 10; | ||
str += `<line ${linePoints} stroke="#D4DDE4"/>`; | ||
return str; | ||
} | ||
var padding = (height / width) * 100; | ||
var xpos = 1; | ||
var ypos = 1; | ||
var viewbox = 'viewbox="-'+ offset + ' 0 '+ width + ' ' + height +'"'; | ||
function connectingLineWithTriangle() { | ||
let str = ''; | ||
if (rtl) { | ||
viewbox = 'viewbox="510 0 '+ width + ' ' + height +'" transform="scale(-1 1)"'; | ||
str += `<polyline points="${xpos},${ypos+14} ${xpos+10},${ypos+9} ${xpos+10},${ypos+19} ${xpos},${ypos+14}" stroke="#D4DDE4" fill="none"/>`; | ||
xpos += 10; | ||
str += `<line x1="${xpos}" y1="${ypos+14}" x2="${xpos+8}" y2="${ypos+14}" stroke="#D4DDE4"/>`; | ||
xpos += 8; | ||
str += `<line x1="${xpos}" y1="${ypos+14}" x2="${xpos}" y2="${ypos+59}" stroke="#D4DDE4"/>`; | ||
ypos = 60; | ||
str += `<line x1="${xpos}" y1="${ypos}" x2="${xpos-17}" y2="${ypos}" stroke="#D4DDE4"/>`; | ||
return str; | ||
} | ||
result = '<div id="interfaceDiagram" style="display: inline-block; position: relative; width: 100%; padding-bottom: '+ padding +'%; vertical-align: middle; overflow: hidden;">' + | ||
'<svg style="display: inline-block; position: absolute; top: 0; left: 0;" '+ viewbox +' preserveAspectRatio="xMinYMin meet">'; | ||
for (var i = 0; i < inheritanceChain.length; i++) { | ||
var fill = (inheritanceChain[i] == mainIF) ? '#F4F7F8': '#fff'; | ||
// we are going to the second row with a special line | ||
if (i == 4) { | ||
result += '<polyline points="'+xpos+','+(ypos+24)+' '+(xpos+10)+','+(ypos+19)+' '+(xpos+10)+','+(ypos+29)+' '+xpos+','+(ypos+24)+'" stroke="#D4DDE4" fill="none"/>' | ||
xpos += 10; | ||
result += '<line x1="'+xpos+'" y1="'+(ypos+24)+'" x2="'+(xpos+8)+'" y2="'+(ypos+24)+'" stroke="#D4DDE4"/>'; | ||
xpos += 8; | ||
result += '<line x1="'+xpos+'" y1="'+(ypos+24)+'" x2="'+xpos+'" y2="'+(ypos+89)+'" stroke="#D4DDE4"/>'; | ||
ypos = 90; | ||
result += '<line x1="'+xpos+'" y1="'+ypos+'" x2="'+(xpos-17)+'" y2="'+ypos+'" stroke="#D4DDE4"/>'; | ||
xpos -= 18; | ||
ypos = 65; | ||
} | ||
// first row | ||
if (i < 4) { | ||
result += rectWithText(xpos, ypos, fill, inheritanceChain[i]); | ||
if (i != inheritanceChain.length - 1 && i != 3) { | ||
result += lineWithTriangle(xpos, ypos); | ||
xpos += 40; | ||
function drawDiagram(inheritanceChain) { | ||
let str = ''; | ||
for (let i = 0; i < inheritanceChain.length; i++) { | ||
const fill = (inheritanceChain[i] == mainInterfaceName) ? '#F4F7F8': '#fff'; | ||
// we are going to the second row with a connecting line | ||
if (i === 4) { | ||
str += connectingLineWithTriangle(); | ||
xpos -= 18; | ||
ypos = 47; | ||
} | ||
} else { | ||
// first row | ||
if (i < 4) { | ||
str += rectWithText(xpos, ypos, fill, inheritanceChain[i]); | ||
if (i != inheritanceChain.length - 1 && i != 3) { | ||
str += lineWithTriangle(xpos, ypos); | ||
xpos += 30; | ||
} | ||
// second row | ||
result += rectWithText(xpos, ypos, fill, inheritanceChain[i], true); | ||
if (i != inheritanceChain.length - 1 && i != 3) { | ||
result += lineWithTriangle(xpos, ypos, true); | ||
xpos -= 40; | ||
} else { | ||
height = 80; // need more space | ||
str += rectWithText(xpos, ypos, fill, inheritanceChain[i], true); | ||
if (i != inheritanceChain.length - 1) { | ||
str += lineWithTriangle(xpos, ypos, true); | ||
xpos -= 30; | ||
} | ||
if (xpos < 0) { | ||
// prevent cut off in case of a really long chain (see e.g. SVGTextPositioningElement) | ||
offset = 1 + Math.abs(xpos); | ||
} | ||
} | ||
} | ||
return str; | ||
} | ||
result +='</svg></div>'; | ||
} | ||
%> | ||
<div class="hidden" id="inheritance_diagram"> | ||
|
||
<pre class="brush: html"> | ||
<%=result%> | ||
</pre> | ||
let output = ''; | ||
<pre class="brush: css"> | ||
a:hover text { fill: #0095DD; pointer-events: all;} | ||
</pre> | ||
|
||
</div> | ||
if (inheritanceChain.length > 1) { | ||
let diagram = drawDiagram(inheritanceChain); // needs to run first to calculate offset and height | ||
output = `<svg viewbox="-${offset} 0 650 ${height}" preserveAspectRatio="xMinYMin meet">`; | ||
output += diagram; | ||
output +='</svg>'; | ||
} | ||
<%-await template("EmbedLiveSample", ["inheritance_diagram", width, height, '', '', 'inheritance-diagram-frame'])%> | ||
%> | ||
<%-output%> |