Adj – User Documentation

1. User Guide

1.1. Simplified BSD License

// Copyright (c) 2002-2016, Nirvana Research
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

1.2. Contributors

// Idea and first implementation - Leo Baschy <srguiwiz12 AT nrvr DOT com>
// Contributor - Hans Baschy

1.3. Contact

// Project contact: <adj.project AT nrvr DOT com>

1.4. Repository

// Public repository - https://github.com/srguiwiz/adj-js

1.4.1. Staying Current

// Stable releases (recent) - https://github.com/srguiwiz/adj-js/releases
//
// Blog - http://leosbog.nrvr.com/category/adj/
//
// Commit list - https://github.com/srguiwiz/adj-js/commits/master

1.5. For The Impatient

If you have seen a demo or attended a class, and quickly want to get started on your own, consider:

1.6. Introduction

Adj commands modify SVG.

One significant feature is "relative constraints".

It is possible to execute all Adj modification of SVG on the SVG document author's workstation, then save the document and let other users view it.

Alternatively, it is possible to allow execution of Adj modification of SVG when a user is viewing, possibly interacting with an SVG document.

As implemented, it builds on SVG and contemporary browsers.

1.7. Purpose

The original purpose of the Adj framework has been to facilitate creation and long-term maintenance of system diagrams.

Adj has been designed specifically for diagrams of large complexity.

Because of its general nature, other uses may be possible.

1.8. Implementation Rationale

Other attempts had been made at enhancing drawing tools, e.g. an Adobe Illustrator plug-in. Still there were good reasons to implement Adj.

Adj leverages several existing technologies:

Additional highlights:

SVG WYSIWYG editors at the time Adj has been developed have been found to be suboptimal in reliability and ease of use, and have not effectively supported JavaScript manipulation of SVG.

1.9. Modifying SVG

1.9.1. Applying Transformations

Adj commands modify SVG:

source
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
image before being processed by Adj example
becomes
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList gap="5"/>
    <rect width="45" height="30" fill="#000" transform="translate(5,5)"/>
    <rect width="40" height="25" fill="#444" transform="translate(5,40)"/>
    <rect width="35" height="20" fill="#888" transform="translate(5,70)"/>
  </g>
</svg>
image after processing by Adj example

1.9.2. Storing Away Authoring Coordinates

With some modifications, authoring coordinates are stored away for reuse by authors and algorithms:

source
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none">
    <adj:connection from="one % 1, 0.5" to="other % 0, 0.5"/>
  </path>
</svg>
becomes
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M45,20q22.127,17.078 50,15t50,15" stroke="#777" stroke-width="2" fill="none" adj:d="M5,100 q40,10 80,0 t80,0">
    <adj:connection from="one % 1, 0.5" to="other % 0, 0.5"/>
  </path>
</svg>

1.9.3. Storing Away Original Attributes

With some modifications, original attributes are stored away for reuse by algorithms. E.g. SVG attribute display may be stored away in an attribute adj:originalDisplay.

1.9.4. Paragraph Alignment

Command paragraph makes small changes to the content of its text element.

TODO: explain command paragraph, emphasize what we need browsers to keep providing consistently to remain compatible

1.10. Commands Overview

The main commands shown by simple examples:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="5"/>
    <rect fill="none" stroke="black" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g font-size="12">
    <adj:textBreaks wordBreaks="true"/>
    <adj:horizontalList maxWidth="170" gap="5" centerGap="3" topGap="10" leftGap="10"/>
    <text>This is a sentence of text that will wrap.</text>
    <text>Here is more.</text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none">
    <adj:connection from="one % 1, 0.5" to="other % 0, 0.5"/>
  </path>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="lightgray" stroke-width="2" fill="none" />
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
  <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
  <g>
    <adj:connection from="one%1,0.5" to="other%0,0.5"/>
    <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
    <rect width="30" height="20" fill="#444">
      <adj:rider at="0.5"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <rect x="30" y="30" width="50" height="20" fill="#000"/>
    <circle r="5" stroke="gray" fill="gray" fill-opacity="0.2">
      <adj:circleForParent/>
    </circle>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <rect x="30" y="30" width="50" height="20" fill="#000"/>
    <ellipse rx="5" ry="5" stroke="gray" fill="gray" fill-opacity="0.2">
      <adj:ellipseForParent/>
    </ellipse>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:circularList gap="5"/>
    <circle r="10" fill="#000"/>
    <rect width="30" height="20" fill="#222"/>
    <rect width="30" height="20" fill="#444"/>
    <rect width="30" height="20" fill="#666"/>
    <rect width="30" height="20" fill="#888"/>
    <rect width="30" height="20" fill="#aaa"/>
    <rect width="30" height="20" fill="#bbb"/>
    <rect width="30" height="20" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="130" fill="linen"/>
  <g>
    <adj:verticalTree/>
    <text adj:id="r-1">R1</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.8,0"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:horizontalTree/>
    <text adj:id="r-1">R1</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%1,0.2" to="l-1-1%0,0.8"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="180" fill="linen"/>
  <g>
    <adj:verticalTree leftGap="20" centerGap="30" childlessGap="10" middleGap="40"/>
    <rect adj:id="o1" width="40" height="30" fill="#000"/>
    <rect adj:id="o2" adj:treeParent="o1" width="30" height="20" fill="#666"/>
    <rect adj:id="o3" adj:treeParent="o2" width="25" height="15" fill="#888"/>
    <rect adj:id="o4" adj:treeParent="o2" width="25" height="15" fill="#aaa"/>
    <rect adj:id="o5" adj:treeParent="o1" width="30" height="20" fill="#bbb"/>
    <rect adj:id="o6" adj:treeParent="o5" width="25" height="15" fill="#ccc"/>
    <rect adj:id="o7" adj:treeParent="o5" width="25" height="15" fill="#ddd"/>
  </g>
  <path d="M0,0" stroke="#777" stroke-width="2" fill="none" adj:d="M ~o1#x - 10, ~o1#yh
  C ~o1#x - 10, ~o1#yh + 10 ~o2#x - 10, ~o2#y%-0.3 ~o2#x - 10, ~o2#yc
  S ~o3#x - 10, ~o3#y%-0.3 ~o3#x - 10, ~o3#yc
  C ~o3#x - 10, ~o3#yh + 10 ~o3#x, ~o3#yh + 10 ~o3#xc, ~o3#yh + 10
  S ~o4#x, ~o4#yh + 10 ~o4#xc, ~o4#yh + 10
  S ~o4#xw + 10, ~o4#yh + 10 ~o4#xw + 10, ~o4#yc
  C ~o4#xw + 10, ~o4#y * 0.5 + ~o2#yh * 0.5 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5 + 10 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5
  S ~o2#xw, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10 ~o2#xw * 0.5 + ~o5#x * 0.5, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10">
    <adj:vine/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <rect adj:id="one" x="15" y="65" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="95" y="15" width="40" height="30" fill="#666"/>
    <rect adj:id="another" x="145" y="115" width="40" height="30" fill="#aaa"/>
    <path d="M0,0 l40,0 -20,-50 z" fill="#444">
      <adj:floater at="~one#xc*0.333+~other#xc*0.333+~another#xc*0.333,~one#yc*0.333+~other#yc*0.333+~another#yc*0.333"/>
    </path>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <style type="text/css"><![CDATA[
  circle { stroke: black; stroke-width: 1; }
  ]]></style>
  <rect width="200" height="150" fill="linen"/>
  <g adj:command="horizontalList" adj:makeGrid="true" adj:maxWidth="200" adj:gap="10" adj:hAlign="center" adj:vAlign="middle">
    <circle fill="#444" r="25"/>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxHeight="20"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxWidth="40" adj:maxHeight="30"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxWidth="100"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:height="70"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:width="120" adj:height="80" adj:maxWidth="40"/>
    </g>
  </g>
  <g adj:command="floater" adj:at="0,0" adj:pin="0,0">
    <adj:variable name="w" value="200"/>
    <adj:variable name="h" value="150"/>
    <path adj:command="vine" stroke="#777" stroke-width="1" opacity="0.2" fill="none" d="
    M 0,10 h ^w
    M 0,20 h ^w
    …
    "/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:stackFrames stacking="3, -5, 5" inset="-1"/>
    <rect fill="white" stroke="black" stroke-width="2" width="30" height="20"/>
    <ellipse cx="60" cy="40" rx="40" ry="20" fill="#666"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <rect x="5" y="5" width="30" height="20" stroke="black" stroke-width="1" fill="#000"/>
  <rect width="45" height="35" stroke="gray" stroke-width="1" fill="white" opacity="0.5">
    <adj:zoomFrames/>
  </rect>
  <rect x="135" y="65" width="60" height="50" stroke="black" stroke-width="1" fill="#888"/>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="skimpyList">
    <g>
      <rect width="50" height="70" stroke="black" stroke-width="1" fill="#888">
        <adj:tilt alpha="15"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:pinnedList/>
    <g>
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#aaa" adj:id="top">
        <adj:tilt alpha="30" beta="60"/>
      </rect>
    </g>
    <g adj:pinThis="front % 0.5, 0.0" adj:pinTo="top % 0.5, 1.0">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#888" adj:id="front">
        <adj:tilt alpha="30"/>
      </rect>
    </g>
    <g adj:pinThis="side % 0.5, 0.0" adj:pinTo="top % 1.0, 0.5">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#666" adj:id="side">
        <adj:tilt alpha="-30"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:telescopicTree gap="5"/>
    <rect width="30" height="20" fill="#000" adj:id="id1"/>
    <adj:boom/>
    <rect width="32" height="22" fill="#222"/>
    <adj:boom angle="east"/>
    <rect width="34" height="24" fill="#444"/>
    <adj:boom from="id1" angle="90" gap="15"/>
    <rect width="36" height="26" fill="#666" adj:id="id2"/>
    <adj:boom angle="10"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <adj:boom from="id2%0.5,1" to="0.5,0" angle="100" gap="~id2#h * 0.5"/><!--  -->
    <rect width="42" height="32" fill="#bbb"/>
    <adj:boom angle="-10"/>
    <rect width="44" height="34" fill="#ccc"/>
    <adj:boom angle="10"/>
    <rect width="46" height="36" fill="#ddd"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList/>
    <text adj:command="paragraph" adj:maxWidth="155">
This is a sentence of text that will wrap.
Here is more.
    </text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <path d="M15,20 q30,0 30,30 l50,0 30,-30 30,0" stroke="none" fill="none"/>
  <path d="M0,0" adj:d="M50,25 l5,-5 ,-5,-5 0,0 20,0 0,0 5,5 ,-5,5 0,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:rcGrid/>
    <g adj:rcGridPart="row">
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
      <circle r="8" fill="#666"/>
      <circle r="10" fill="#888"/>
    </g>
    <g adj:rcGridPart="column">
      <rect width="10" height="10" fill="#000"/>
      <rect width="14" height="12" fill="#222"/>
      …
    </g>
    …
    <g adj:rcGridPart="column"/>
    <g adj:rcGridPart="column">
      <rect width="22" height="16" fill="#000"/>
      …
    </g>
    <g adj:rcGridPart="row">
      <g/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
      …
    </g>
    …
  </g>
</svg>
example

You can view the SVG by itself and drag the sliderKnob.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <g transform="translate(20,20)">
    <rect x="0" y="0" width="140" height="20" fill="white" stroke="dimgrey"/>
    <rect x="6" y="6" width="128" height="8" fill="lightgrey" stroke="dimgrey"/>
    <g>
      <adj:sliderKnob/>
      <rect x="0" y="0" width="20" height="20" fill="gainsboro" stroke="black"/>
      <rect x="3" y="3" width="14" height="14" fill="lightgrey" stroke="none"/>
    </g>
  </g>
  <text id="setme" style="font-size:10;font-family:sans-serif;" transform="translate(20,60)">0</text>
  <script><![CDATA[
document.addEventListener("change", function (event) {
  var elementToSet = document.getElementById("setme");
  elementToSet.textContent = event.detail.value;
  Adj.doSvg();
});
  ]]></script>
</svg>
example

You can view the SVG by itself and click the toggleButton.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:skimpyList/>
    <g>
      <rect width="70" height="100" stroke="black" stroke-width="1" fill="darkgrey"/>
      <g>
        <adj:tilt alpha="0"/>
        <rect width="70" height="100" stroke="dimgrey" stroke-width="1" fill="lightgrey"/>
        <g adj:id="lockIt">
          <adj:floater at="45,50"/>
          <adj:toggleButton/>
          <path adj:alternativeValue="lock" title="click to flip"
                d="M0,0 l0,-30 30,0 0,30 z M5,-30 l0,-10 q0,-10 10,-10 10,0 10,10 … z"
                fill="darkgrey" stroke="black"/>
          <path adj:alternativeValue="unlock" title="click to flip"
                d="M0,0 l0,-30 30,0 0,30 z M22,-30 l0,-10 q0,-10 10,-10 10,0 10,10 … z"
                fill="darkgrey" stroke="black"/>
        </g>
      </g>
    </g>
  </g>
  <script><![CDATA[
Adj.getElementById("lockIt").addEventListener("change", function (event) {
  var newToggle = event.detail.value;
  document.querySelector("[alpha]").setAttribute("alpha", newToggle === "lock" ? "0" : "15");
  Adj.doSvg();
});
  ]]></script>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444" adj:hide="true"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect width="200" height="140" fill="linen"/>
  <g adj:command="horizontalList" adj:gap="2" adj:itemsH2V="1">
    <rect width="40" height="80" fill="#222"/>
    <g>
      <adj:include xlink:href="subdir-080/adj-ex-080-include-to-include.svg"/>
    </g>
    <rect width="40" height="40" fill="#444"/>
    <rect width="80" height="40" fill="#888"/>
  </g>
</svg>

1.11. Commands Options

Most commands take optional parameters.

1.11.1. Command horizontalList Options

Optional parameters of horizontalList:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList gap="5"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <rect width="36" height="26" fill="#666"/>
    <rect width="38" height="28" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList maxPerRow="3" gap="5"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <rect width="36" height="26" fill="#666"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <rect width="42" height="32" fill="#bbb"/>
    <rect width="44" height="34" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="150" fill="linen"/>
  <g>
    <adj:horizontalList maxWidth="120" gap="5"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <rect width="36" height="26" fill="#666"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <rect width="42" height="32" fill="#bbb"/>
    <rect width="44" height="34" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList makeGrid="true" maxPerRow="3" gap="5"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <rect width="36" height="26" fill="#666"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <rect width="42" height="32" fill="#bbb"/>
    <rect width="44" height="34" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList makeGrid="true" hAlign="center" vAlign="middle" maxPerRow="3" gap="5"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <rect width="36" height="26" fill="#666"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <rect width="42" height="32" fill="#bbb"/>
    <rect width="44" height="34" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList maxPerRow="4" horizontalGap="15" verticalGap="3"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="30" height="20" fill="#222"/>
    <rect width="30" height="20" fill="#444"/>
    <rect width="30" height="20" fill="#666"/>
    <rect width="30" height="20" fill="#888"/>
    <rect width="30" height="20" fill="#999"/>
    <rect width="30" height="20" fill="#aaa"/>
    <rect width="30" height="20" fill="#bbb"/>
    <rect width="30" height="20" fill="#ccc"/>
    <rect width="30" height="20" fill="#ddd"/>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:horizontalList maxPerRow="4" leftGap="20" centerGap="5" rightGap="12" topGap="10" middleGap="3" bottomGap="7"/>
    <rect width="30" height="20" fill="#000"/>
    <rect width="30" height="20" fill="#222"/>
    <rect width="30" height="20" fill="#444"/>
    <rect width="30" height="20" fill="#666"/>
    <rect width="30" height="20" fill="#888"/>
    <rect width="30" height="20" fill="#999"/>
    <rect width="30" height="20" fill="#aaa"/>
    <rect width="30" height="20" fill="#bbb"/>
    <rect width="30" height="20" fill="#ccc"/>
    <rect width="30" height="20" fill="#ddd"/>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList itemsH2V="1.5" gap="5"/>
    <rect width="20" height="20" fill="#000"/>
    <rect width="20" height="20" fill="#222"/>
    <rect width="20" height="20" fill="#444"/>
    <rect width="20" height="20" fill="#666"/>
    <rect width="20" height="20" fill="#888"/>
    <rect width="20" height="20" fill="#999"/>
    <rect width="20" height="20" fill="#aaa"/>
    <rect width="20" height="20" fill="#bbb"/>
    <rect width="20" height="20" fill="#ccc"/>
    <rect width="20" height="20" fill="#ddd"/>
  </g>
</svg>

The fractions in parameters hAlign (horizontally align) and vAlign (vertically align) accept decimal numbers, but they also recognize some symbols (strings in JavaScript).

hAlign left 0.0
center 0.5
right 1.0
vAlign top 0.0
middle 0.5
bottom 1.0

1.11.2. Command verticalList Options

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>

Optional parameters of verticalList are very similar to optional parameters of horizontalList.

Notably different, there is maxHeight (instead of maxWidth, duh) and maxPerColumn (instead of maxPerRow).

1.11.3. Command frameForParent Options

Optional parameters of frameForParent:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="10"/>
    <rect fill="none" stroke="black" stroke-width="4" width="0" height="0" rx="4" ry="4">
      <adj:frameForParent inset="2"/>
    </rect>
    <rect fill="none" stroke="gray" stroke-width="2" width="0" height="0" rx="2" ry="2">
      <adj:frameForParent horizontalInset="4" verticalInset="3"/>
    </rect>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="10"/>
    <rect fill="none" stroke="black" stroke-width="4" width="0" height="0">
      <adj:frameForParent leftInset="2" rightInset="0" topInset="2" bottomInset="0"/>
    </rect>
    <rect fill="none" stroke="gray" stroke-width="4" width="0" height="0">
      <adj:frameForParent inset="3"/>
    </rect>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>

1.11.4. Command textBreaks Options

Optional parameters of textBreaks:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g font-size="12">
    <adj:textBreaks wordBreaks="true"/>
    <adj:horizontalList maxWidth="190" gap="5" centerGap="3" topGap="10" leftGap="10"/>
    <text>Source line one,
source line two.</text>
    <text>And source line three.</text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g font-size="12">
    <adj:textBreaks lineBreaks="true"/>
    <adj:horizontalList maxPerRow="1" gap="5" topGap="10" leftGap="10"/>
    <text>Source line one,
source line two.</text>
    <text>And source line three.</text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>

If not given, default values are wordBreaks="false" and lineBreaks="true".

1.11.5. Command connection Options

Optional parameters of connection:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" stroke="#000" fill="#aaa"/>
  <rect adj:id="other" x="145" y="55" width="40" height="30" stroke="#000" fill="#ccc"/>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="#000" stroke-width="2" fill="none">
    <adj:connection from="one" to="other"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" stroke="#000" fill="#aaa"/>
  <rect adj:id="other" x="145" y="55" width="40" height="30" stroke="#000" fill="#ccc"/>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="#000" stroke-width="2" fill="none">
    <adj:connection from="one%1,0.5" to="other%0,0.5"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" stroke="#000" fill="#aaa"/>
  <rect adj:id="other" x="145" y="55" width="40" height="30" stroke="#000" fill="#ccc"/>
  <g>
    <adj:connection from="one%1,0.5" to="other%0,0.5"/>
    <line x1="5" y1="100" x2="185" y2="100"/>
    <path d="M15,100 l-10,-10 20,0 5,5 135,0 0,-5 20,10 -20,10 0,-5 -135,0 -5,5 -20,0 z"
      stroke="#000" stroke-width="1" fill-opacity="0.5" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" stroke="#000" fill="#aaa"/>
  <rect adj:id="other" x="145" y="55" width="40" height="30" stroke="#000" fill="#ccc"/>
  <g>
    <adj:connection from="one%1,0.5" to="other%0,0.5" vector="1"/>
    <path d="M15,100 l-10,-10 20,0 5,5 135,0 0,-5 20,10 -20,10 0,-5 -135,0 -5,5 -20,0 z"
      stroke="#000" stroke-width="1" fill-opacity="0.5" fill="#888"/>
    <line x1="5" y1="100" x2="185" y2="100"/>
  </g>
</svg>

In parameters from and to an expression identifier % decimal , decimal means from the element referenced by the identifier determine coordinates with 0,0 being its bounding box x,y and 1,1 being its x+width,y+height. With decimal number values often between 0.0 and 1.0 they also can be outside that range.

As implemented, connection works for simplified cases line and path, and for general case group g containing one line (or path) as vector (default first, i.e. index 0) and any number of lines and paths as children of that group.

1.11.6. Command rider Options

Optional parameters of rider:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
  <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
  <g>
    <adj:connection from="one%1,0.5" to="other%0,0.5"/>
    <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
    <rect width="30" height="20" fill="#444">
      <adj:rider at="0.7"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider at="0.2,0.7"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider at="0.2,0.7" adjust="near"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect x="85" y="15" width="40" height="30" fill="#666"/>
    <rect x="25" y="45" width="40" height="30" fill="#888"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect x="85" y="15" width="40" height="30" fill="#666"/>
    <rect x="25" y="45" width="40" height="30" fill="#888"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider at="0.2,0.7" adjust="near" gap="2"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#444">
        <adj:rider pin="0.0,1.0"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#aaa"/>
    <path adj:id="connect" d="M5,100 q40,10 80,0 t80,0" stroke="#777" stroke-width="2" fill="none">
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
    </path>
    <rect width="30" height="20" fill="#444">
      <adj:rider path="connect"/>
    </rect>
  </g>
</svg>

The fraction or fraction pair in parameter at accepts decimal numbers. With values often between 0.0 and 1.0 they also can be outside that range.

Parameter adjust accepts some symbols (strings in JavaScript).

adjust clear
near
none

If given no at and no adjust then at defaults from 0.0 to 1.0 and adjust defaults to clear. If given no at but adjust given near then at defaults from 0.0 to 0.5.

If given one decimal number for at then adjust defaults to none.

If given two decimal numbers for at then adjust defaults to clear.

The fraction pair in parameter pin accepts decimal numbers. With values often between 0.0 and 1.0 they also can be outside that range.

As implemented, rider tries to stay clear of its group's siblings, or to stay clear of its own siblings if given a path attribute.

Parameter steps should not be set in most circumstances. It accepts an integer number and defaults to 10. It does not correspond to the final resolution of adjusting coordinates.

1.11.7. Command circleForParent Options

An optional parameter of circleForParent:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <rect x="30" y="30" width="50" height="20" fill="#000"/>
    <circle r="5" stroke="gray" stroke-width="4" fill="gray" fill-opacity="0.2">
      <adj:circleForParent inset="-2"/>
    </circle>
  </g>
</svg>

1.11.8. Command ellipseForParent Options

Optional parameters of ellipseForParent:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <rect x="30" y="30" width="50" height="20" fill="#000"/>
    <ellipse rx="5" ry="5" stroke="gray" stroke-width="4" fill="gray" fill-opacity="0.2">
      <adj:ellipseForParent inset="-2"/>
    </ellipse>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <rect x="30" y="30" width="50" height="20" fill="#000"/>
    <ellipse rx="5" ry="5" stroke="gray" stroke-width="4" fill="gray" fill-opacity="0.2">
      <adj:ellipseForParent horizontalInset="-3" verticalInset="-1"/>
    </ellipse>
  </g>
</svg>

1.11.9. Command circularList Options

Optional parameters of circularList:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="130" fill="linen"/>
  <g>
    <adj:circularList gap="5"/>
    <rect width="20" height="20" fill="#000"/>
    <rect width="20" height="20" fill="#222"/>
    <rect width="20" height="20" fill="#444"/>
    <rect width="20" height="20" fill="#666"/>
    <rect width="20" height="20" fill="#888"/>
    <rect width="20" height="20" fill="#aaa"/>
    <rect width="20" height="20" fill="#bbb"/>
    <rect width="20" height="20" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:circularList rGap="5" cGap="15"/>
    <rect width="20" height="20" fill="#000"/>
    <rect width="20" height="20" fill="#222"/>
    <rect width="20" height="20" fill="#444"/>
    <rect width="20" height="20" fill="#666"/>
    <rect width="20" height="20" fill="#888"/>
    <rect width="20" height="20" fill="#aaa"/>
    <rect width="20" height="20" fill="#bbb"/>
    <rect width="20" height="20" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:circularList fromAngle="225" toAngle="315" cGap="4" horizontalGap="5" verticalGap="20"/>
    <g/>
    <rect width="15" height="15" fill="#000"/>
    <rect width="15" height="15" fill="#222"/>
    <rect width="15" height="15" fill="#444"/>
    <rect width="15" height="15" fill="#666"/>
    <rect width="15" height="15" fill="#888"/>
    <rect width="15" height="15" fill="#aaa"/>
    <rect width="15" height="15" fill="#bbb"/>
    <rect width="15" height="15" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <adj:circularList rAlign="inside" gap="2" leftGap="10" topGap="10" rightGap="5" bottomGap="5"/>
    <circle r="20" fill="#000"/>
    <rect width="3" height="3" fill="#222"/>
    <rect width="6" height="6" fill="#444"/>
    <rect width="9" height="9" fill="#666"/>
    <rect width="12" height="12" fill="#888"/>
    <rect width="15" height="15" fill="#aaa"/>
    <rect width="18" height="18" fill="#bbb"/>
    <rect width="21" height="21" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:circularList fromAngle="0" toAngle="90" packArc="true"/>
    <circle r="20" fill="#000"/>
    <rect width="3" height="3" fill="#222"/>
    <rect width="6" height="6" fill="#444"/>
    <rect width="9" height="9" fill="#666"/>
    <rect width="12" height="12" fill="#888"/>
    <rect width="36" height="36" fill="#aaa"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="90" fill="linen"/>
  <g>
    <adj:circularList fromAngle="0" toAngle="90" packArc="true" cAlign="from"/>
    <circle r="20" fill="#000"/>
    <rect width="3" height="3" fill="#222"/>
    <rect width="6" height="6" fill="#444"/>
    <rect width="9" height="9" fill="#666"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:circularList fromAngle="135" toAngle="45" dullness="0.8"/>
    <rect width="15" height="15" fill="#000"/>
    <rect width="15" height="15" fill="#222"/>
    <rect width="15" height="15" fill="#444"/>
    <rect width="15" height="15" fill="#666"/>
    <rect width="15" height="15" fill="#888"/>
    <rect width="15" height="15" fill="#aaa"/>
    <rect width="15" height="15" fill="#bbb"/>
    <rect width="15" height="15" fill="#ccc"/>
  </g>
</svg>

First element is trunk in the center, remaining elements are branches. First element could be an empty group.

The fractions in parameters rAlign (radially align), cAlign (circumferentially align), and dullness accept decimal numbers, but they also recognize some symbols (strings in JavaScript).

rAlign inside 0.0
median 0.5
outside 1.0
cAlign from 0.0
halfway 0.5
to 1.0
dullness pointed 0.0
dull 1.0

1.11.10. Command verticalTree Options

Optional parameters of verticalTree:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="130" fill="linen"/>
  <g>
    <adj:verticalTree/>
    <text adj:id="r-1">R1</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.8,0"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="130" fill="linen"/>
  <g>
    <adj:verticalTree autoParrots="true"/>
    <text adj:id="r-1">R1</text>
    <text adj:id="r-2">R2</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-1-3" adj:treeParent="n-1-2-1">L1213</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-2-3" adj:treeParent="n-1-2">L123</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.8,0"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <adj:verticalTree autoParrots="true" hAlign="left" vAlign="0.2" gap="12"/>
    <text adj:id="r-1" font-size="25">R1</text>
    <text adj:id="r-2">R2</text>
    <text adj:id="l-1-1" font-size="20" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" font-size="15" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" font-size="12" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-1-3" adj:treeParent="n-1-2-1">L1213</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-2-3" adj:treeParent="n-1-2">L123</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.2,0"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="210" fill="linen"/>
  <g>
    <adj:verticalTree autoParrots="true" horizontalGap="15" verticalGap="30"/>
    <text adj:id="r-1">R1</text>
    <text adj:id="r-2">R2</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-1-3" adj:treeParent="n-1-2-1">L1213</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-2-3" adj:treeParent="n-1-2">L123</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.8,0"/>
    </line>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="210" fill="linen"/>
  <g>
    <adj:verticalTree autoParrots="true" leftGap="5" centerGap="20" rightGap="5" topGap="5" middleGap="40" bottomGap="5" childlessGap="10" earGap="30"/>
    <text adj:id="r-1">R1</text>
    <text adj:id="r-2">R2</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-1-3" adj:treeParent="n-1-2-1">L1213</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-2-3" adj:treeParent="n-1-2">L123</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%0.2,1" to="l-1-1%0.8,0"/>
    </line>
    …
  </g>
</svg>

Only layout is provided. This allows the most freedom for illustrating anything. Examples provided here use instances of command connection to indicate relationships.

Relationships in verticalTree are defined by child element attributes adj:treeParent pointing at their sibling element attributes adj:id.

Nodes intentionally are elements at the same level in SVG. To be clear: There is not SVG element nesting corresponding to the tree structure.

Multiple roots are possible.

Several optional parameters of verticalTree are similar to optional parameters of horizontalList. These include gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, and vAlign.

Parameter hAlign aligns a node relative to its children. The fraction in parameter hAlign accepts decimal numbers, but it also recognizes some symbols (strings in JavaScript), similar to parameter hAlign of horizontalList.

Parameter autoParrots lets siblings that have no child sit on the shoulders of subtrees headed by siblings that do have children.

Parameter earGap is in effect instead of centerGap between the head of a subtree and its adjacent siblings if they sit on its shoulders.

Parameter childlessGap is in effect instead of centerGap when all siblings have no child.

1.11.11. Command horizontalTree Options

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:horizontalTree/>
    <text adj:id="r-1">R1</text>
    <text adj:id="l-1-1" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
    <line stroke="#666">
      <adj:connection from="r-1%1,0.2" to="l-1-1%0,0.8"/>
    </line>
    …
  </g>
</svg>

Optional parameters of horizontalTree are very similar to optional parameters of verticalTree.

1.11.12. Command vine Options

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="180" fill="linen"/>
  <g>
    <adj:verticalTree leftGap="20" centerGap="30" childlessGap="10" middleGap="40"/>
    <rect adj:id="o1" width="40" height="30" fill="#000"/>
    <rect adj:id="o2" adj:treeParent="o1" width="30" height="20" fill="#666"/>
    <rect adj:id="o3" adj:treeParent="o2" width="25" height="15" fill="#888"/>
    <rect adj:id="o4" adj:treeParent="o2" width="25" height="15" fill="#aaa"/>
    <rect adj:id="o5" adj:treeParent="o1" width="30" height="20" fill="#bbb"/>
    <rect adj:id="o6" adj:treeParent="o5" width="25" height="15" fill="#ccc"/>
    <rect adj:id="o7" adj:treeParent="o5" width="25" height="15" fill="#ddd"/>
  </g>
  <path d="M0,0" stroke="#777" stroke-width="2" fill="none" adj:d="M ~o1#x - 10, ~o1#yh
  C ~o1#x - 10, ~o1#yh + 10 ~o2#x - 10, ~o2#y%-0.3 ~o2#x - 10, ~o2#yc
  S ~o3#x - 10, ~o3#y%-0.3 ~o3#x - 10, ~o3#yc
  C ~o3#x - 10, ~o3#yh + 10 ~o3#x, ~o3#yh + 10 ~o3#xc, ~o3#yh + 10
  S ~o4#x, ~o4#yh + 10 ~o4#xc, ~o4#yh + 10
  S ~o4#xw + 10, ~o4#yh + 10 ~o4#xw + 10, ~o4#yc
  C ~o4#xw + 10, ~o4#y * 0.5 + ~o2#yh * 0.5 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5 + 10 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5
  S ~o2#xw, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10 ~o2#xw * 0.5 + ~o5#x * 0.5, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10">
    <adj:vine/>
  </path>
</svg>

As implemented, vine works for path.

Command vine evaluates simple arithmetic into plain decimal numbers.

An expression ~ identifier # axis % decimal means from the element referenced by the identifier determine a coordinate with 0.0 being its bounding box x or y and 1.0 being its x+width or y+height. With decimal number values often between 0.0 and 1.0 they also can be outside that range.

fine control,
absolute
x or y
~ identifier # x % decimal
x + decimal * width
~ identifier # y % decimal
y + decimal * height
shortcuts,
absolute
x or y
~ identifier # x #x%0, left
~ identifier # y #y%0, top
~ identifier # xw
#x%1, which would be x+width, right
~ identifier # yh
#y%1, which would be y+height, bottom
~ identifier # xc
#x%.5, same as #x%0.5, which would be x+width/2, horizontal center
~ identifier # yc
#y%.5, same as #y%0.5, which would be y+height/2, vertical center
relative
w, h, or d
~ identifier # w
width
~ identifier # h
height
~ identifier # d
diagonal

Linear polynomial expressions are evaluated with normal order of operations. Addition +, subtraction -, and multiplication * are supported.

As an example, to get the horizontal coordinate exactly in the middle between the right edge of element one and the left edge of element other, a possible expression is ~one#xw*0.5+~other#x*0.5. That would be the equivalent of ((one.x + one.width) + other.x) / 2.

Parentheses are not needed and parentheses are not supported.

Command vine also performs substitution of variables.

1.11.12.1. Caveat Regarding - Minus Sign

After a space separating path coordinates, one must not start with a - minus sign.

For example, if trying to achieve

adj:d="M 50,50
  c 20,20 60,20 80,0
  c -20,30 -60,30 -80,0
  m 40,10
  c 40,0 10,60 0,60
  s -40,-60 0,-60"

the problem is Adj.evaluateArithmetic would evaluate

adj:d="M 50,50
  c 20,20 60,20 80,0
  c -20,(30 -60),(30 -80),0
  m 40,10
  c 40,0 10,60 0,60
  s -40,-60 0,-60"

which would give

adj:d="M 50,50
  c 20,20 60,20 80,0
  c -20,-30,-50,0
  m 40,10
  c 40,0 10,60 0,60
  s -40,-60 0,-60"

which is not a valid path.

Therefore, one can for example write

adj:d="M 50,50
  c 20,20 60,20 80,0
  c -20,30 0-60,30 0-80,0
  m 40,10
  c 40,0 10,60 0,60
  s -40,-60 0,-60"

The problem has several possible solutions.

intention, but doesn't work this way, don't do this

results in unintended evaluation, not a valid path, bad result
c -20,30 -60,30 -80,0

c -20,-30,-50,0
one possibility, write extra zeros c -20,30 0-60,30 0-80,0
other possibility, write extra commas c -20,30, -60,30, -80,0
variations of spacing are allowed c -20,30 , -60,30 ,-80,0

1.11.13. Command floater Options

Command floater required parameter at evaluates simple arithmetic very similar to command vine.

An optional parameter of floater:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <rect adj:id="one" x="15" y="65" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="95" y="15" width="40" height="30" fill="#666"/>
    <rect adj:id="another" x="145" y="115" width="40" height="30" fill="#aaa"/>
    <path d="M0,0 l40,0 -20,-50 z" fill="#444">
      <adj:floater pin="0.5,0" at="~one#xc*0.333+~other#xc*0.333+~another#xc*0.333,~one#yc*0.333+~other#yc*0.333+~another#yc*0.333"/>
    </path>
  </g>
</svg>

1.11.14. Command fit Options

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <style type="text/css"><![CDATA[
  circle { stroke: black; stroke-width: 1; }
  ]]></style>
  <rect width="200" height="150" fill="linen"/>
  <g adj:command="horizontalList" adj:makeGrid="true" adj:maxWidth="200" adj:gap="10" adj:hAlign="center" adj:vAlign="middle">
    <circle fill="#444" r="25"/>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxHeight="20"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxWidth="40" adj:maxHeight="30"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:maxWidth="100"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:height="70"/>
    </g>
    <g>
      <circle fill="#ccc" r="25" adj:command="fit" adj:width="120" adj:height="80" adj:maxWidth="40"/>
    </g>
  </g>
  <g adj:command="floater" adj:at="0,0" adj:pin="0,0">
    <adj:variable name="w" value="200"/>
    <adj:variable name="h" value="150"/>
    <path adj:command="vine" stroke="#777" stroke-width="1" opacity="0.2" fill="none" d="
    M 0,10 h ^w
    M 0,20 h ^w
    …
    "/>
  </g>
</svg>

All command fit parameters are optional.

Scaling is done proportionally for horizontal and vertical. Always the smallest scale is picked to fulfill all constraints. If parameter maxWidth and parameter maxHeight would cause two different scales, the smaller scale is picked.

Other than parameters maxWidth and maxHeight, parameters width and height can cause a scale larger than 1.0. Parameters maxWidth and maxHeight never cause an increase of scale, while parameters width and height can cause an increase of scale.

Parameters maxWidth and maxHeight can further constrain than parameters width and height, in case they have been given along the same axis.

1.11.15. Command stackFrames Options

Optional parameters of stackFrames:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:stackFrames stacking="3, -5, 5" inset="-1"/>
    <rect fill="white" stroke="black" stroke-width="2" width="30" height="20"/>
    <ellipse cx="60" cy="40" rx="40" ry="20" fill="#666"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:stackFrames stacking="3, -5, 5" inset="-1" frame="1" subject="3"/>
    <circle cx="140" cy="40" r="20" fill="#000"/>
    <rect fill="white" stroke="black" stroke-width="2" width="60" height="20"/>
    <circle cx="140" cy="40" r="10" fill="#888"/>
    <ellipse cx="60" cy="40" rx="40" ry="20" fill="#666"/>
  </g>
</svg>

Optional inset family parameters of stackFrames are equivalent to optional inset family parameters of frameForParent.

1.11.16. Command zoomFrames Options

Optional parameters of zoomFrames:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <rect x="5" y="5" width="30" height="20" stroke="black" stroke-width="1" fill="#000"/>
  <rect width="45" height="35" stroke="gray" stroke-width="1" fill="white" opacity="0.5">
    <adj:zoomFrames/>
  </rect>
  <rect x="135" y="65" width="60" height="50" stroke="black" stroke-width="1" fill="#888"/>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect width="200" height="120" fill="linen"/>
  <rect x="5" y="5" width="30" height="20" stroke="black" stroke-width="1" fill="#000" adj:id="small"/>
  <rect x="155" y="5" width="40" height="30" stroke="black" stroke-width="1" fill="#444"/>
  <rect x="5" y="75" width="50" height="40" stroke="black" stroke-width="1" fill="#666"/>
  <rect width="45" height="35" stroke="lightgray" stroke-width="1" fill="white" opacity="0.75">
    <adj:zoomFrames adj:from="small" adj:step="20"/>
  </rect>
  <rect x="135" y="65" width="60" height="50" stroke="black" stroke-width="1" fill="#888"/>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect width="200" height="120" fill="linen"/>
  <rect x="5" y="5" width="30" height="20" stroke="black" stroke-width="1" fill="#000"/>
  <rect width="45" height="35" stroke="gray" stroke-width="1" fill="none">
    <adj:zoomFrames adj:to="big" adj:step="60"/>
  </rect>
  <rect x="155" y="5" width="40" height="30" stroke="black" stroke-width="1" fill="#444"/>
  <rect x="5" y="75" width="50" height="40" stroke="black" stroke-width="1" fill="#666"/>
  <rect x="135" y="65" width="60" height="50" stroke="black" stroke-width="1" fill="#888" adj:id="big"/>
</svg>

1.11.17. Command tilt Options

Optional parameters of tilt:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="skimpyList">
    <g>
      <rect width="50" height="70" stroke="black" stroke-width="1" fill="#888">
        <adj:tilt alpha="15"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="skimpyList">
    <g>
      <rect width="90" height="60" stroke="black" stroke-width="1" fill="#888">
        <adj:tilt alpha="15" beta="10"/>
      </rect>
    </g>
  </g>
</svg>

1.11.18. Command pinnedList Options

Different than with other lists, within pinnedList respective placement parameters pinThis and pinTo are found within individual elements of the list. By allowing pinning to hinge on elements further nested inside elements of the list, this works great for isometric drawings.

Optional parameters of pinnedList:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:pinnedList/>
    <g>
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#aaa" adj:id="top">
        <adj:tilt alpha="30" beta="60"/>
      </rect>
    </g>
    <g adj:pinThis="front % 0.5, 0.0" adj:pinTo="top % 0.5, 1.0">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#888" adj:id="front">
        <adj:tilt alpha="30"/>
      </rect>
    </g>
    <g adj:pinThis="side % 0.5, 0.0" adj:pinTo="top % 1.0, 0.5">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#666" adj:id="side">
        <adj:tilt alpha="-30"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="pinnedList" adj:gap="10">
    <g>
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#aaa" adj:tilt="true" adj:alpha="30" adj:beta="60" adj:id="top"/>
    </g>
    <g adj:pinThis="front % 0.5, 0.0" adj:pinTo="top % 0.5, 1.0">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#888" adj:tilt="true" adj:alpha="30" adj:id="front"/>
    </g>
    <g adj:pinThis="side % 0.5, 0.0" adj:pinTo="top % 1.0, 0.5">
      <rect width="40" height="40" stroke="black" stroke-width="1" fill="#666" adj:tilt="true" adj:alpha="30" adj:id="side"/>
    </g>
  </g>
</svg>

Optional parameters gap, horizontalGap, leftGap, rightGap, verticalGap, topGap, bottomGap are equivalent to optional parameters of horizontalList, yet effecting padding for the whole list only rather than between elements.

1.11.19. Command telescopicTree Options

Different than with other trees or lists, within telescopicTree placement is mostly defined by optional boom elements listed between individual elements of the tree.

Optional parameters of telescopicTree:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:telescopicTree gap="5"/>
    <rect width="30" height="20" fill="#000" adj:id="id1"/>
    <adj:boom/>
    <rect width="32" height="22" fill="#222"/>
    <adj:boom angle="east"/>
    <rect width="34" height="24" fill="#444"/>
    <adj:boom from="id1" angle="90" gap="15"/>
    <rect width="36" height="26" fill="#666" adj:id="id2"/>
    <adj:boom angle="10"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <adj:boom from="id2%0.5,1" to="0.5,0" angle="100" gap="~id2#h * 0.5"/><!--  -->
    <rect width="42" height="32" fill="#bbb"/>
    <adj:boom angle="-10"/>
    <rect width="44" height="34" fill="#ccc"/>
    <adj:boom angle="10"/>
    <rect width="46" height="36" fill="#ddd"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="150" fill="linen"/>
  <g>
    <adj:telescopicTree gap="5" from="0,0" to="0,0"/>
    <rect width="30" height="20" fill="#000" adj:id="id1"/>
    <adj:boom angle="east"/>
    <rect width="32" height="22" fill="#222"/>
    <rect width="34" height="24" fill="#444"/>
    <adj:boom from="id1" angle="south" gap="15"/>
    <rect width="36" height="26" fill="#666" adj:id="id2"/>
    <adj:boom angle="east"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <adj:boom from="id2" angle="south" gap="15"/>
    <rect width="42" height="32" fill="#bbb"/>
    <adj:boom angle="east"/>
    <rect width="44" height="34" fill="#ccc"/>
    <rect width="46" height="36" fill="#ddd"/>
  </g>
</svg>

Optional telescopicTree parameter gap is the default value for boom parameter gap.

Optional telescopicTree parameters from and to are default values for boom parameters from and to. They default to middle 0.5,0.5. An identifier must not be given to telescopicTree parameters from and to.

When no boom is specificed between two elements, the most recent angle and gap will be used again.

If not given an identifier, optional boom parameter from defaults to the preceeding element, which commonly can be anonymous. An identifier must not be given to optional boom parameter to, which always implies the following element.

The degree value of boom parameter angle accepts decimal numbers, but also recognizes some symbols (strings in JavaScript).

angle east 0
south 90
west 180
north 270

This at first experimental command works great for a number of uses.

Another example of command telescopicTree is 075-002.

As implemented, command telescopicTree may still be subject to minor changes in how it places under some circumstances, because the implementation at the time has been optimized for speed rather than ideal coverage of all possible cases.

1.11.20. Command paragraph Options

Optional parameters of paragraph:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList/>
    <text adj:command="paragraph" adj:maxWidth="155">
This is a sentence of text that will wrap.
Here is more.
    </text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList gap="15"/>
    <text>
      <adj:paragraph maxWidth="160" lineGap="2" hAlign="center"/>
Source line one is here,
source line
<tspan font-style="italic">t<tspan font-weight="bolder">w</tspan>o</tspan>
is <a xlink:href="#"><tspan fill="blue">here</tspan></a> too.
And then there is more text.</text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList/>
    <text adj:command="paragraph" adj:maxWidth="160" adj:indent="8">
This is a sentence of text that will wrap
with the first line indented.
    </text>
    <rect fill="none" stroke="lightgray" stroke-width="2" width="0" height="0">
      <adj:frameForParent inset="1"/>
    </rect>
  </g>
</svg>

The fraction in parameter hAlign accepts decimal numbers, but it also recognizes some symbols (strings in JavaScript), similar to parameter hAlign of horizontalList.

As implemented, command paragraph handles nested tspan and a. It is not known to handle tref, altGlyph, or textPath.

A known workaround: As implemented, it is known that extraneous whitespace near a hyperlink a element can cause line height calculation on Firefox to be wrong. The workaround is not to have extraneous whitespace near a hyperlink a element inside a text element which uses command paragraph.

1.11.21. Command pathArrow Options

Command pathArrow takes a path given as arrow shape and stretches and bends its shaft along another path given to follow.

example

The path given as arrow shape has to be defined clockwise:

The distance between the nock's two points of connection to the shaft must be equal to the distance between the point's two points of connection to the shaft.

Optional parameters of pathArrow:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <path d="M15,20 q30,0 30,30 l50,0 30,-30 30,0" stroke="none" fill="none"/>
  <path d="M0,0" adj:d="M50,25 l5,-5 ,-5,-5 0,0 20,0 0,0 5,5 ,-5,5 0,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M15,50 q40,-15 80,0" stroke="none" fill="none">
    <adj:connection from="one % 1, 0.5" to="other % 0, 0.5"/>
  </path>
  <path d="M0,0" adj:d="M50,60 l-5,5 ,-15,0 10,-10 ,-10,-10 15,0 5,5 0,0 30,0 0,0 0,-5 20,10 ,-20,10 0,-5 0,0 ,-30,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow setback="10"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <path d="M15,20 c20,0 30,10 30,30 h20 v-30 q30,0 45,15 t45,15"
    stroke="none" fill="none" transform="translate(0,15) rotate(-10)"/>
  <path d="M0,0" adj:d="M50,25 c3,0 5,-2 5,-5 s-2,-5 ,-5,-5 l0,0 20,0 0,0 q5,0 5,5 t-5,5 l0,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow nockSetback="-2" pointSetback="3"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <path d="M0,0" adj:d="M50,25 l0,-10 0,0 20,0 0,0 0,10 0,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow path="p1"/>
  </path>
  <path adj:id="p1" d="M15,20 C35,20 45,30 45,50 H65 V20 c30,0 30,0 45,15 s15,15 45,15"
    stroke="none" fill="none"/>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <adj:variable name="ratio" value="0.5"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M15,50 q40,-15 80,0" stroke="none" fill="none">
    <adj:connection from="one % 0.8, 0.5" to="other % 0.2, 0.5"/>
  </path>
  <path d="M0,0" adj:d="M50,25 l0,-~one#h*^ratio 0,0 20,0 0,0 0,~one#h*^ratio 0,0 z"
    stroke="gray" stroke-width="1" fill="white" opacity="0.75">
    <adj:pathArrow/>
  </path>
</svg>

Optionally, command pathArrow for coordinates of the shape of the nock and the point of the arrow can evaluate simple arithmetic into plain decimal numbers, similar to command vine. Same caveat regarding - minus sign applies.

For best results, to avoid unintended application of respectively different transformations, the path given to follow and the path given as arrow shape often should be together inside the same SVG group element g, even if this is the only raison d'être for that group.

1.11.22. Command rcGrid Options

Optional parameters of rcGrid:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:rcGrid/>
    <g adj:rcGridPart="row">
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
      <circle r="8" fill="#666"/>
      <circle r="10" fill="#888"/>
    </g>
    <g adj:rcGridPart="column">
      <rect width="10" height="10" fill="#000"/>
      <rect width="14" height="12" fill="#222"/>
      …
    </g>
    …
    <g adj:rcGridPart="column"/>
    <g adj:rcGridPart="column">
      <rect width="22" height="16" fill="#000"/>
      …
    </g>
    <g adj:rcGridPart="row">
      <g/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
      …
    </g>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="200" fill="linen"/>
  <g>
    <adj:rcGrid rcGridPart="column" gap="5"/>
    <rect fill="#fff" width="0" height="0">
      <adj:frameForParent/>
    </rect>
    <g adj:rcGridPart="row" adj:vAlign="bottom">
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      …
    </g>
    <g adj:rcGridPart="column" adj:hAlign="right">
      <rect fill="#eee" width="0" height="0">
        <adj:frameForParent/>
      </rect>
      <rect width="10" height="10" fill="#000"/>
      <rect width="14" height="12" fill="#222"/>
      …
    </g>
    <g adj:hAlign="left">
      …
    </g>
    …
    <g adj:rcGridPart="column" adj:cellLeftGap="10" adj:cellRightGap="2" adj:cellTopGap="8" adj:cellBottomGap="2">
      <rect width="26" height="18" fill="#000"/>
      …
    </g>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:rcGrid gap="5"/>
    <g adj:vAlign="bottom">
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
    </g>
    <adj:rcGridCellTemplates>
      <adj:rcGridCellTemplate hAlign="right"/>
      <adj:rcGridCellTemplate hAlign="left"/>
    </adj:rcGridCellTemplates>
    <g>
      <rect width="10" height="10" fill="#000"/>
      <rect width="14" height="12" fill="#000"/>
      <rect width="18" height="14" fill="#000"/>
    </g>
    <g>
      <rect width="14" height="12" fill="#222"/>
      <rect width="18" height="14" fill="#222"/>
      <rect width="22" height="16" fill="#222"/>
    </g>
    …
    <adj:rcGridCellTemplates/>
    <g>
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
    </g>
  </g>
</svg>

An adj:rcGrid group element g must have children which are group elements g with attribute adj:rcGridPart having value row or column.

Optional parameters gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, hAlign, vAlign are similar to optional parameters of horizontalList.

Optional parameters hAlign, vAlign, cellLeftGap, cellRightGap, cellTopGap, cellBottomGap, rcGridPart can be specified per grid and per grid part. Per part specification, if present, overrides whole grid specification.

Optional elements adj:rcGridCellTemplates listing elements adj:rcGridCellTemplate are in effect for following parts until the next switch between row and column either way. Optional parameters hAlign, vAlign, cellLeftGap, cellRightGap, cellTopGap, cellBottomGap, can be specified per adj:rcGridCellTemplate. Per cell template specification, if present, overrides per part specification. Lack of specification means a level up is in effect, up to default values. Consequentially an empty adj:rcGridCellTemplates can be used to end the effect of an earlier adj:rcGridCellTemplates.

Rules of combination are defined by implementation.

Another example of command rcGrid is in 090-002.

TODO: neat examples

1.11.23. Command sliderKnob Options

Optional parameters of sliderKnob:

example

You can view the SVG by itself and drag the sliderKnob. Contemporary browsers don't run scripts in SVG in an img element.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <g transform="translate(20,20)">
    <rect x="0" y="0" width="140" height="20" fill="white" stroke="dimgrey"/>
    <rect x="6" y="6" width="128" height="8" fill="lightgrey" stroke="dimgrey"/>
    <g>
      <adj:sliderKnob/>
      <rect x="0" y="0" width="20" height="20" fill="gainsboro" stroke="black"/>
      <rect x="3" y="3" width="14" height="14" fill="lightgrey" stroke="none"/>
    </g>
  </g>
  <text id="setme" style="font-size:10;font-family:sans-serif;" transform="translate(20,60)">0</text>
  <script><![CDATA[
document.addEventListener("change", function (event) {
  var elementToSet = document.getElementById("setme");
  elementToSet.textContent = event.detail.value;
  Adj.doSvg();
});
  ]]></script>
</svg>
example

You can view the SVG by itself and drag the sliderKnob. Contemporary browsers don't run scripts in SVG in an img element.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <adj:verticalList gap="20" hAlign="center"/>
    <g>
      <rect x="0" y="0" width="140" height="20" rx="10" ry="10" fill="white" stroke="dimgrey"/>
      <rect x="6" y="6" width="128" height="8" rx="4" ry="4" fill="lightgrey" stroke="dimgrey"/>
      <g>
        <adj:sliderKnob min="0.3" max="5.0" step="0.1" preset="2.0"/>
        <rect x="0" y="0" width="20" height="20" rx="10" ry="10" fill="gainsboro" stroke="black"/>
        <rect x="7" y="3" width="6" height="14" rx="3" ry="7" fill="lightgrey" stroke="none"/>
      </g>
    </g>
    <g id="setme">
      <adj:horizontalList gap="2" itemsH2V="2"/>
      <rect width="10" height="10" fill="#000" transform="translate(2,2)"/>
      <rect width="10" height="10" fill="#111" transform="translate(14,2)"/>
      <rect width="10" height="10" fill="#222" transform="translate(26,2)"/>
      …
    </g>
  </g>
  <script><![CDATA[
document.addEventListener("change", function (event) {
  var elementToSet = document.getElementById("setme").firstElementChild;
  elementToSet.setAttribute("itemsH2V", event.detail.value);
  Adj.doSvg();
});
  ]]></script>
</svg>

The knob moves within the rectangular size of its parent element, the slider. The slider's size for example may be defined by the size of a child rect, a sibling of the knob.

There is no default look of sliders and knobs made with sliderKnob. An author has broad freedom of choice.

More examples of command sliderKnob are 093-001, and 093-003.

TODO: better document command sliderKnob, event, nesting in slider, widths and heights of groups, many appearances possible, detection of horizontal or vertical

1.11.24. Command toggleButton Options

Optional parameters of toggleButton:

example

You can view the SVG by itself and click the toggleButton. Contemporary browsers don't run scripts in SVG in an img element.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="140" fill="linen"/>
  <g>
    <adj:skimpyList/>
    <g>
      <rect width="70" height="100" stroke="black" stroke-width="1" fill="darkgrey"/>
      <g>
        <adj:tilt alpha="0"/>
        <rect width="70" height="100" stroke="dimgrey" stroke-width="1" fill="lightgrey"/>
        <g adj:id="lockIt">
          <adj:floater at="45,50"/>
          <adj:toggleButton/>
          <path adj:alternativeValue="lock" title="click to flip"
                d="M0,0 l0,-30 30,0 0,30 z M5,-30 l0,-10 q0,-10 10,-10 10,0 10,10 … z"
                fill="darkgrey" stroke="black"/>
          <path adj:alternativeValue="unlock" title="click to flip"
                d="M0,0 l0,-30 30,0 0,30 z M22,-30 l0,-10 q0,-10 10,-10 10,0 10,10 … z"
                fill="darkgrey" stroke="black"/>
        </g>
      </g>
    </g>
  </g>
  <script><![CDATA[
Adj.getElementById("lockIt").addEventListener("change", function (event) {
  var newToggle = event.detail.value;
  document.querySelector("[alpha]").setAttribute("alpha", newToggle === "lock" ? "0" : "15");
  Adj.doSvg();
});
  ]]></script>
</svg>
example

You can view the SVG by itself and click the toggleButton. Contemporary browsers don't run scripts in SVG in an img element.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <defs>
    <radialGradient id="rg" gradientUnits="objectBoundingBox" cx="50%" cy="50%" r="50%">
      <stop stop-color="#0000FF" offset="0"/>
      <stop stop-color="#ffff00" offset="1"/>
    </radialGradient>
  </defs>
  <g>
    <adj:verticalList gap="20"/>
    <g adj:id="switchIt">
      <adj:horizontalList gap="0" centerGap="5" vAlign="middle"/>
      <adj:toggleButton preset="white" congruent="true"/>
      <rect adj:alternativeValue="white" title="click to switch"
            width="12" height="12" fill="white" stroke="dimgrey"/>
      <rect adj:alternativeValue="grey" title="click to switch"
            width="12" height="12" fill="grey" stroke="dimgrey"/>
      <rect adj:alternativeValue="colorful" title="click to switch"
            width="12" height="12" fill="url(#rg)" stroke="dimgrey"/>
      <rect adj:alternativeValue="black" title="click to switch"
            width="12" height="12" fill="black" stroke="dimgrey"/>
      <text>switch</text>
    </g>
    <rect adj:id="switchThis" width="40" height="20" fill="white" stroke="dimgrey"/>
  </g>
  <script><![CDATA[
Adj.getElementById("switchIt").addEventListener("change", function (event) {
  var newToggle = event.detail.value;
  var alternativeValueElement = Adj.getElementById("switchIt").adjS.toggleButtonRecord.getAlternative(newToggle);
  Adj.getElementById("switchThis").setAttribute("fill", alternativeValueElement.getAttribute("fill"));
});
  ]]></script>
</svg>

Optional boolean parameter congruent should be set true if and only if all alternatives in their own coordinate system have the same location and size, e.g. all x=0, y=0, width=12, height=12. One benefit is avoiding on change an automatic invocation of Adj.doSvg(), which may or may not matter to an author. It is OK to not use parameter congruent.

Another example of command toggleButton is in 087-001.

TODO: better document command toggleButton, event, many appearances possible, detection of value, alternative

1.11.25. Command hide Options

Command hide has no options:

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:horizontalList gap="5"/>
    <rect width="45" height="30" fill="#000"/>
    <rect width="40" height="25" fill="#444" adj:hide="true"/>
    <rect width="35" height="20" fill="#888"/>
  </g>
</svg>

1.11.26. Command include Options

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect width="200" height="140" fill="linen"/>
  <g adj:command="horizontalList" adj:gap="2" adj:itemsH2V="1">
    <rect width="40" height="80" fill="#222"/>
    <g>
      <adj:include xlink:href="subdir-080/adj-ex-080-include-to-include.svg"/>
    </g>
    <rect width="40" height="40" fill="#444"/>
    <rect width="80" height="40" fill="#888"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect width="200" height="140" fill="linen"/>
  <g adj:command="horizontalList" adj:gap="2" adj:itemsH2V="1">
    <rect width="40" height="80" fill="#222"/>
    <g>
      <adj:include xlink:href="subdir-080/adj-ex-080-include-to-include.svg#four"/>
    </g>
    <rect width="40" height="40" fill="#444"/>
    <rect width="80" height="40" fill="#888"/>
  </g>
</svg>

Command include parameter xlink:href is required. Note the required XLink namespace, as is commonly used in SVG.

Command include causes asynchronous execution when invoking Adj.doSvg().

There is or should be no problem, no special attention required, with http links on the same server.

As implemented, include is subject to browser imposed restrictions of cross-origin HTTP requests, via XMLHttpRequest. A mechanism often used in this context is Cross-Origin Resource Sharing (CORS).

For best productivity when using URI scheme file, a Firefox add-on File URI Scheme GET from Page Script, from https://addons.mozilla.org/en-US/firefox/addon/file-scheme-get-from-script/, e.g. 1.0.4, is available.

Notably, the same document can be stored without (before) or with the result of (after) invoking Adj. If inspecting in browser development tools, with command include a large difference in verbosity and hence size between such two documents as stored should be easy to recognize by viewing the sources of the documents respectively. Once processed by Adj, which in case there is a command include may mostly be paced by time it takes to remotely get an included document, once processed by Adj the two versions of the document should be identical. Their DOM trees then should be identical.

Adj command include has been implemented if so stored then to display the stored included result of an earlier invocation, until a current inclusion completes successfully. This should give greater certainty that something useful will be displayed even in case the origin of an inclusion becomes unavailable.

1.12. Auxiliary Commands

1.12.1. Option explain

An optional parameter explain inserts explanatory elements.

As implemented, explain inserts explanatory elements for verticalList, horizontalList, connection, rider, circularList, verticalTree, vine, floater, telescopicTree, paragraph, pathArrow, and rcGrid.

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  …
  <g>
    <adj:horizontalList makeGrid="true" gap="5" maxPerRow="3" hAlign="center" explain="true"/>
    <g adj:id="subject-editor">
    <adj:horizontalList gap="10"/>
      <rect width="0" height="0" class="subject">
        <adj:frameForParent inset="1"/>
      </rect>
      <text>XML editor</text>
    </g>
    <g/>
    …
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#aaa"/>
  <rect adj:id="other" x="145" y="55" width="40" height="30" fill="#ccc"/>
  <path d="M5,100 q40,10 80,0 t80,0" stroke="#666" stroke-width="2" fill="none">
    <adj:connection from="one%1,0.5" to="other%0,0.5" explain="true"/>
  </path>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g>
    <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#ddd"/>
    <rect x="85" y="15" width="40" height="30" fill="#ccc"/>
    <rect x="25" y="45" width="40" height="30" fill="#ccc"/>
    <rect adj:id="other" x="145" y="75" width="40" height="30" fill="#bbb"/>
    <g>
      <adj:connection from="one%1,0.5" to="other%0,0.5"/>
      <path d="M45,20q19.265,25.692 50,35t50,35" stroke="#666" stroke-width="2" fill="none"/>
      <rect width="30" height="20" fill="#aaa">
        <adj:rider at="0.2,0.7" adjust="near" gap="2" explain="true"/>
      </rect>
    </g>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:circularList rAlign="inside" gap="2" explain="true"/>
    <circle r="20" fill="#000"/>
    <rect width="3" height="3" fill="#222"/>
    <rect width="6" height="6" fill="#444"/>
    <rect width="9" height="9" fill="#666"/>
    <rect width="12" height="12" fill="#888"/>
    <rect width="15" height="15" fill="#aaa"/>
    <rect width="18" height="18" fill="#bbb"/>
    <rect width="21" height="21" fill="#ccc"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <adj:verticalTree autoParrots="true" hAlign="0.1" vAlign="0.2" gap="12" explain="true"/>
    <text adj:id="r-1" font-size="20">R1</text>
    <text adj:id="r-2">R2</text>
    <text adj:id="l-1-1" font-size="20" adj:treeParent="r-1">L11</text>
    <text adj:id="n-1-2" font-size="15" adj:treeParent="r-1">N12</text>
    <text adj:id="n-1-2-1" font-size="12" adj:treeParent="n-1-2">N121</text>
    <text adj:id="l-1-2-1-1" adj:treeParent="n-1-2-1">L1211</text>
    <text adj:id="l-1-2-1-2" adj:treeParent="n-1-2-1">L1212</text>
    <text adj:id="l-1-2-1-3" adj:treeParent="n-1-2-1">L1213</text>
    <text adj:id="l-1-2-2" adj:treeParent="n-1-2">L122</text>
    <text adj:id="l-1-2-3" adj:treeParent="n-1-2">L123</text>
    <text adj:id="l-1-3" adj:treeParent="r-1">L13</text>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="180" fill="linen"/>
  <g>
    <adj:verticalTree leftGap="20" centerGap="30" childlessGap="10" middleGap="40"/>
    <rect adj:id="o1" width="40" height="30" fill="#000"/>
    <rect adj:id="o2" adj:treeParent="o1" width="30" height="20" fill="#666"/>
    <rect adj:id="o3" adj:treeParent="o2" width="25" height="15" fill="#888"/>
    <rect adj:id="o4" adj:treeParent="o2" width="25" height="15" fill="#aaa"/>
    <rect adj:id="o5" adj:treeParent="o1" width="30" height="20" fill="#bbb"/>
    <rect adj:id="o6" adj:treeParent="o5" width="25" height="15" fill="#ccc"/>
    <rect adj:id="o7" adj:treeParent="o5" width="25" height="15" fill="#ddd"/>
  </g>
  <path d="M0,0" stroke="#777" stroke-width="2" fill="none" adj:d="M ~o1#x - 10, ~o1#yh
  C ~o1#x - 10, ~o1#yh + 10 ~o2#x - 10, ~o2#y%-0.3 ~o2#x - 10, ~o2#yc
  S ~o3#x - 10, ~o3#y%-0.3 ~o3#x - 10, ~o3#yc
  C ~o3#x - 10, ~o3#yh + 10 ~o3#x, ~o3#yh + 10 ~o3#xc, ~o3#yh + 10
  S ~o4#x, ~o4#yh + 10 ~o4#xc, ~o4#yh + 10
  S ~o4#xw + 10, ~o4#yh + 10 ~o4#xw + 10, ~o4#yc
  C ~o4#xw + 10, ~o4#y * 0.5 + ~o2#yh * 0.5 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5 + 10 ~o2#xw, ~o2#yh * 0.5 + ~o4#y * 0.5
  S ~o2#xw, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10 ~o2#xw * 0.5 + ~o5#x * 0.5, ~o2#yh * 0.5 + ~o5#yh * 0.5 + 10">
    <adj:vine explain="true"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="160" fill="linen"/>
  <g>
    <rect adj:id="one" x="15" y="65" width="40" height="30" fill="#000"/>
    <rect adj:id="other" x="95" y="15" width="40" height="30" fill="#666"/>
    <rect adj:id="another" x="145" y="115" width="40" height="30" fill="#aaa"/>
    <path d="M0,0 l40,0 -20,-50 z" fill="#ccc">
      <adj:floater pin="0.5,0" at="~one#xc*0.333+~other#xc*0.333+~another#xc*0.333,~one#yc*0.333+~other#yc*0.333+~another#yc*0.333" explain="true"/>
    </path>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:telescopicTree gap="5" explain="true"/>
    <rect width="30" height="20" fill="#000" adj:id="id1"/>
    <adj:boom/>
    <rect width="32" height="22" fill="#222"/>
    <adj:boom angle="east"/>
    <rect width="34" height="24" fill="#444"/>
    <adj:boom from="id1" angle="90" gap="15"/>
    <rect width="36" height="26" fill="#666" adj:id="id2"/>
    <adj:boom angle="10"/>
    <rect width="38" height="28" fill="#888"/>
    <rect width="40" height="30" fill="#aaa"/>
    <adj:boom from="id2%0.5,1" to="0.5,0" angle="100" gap="~id2#h * 0.5"/><!--  -->
    <rect width="42" height="32" fill="#bbb"/>
    <adj:boom angle="-10"/>
    <rect width="44" height="34" fill="#ccc"/>
    <adj:boom angle="10"/>
    <rect width="46" height="36" fill="#ddd"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:verticalList/>
    <text adj:command="paragraph" adj:maxWidth="155" adj:explain="true">
This is a sentence of text that will wrap.
Here is more.
    </text>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="80" fill="linen"/>
  <rect adj:id="one" x="5" y="5" width="40" height="30" fill="#444"/>
  <rect adj:id="other" x="145" y="35" width="40" height="30" fill="#aaa"/>
  <path d="M15,50 q40,-15 80,0" stroke="none" fill="none">
    <adj:connection from="one % 1, 0.5" to="other % 0, 0.5"/>
  </path>
  <path d="M0,0" adj:d="M50,60 l-5,5 ,-15,0 10,-10 ,-10,-10 15,0 5,5 0,0 30,0 0,0 0,-5 20,10 ,-20,10 0,-5 0,0 ,-30,0 z"
    stroke="black" stroke-width="1" fill="white">
    <adj:pathArrow setback="10" explain="true"/>
  </path>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="170" fill="linen"/>
  <g>
    <adj:rcGrid explain="true"/>
    <g adj:rcGridPart="row">
      <circle r="10" fill="none" stroke="#000"/>
      <circle r="4" fill="#222"/>
      <circle r="6" fill="#444"/>
      <circle r="8" fill="#666"/>
      <circle r="10" fill="#888"/>
    </g>
    <g adj:rcGridPart="column">
      <rect width="10" height="10" fill="#000"/>
      <rect width="14" height="12" fill="#222"/>
      …
    </g>
    …
  </g>
</svg>

1.12.2. Command explain

Similar to optional parameter explain, command explain inserts explanatory elements for an SVG path element.

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <path stroke="#777" stroke-width="2" fill="none" d="M 20,20
    c 20,20 60,20 80,0
    c -20,30 -60,30 -80,0
    m 40,10
    c 40,0 10,60 0,60
    s -40,-60 0,-60">
    <adj:explain/>
  </path>
</svg>

1.12.3. Command relativate

Command relativate converts the coordinates of a path into relative coordinates. Can be useful when editing.

1.12.4. Command skimpyList

Command skimpyList may be easier to comprehend than would be similar use of horizontalList for a single element. One use may be to align to 0,0 the top left corner of an Adj modified SVG element which has no further Adj modified SVG ancestors. Can be useful when top left corner coordinates are not easily known at the time of authoring, e.g. when using tilt.

Slightly different for multiple elements.

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="skimpyList">
    <rect x="-30" y="-20" width="80" height="30" stroke="black" stroke-width="1" fill="#666"/>
    <rect x="30" y="20" width="80" height="30" stroke="black" stroke-width="1" fill="#aaa"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g adj:command="skimpyList" adj:gap="10">
    <rect adj:command="frameForParent" fill="none" stroke="black" stroke-width="1" width="60" height="40"/>
    <rect x="-30" y="-20" width="80" height="30" stroke="black" stroke-width="1" fill="#666"/>
    <rect x="30" y="20" width="80" height="30" stroke="black" stroke-width="1" fill="#aaa"/>
  </g>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <g>
    <adj:skimpyList minWidth="100" minHeight="40" hAlign="left" vAlign="middle"/>
    <rect fill="white" stroke="black" stroke-width="1" width="20" height="5"><adj:frameForParent/></rect>
    <text>Joe</text>
  </g>
</svg>

Optional parameters gap, horizontalGap, leftGap, rightGap, verticalGap, topGap, bottomGap, hAlign, vAlign are equivalent to optional parameters of horizontalList, yet effecting padding for the whole list only rather than between elements.

1.13. Auxiliary Functions

1.13.1. Functions hide, unhide, and toggleHide

Auxiliary function Adj.toggleHide(element) hides or unhides an element.

As implemented, toggleHide inserts or removes an instance of command hide.

An optional second parameter tells whether to invoke Adj.doSvg().

Similarly there are functions Adj.hide(element) and Adj.unhide(element).

1.13.2. Function toggleHideSiblingsFollowing

Auxiliary function toggleHideSiblingsFollowing hides or unhides siblings.

As implemented, toggleHideSiblingsFollowing inserts or removes instances of command hide.

example

You can view the SVG by itself and click elements having onclick. Contemporary browsers don't run scripts in SVG in an img element.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="120" fill="linen"/>
  <g adj:command="horizontalList" adj:gap="5">
    <rect class="frame" adj:command="frameForParent" width="0" height="0"/>
    <g adj:command="verticalList">
      <rect class="frame" adj:command="frameForParent" width="0" height="0"/>
      <text class="heading" onclick="Adj.toggleHideSiblingsFollowing(this, true);">fruits</text>
      <text>apple</text>
      <text>banana</text>
      <text>cantaloupe</text>
    </g>
    <g adj:command="verticalList">
      <rect class="frame" adj:command="frameForParent" width="0" height="0"/>
      <text class="heading" onclick="Adj.toggleHideSiblingsFollowing(this, true);">vegetables</text>
      <text>asparagus</text>
      <text>beet</text>
      <text>cauliflower</text>
    </g>
  </g>
</svg>

The optional second parameter tells whether to invoke Adj.doSvg().

Similarly there are functions hideSiblingsFollowing and unhideSiblingsFollowing.

1.14. Referencing By Identifier Attribute

Using identifier attribute adj:id is simple.

In contrast, here it is explained with more correctness, completeness, and detail than you were hoping for.

1.14.1. Need

Some commands refer to elements by identifier. These include:

connection parameters from and to
rider parameter path
verticalTree child element attribute adj:treeParent
horizontalTree child element attribute adj:treeParent
vine when evaluating element attribute adj:d
floater when evaluating parameter at
fit when evaluating parameters width, height, maxWidth, maxHeight
telescopicTree a boom element's parameter from
pathArrow parameter path, and when evaluating element attribute adj:d
include in case element attribute xlink:href references a fragment in another document

1.14.2. Attribute adj:id

The recommended kind of identifier to use is attribute adj:id.

For attribute adj:id there is no strict uniqueness requirement. At least not per document. Hence, adj:id is not of XML attribute type ID. Values of attribute adj:id should match the XML Name production.

In addition, Adj version 3.3 still recognizes plain id attributes. Future versions of Adj may or may not recognize plain id attributes for identifying elements to commands.

1.14.3. Function Adj.getElementByIdNearby

As implemented, some commands are using JavaScript functionAdj.getElementByIdNearby. These include:

connection parameters from and to
rider parameter path
vine when evaluating element attribute adj:d
floater when evaluating parameter at
fit when evaluating parameters width, height, maxWidth, maxHeight
pathArrow parameter path, and when evaluating element attribute adj:d
include in case element attribute xlink:href references a fragment in another document

Function Adj.getElementByIdNearby finds the element with a given identifier that is nearest to the referencing element, rather than another element with the same identifier that is further away in the same document.

A simplified description of an implementation goes: If there is more than one element with the same identifier, then for each of those elements with the same identifier their respective common ancestor with the referencing element is determined, and the one which is the least number of steps away is it.

One benefit is, when copying a fragment of SVG and pasting it into the same document, references to "nearby" elements within the same structure should still resolve as one could intuitively expect – to nearby elements. Hence, graphics structures with Adj commands referring to "nearby" elements within the same structure should remain intact, even when pasting another copy into the same document.

Authors could be less worried when creating large documents, by hand or from a script. Multiple copies of the same structure should not require fixing up identifiers that are used only within such structure.

An illustration of function Adj.getElementByIdNearby finding instances of attribute adj:id:

Adj.getElementByIdNearby finding adj:ids

1.14.4. Different Search Strategies

Command verticalTree child element attribute adj:treeParent is only looking for identifiers among siblings of the referencing element. That is more narrow of a search than function Adj.getElementByIdNearby.

1.15. Substitution Of Variables

example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="100" fill="linen"/>
  <adj:variable name="myvar" value="10" desc="optional description of variable"/>
  <rect adj:id="one" x="15" y="45" width="40" height="10" fill="#000"/>
  <rect adj:id="other" x="95" y="15" width="40" height="10" fill="#666"/>
  <rect adj:id="another" x="145" y="75" width="40" height="10" fill="#aaa"/>
  <path adj:command="vine" stroke="#777" stroke-width="2" fill="none" d="M0,0" adj:d="
    M ~one#xw + ^myvar, ~one#yc
    C ~one#xw + ^myvar, ~one#yc - 20  ~other#xc - 20, ~other#yh + ^myvar  ~other#xc, ~other#yh + ^myvar
    S ~another#x - ^myvar, ~another#yc - 20  ~another#x - ^myvar, ~another#yc"/>
</svg>
example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj">
  <rect width="200" height="200" fill="linen"/>
  <adj:variable name="myvar" value="10" desc="in outer scope"/>
  <g>
    <adj:variable name="myvar" value="3" desc="in inner scope #1"/>
    <rect adj:id="one" x="15" y="45" width="40" height="10" fill="#000"/>
    <rect adj:id="other" x="95" y="15" width="40" height="10" fill="#666"/>
    <rect adj:id="another" x="145" y="75" width="40" height="10" fill="#aaa"/>
    <path adj:command="vine" stroke="#777" stroke-width="2" fill="none" d="M0,0" adj:d="
      M ~one#xw + ^myvar, ~one#yc
      C ~one#xw + ^myvar, ~one#yc - 20  ~other#xc - 20, ~other#yh + ^myvar  ~other#xc, ~other#yh + ^myvar
      S ~another#x - ^myvar, ~another#yc - 20  ~another#x - ^myvar, ~another#yc"/>
  </g>
  <g transform="translate(0,100)">
    <adj:variable name="myvar" value="17" desc="in inner scope #2"/>
    <rect adj:id="one" x="15" y="45" width="40" height="10" fill="#000"/>
    <rect adj:id="other" x="95" y="15" width="40" height="10" fill="#666"/>
    <rect adj:id="another" x="145" y="75" width="40" height="10" fill="#aaa"/>
    <path adj:command="vine" stroke="#777" stroke-width="2" fill="none" d="M0,0" adj:d="
      M ~one#xw + ^myvar, ~one#yc
      C ~one#xw + ^myvar, ~one#yc - 20  ~other#xc - 20, ~other#yh + ^myvar  ~other#xc, ~other#yh + ^myvar
      S ~another#x - ^myvar, ~another#yc - 20  ~another#x - ^myvar, ~another#yc"/>
  </g>
</svg>

The scope of an adj:variable is all descendants of the SVG element in which it is defined. It is not defined whether an adj:variable is or is not available in the very SVG element in which it is defined.

Multiple definitions of a variable by the same name in the same document are possible, with values of their own. If so, then each one by itself has as scope all descendants of the SVG element in which it is defined. In case of nested scopes of variables of the same name, the value used will be the one found first when searching from use upwards through ancestors.

Substitution of variables also evaluates simple arithmetic into plain decimal numbers.

Only some parameters of some commands substitute variables:

horizontalList gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, maxWidth, maxPerRow, itemsH2V, hAlign, vAlign
verticalList gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, maxHeight, maxPerColumn, itemsH2V, hAlign, vAlign
frameForParent inset, horizontalInset, leftInset, rightInset, verticalInset, topInset, bottomInset
rider gap
circleForParent inset
ellipseForParent inset, horizontalInset, verticalInset
circularList gap, rGap, cGap, fromAngle, toAngle, rAlign, cAlign, dullness, horizontalGap, leftGap, rightGap, verticalGap, topGap, bottomGap
verticalTree gap, horizontalGap, leftGap, centerGap, rightGap, childlessGap, earGap, verticalGap, topGap, middleGap, bottomGap, hAlign, vAlign
horizontalTree gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, childlessGap, earGap, hAlign, vAlign
vine d
floater at
fit maxWidth, maxHeight, width, height
stackFrames inset, horizontalInset, leftInset, rightInset, verticalInset, topInset, bottomInset, stacking
zoomFrames step
tilt alpha, beta
pinnedList gap, horizontalGap, leftGap, rightGap, verticalGap, topGap, bottomGap
telescopicTree gap, and a boom element's gap
paragraph maxWidth, lineGap, hAlign, indent
pathArrow d, setback, nockSetback, pointSetback
rcGrid gap, horizontalGap, leftGap, centerGap, rightGap, verticalGap, topGap, middleGap, bottomGap, hAlign, vAlign, cellLeftGap, cellRightGap, cellTopGap, cellBottomGap
sliderKnob min, max, step, preset
skimpyList gap, horizontalGap, leftGap, rightGap, verticalGap, topGap, bottomGap

Some parameters of some commands substitute variables with boolean true or false:

horizontalList makeGrid, explain
verticalList makeGrid, explain
connection explain
rider explain
circularList packArc, explain
verticalTree autoParrots, explain
horizontalTree autoParrots, explain
vine explain
floater explain
telescopicTree explain
paragraph explain
pathArrow explain
rcGrid explain
toggleButton congruent

There is at least one real use example file with substitution of variables.

1.15.1. Predefined Variables

Some special global variables have been predefined:

windowInnerWidth dynamically window.innerWidth
windowInnerHeight dynamically window.innerHeight

1.16. Issuing Commands Via adj: Attributes Instead Of Via adj: Elements

A newly implemented alternative syntax allows Adj commands to be attributes of SVG elements instead of requiring them to be XML elements of their own. This can be convenient for an author. Arguably there are distinct flavors of clarity in using the two different syntaxes. Both syntaxes are supported in the foreseeable future.

adj: elements

original, still OK to write this way

<g>
  <adj:verticalList hAlign="center"/>
  <rect width="60" height="40">
    <adj:frameForParent inset="0.5"/>
  </rect>
  <text>innermost</text>
  <text>one</text>
</g>
adj: attributes

new, OK to write
<g adj:command="verticalList" adj:hAlign="center">
  <rect adj:command="frameForParent" adj:inset="0.5" width="60" height="40"/>
  <text>innermost</text>
  <text>one</text>
</g>

This user guide contains at least one set of images which while similar in content have been written one with commands via adj: attributes versus the other with commands via adj: elements. More examples of commands via adj: attributes are here.

Despite at least a theoretical, but also avoidable, risk involving identical parameter names in future extensions, the benefits of commands via adj: attributes appear to be worth it.

1.17. Command Combinations

Some commands make sense to combine for the same SVG element. Others don't make sense, and others would be plain impossible.

It makes sense to combine textBreaks and horizontalList, for the same SVG element.

It could make sense, for example, to combine verticalList or horizontalList with rider or floater.

Obviously it would not make sense to combine horizontalList and verticalList, for the same SVG element. It wouldn't make sense to combine connection and rider, for the same SVG element. It wouldn't make sense to combine rider and floater, for the same SVG element.

Mentioned because maybe not obvious: It makes no sense to combine vine and floater.

There is no complete list. Factual feedback about noteworthy combinations, maybe example files, from an author using Adj is welcome.

1.17.1. Command Combinations Via adj: Attributes Instead Of Via adj: Elements

Commands textBreaks, rider, floater, fit, tilt, hide, and explain instead of being written e.g. as adj:command="textBreaks" alternatively can be written as adj:textBreaks="true".

This allows command combinations via adj: attributes, as shown by example:

adj: elements

original, still OK to write this way

<g>
  <adj:verticalList/>
  <adj:textBreaks/>
  <text>line one
line two</text>
</g>
adj: attribute and element

OK to write
<g adj:command="verticalList">
  <adj:textBreaks/>
  <text>line one
line two</text>
</g>
adj: attributes only

newest, OK to write
<g adj:command="verticalList" adj:textBreaks="true">
  <text>line one
line two</text>
</g>

This alleviates the fact it is not possible to combine two adj:command attributes as such for a single element, as in XML an attribute name must not appear more than once in the same element.

1.18. Complete Authoring Workflow

An author can increase productivity by using browser add-ons.

Those who don't like using existing Firefox add-ons could implement alternate workflows and tools, e.g. Chrome extensions. Resulting images should not depend on the brand authoring tools used.

An example workflow:

A diagram of this example workflow:

example workflow

Only a PNG here to accommodate a browser limitation, with a link to SVG.

TODO: make short video how simple and fun this workflow is to use and to set up

1.19. Invocation

Invoking Adj is relatively simple, once you decide which option works best for you.

For the sake of completeness, other choices are explained too.

1.19.1. Explicit Invocation

As implemented, Adj is a JavaScript library. Hence, most straight forward, Adj can be invoked explicitly, e.g. like

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-flat-20030114.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Adj.doSvg();">
  <script type="text/javascript" xlink:href="js/adj.js"/>
  <g>…

Obviously, there must be a correct reference (path) to a copy of the essential adj.js file from this project.

1.19.2. Explicit Invocation And Saving Processed Document

For best results for most users, Adj can be invoked explicitely and the processed document can be saved.

Benefits:

Most SVG files in this documentation have been processed this way. You can look at their source code.

SVG files in this documentation so far have been finalized with the help of Firefox add-on Save Back to File from DOM. It has become an easy habit to work this way.

An example workflow combining explicit invocation and saving processed documents has been described above.

1.19.3. No Invocation – If Saving Processed Document

If chosen to do so, with an author saving a processed document, invocation in users' browsers can be avoided.

As an example implementation, the Firefox add-on Save Back to File from DOM can do the necessary saving, obviating invocation.

Avoiding invocation in users' browsers may mean less problems with viewing in users' browsers that are set not to allow script invocation. This may be an antiquated concern: Allowing JavaScript has become normal.

Avoiding invocation in users' browsers also means no need to distribute the Adj JavaScript library. One downside, however, of not distributing the Adj JavaScript library is inability to dynamically adjust, e.g. to different fonts available in a different browser instance. This may be an acceptable compromise.

1.19.4. Implicit Invocation

With script injection, explicit invocation can be avoided. Probably not worth the trouble.

1.20. Invocation Parameters

The complete API of function Adj.doSvg() is

doSvg (documentNodeOrAnSvgElement, doSvgDoneCallback)

Adj.doSvg() accommodates sloppy parameter passing: Either parameter or both parameters can be omitted.

1.20.1. What SVG Element

If not given a documentNodeOrAnSvgElement then Adj.doSvg() defaults to doing all SVG elements in the document.

This allows for concise onload="Adj.doSvg();" to work for an SVG document proper and also for an HTML document with SVG inlined.

1.20.2. Asynchronicity And Completion

Adj.doSvg() runs asynchronously. Therefore, optionally a callback function can be given.

In this example note the sequence when running

Adj.doSvg(function () {
  console.log('done')
});
console.log('starting');

The callback function optionally may use the SVG element or array of SVG elements it will be passed. For example

Adj.doSvg(function (svg) {
  console.log('done with', svg)
});

As Adj.doSvg() runs asynchronously, there is little benefit to catching exceptions.

1.21. More Details

1.21.1. Using SVG Group Element g

Judicious use of SVG group elements g makes Adj quite practical.

TODO: some good examples

1.21.2. Overwriting Preexisting Transform Attributes

When Adj inserts a transform attribute it overwrites a preexisting transform attribute, if any.

This is actually quite practical when transformations are changing, and the preexisting transformation has been the older version.

If indeed a separate transformation is needed, one possible solution seems to be applying it as appropriate at a parent or child element, possibly at a dedicate group element g.

TODO: a good example

1.21.3. Transforming An SVG Path

For a connection its content may be scaled and rotated. This is different than merely moving around an element, which can be and is done by an arguably simpler translation transformation.

Other changes to paths are performed by vine, and more complex changes to paths are performed by pathArrow.

1.21.3.1. Changing Points

For transforming an SVG path or line element in a connection Adj changes the coordinates of its points. For transforming an SVG path or line element in a connection Adj does not insert transform attributes.

This has been implemented this way because scaling effectively changes stroke width, which is undesirable. The issue of scaling and stroke width has been discussed for SVG version 2, which is far out.

1.21.3.2. Storing Away Authoring Coordinates

Essential authoring coordinates are stored away in Adj namespace attributes, for reuse by authors and algorithms.

Algorithms which store away authoring coordinates also look for authoring coordinates in Adj namespace attributes, and if present use the values of Adj namespace attributes rather than equivalent SVG attributes.

1.21.3.3. Transforming Arcs Is Not Supported

As implemented, other than straight lines and curves, arcs in an SVG path element in a connection or in a pathArrow don't get handled correctly by Adj. As implemented, Adj replaces such arcs, if any, by straight lines. This could be improved.

1.21.4. Exception Handling

A visual display is provided instead of the expected SVG in case a JavaScript exception occurs in an invocation of Adj.doSvg();.

1.21.5. Bad Command Handling

As a matter of practicality, if authors reload documents after each change, they should be able to quickly know whether their most recent incremental change has the desired effect, doesn't have the desired effect, has bad syntax, or is otherwise defective.

Some cases are handled well already. This works with a visual display of exceptions.

Bad command handling can further be improved with feedback from authors using Adj. Frequent, puzzling, time consuming, and painful cases should have priority.

It should be considered though, absolute perfection in bad command handling may not be a goal: A library providing help for every theoretically possible authoring issue would be significantly larger, which means more expensive to produce, to maintain, and using more resources and time to download, and to execute.

1.22. Helpful Hints

1.22.1. Defining An SVG rect Element

When defining an SVG rect element which will be sized and positioned by Adj, e.g. by a frameForParent, it is possible to be minimalist.

An SVG rect element only needs a width and height attribute, which can be zero. An SVG rect element needs neither an x nor a y attribute.

1.22.2. Considerations For Nesting

TODO: describe special limitations or benefits, if any

1.23. Extending SVG With The Adj Namespace

For standards compliant extension of SVG, Adj uses XML namespace http://www.nrvr.com/2012/adj with preferred prefix adj, as declared in xmlns:adj="http://www.nrvr.com/2012/adj".

1.24. Alternate Syntax – JavaScript Instead Of XML

It is expected that authors will prefer the concise form Adj syntax, which is prevalently used in this documentation, over more verbose JavaScript function calls.

Nevertheless, via JavaScript function calls someone interested could invoke the Adj JavaScript library as needed, partially or wholly.

One entry point could be explicit invocation with Adj.doSvg();.

Another kind of entry point could be the setting of algorithms to be applied to an element. E.g. the concise form Adj command

<adj:horizontalList makeGrid="true" hAlign="center" vAlign="middle" maxPerRow="3" gap="5"/>

actually gets converted into, could have been written as, and gets interpreted as JavaScript

Adj.setAlgorithm(this, 'horizontalList', {makeGrid:true, hAlign:'center', vAlign:'middle', maxPerRow:3, gap:5});

Some details of the syntax of Adj may change after feedback from authors using it.

1.25. Implementation Details

This may matter to some authors.

1.25.1. Need Driven

How Adj is implemented partially has been a function of what needs it was supposed to fulfill. Drawing, specifically in engineering, often has meant abstraction. Photographic realism has its place, but it is not a topic here. Available size of drawing surfaces often has been a limitation. Limitations of medium effect limitations of content represented. On large drawing boards of past centuries the area available often was an order of magnitude larger than on contemporary computer displays. Adj has been designed to facilitate creation and long-term maintenance of system diagrams, specifically for diagrams of large complexity. This is a different motivation and sets different priorities than what for nontechnical and technical users has been prevalent since the second half of the twentieth century: The low resolutions and small sizes of television screens, computer monitors, cell phones, and more recently mobile tablets. Arguably those screens combined with software such as PowerPoint have influenced the thinking of many.

Adj prioritizes the showing of all necessary information. Adj facilitates representation and communication of complexity.

How to organize rich sets of relevant detail?

In Adj the metaphor is a large sheet that expands as needed, when more information gets added. Expansion is in both dimensions, x and y.

In contrast, in word processing, the metaphor is a sufficiently long scroll of paper, continuous for a webpage, paginated for printing: When more information gets inserted, the scroll gets longer, the webpage gets longer, more pages will be printed. In most presentation programs, detail must go on other slides, or might be rephrased to fit.

Change happens.

To accommodate change, Adj facilitates diagrams being updated in ways that maintain perfect looks. Adj facilitates automated propagation of change, both change of content and change of appearance.

In contrast, without Adj, large and complex diagrams, and large sets of diagrams, could become outdated too quickly. The cost of updating diagrams can become prohibitive. Editing change into a diagram too easily can destroy an appearance of perfection that has been achieved in a first version.

Adj also may facilitate linking, scripting, and folding.

Undeniably, while Adj users will enjoy using large and very large computer displays, large images for some users will require panning, zooming, and possibly folding.

1.25.2. Sizing From Small Parts To Whole Image

One of the first patterns implemented in Adj has been collections of graphics objects, such as lists in different shapes. As implemented, on purpose, these collections resize to accommodate the size, number, and desired relative positions of their contents elements.

before nested collections
insertion
after nested collections with additional contents

Instead of "these collections resize" one could think "these collections are resized". Whether one considers collections resizing themselves or being resized by Adj depends on one's point of view: Whether one focuses on the effect, a user's, a graphics author's, an SVG point of view (resize), versus whether one pays attention to details of how it is done, an implementer's, a programmer's, a JavaScript point of view (are resized).

The size of the smallest parts, the leaves of the SVG element tree, which are not collections themselves, e.g. text, are found by asking SVG for the bounding box. Only when the sizes of all siblings are known then they can be laid out within their parent (the collection) and then the parent's (the collection's) size can be known. Adj collections automatically do such sizing, so authors don't have to.

1.25.3. Execution Path

With nested collections the size of the smallest parts, the leaves of the SVG element tree, which are not collections themselves, e.g. text, are found by asking SVG for the bounding box. When walking the SVG element tree, only when the sizes of all siblings are known then they can be laid out within their parent (the collection) and then the parent's (the collection's) size can be known.

walking SVG tree

Hence, in a first walk of the SVG element tree Adj collections are laid out.

To perform all commands, Adj walks the SVG element tree 4 times, in 4 phases:

phaseHandlerName algorithmName
adjPhase1Down textBreaks, paragraph, relativate, include, toggleButton
adjPhase1Up verticalList, horizontalList, circularList, verticalTree, horizontalTree, fit, stackFrames, tilt, skimpyList, pinnedList, telescopicTree, rcGrid, sliderKnob
adjPhase3 with
processSubtreeOnlyInPhaseHandler
floater
adjPhase5Down frameForParent, circleForParent, ellipseForParent, zoomFrames
adjPhase5Up connection
adjPhase7 with
processSubtreeOnlyInPhaseHandler
rider
adjPhase7Up vine, pathArrow, explain

The 4 phases adjPhase1, adjPhase3, adjPhase5, and adjPhase7 are known to developers of Adj commands (algorithms). Their numbers have been spaced out without impending necessity.

walking SVG tree multiple times

In addition, there are unnamed administrative walks of the SVG element tree.

Phases have been a simple solution to ensure order of execution. Regrettably, phases impose some limitations of what can be done. A list of limitations has not been compiled yet. To get one started, factual feedback about noteworthy limitations, if encountered, preferably with example files, is welcome.

A future implementation may or may not be structured differently, hopefully with less limitations. For the foreseeable future, however, this is it. Required effort and consideration for authors with existing documents are reducing the probability of gratuitous changes.

1.25.4. More Implementation Details

There should be more architectural information, implementation insights, and usage hints available from the original authors. Ask specific questions to justify the effort of documenting more details.

1.26. Extending Adj With Your Own Commands And Algorithms

A first example of extending Adj with commands (algorithms) has been given in the user-docs/contrib directory with command randomTilt.

There should be more information, insights, and hints available from the original authors. Ask specific questions to justify the effort of documenting more details.

1.27. Automated Testing

To facilitate continuing compatibility as both Adj and browsers are moving along with new code, an automated test suite has been implemented here.

For a set of prepared test documents, freshly computed results of Adj processing are compared with expected results.

Images that are made from graphic elements without text, hence not using fonts, should achieve exactly the same results each time in each browser. Variations in less significant digits do occur and are tolerated in order to pass.

Furthermore, for images that contain text, an explicitly provided font should, someday hopefully will, allow achieving the same results each time in each browser too. Out of necessity, however, for now, when text is present, larger variations are tolerated in order to pass.

For contributing to increasing the number of test cases, or with questions, please use contact and/or repository info provided above.

1.27.1. Making More Test Cases

An additional test case can be made by steps:

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink"
     onclick="Adj.doSvg();">
  <script type="text/javascript" xlink:href="../js/adj.js"/>
  <script type="text/javascript" xlink:href="../js/adj-tests.js"/>
test-adj-ex-002-verticalList.svg
test-adj-ex-002-verticalList-result.svg

1.28. Compatibility Issues

At the time of the first writing of this section, for the release of Adj version 3.0, there had been compatibility problems with Internet Explorer.

By the time of the release of Adj version 4.0, improvements in Internet Explorer 11 appear to have been achieved.

Good results have been achieved with Firefox, Chrome, Safari, and Opera.

1.28.1. Internet Explorer 11

While problems may exist, it passes the test suite.

Because of security settings of Internet Explorer, one may have to explicitly click to approve the Adj JavaScript library to run.

1.28.2. Internet Explorer 10

Support of Internet Explorer 10 and older versions has ended 2016-01-12. Adj is no longer suported for Internet Explorer 10 and earlier.

1.28.3. Internet Explorer 9 And Earlier

Adj version 6.0.1 is no longer compatible with Internet Explorer 9 and earlier.

1.28.4. Firefox 32

Apparently inside a text element extraneous whitespace near a hyperlink a element can cause line height calculation on Firefox to be wrong. See command paragraph.

1.29. SVG Inline In HTML

Support for SVG inline in HTML is a relatively new addition since Adj 5.0.1.

A simple first example is in JS Bin at http://jsbin.com/limeba/edit?html,output, which should let you experiment, clone, etc..

Some leftover examples from QA are 002, 023, 063, 075, 080, 081, 090, 091, 092, 093, and more.

TODO: document Adj in SVG inline in HTML, with compelling examples, description of limitations and caveats

1.30. Example Files

1.30.1. Example File 001 Source Code

The source code, before processing, of this older version

example workflow

of above diagram of the example workflow:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:adj="http://www.nrvr.com/2012/adj" xmlns:xlink="http://www.w3.org/1999/xlink"
     onload="Adj.doSvg();" width="200" height="120">
    <script type="text/javascript" xlink:href="../js/adj.js"/>
    <title>Example Workflow</title>
    <!-- Illustration idea and first version - Leo Baschy <srguiwiz12 AT nrvr DOT com> -->
    <style type="text/css"><![CDATA[
    svg {
        font-size: 12px;
        font-family: sans-serif;
    }
    .subject {
        fill: lightgray;
        opacity: 0.5;
        stroke: gray;
    }
    .arrow {
        stroke: gray;
        fill: none;
    }
]]></style>
    <defs>
        <marker id="arrowhead" class="arrow" markerUnits="strokeWidth" orient="auto"
                viewBox="-4 -2 5 4" refX="0" refY="0" markerWidth="5" markerHeight="4" stroke-width="1" fill="none">
            <path d="M -3 1 L 0 0 L -3 -1"/>
        </marker>
    </defs>
    <g>
        <adj:horizontalList makeGrid="true" gap="5" maxPerRow="3" hAlign="center"/>
        <g adj:id="subject-editor">
            <adj:horizontalList gap="10"/>
            <rect width="0" height="0" class="subject">
                <adj:frameForParent inset="1"/>
            </rect>
            <text>XML editor</text>
        </g>
        <g/>
        <g/>
        <g/>
        <g>
            <rect width="50" height="50" fill="none"/>
        </g>
        <g/>
        <g adj:id="subject-disk">
            <adj:horizontalList gap="10"/>
            <rect width="0" height="0" class="subject">
                <adj:frameForParent inset="1"/>
            </rect>
            <text>disk</text>
        </g>
        <g/>
        <g adj:id="subject-author">
            <adj:horizontalList gap="10"/>
            <rect width="0" height="0" class="subject">
                <adj:frameForParent inset="1"/>
            </rect>
            <text>author</text>
        </g>
        <g/>
        <g>
            <rect width="50" height="150" fill="none"/>
        </g>
        <g/>
        <g adj:id="subject-firefox">
            <adj:horizontalList gap="10"/>
            <rect width="0" height="0" class="subject">
                <adj:frameForParent inset="1"/>
            </rect>
            <text>Firefox</text>
            <g>
                <adj:horizontalList gap="10"/>
                <g adj:id="add-on-auto-reload">
                    <adj:verticalList gap="5"/>
                    <rect width="0" height="0" class="subject">
                        <adj:frameForParent inset="1"/>
                    </rect>
                    <text>Auto Reload</text>
                    <text>add-on</text>
                </g>
                <g adj:id="add-on-save-back">
                    <adj:verticalList gap="5"/>
                    <rect width="0" height="0" class="subject">
                        <adj:frameForParent inset="1"/>
                    </rect>
                    <text>Save Back to File</text>
                    <text>from DOM</text>
                    <text>add-on</text>
                </g>
            </g>
        </g>
        <g>
            <adj:connection from="subject-editor % 0.2, 1.2" to="subject-disk % 0.2, -0.2"/>
            <path class="arrow" d="M0,0 q50,10 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.4" pin="1.1,0.5"/>
                <adj:verticalList gap="1"/>
                <text>saves</text>
            </g>
        </g>
        <g>
            <adj:connection from="subject-disk % 0.2, 1.2" to="subject-firefox % 0.1, -0.2"/>
            <path class="arrow" d="M0,0 q50,10 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.4" pin="1,1"/>
                <adj:verticalList gap="1"/>
                <text>first time</text>
                <text>opens</text>
            </g>
        </g>
        <g>
            <adj:connection from="subject-disk % 0.4, 1.2" to="add-on-auto-reload % 0.6, -0.1"/>
            <path class="arrow" d="M0,0 q50,10 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.9" pin="1,1"/>
                <adj:verticalList gap="1"/>
                <text>auto</text>
                <text>reloads</text>
            </g>
        </g>
        <g>
            <adj:connection from="add-on-save-back % 0.6, -0.05" to="subject-disk % 0.6, 1.2"/>
            <path class="arrow" d="M0,0 q50,10 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.1" pin="0,1"/>
                <adj:verticalList gap="1"/>
                <text>can</text>
                <text>save</text>
                <text>back</text>
            </g>
        </g>
        <g>
            <adj:connection from="subject-author % 0.0, -0.2" to="subject-editor % 1.2, 1.0"/>
            <path class="arrow" d="M0,0 q50,10 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.4" pin="0,1.1"/>
                <adj:verticalList gap="1"/>
                <text>edits</text>
            </g>
        </g>
        <g>
            <adj:connection from="subject-author % 0.0, 1.2" to="subject-firefox % 1.05, 0.0"/>
            <path class="arrow" d="M0,0 q70,-30 100,0" stroke-width="3" marker-end="url(#arrowhead)"/>
            <g>
                <adj:rider at="0.4" pin="-0.1,0"/>
                <adj:verticalList gap="1"/>
                <text>views</text>
            </g>
        </g>
    </g>
</svg>

1.30.2. Example File 002

An example:

example image 002

1.30.3. Example File 003

An example:

example image 003

1.30.4. Example File 004

An example:

example image 004