Skip to content

Instantly share code, notes, and snippets.

@jakebrinkmann
Last active January 27, 2022 23:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakebrinkmann/fc80f2d10212db23515dff1252ec973d to your computer and use it in GitHub Desktop.
Save jakebrinkmann/fc80f2d10212db23515dff1252ec973d to your computer and use it in GitHub Desktop.
XSD (XML) schema viewer
<!doctype html>
<html>
<!-- This tool is licenced under the MIT licence on GitHub:
https://github.com/peterraf/online-xsd-viewer
Copyright (c) 2017-2018 by Peter Raffelsberger (peter@raffelsberger.net)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<head>
<TITLE>XML Schema Viewer</TITLE>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type/>
<META name=description content=""/>
<META name=keywords content=""/>
</head>
<style type="text/css">
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px; /*14px*/
/*line-height: 1.42857143;*/
background-color: #EDEDED;
/*color: #C8C8C8;
background-color: #4c5252;
height: 100%;
*/
float1: center;
margin: 0px; /*10px;*/
text-align: left; /*center;*/
}
a, p {
text-align: left;
}
canvas {
background-color: #FFFFFF;
}
/* Dropdown Content (Hidden by Default) */
div.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}
div.node-details {
display: none;
position: absolute;
background-color: #FFFFFF;
/*min-width: 160px;*/
box-shadow: 1px 1px 5px 5px rgba(0,0,0,0.4); /* oben, rechts, unten, links */
/*box-shadow: 1px 1px 6px 6px rgba(0,0,0,0.4); /* oben, rechts, unten, links */
}
INPUT {
FONT-FAMILY: Verdana,Arial,Helv,Helvetica;
border-style: solid;
border-width: 1px;
border-color: #808080;
border-radius: 5px;
height: 22px;
color: #404040;
margin: 2px 2px 2px 2px;
padding: 0px 5px 0px 5px; /* oben, rechts, unten, links */
outline-size: 0px;
}
INPUT:hover {
border-color: #303030;
color: #000000;
}
INPUT:focus {
border-color: #303030;
color: #000000;
outline-style: none;
}
INPUT.button, a.button {
border-style: solid;
border-width: 1px;
border-color: #808080;
height: 24px;
text-decoration: none;
padding: 5px 15px 5px 15px; /* oben, rechts, unten, links */
color: #000000;
background-color: #FFFFFF;
}
INPUT.button:hover {
bor-der-color: #303030;
co-lor: #000000;
background: linear-gradient(to top, #EDEDED, #C0C0C0);
}
a.button {
background-color: #FFFF70; /* #EDEDED; */
cursor: pointer;
font-weight: bold;
}
a.button:hover {
background-color: #FFFF20; /* #EDEDED; */
}
p.XSD {
padding: 0px 12px 4px 12px; /* oben, rechts, unten, links */
}
textarea {
font-size: 12px; /*14px*/
}
/*
.inner {
height: 100%;
}
*/
table {
border: 0px;
border-spacing: 0px;
}
table.subtable {
height: 100%;
}
table.node-details {
background-color: #FFFFFF;
border: 2px solid #606060; /*2px solid #606060; #707070;*/
border-collapse: collapse;
}
tr {
/*
font-size: 1px;
line-height: 1px;
*/
}
tr.horline {
background-image: url("horline.png");
}
tr.before-node {
height: 44%;
}
tr.after-node {
height: 56%;
}
td {
margin: 0px;
padding: 0px; /*6px 2px 6px 2px; /* oben, rechts, unten, links */
spacing: 0px;
text-align: left;
vertical-align: middle;
/*
white-space: nowrap;
background-color: #A0A0A0;
font-size: 1px;
line-height: 1px;
text-align: center;
*/
}
td.nd-column {
background-color: #808080; /*#808080;*/
border: 1px solid #B0B0B0;
color: #E0E0E0;
font-size: 10px;
font-weight: bold;
padding: 1px 4px 1px 3px; /* oben, rechts, unten, links */
text-align: center;
vertical-align: middle;
}
td.nd-name {
background-color: #FFFF80;
border: 1px solid #B0B0B0;
color: #000000; /*#404040;#000090;*/
font-size: 11pt;
font-weight: bold;
padding: 1px 10px 1px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
/*width: 80%;*/
}
td.nd-count {
background-color: #FFFF80;
border: 1px solid #B0B0B0;
color: #303030; /*#404040;#000090;*/
font-size: 11pt;
font-weight: bold;
padding: 1px 8px 1px 6px; /* oben, rechts, unten, links */
text-align: right;
vertical-align: top;
/*width: 10%;*/
}
td.nd-attr {
background-color: #FFFF80;
border: 1px solid #B0B0B0;
color: #303030; /*#606060;*/
font-size: 12px; /*9pt;*/
/*line-height: 8pt;*/
padding: 3px 10px 2px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
}
td.nd-type {
background-color: #FFFFFF;
border: 1px solid #B0B0B0;
color: #282828; /*#202020;#000000;*/
font-size: 11px; /*8pt;*/
font-weight: bold;
padding: 3px 10px 2px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
}
td.nd-pattern {
background-color: #FFFFFF;
border: 1px solid #B0B0B0;
color: #282828; /*#202020;#000000;*/
font-size: 11px; /*8pt;*/
font-weight: bold;
padding: 3px 10px 2px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
}
td.nd-anno {
background-color: #FFFFFF;
border: 1px solid #B0B0B0;
color: #006000; /*#282828;#202020;#000000;*/
font-size: 12px; /*11px;*/
/*font-style: italic;*/
font-weight: bold;
line-height: 14px; /*13px;*/
padding: 4px 10px 3px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
}
td.nd-enum {
background-color: #FFFFFF;
border: 1px solid #B0B0B0;
color: #383838; /*#202020;#000000;*/
font-size: 11px; /*8pt;*/
font-weight: bold;
line-height: 13px;
padding: 4px 10px 3px 6px; /* oben, rechts, unten, links */
text-align: left;
vertical-align: top;
}
td.nd-xpath {
background-color: #E0E0E0; /*#E4E4E4;#EDEDED;*/
border: 1px solid #B0B0B0;
color: #282828; /*#202020;#000000;*/
font-size: 11px; /*8pt;*/
font-weight: bold;
max-width: 300px;
padding: 3px 10px 2px 6px; /* oben, rechts, unten, links */
text-align: left;
overflow: hidden;
vertical-align: top;
}
td.nd-xpath:hover {
overflow: visible;
}
td.node {
/*
font-size: 10pt;
line-height: 1px;
*/
width: 1%;
}
td.hor-line-old {
font-size: 1px;
line-height: 1px;
width: 40%;
}
td.image {
border-spacing: 0;
height: 1px;
font-size: 1px;
line-height: 1px;
max-height: 1px;
margin: 0;
padding: 0;
}
td.horline {
/*background-image: url("horline.png");*/
min-width: 14px;
width1: 40%;
}
td.leftline {
background-image: url("leftline.png");
}
td.text {
font-size: 10pt;
line-height: 12pt;
}
td.subtable {
/*display: block;*/
height: 100%;
}
div.node-mand {
border-style: solid;
border-width: 1px;
border-color: #000000;
color: #000000;
/*height: 23px;*/
font-size: 9pt;
font-weight: bold;
padding: 3px 6px 1px 5px; /* oben, rechts, unten, links */
text-decoration: none;
width1: 5%;
background-color: #EDEDED;
}
select.version {
margin: 3px 16px 3px 16px; /* oben, rechts, unten, links */
padding: 5px 8px 4px 8px; /* oben, rechts, unten, links */
}
option.version {
/*height: 60px;*/
/*line-height: 200%;*/
margin: 4px 6px 3px 5px; /* oben, rechts, unten, links */
padding: 4px 6px 3px 5px; /* oben, rechts, unten, links */
}
/*
#multiple option {
padding: 80px;
}
*/
p.bottom-line {
background-color: #404040; /*#606060;*/
color: #808080; /*#A0A0A0;*/
font-size: 9pt;
font-weight: bold;
margin: 0px;
padding: 4px 8px 3px 8px; /* oben, rechts, unten, links */
}
a.bottom-line {
/*background-color: #404040; /*#606060;*/
color: #808080; /*#A0A0A0;*/
text-decoration: none;
font-size: 9pt;
font-weight: bold;
margin: 0px;
padding: 4px 8px 3px 8px; /* oben, rechts, unten, links */
}
a.bottom-line:hover {
color: #D0D0D0; /*#A0A0A0;*/
}
fieldset {
background-color: #606060; /*#404040;*/
border: 0px;
margin: 0px;
padding: 1px 5px 0px 5px; /* oben, rechts, unten, links */
}
label {
/*background-color: #606060; /*#404040;*/
color: #E0E0E0; /*#E0E0E0;*/
cursor: pointer;
/*height: 25px;*/
/*min-height: 25px;*/
margin: 1px;
padding: 3px 15px 3px 15px; /* oben, rechts, unten, links */
vertical-align: middle;
}
label.search {
cursor: text;
/*vertical-align: bottom;*/
}
input {
background-color: #EDEDED;
color: #000000;
cursor: pointer;
margin: 2px;
}
input[type="checkbox"] {
background-color: #FFFFFF;
vertical-align: bottom;
}
input.search-text {
cursor: text;
margin: 2px 1px 2px 2px; /* oben, rechts, unten, links */
}
input.search-button {
background-color: #C0C0C0;
color: #000000;
font-size: 8pt;
/*font-weight: bold;*/
text-align: center;
}
a.search-button {
background-color: #C0C0C0;
border-color: #808080;
border-radius: 5px;
color: #404040;
font-size: 8pt;
font-weight: bolder;
height: 22px;
margin: 2px;
padding: 5px 9px 5px 9px; /* oben, rechts, unten, links */
text-align: center;
text-decoration: none;
vertical-align: middle;
}
a.search-button:hover {
background-color: #C0C0C0;
border-color: #000000;
color: #202020;
}
div.search-result {
background-color: #484848; /*#606060; /*#404040;*/
border: 0px;
display: none;
margin: 0px;
padding: 4px 4px 4px 4px; /* oben, rechts, unten, links */
}
table.search-result {
color: #C0C0C0; /*#B8B8B8;*/
font-size: 10pt;
line-height: 13pt;
/*color: #B0B0B0;
font-size: 13px; /*10pt;* /
font-weight: bold;
line-height: 12pt; /*13pt;*/
width: 100%;
}
tr.search-result {
background-color: #606060; /*#E4E4E4;#EDEDED;*/
cursor: pointer;
/*padding: 3px 10px 2px 6px; /* oben, rechts, unten, links */
}
tr.search-result:nth-child(even) {background: #606060; }
tr.search-result:nth-child(odd) {background: #545454; } /*#686868;*/
tr.search-result:hover {
background-color: #484848; /*#505050;*/
color: #F0F0C0; /*#C0C0C0;*/
}
td.xpath {
padding: 0px 5px 0px 5px; /* oben, rechts, unten, links */
}
</style>
<body>
<p class="XSD" id="LoadSchemaParagraph">
<b>XML Schema Definition:</b><br>
<input type="file" id="get_the_file">
<br>
<code id="Status" style="display: none;"></code>
</p>
<fieldset id="SchemaOptions" style="display: none;">
<label><input type="checkbox" id="cbAnnotations" onclick="AnnotationChanged();" value="1" checked> Annotations</label>
<label><input type="checkbox" id="cbTypeInfo" onclick="TypeInfoChanged();" value="1" checked> Type Info</label>
&nbsp;&nbsp;&nbsp;
<label class="search">
<input class="search-text" id="SearchText" value=""><input class="search-button" id="SearchButton" onclick="SearchButtonPressed();" value="SEARCH" size="5" readonly><input class="search-button" id="SearchReset" onclick="SearchResetPressed();" value="RESET" size="4" readonly>
</label>
</fieldset>
<div class="search-result" id="SearchResultDiv" style="height: 152px; overflow: scroll;">
<table class="search-result">
<tr class="search-result" onclick="SearchResultClicked(0);"><td class="xpath" id="SearchResult1">XPath-1</td></tr>
<tr class="search-result" onclick="SearchResultClicked(1);"><td class="xpath" id="SearchResult2">XPath-2</td></tr>
<tr class="search-result" onclick="SearchResultClicked(2);"><td class="xpath" id="SearchResult3">XPath-3</td></tr>
<tr class="search-result" onclick="SearchResultClicked(3);"><td class="xpath" id="SearchResult4">XPath-4</td></tr>
<tr class="search-result" onclick="SearchResultClicked(4);"><td class="xpath" id="SearchResult5">XPath-5</td></tr>
<tr class="search-result" onclick="SearchResultClicked(5);"><td class="xpath" id="SearchResult6">XPath-6</td></tr>
<tr class="search-result" onclick="SearchResultClicked(6);"><td class="xpath" id="SearchResult7">XPath-7</td></tr>
<tr class="search-result" onclick="SearchResultClicked(7);"><td class="xpath" id="SearchResult8">XPath-8</td></tr>
<tr class="search-result" onclick="SearchResultClicked(8);"><td class="xpath" id="SearchResult9">XPath-9</td></tr>
<tr class="search-result" onclick="SearchResultClicked(9);"><td class="xpath" id="SearchResult10">XPath-10</td></tr>
<tr class="search-result" onclick="SearchResultClicked(10);"><td class="xpath" id="SearchResult11">XPath-11</td></tr>
<tr class="search-result" onclick="SearchResultClicked(11);"><td class="xpath" id="SearchResult12">XPath-12</td></tr>
<tr class="search-result" onclick="SearchResultClicked(12);"><td class="xpath" id="SearchResult13">XPath-13</td></tr>
<tr class="search-result" onclick="SearchResultClicked(13);"><td class="xpath" id="SearchResult14">XPath-14</td></tr>
<tr class="search-result" onclick="SearchResultClicked(14);"><td class="xpath" id="SearchResult15">XPath-15</td></tr>
<tr class="search-result" onclick="SearchResultClicked(15);"><td class="xpath" id="SearchResult16">XPath-16</td></tr>
<tr class="search-result" onclick="SearchResultClicked(16);"><td class="xpath" id="SearchResult17">XPath-17</td></tr>
<tr class="search-result" onclick="SearchResultClicked(17);"><td class="xpath" id="SearchResult18">XPath-18</td></tr>
<tr class="search-result" onclick="SearchResultClicked(18);"><td class="xpath" id="SearchResult19">XPath-19</td></tr>
<tr class="search-result" onclick="SearchResultClicked(19);"><td class="xpath" id="SearchResult20">XPath-20</td></tr>
<tr class="search-result" onclick="SearchResultClicked(20);"><td class="xpath" id="SearchResult21">XPath-21</td></tr>
<tr class="search-result" onclick="SearchResultClicked(21);"><td class="xpath" id="SearchResult22">XPath-22</td></tr>
<tr class="search-result" onclick="SearchResultClicked(22);"><td class="xpath" id="SearchResult23">XPath-23</td></tr>
<tr class="search-result" onclick="SearchResultClicked(23);"><td class="xpath" id="SearchResult24">XPath-24</td></tr>
<tr class="search-result" onclick="SearchResultClicked(24);"><td class="xpath" id="SearchResult25">XPath-25</td></tr>
<tr class="search-result" onclick="SearchResultClicked(25);"><td class="xpath" id="SearchResult26">XPath-26</td></tr>
<tr class="search-result" onclick="SearchResultClicked(26);"><td class="xpath" id="SearchResult27">XPath-27</td></tr>
<tr class="search-result" onclick="SearchResultClicked(27);"><td class="xpath" id="SearchResult28">XPath-28</td></tr>
<tr class="search-result" onclick="SearchResultClicked(28);"><td class="xpath" id="SearchResult29">XPath-29</td></tr>
<tr class="search-result" onclick="SearchResultClicked(29);"><td class="xpath" id="SearchResult30">XPath-30</td></tr>
<tr class="search-result" onclick="SearchResultClicked(30);"><td class="xpath" id="SearchResult31">XPath-31</td></tr>
<tr class="search-result" onclick="SearchResultClicked(31);"><td class="xpath" id="SearchResult32">XPath-32</td></tr>
<tr class="search-result" onclick="SearchResultClicked(32);"><td class="xpath" id="SearchResult33">XPath-33</td></tr>
<tr class="search-result" onclick="SearchResultClicked(33);"><td class="xpath" id="SearchResult34">XPath-34</td></tr>
<tr class="search-result" onclick="SearchResultClicked(34);"><td class="xpath" id="SearchResult35">XPath-35</td></tr>
<tr class="search-result" onclick="SearchResultClicked(35);"><td class="xpath" id="SearchResult36">XPath-36</td></tr>
<tr class="search-result" onclick="SearchResultClicked(36);"><td class="xpath" id="SearchResult37">XPath-37</td></tr>
<tr class="search-result" onclick="SearchResultClicked(37);"><td class="xpath" id="SearchResult38">XPath-38</td></tr>
<tr class="search-result" onclick="SearchResultClicked(38);"><td class="xpath" id="SearchResult39">XPath-39</td></tr>
<tr class="search-result" onclick="SearchResultClicked(39);"><td class="xpath" id="SearchResult40">XPath-40</td></tr>
<tr class="search-result" onclick="SearchResultClicked(40);"><td class="xpath" id="SearchResult41">XPath-41</td></tr>
<tr class="search-result" onclick="SearchResultClicked(41);"><td class="xpath" id="SearchResult42">XPath-42</td></tr>
<tr class="search-result" onclick="SearchResultClicked(42);"><td class="xpath" id="SearchResult43">XPath-43</td></tr>
<tr class="search-result" onclick="SearchResultClicked(43);"><td class="xpath" id="SearchResult44">XPath-44</td></tr>
<tr class="search-result" onclick="SearchResultClicked(44);"><td class="xpath" id="SearchResult45">XPath-45</td></tr>
<tr class="search-result" onclick="SearchResultClicked(45);"><td class="xpath" id="SearchResult46">XPath-46</td></tr>
<tr class="search-result" onclick="SearchResultClicked(46);"><td class="xpath" id="SearchResult47">XPath-47</td></tr>
<tr class="search-result" onclick="SearchResultClicked(47);"><td class="xpath" id="SearchResult48">XPath-48</td></tr>
<tr class="search-result" onclick="SearchResultClicked(48);"><td class="xpath" id="SearchResult49">XPath-49</td></tr>
<tr class="search-result" onclick="SearchResultClicked(49);"><td class="xpath" id="SearchResult50">XPath-50</td></tr>
<tr class="search-result" onclick="SearchResultClicked(50);"><td class="xpath" id="SearchResult51">XPath-51</td></tr>
<tr class="search-result" onclick="SearchResultClicked(51);"><td class="xpath" id="SearchResult52">XPath-52</td></tr>
<tr class="search-result" onclick="SearchResultClicked(52);"><td class="xpath" id="SearchResult53">XPath-53</td></tr>
<tr class="search-result" onclick="SearchResultClicked(53);"><td class="xpath" id="SearchResult54">XPath-54</td></tr>
<tr class="search-result" onclick="SearchResultClicked(54);"><td class="xpath" id="SearchResult55">XPath-55</td></tr>
<tr class="search-result" onclick="SearchResultClicked(55);"><td class="xpath" id="SearchResult56">XPath-56</td></tr>
<tr class="search-result" onclick="SearchResultClicked(56);"><td class="xpath" id="SearchResult57">XPath-57</td></tr>
<tr class="search-result" onclick="SearchResultClicked(57);"><td class="xpath" id="SearchResult58">XPath-58</td></tr>
<tr class="search-result" onclick="SearchResultClicked(58);"><td class="xpath" id="SearchResult59">XPath-59</td></tr>
<tr class="search-result" onclick="SearchResultClicked(59);"><td class="xpath" id="SearchResult60">XPath-60</td></tr>
<tr class="search-result" onclick="SearchResultClicked(60);"><td class="xpath" id="SearchResult61">XPath-61</td></tr>
<tr class="search-result" onclick="SearchResultClicked(61);"><td class="xpath" id="SearchResult62">XPath-62</td></tr>
<tr class="search-result" onclick="SearchResultClicked(62);"><td class="xpath" id="SearchResult63">XPath-63</td></tr>
<tr class="search-result" onclick="SearchResultClicked(63);"><td class="xpath" id="SearchResult64">XPath-64</td></tr>
<tr class="search-result" onclick="SearchResultClicked(64);"><td class="xpath" id="SearchResult65">XPath-65</td></tr>
<tr class="search-result" onclick="SearchResultClicked(65);"><td class="xpath" id="SearchResult66">XPath-66</td></tr>
<tr class="search-result" onclick="SearchResultClicked(66);"><td class="xpath" id="SearchResult67">XPath-67</td></tr>
<tr class="search-result" onclick="SearchResultClicked(67);"><td class="xpath" id="SearchResult68">XPath-68</td></tr>
<tr class="search-result" onclick="SearchResultClicked(68);"><td class="xpath" id="SearchResult69">XPath-69</td></tr>
<tr class="search-result" onclick="SearchResultClicked(69);"><td class="xpath" id="SearchResult70">XPath-70</td></tr>
<tr class="search-result" onclick="SearchResultClicked(70);"><td class="xpath" id="SearchResult71">XPath-71</td></tr>
<tr class="search-result" onclick="SearchResultClicked(71);"><td class="xpath" id="SearchResult72">XPath-72</td></tr>
<tr class="search-result" onclick="SearchResultClicked(72);"><td class="xpath" id="SearchResult73">XPath-73</td></tr>
<tr class="search-result" onclick="SearchResultClicked(73);"><td class="xpath" id="SearchResult74">XPath-74</td></tr>
<tr class="search-result" onclick="SearchResultClicked(74);"><td class="xpath" id="SearchResult75">XPath-75</td></tr>
<tr class="search-result" onclick="SearchResultClicked(75);"><td class="xpath" id="SearchResult76">XPath-76</td></tr>
<tr class="search-result" onclick="SearchResultClicked(76);"><td class="xpath" id="SearchResult77">XPath-77</td></tr>
<tr class="search-result" onclick="SearchResultClicked(77);"><td class="xpath" id="SearchResult78">XPath-78</td></tr>
<tr class="search-result" onclick="SearchResultClicked(78);"><td class="xpath" id="SearchResult79">XPath-79</td></tr>
<tr class="search-result" onclick="SearchResultClicked(79);"><td class="xpath" id="SearchResult80">XPath-80</td></tr>
<tr class="search-result" onclick="SearchResultClicked(80);"><td class="xpath" id="SearchResult81">XPath-81</td></tr>
<tr class="search-result" onclick="SearchResultClicked(81);"><td class="xpath" id="SearchResult82">XPath-82</td></tr>
<tr class="search-result" onclick="SearchResultClicked(82);"><td class="xpath" id="SearchResult83">XPath-83</td></tr>
<tr class="search-result" onclick="SearchResultClicked(83);"><td class="xpath" id="SearchResult84">XPath-84</td></tr>
<tr class="search-result" onclick="SearchResultClicked(84);"><td class="xpath" id="SearchResult85">XPath-85</td></tr>
<tr class="search-result" onclick="SearchResultClicked(85);"><td class="xpath" id="SearchResult86">XPath-86</td></tr>
<tr class="search-result" onclick="SearchResultClicked(86);"><td class="xpath" id="SearchResult87">XPath-87</td></tr>
<tr class="search-result" onclick="SearchResultClicked(87);"><td class="xpath" id="SearchResult88">XPath-88</td></tr>
<tr class="search-result" onclick="SearchResultClicked(88);"><td class="xpath" id="SearchResult89">XPath-89</td></tr>
<tr class="search-result" onclick="SearchResultClicked(89);"><td class="xpath" id="SearchResult90">XPath-90</td></tr>
<tr class="search-result" onclick="SearchResultClicked(90);"><td class="xpath" id="SearchResult91">XPath-91</td></tr>
<tr class="search-result" onclick="SearchResultClicked(91);"><td class="xpath" id="SearchResult92">XPath-92</td></tr>
<tr class="search-result" onclick="SearchResultClicked(92);"><td class="xpath" id="SearchResult93">XPath-93</td></tr>
<tr class="search-result" onclick="SearchResultClicked(93);"><td class="xpath" id="SearchResult94">XPath-94</td></tr>
<tr class="search-result" onclick="SearchResultClicked(94);"><td class="xpath" id="SearchResult95">XPath-95</td></tr>
<tr class="search-result" onclick="SearchResultClicked(95);"><td class="xpath" id="SearchResult96">XPath-96</td></tr>
<tr class="search-result" onclick="SearchResultClicked(96);"><td class="xpath" id="SearchResult97">XPath-97</td></tr>
<tr class="search-result" onclick="SearchResultClicked(97);"><td class="xpath" id="SearchResult98">XPath-98</td></tr>
<tr class="search-result" onclick="SearchResultClicked(98);"><td class="xpath" id="SearchResult99">XPath-99</td></tr>
<tr class="search-result" onclick="SearchResultClicked(99);"><td class="xpath" id="SearchResult100">XPath-100</td></tr>
<tr class="search-result"><td class="xpath" id="TooManyResults">Too many results found</td></tr>
</table>
</div>
<div id="canvas-container" style="height: 750px; overflow: scroll; display: none;">
<canvas id="tree" width="5000" height="5000" style="border:1px solid #000000; background-color: #EDEDED;">Your browser does not support canves :-(</canvas>
<!--div id="node-details" class="nodedetails">Line One is longer then the rest<br />Line Two is shorter<br />Line Three <br />Line Four is medium length</div-->
<div id="node-details" class="node-details">
<table class="node-details">
<tr><td class="nd-column">Name</td><td class="nd-name" id="nd-name">SampleNodeName</td></tr>
<tr><td class="nd-column">Attr</td><td class="nd-attr" id="nd-attr"><b>AttrOne:</b> TypeInfo<br/><b>AttributeTwo:</b> TypeInfo</td></tr>
<tr><td class="nd-column">Type</td><td class="nd-type" id="nd-type">Type Description</td></tr>
<tr><td class="nd-column">Pattern</td><td class="nd-pattern" id="nd-pattern">Pattern</td></tr>
<tr><td class="nd-column">Descr</td><td class="nd-anno" id="nd-anno">First line of annotation text<br/>second line of annotation text<br/>third line</td></tr>
<tr><td class="nd-column">Enum</td><td class="nd-enum" id="nd-enum">FIRST<br/>SECOND<br/>THIRD<br/>FOURTH</td></tr>
<tr><td class="nd-column">XPath</td><td class="nd-xpath" id="nd-xpath">/FundsXML4/Funds/Fund/FundDynamicData/TotalAssetValues/TotalAssetValue</td></tr>
</table>
</div>
</div>
<p id="trace" style="display: none; margin: 0px;"></p>
</body>
<script language="JavaScript">
var loadSchemaParagraph = document.getElementById('LoadSchemaParagraph');
var schemaOptions = document.getElementById('SchemaOptions');
var searchText = document.getElementById('SearchText');
var lastSearchText = '';
var searchResetButton = document.getElementById('SearchReset');
var openNewWindow = document.getElementById('OpenNewWindow');
var searchResultDiv = document.getElementById('SearchResultDiv');
var firstSearchResult = document.getElementById('SearchResult1');
var tooManyResults = document.getElementById('TooManyResults');
var statusText = document.getElementById('Status');
var canvasContainer = document.getElementById('canvas-container');
var tracePar = document.getElementById('trace');
var Nodes = new Array();
//Nodes.push({name: 'FundsXML4', left: 0, top: 0, right: 0, bottom: 0});
var ComplexTypes = new Array();
var SimpleTypes = new Array();
var SearchResults = new Array();
var rootNodeIndex = null;
var bResolveComplexTypes = false;
var NodeTypeComplex = 1;
var NodeTypeSimple = 2;
var NodeTypeSequence = 3;
var NodeTypeChoice = 4;
var NodeTypeString = 5;
var NodeTypeNumber = 6;
var NodeTypeInteger = 7;
var NodeTypeDate = 8;
var NodeTypeDateTime = 9;
var NodeTypeBoolean = 10;
var NodeTypeNames = ["", "Complex", "Simple", "Sequence", "Choice", "String", "Number", "Integer", "Date", "DateTime", "Boolean"];
var nMaxSearchResults = 100;
var bTooManySearchResults = false;
searchResetButton.style.display = "none";
if (window != window.top)
openNewWindow.style.display = "inline-block";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Schema functions
function IsRealNode(nodeType)
{
var result = true;
if (nodeType == NodeTypeChoice || nodeType == NodeTypeSequence)
result = false;
return result;
}
function GetFirstChildNode(parentNode, nodeName)
{
var result;
var childNodes = parentNode.childNodes;
var i = 0;
while (i < childNodes.length && !result)
if (childNodes[i].nodeName == nodeName)
result = childNodes[i];
else
i++;
return result;
}
function ShowChildNodes(parentNode)
{
var childNodes = parentNode.childNodes;
var txt = "ChildNodes: <br>";
for (i = 0; i < childNodes.length; i++)
txt += "Nodename: " + childNodes[i].nodeName + " (nodetype: " + childNodes[i].nodeType + ") <br>";
tracePar.innerHTML = txt;
}
/*
<xs:element name="FundsXML4">
<xs:annotation>
<xs:documentation>Root element of FundsXML V4</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="ControlData" type="ControlDataType">
<xs:annotation>
<xs:documentation>Meta data of xml document (like unique id, date, data supplier, language, ...)</xs:documentation>
</xs:annotation>
...
</xs:element>
<xs:complexType name="FundType">
<xs:sequence>
<xs:element name="Identifiers" type="IdentifiersType">
<xs:annotation>
<xs:documentation>Identifiers of fund</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Names" type="NamesType">
<xs:annotation>
<xs:documentation>Names of fund</xs:documentation>
</xs:annotation>
</xs:element>
<xs:complexType name="CountrySpecificDataATType">
<xs:complexContent>
<xs:extension base="xs:anyType"/>
</xs:complexContent>
</xs:complexType>
*/
function ParseComplexTypeNode(node, parentIndex)
{
//Nodes[parentIndex].type = NodeTypeComplex;
var childNodes = node.childNodes;
var nodeName;
var previousIndex = null;
var nodeIndex = null;
var i = null;
for (i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == 1) {
nodeName = childNodes[i].nodeName;
/*if (nodeName == "xs:annotation") {
// todo
}*/
if (nodeName == "xs:choice" || nodeName == "xs:sequence") {
previousIndex = nodeIndex;
nodeIndex = AddNode(childNodes[i], parentIndex, previousIndex);
if (parentIndex != null && previousIndex == null)
Nodes[parentIndex].firstChildIndex = nodeIndex;
if (previousIndex != null)
Nodes[previousIndex].nextIndex = nodeIndex;
}
if (nodeName == "xs:complexContent") {
var extensionNode = GetFirstChildNode(childNodes[i], "xs:extension");
if (extensionNode) {
Nodes[parentIndex].baseTypeName = extensionNode.getAttribute("base");
}
}
}
}
}
function ParseSequenceNode(node, parentIndex)
{
var childNodes = node.childNodes;
var previousIndex = null;
var nodeIndex = null;
var i = null;
for (i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == 1) {
previousIndex = nodeIndex;
nodeIndex = AddNode(childNodes[i], parentIndex, previousIndex);
if (parentIndex != null && previousIndex == null)
Nodes[parentIndex].firstChildIndex = nodeIndex;
if (previousIndex != null)
Nodes[previousIndex].nextIndex = nodeIndex;
}
}
}
function StrLen(text)
{
var result = 0;
var vt = typeof value;
if (vt == 'string')
result = Number(text.length);
return result;
}
function ToNumber(value, default_value)
{
var result;
var vt = typeof value;
if (vt == 'number' || vt == 'string')
result = Number(value);
else
result = default_value;
return result;
}
function ToNumberUnbounded(value, default_value)
{
var result;
if (value == 'unbounded')
result = -1;
else {
var vt = typeof value;
if (vt == 'number' || vt == 'string')
result = Number(value);
else
result = default_value;
}
return result;
}
/*
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="AssetMasterData"/>
<xs:simpleType name="ISOCurrencyCodeType">
<xs:annotation>
<xs:documentation xml:lang="en">Three-letter ISO-CurrencyCode (ISO 4217)</xs:documentation>
<xs:documentation xml:lang="de">Dreistelliger ISO-Waehrungscode (ISO 4217)</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="3"/>
<xs:minLength value="3"/>
<xs:pattern value="[A-Z]{3}"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="DataOperation" minOccurs="0">
<xs:annotation>
<xs:documentation>Initial, Amend, Delete</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="5"/>
<xs:maxLength value="7"/>
<xs:enumeration value="INITIAL"/>
<xs:enumeration value="AMEND"/>
<xs:enumeration value="DELETE"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="UnlistedType">
<xs:annotation>
<xs:documentation>Description of other document types</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="Text128Type">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
*/
function ParseSimpleTypeNode(node, destIndex)
{
var internalNodeName;
var restrictionNode = GetFirstChildNode(node, "xs:restriction");
internalNodeName = Nodes[destIndex].name;
if (internalNodeName == "AssetTypeType")
internalNodeName = "";
if (restrictionNode) {
Nodes[destIndex].baseTypeName = restrictionNode.getAttribute("base");
Nodes[destIndex].enumeration = new Array();
var childNodes = restrictionNode.childNodes;
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeType == 1) {
internalNodeName = childNodes[i].nodeName;
if (internalNodeName == "xs:minLength")
Nodes[destIndex].minLength = childNodes[i].getAttribute("value");
if (internalNodeName == "xs:maxLength")
Nodes[destIndex].maxLength = childNodes[i].getAttribute("value");
if (internalNodeName == "xs:pattern")
Nodes[destIndex].pattern = childNodes[i].getAttribute("value");
if (internalNodeName == "xs:enumeration")
Nodes[destIndex].enumeration.push(childNodes[i].getAttribute("value"));
}
}
}
/*
<xs:element name="Amount" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation xml:lang="en">Amounts in currency as defined in attribute</xs:documentation>
<xs:documentation xml:lang="de">Betrag in frei waehlbarer Waehrung</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="ccy" type="ISOCurrencyCodeType" use="required"/>
<xs:attribute name="isfundccy" type="xs:boolean"/>
<xs:attribute name="issubfundccy" type="xs:boolean"/>
<xs:attribute name="isshareclassccy" type="xs:boolean"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
*/
function ParseSimpleContentNode(node, destIndex)
{
var internalNodeName;
var extensionNode = GetFirstChildNode(node, "xs:extension");
if (extensionNode) {
Nodes[destIndex].baseTypeName = extensionNode.getAttribute("base");
Nodes[destIndex].attributes = new Array();
var childNodes = extensionNode.childNodes;
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeType == 1) {
internalNodeName = childNodes[i].nodeName;
if (internalNodeName == "xs:attribute") {
var attribute = new Object();
attribute.name = childNodes[i].getAttribute("name");
attribute.type = childNodes[i].getAttribute("type");
attribute.use = childNodes[i].getAttribute("use"); // mandatory attribute: use="required"
Nodes[destIndex].attributes.push(attribute);
}
}
}
}
function UpdateTypeDescription(nodeIndex)
{
var typeDescription;
if (Nodes[nodeIndex].typeName)
typeDescription = Nodes[nodeIndex].typeName;
if (Nodes[nodeIndex].baseTypeName) {
if (typeDescription)
typeDescription += ": " + Nodes[nodeIndex].baseTypeName;
else
typeDescription = Nodes[nodeIndex].baseTypeName;
var minLength = Nodes[nodeIndex].minLength;
var maxLength = Nodes[nodeIndex].maxLength;
if (minLength)
if (maxLength)
if (minLength == maxLength)
typeDescription += " (" + maxLength + " chars)";
else
typeDescription += " (" + minLength + "-" + maxLength + " chars)";
else
typeDescription += " (min " + minLength + " chars)";
else
if (maxLength)
typeDescription += " (max " + maxLength + " chars)";
/*
if (Nodes[nodeIndex].pattern)
typeDescription += " " + Nodes[nodeIndex].pattern;
*/
}
if (typeDescription) {
var minOccurs = Nodes[nodeIndex].minOccurs;
var maxOccurs = Nodes[nodeIndex].maxOccurs;
/*
if (maxOccurs == "1")
if (minOccurs == "0")
typeDescription += " [optional]";
else
typeDescription += " [mandatory]";
else
*/
if (maxOccurs != "1")
if (minOccurs == maxOccurs)
typeDescription += " [" + maxOccurs + "]";
else
if (maxOccurs > 0)
typeDescription += " [" + minOccurs + "..." + maxOccurs + "]";
else
typeDescription += " [" + minOccurs + "...unbound]"; // "...&#8734;]"; // "...&infin;]";
}
Nodes[nodeIndex].typeDescription = typeDescription;
}
function AddNode(node, parentIndex, previousIndex)
{
var mynode = new Object();
var complexTypeNode;
mynode.parentIndex = parentIndex;
mynode.previousIndex = previousIndex;
var internalNodeName = node.nodeName;
if (internalNodeName == "xs:choice") {
mynode.type = NodeTypeChoice;
}
if (internalNodeName == "xs:sequence") {
mynode.type = NodeTypeSequence;
}
if (internalNodeName == "xs:element") {
mynode.name = node.getAttribute("name");
mynode.typeName = node.getAttribute("type");
mynode.minOccurs = ToNumber(node.getAttribute("minOccurs"), 1);
mynode.maxOccurs = ToNumberUnbounded(node.getAttribute("maxOccurs"), 1); // 'unbounded'
if (mynode.typeName && mynode.typeName.length > 0 && mynode.typeName.substr(0, 3) != "xs:")
mynode.type = NodeTypeComplex;
}
//mynode.annotation = null;
mynode.firstChildIndex = null;
mynode.expanded = false;
mynode.showAttributes = true;
var annotationNode = GetFirstChildNode(node, "xs:annotation");
if (annotationNode) {
mynode.annotation = "Trace-1";
docNode = GetFirstChildNode(annotationNode, "xs:documentation");
if (docNode) {
mynode.annotation = "Trace-2";
mynode.annotation = docNode.textContent; //.nodeValue;
}
}
var nodeIndex = Nodes.length;
Nodes.push(mynode);
/*
if (mynode.name == "UnlistedType")
var i = 0;
*/
if (!mynode.typeName) {
var simpleTypeNode = GetFirstChildNode(node, "xs:simpleType");
if (simpleTypeNode)
ParseSimpleTypeNode(simpleTypeNode, nodeIndex);
}
if (!mynode.typeName) {
complexTypeNode = GetFirstChildNode(node, "xs:complexType");
if (complexTypeNode) {
var simpleContentNode = GetFirstChildNode(complexTypeNode, "xs:simpleContent");
if (simpleContentNode)
ParseSimpleContentNode(simpleContentNode, nodeIndex);
}
}
UpdateTypeDescription(nodeIndex);
if (Nodes.length < 100000) {
if (mynode.type == NodeTypeChoice || mynode.type == NodeTypeSequence)
ParseSequenceNode(node, nodeIndex);
else {
if (!mynode.typeName) {
complexTypeNode = GetFirstChildNode(node, "xs:complexType");
if (complexTypeNode) {
Nodes[nodeIndex].type = NodeTypeComplex;
ParseComplexTypeNode(complexTypeNode, nodeIndex);
}
}
}
if (bResolveComplexTypes && !Nodes[nodeIndex].firstChildIndex) {
if (mynode.type == NodeTypeComplex && mynode.typeName && mynode.typeName.length > 0)
ResolveComplexType(nodeIndex);
if (mynode.baseTypeName && mynode.baseTypeName.length > 0)
ResolveSimpleBaseType(nodeIndex);
}
}
return nodeIndex;
}
function XPath(nodeIndex)
{
var result = "";
var nodeType = Nodes[nodeIndex].type;
if (nodeType != NodeTypeChoice && nodeType != NodeTypeSequence)
result = "/" + Nodes[nodeIndex].name;
var parentIndex = Nodes[nodeIndex].parentIndex;
if (parentIndex)
result = XPath(parentIndex) + result;
return result;
}
function TypeNameUsedAbove(nodeIndex, typeName)
{
var result = false;
var parentIndex = Nodes[nodeIndex].parentIndex;
/*
if (parentIndex) {
if (Nodes[parentIndex].typeName == typeName)
result = true;
else
result = TypeNameUsedAbove(parentIndex, typeName);
}*/
while (parentIndex && !result) {
if (Nodes[parentIndex].typeName == typeName)
result = true;
else
parentIndex = Nodes[parentIndex].parentIndex;
}
return result;
}
function SetNodesExpanded(nNodeIndex, bExpanded, nLevels)
{
var firstChildIndex = Nodes[nNodeIndex].firstChildIndex;
if (firstChildIndex) {
Nodes[nNodeIndex].expanded = bExpanded;
if (nLevels > 1) {
var nextNodeIndex = firstChildIndex;
var nNextLevels = nLevels - 1;
while (nextNodeIndex) {
SetNodesExpanded(nextNodeIndex, bExpanded, nNextLevels);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
}
}
function CopyChildNodes(destNodeIndex, sourceNodeIndex)
{
var firstChildIndex = Nodes[sourceNodeIndex].firstChildIndex;
if (firstChildIndex) {
var sourceNode = Nodes[firstChildIndex];
var newNode = new Object();
newNode.parentIndex = destNodeIndex;
newNode.name = sourceNode.name;
newNode.type = sourceNode.type;
newNode.typeName = sourceNode.typeName;
newNode.baseTypeName = sourceNode.baseTypeName;
newNode.minOccurs = sourceNode.minOccurs;
newNode.maxOccurs = sourceNode.maxOccurs;
newNode.minLength = sourceNode.minLength;
newNode.maxLength = sourceNode.maxLength;
newNode.annotation = sourceNode.annotation;
newNode.enumeration = sourceNode.enumeration;
newNode.attributes = sourceNode.attributes;
newNode.typeDescription = sourceNode.typeDescription;
if (newNode.attributes)
newNode.showAttributes = true; // for testing only !!!
var newNodeIndex = Nodes.length;
Nodes.push(newNode);
Nodes[destNodeIndex].firstChildIndex = newNodeIndex;
CopyChildNodes(newNodeIndex, firstChildIndex);
var nextSourceIndex = sourceNode.nextIndex;
while (nextSourceIndex) {
var previousIndex = newNodeIndex;
var sourceNode = Nodes[nextSourceIndex];
var newNode = new Object();
newNode.parentIndex = destNodeIndex;
newNode.name = sourceNode.name;
newNode.type = sourceNode.type;
newNode.typeName = sourceNode.typeName;
newNode.baseTypeName = sourceNode.baseTypeName;
newNode.minOccurs = sourceNode.minOccurs;
newNode.maxOccurs = sourceNode.maxOccurs;
newNode.minLength = sourceNode.minLength;
newNode.maxLength = sourceNode.maxLength;
newNode.annotation = sourceNode.annotation;
newNode.enumeration = sourceNode.enumeration;
newNode.attributes = sourceNode.attributes;
newNode.typeDescription = sourceNode.typeDescription;
if (newNode.attributes)
newNode.showAttributes = true; // for testing only !!!
newNodeIndex = Nodes.length;
Nodes.push(newNode);
Nodes[previousIndex].nextIndex = newNodeIndex;
CopyChildNodes(newNodeIndex, nextSourceIndex);
nextSourceIndex = sourceNode.nextIndex;
}
}
else {
if (bResolveComplexTypes) {
if (Nodes[destNodeIndex].type == NodeTypeComplex)
ResolveComplexType(destNodeIndex);
var baseTypeName = Nodes[sourceNodeIndex].baseTypeName;
if (baseTypeName && baseTypeName.length > 0)
ResolveSimpleBaseType(destNodeIndex);
}
}
}
function ResolveComplexType(nodeIndex)
{
var typeName = Nodes[nodeIndex].typeName;
var complexTypeIndex = null;
var i = 1;
if (typeName) {
while (i < ComplexTypes.length && !complexTypeIndex) {
if (ComplexTypes[i].name == typeName)
complexTypeIndex = i;
else
i++;
}
}
if (complexTypeIndex != null)
if (TypeNameUsedAbove(nodeIndex, typeName))
Nodes[nodeIndex].recursiveType = true;
else {
var sourceNodeIndex = ComplexTypes[complexTypeIndex].nodeIndex;
Nodes[nodeIndex].baseTypeName = Nodes[sourceNodeIndex].baseTypeName;
if (Nodes[sourceNodeIndex].firstChildIndex)
CopyChildNodes(nodeIndex, ComplexTypes[complexTypeIndex].nodeIndex);
UpdateTypeDescription(nodeIndex);
}
if (complexTypeIndex == null && typeName) {
var simpleTypeIndex = null;
i = 1;
while (i < SimpleTypes.length && !simpleTypeIndex) {
if (SimpleTypes[i].name == typeName)
simpleTypeIndex = i;
else
i++;
}
if (simpleTypeIndex) {
var sourceNodeIndex = SimpleTypes[simpleTypeIndex].nodeIndex;
/*if (typeName == "Text128Type")
i = 0;*/
Nodes[nodeIndex].baseTypeName = Nodes[sourceNodeIndex].baseTypeName;
Nodes[nodeIndex].minLength = Nodes[sourceNodeIndex].minLength;
Nodes[nodeIndex].maxLength = Nodes[sourceNodeIndex].maxLength;
Nodes[nodeIndex].pattern = Nodes[sourceNodeIndex].pattern;
Nodes[nodeIndex].enumeration = Nodes[sourceNodeIndex].enumeration;
UpdateTypeDescription(nodeIndex);
}
}
}
function ResolveSimpleBaseType(nodeIndex)
{
var baseTypeName = Nodes[nodeIndex].baseTypeName;
var simpleTypeIndex = null;
var i = 1;
while (i < SimpleTypes.length && !simpleTypeIndex) {
if (SimpleTypes[i].name == baseTypeName)
simpleTypeIndex = i;
else
i++;
}
if (simpleTypeIndex) {
var sourceNodeIndex = SimpleTypes[simpleTypeIndex].nodeIndex;
if (baseTypeName == "AssetTypeType")
i = 0;
if (!Nodes[nodeIndex].minLength)
Nodes[nodeIndex].minLength = Nodes[sourceNodeIndex].minLength;
if (!Nodes[nodeIndex].maxLength)
Nodes[nodeIndex].maxLength = Nodes[sourceNodeIndex].maxLength;
if (!Nodes[nodeIndex].pattern)
Nodes[nodeIndex].pattern = Nodes[sourceNodeIndex].pattern;
if (!Nodes[nodeIndex].enumeration || Nodes[nodeIndex].enumeration.length == 0)
Nodes[nodeIndex].enumeration = Nodes[sourceNodeIndex].enumeration;
UpdateTypeDescription(nodeIndex);
}
}
function LoadComplexTypes(node)
{
//var mynode = {};
var nodeCount = null;
var childNodes = node.childNodes;
//var complexType = {};
var i = null;
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeType == 1 && childNodes[i].nodeName == "xs:complexType") {
var complexType = new Object();
complexType.name = childNodes[i].getAttribute("name");
var mynode = new Object();
mynode.name = complexType.name;
mynode.type = NodeTypeComplex;
nodeCount = Nodes.length;
Nodes.push(mynode);
complexType.nodeIndex = nodeCount;
ParseComplexTypeNode(childNodes[i], nodeCount);
ComplexTypes.push(complexType);
}
}
function LoadSimpleTypes(node)
{
var nodeCount = null;
var childNodes = node.childNodes;
var i = null;
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeType == 1 && childNodes[i].nodeName == "xs:simpleType") {
var simpleType = new Object();
simpleType.name = childNodes[i].getAttribute("name");
var mynode = new Object();
mynode.name = simpleType.name;
mynode.type = NodeTypeSimple;
nodeCount = Nodes.length;
Nodes.push(mynode);
simpleType.nodeIndex = nodeCount;
ParseSimpleTypeNode(childNodes[i], nodeCount);
SimpleTypes.push(simpleType);
}
}
//<xs:include schemaLocation="FundsXML4_Core.xsd"/>
function LoadIncludes(sourcePath, node)
{
var schemaLocation;
var schemaURL;
var childNodes = node.childNodes;
var xhttp;
var xmlDoc;
var schemaNode;
var nIncludes = 0;
var i = null;
for (i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeType == 1 && childNodes[i].nodeName == "xs:include") {
schemaLocation = childNodes[i].getAttribute("schemaLocation");
if (schemaLocation) {
statusText.innerHTML = "Loading include file '" + schemaLocation + "' ...";
schemaURL = sourcePath + schemaLocation;
xhttp = new XMLHttpRequest();
xhttp.overrideMimeType('text/xml');
xhttp.open("GET", schemaURL, false);
xhttp.send(null);
xmlDoc = xhttp.responseXML;
nIncludes++;
schemaNode = GetFirstChildNode(xmlDoc, "xs:schema");
LoadSimpleTypes(schemaNode);
LoadComplexTypes(schemaNode);
}
}
return nIncludes;
}
function ToString(txt)
{
var result = '';
if (txt !== undefined)
result = txt;
return result;
}
function LoadSchemaUI()
{
if (rootNodeIndex)
return;
statusText.innerHTML = "Loading schema file ...";
//statusText.offsetHeight;
statusText.style.display = 'block';
//statusText.offsetHeight;
/*
var offsetLeft = statusText.offsetLeft;
var offsetTop = statusText.offsetTop;
var clientWidth = statusText.clientWidth;
var clientHeight = statusText.clientHeight;
*/
//statusText.redraw(true) // force redraw
/*
var n = document.createTextNode(' ');
statusText.appendChild(n);
n.parentNode.removeChild(n);
*/
//var ctx = canvas.getContext("2d");
//DrawSizeRuler(ctx, 5, 5, 50);
//setTimeout(function () { nodeDetails.style.display = "block"; }, 50);
setTimeout(LoadSchema(), 500);
//statusText.innerHTML = "offsetLeft = " + offsetLeft;
}
function readFile() {
var file_to_read = document.getElementById('get_the_file').files[0];
var fileread = new FileReader();
fileread.onload = function (e) {
LoadSchema(e.target.result);
loadSchemaParagraph.style.display = 'none';
};
if (file_to_read) {
fileread.readAsText(file_to_read);
document.getElementById('get_the_file').value = null;
}
}
document.getElementById('get_the_file').addEventListener('change', readFile);
function LoadSchema(textarea)
{
if (rootNodeIndex)
return;
var complexType = new Object();
ComplexTypes = new Array();
ComplexTypes.push(complexType);
var mynode = new Object();
Nodes = new Array();
Nodes.push(mynode); // dummy node at the beginning --> first real item starts with index 1
statusText.innerHTML = "Loading schema ...";
var parser = new DOMParser();
try {
xmlDoc = parser.parseFromString(textarea, "text/xml");
} catch (e) {
// if text is not well-formed,
statusText.innerHTML = "Not a valid xml document";
alert("Not a valid xml document");
return false;
};
statusText.innerHTML = "Schema source successfully loaded ...";
//var schemaNode = xmlDoc.getElementsByTagName("xs:schema")[0];
//var rootNode = xmlDoc.getElementsByTagName("/xs:schema/xs:element")[0];
//var txt = "Root-Nodename: " + rootNode.nodeName + " (nodetype: " + rootNode.nodeType + ")";
//tracePar.innerHTML = "Schema-Rootnode-Name: " + schemaNode.nodeName;
//alert(txt);
// Node-Types:
// 1 ... Node
// 3 ... Text
// 8 ... Comment
var schemaNode = GetFirstChildNode(xmlDoc, "xs:schema");
//tracePar.innerHTML = "Schema-Rootnode-Name: " + schemaNode.nodeName;
//ShowChildNodes(schemaNode);
/*
var nIncludes = LoadIncludes(sourcePath, schemaNode);
statusText.innerHTML = "Processing main schema file '" + schemaURL + "' ...";
tracePar.innerHTML = "Include files loaded: " + nIncludes + " - loading simple types of main schema file ...";
*/
LoadSimpleTypes(schemaNode);
tracePar.innerHTML = "Simple types loaded: " + SimpleTypes.length + " - loading complex types of main schema file ...";
LoadComplexTypes(schemaNode);
tracePar.innerHTML = "Complex types loaded: " + ComplexTypes.length + " - processing main tree ...";
var rootNode = GetFirstChildNode(schemaNode, "xs:element");
//tracePar.innerHTML = "Rootnode-Name: " + rootNode.getAttribute("name") + " (nodetype: " + rootNode.nodeType + ")";
//tracePar.innerHTML += " - Rootnode-Type: " + rootNode.getAttribute("type");
bResolveComplexTypes = true;
rootNodeIndex = AddNode(rootNode);
//ShowChildNodes(rootNode);
statusText.innerHTML = ""; //"Ready";
/*
var txt = "Nodes:";
for (i = 0; i < Nodes.length; i++)
txt += "<br>Nodes[" + i + "]: parentIndex=" + Nodes[i].parentIndex + ", type='" + NodeTypeNames[Nodes[i].type] + "', name='" + ToString(Nodes[i].name) + "', typeName='" + ToString(Nodes[i].typeName) + "', baseTypeName='" + ToString(Nodes[i].baseTypeName) + "', minOccurs=" + ToString(Nodes[i].minOccurs) + ", maxOccurs=" + ToString(Nodes[i].maxOccurs) + ", firstChildIndex=" + ToString(Nodes[i].firstChildIndex) + ", annotation='" + ToString(Nodes[i].annotation) + "'";
txt += "<br><br>ComplexTypes:";
for (i = 0; i < ComplexTypes.length; i++)
txt += "<br>ComplexTypes[" + i + "]: name='" + ComplexTypes[i].name + "', nodeIndex=" + ComplexTypes[i].nodeIndex;
txt += "<br><br>SimpleTypes:";
for (i = 0; i < SimpleTypes.length; i++)
txt += "<br>SimpleTypes[" + i + "]: name='" + SimpleTypes[i].name + "', nodeIndex=" + SimpleTypes[i].nodeIndex;
*/
var txt = "ComplexTypes: " + ComplexTypes.length + ", SimpleTypes: " + SimpleTypes.length + ", Nodes: " + Nodes.length + ", rootNodeIndex: " + rootNodeIndex;
/*
txt += "<br>";
for (i = 0; i < Nodes.length; i++)
txt += "<br>Nodes[" + i + "]: parentIndex=" + Nodes[i].parentIndex + ", firstChildIndex=" + ToString(Nodes[i].firstChildIndex) + ", nextIndex=" + ToString(Nodes[i].nextIndex) + ", type='" + NodeTypeNames[Nodes[i].type] + "', name='" + ToString(Nodes[i].name) + "', typeName='" + ToString(Nodes[i].typeName) + "', baseTypeName='" + ToString(Nodes[i].baseTypeName) + "', minOccurs=" + ToString(Nodes[i].minOccurs) + ", maxOccurs=" + ToString(Nodes[i].maxOccurs) + ", annotation='" + ToString(Nodes[i].annotation) + "'";
txt += "<br>";
for (i = 0; i < ComplexTypes.length; i++)
txt += "<br>ComplexTypes[" + i + "]: name='" + ComplexTypes[i].name + "', nodeIndex=" + ComplexTypes[i].nodeIndex;
*/
tracePar.innerHTML = txt;
schemaOptions.style.display = 'block';
statusText.style.display = 'block';
canvasContainer.style.display = 'block';
SetNodeSizes();
SetNodesExpanded(rootNodeIndex, true, 2);
CalcNodePositions();
DrawTree();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Drawing functions
var PIXEL_RATIO = (function () {
var ctx = document.createElement("canvas").getContext("2d"),
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
})();
createHiDPICanvas = function (w, h, ratio) {
if (!ratio) { ratio = PIXEL_RATIO; }
var can = document.createElement("canvas");
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
return can;
}
function SetCanvasSize (w, h, ratio) {
if (!ratio) { ratio = PIXEL_RATIO; }
var can = document.getElementById("tree");
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
}
var canvas = document.getElementById("tree");
var nCanvasHeight = 5000;
var nCanvasWidth = 5000;
SetCanvasSize(nCanvasWidth, nCanvasHeight); //, 2); // 1.1041666
var nSchemaBorder = 10;
var nSchemaHeight = 0;
var nSchemaWidth = 0;
var canvasContainer = document.getElementById("canvas-container");
var canvasContainerWidth = canvasContainer.clientWidth;
var canvasContainerHeight = canvasContainer.clientHeight;
var canvasContainerScrollLeft = canvasContainer.scrollLeft; //.scrollLeftMax
var canvasContainerScrollTop = canvasContainer.scrollTop; //.scrollTopMax
// set height of canvas container to window height (= full screen)
//canvasContainer.style.height = window.innerHeight + "px"; //document.offsetHeight;
var canvasHeight = window.innerHeight - (schemaOptions.offsetTop + schemaOptions.offsetHeight + searchResultDiv.offsetHeight);
canvasContainer.style.height = canvasHeight + "px";
function MakeVisible(x, y)
{
if (x < canvasContainerScrollLeft)
canvasContainerScrollLeft = x - 10;
if (x > canvasContainerScrollLeft + canvasContainerWidth)
canvasContainerScrollLeft = x + 10 - canvasContainerWidth;
if (y < canvasContainerScrollTop)
canvasContainerScrollTop = y - 10;
if (y > canvasContainerScrollTop + canvasContainerHeight)
canvasContainerScrollTop = y + 10 - canvasContainerHeight;
}
//var div = document.getElementById("canvas-container");
//div.height = 700;
//Create canvas with the device resolution.
//var myCanvas = createHiDPICanvas(500, 250);
//Create canvas with a custom resolution.
//var myCustomCanvas = createHiDPICanvas(500, 200, 4);
var sLineColor = "#000000"; //"#303030";
var nLineWidth = 0.75;
var nMultipleNodeOffset = 4;
var nShadowOffset = 4;
var sShadowColor = "#B0B0B0"; //"#C0C0C0"; "#C8C8C8";
//var sSelectedShadowColor = "#3030C0"; //"#FFFFB0";
var sNodeNameFont = "bold 10pt Arial"; //"bold 10pt Helvetica";"10pt Arial"
var sNodeNameColor = "#000090"; //"#303030";
var sNodeBackgroundColor = "#FFFFFF";
var sSelectedNodeBackgroundColor = "#FFFFA0"; //"#E0E0FF"; //"#FFFFB0";
var sMandatoryAttributeNameFont = "bold 11px Arial";
var sOptionalAttributeNameFont = "11px Arial";
var sAttributeNameColor = "#000080";
var nAttributeVerPadding = 3;
var nAttributeLineHeight = 13;
var sTypeDescriptionFont = "bold 11px Arial";
var sAnnotationFont = "11px Arial";
var sAnnotationColor = "#000000"; //"black"
var nAnnotationTextHeight = 10;
var nAnnotationLineDistance = 3;
var nMaxAnnotationWidth = 250;
var nAnnotationDistance = 6; // vertical distance to border of node
var nNodeTextHeight = 10;
var nNodeTextPadding = 7;
var nNodeHeight = nNodeTextHeight + nNodeTextPadding * 2;
var nHalfNodeHeight = nNodeHeight / 2;
var nSequenceWidth = nNodeHeight * 1.5;
var nSequenceHeight = Math.round(nNodeHeight * 0.833); // 0.75
var nSequenceCornerSize = Math.round(nSequenceHeight * 0.26); // 0.28
var sPointsColor = "#606060"; //"#303030";
var nPointsDistance = 6;
var nPointsSize = 4;
var nPointsHalfSize = 2;
var sSequenceBoxColor = "#606060";
var nExpanderHalfSize = nSequenceCornerSize;
var nExpanderSize = nExpanderHalfSize * 2;
var nExpanderDistance = nExpanderHalfSize * 0.28; //0.333;
//var sPlusMinusColor = "#B000A0"; //"#e00000";
//var nPlusMinusLineWidth = 0.85;
var sArrowBackgroundColor = "#787878"; //"#808080"; //"#6060B0";
var sArrowBorderColor = "#404040";
var sArrowColor = "#B000A0";
var nArrowLineWidth = 2.0;
var nMinHorLineLength = 20;
var nVerNodeDistance = 12;
var sTextDelimeters = " .,;:-+*/=<>()&%$§\"!#'[]{}´`~^°";
var nLastClickedNodeIndex;
var nLastExpandedNodeIndex;
var nLastCollapsedNodeIndex;
var bShowAnnotations = true;
var bShowTypeInfo = true;
var cbAnnotations = document.getElementById("cbAnnotations");
var cbTypeInfo = document.getElementById("cbTypeInfo");
function AnnotationChanged()
{
bShowAnnotations = cbAnnotations.checked;
SetVerNodePositions();
DrawTree();
}
function TypeInfoChanged()
{
bShowTypeInfo = cbTypeInfo.checked;
SetVerNodePositions();
DrawTree();
}
function DrawExpander(ctx, px, py, bExpanded)
{
var left = px - nExpanderHalfSize;
var right = px + nExpanderHalfSize;
var top = py - nExpanderHalfSize;
var bottom = py + nExpanderHalfSize;
// clear background
//ctx.clearRect(left, top, nExpanderSize, nExpanderSize);
ctx.beginPath();
ctx.fillStyle = sArrowBackgroundColor; //sNodeBackgroundColor; //"#FFFFFF";
ctx.fillRect(left, top, nExpanderSize, nExpanderSize);
ctx.stroke();
// draw border square
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sArrowBorderColor; //"#404040"; //sLineColor; //"black";
ctx.rect(left - 0.5, top - 0.5, nExpanderSize + 1, nExpanderSize + 1);
ctx.stroke();
if (bExpanded) {
// draw left arrow
ctx.beginPath();
ctx.fillStyle = sNodeBackgroundColor;
//ctx.lineWidth = nArrowLineWidth;
//ctx.strokeStyle = sArrowColor;
ctx.moveTo(px + 2, top + 1.5);
ctx.lineTo(px - 3, py);
ctx.lineTo(px + 2, bottom - 1.5);
//ctx.stroke();
ctx.fill();
}
else {
// draw right arrow
ctx.beginPath();
ctx.fillStyle = sNodeBackgroundColor;
//ctx.lineWidth = nArrowLineWidth;
//ctx.strokeStyle = sArrowColor;
ctx.moveTo(px - 2, top + 1.5);
ctx.lineTo(px + 3, py);
ctx.lineTo(px - 2, bottom - 1.5);
//ctx.stroke();
ctx.fill();
}
/*
// draw minus sign (horizontal line)
ctx.beginPath();
ctx.lineWidth = nPlusMinusLineWidth;
ctx.strokeStyle = sPlusMinusColor; //"#e00000"; //"red"; "blue";
ctx.moveTo(left + nExpanderDistance, py);
ctx.lineTo(right + 0.2 - nExpanderDistance, py);
ctx.stroke();
if (!bExpanded) {
// draw vertical line for plus sign
ctx.beginPath();
ctx.moveTo(px, top + nExpanderDistance);
ctx.lineTo(px, bottom + 0.2 - nExpanderDistance);
ctx.stroke();
}
*/
}
function DrawAttrExpander(ctx, px, py, bExpanded)
{
var left = px - nExpanderHalfSize;
var right = px + nExpanderHalfSize;
var top = py - nExpanderHalfSize;
var bottom = py + nExpanderHalfSize;
// clear background
//ctx.clearRect(left, top, nExpanderSize, nExpanderSize);
ctx.beginPath();
ctx.fillStyle = sArrowBackgroundColor;
ctx.fillRect(left, top, nExpanderSize, nExpanderSize);
ctx.stroke();
// draw border square
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sArrowBorderColor;
ctx.rect(left - 0.5, top - 0.5, nExpanderSize + 1, nExpanderSize + 1);
ctx.stroke();
if (bExpanded) {
// draw up arrow
ctx.beginPath();
ctx.fillStyle = sNodeBackgroundColor;
//ctx.lineWidth = nArrowLineWidth;
//ctx.strokeStyle = sArrowColor;
ctx.moveTo(left + 1.5, py + 2);
ctx.lineTo(px, py - 3);
ctx.lineTo(right - 1.5, py + 2);
//ctx.stroke();
ctx.fill();
}
else {
// draw down arrow
ctx.beginPath();
ctx.fillStyle = sNodeBackgroundColor;
//ctx.lineWidth = nArrowLineWidth;
//ctx.strokeStyle = sArrowColor;
ctx.moveTo(left + 1.5, py - 2);
ctx.lineTo(px, py + 3);
ctx.lineTo(right - 1.5, py - 2);
//ctx.stroke();
ctx.fill();
}
}
function DrawSizeRuler(ctx, x, y, n)
{
var len;
var xx = x;
ctx.lineWidth = 0.25;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + n * 2, y);
ctx.stroke();
for (i = 0; i < n; i++) {
ctx.beginPath();
ctx.moveTo(xx, y);
len = 3;
if (i % 5 == 0) len = 5;
if (i % 10 == 0) len = 8;
ctx.lineTo(xx, y + len);
ctx.stroke();
xx += 2;
}
}
function DrawAnnotation(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
var y = node.bottom + nAnnotationDistance;
if (node.maxOccurs > 1 || node.maxOccurs < 0)
y += nMultipleNodeOffset;
/*
var annotation = nodeIndex;
if (node.annotation)
annotation += ' ' + node.annotation;
*/
var annotation = node.annotation;
if (node.typeDescription && bShowTypeInfo) {
//ctx.clearRect(node.left - 10, y - 1, node.totalWidth + 10, nAnnotationTextHeight + 5);
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.font = sTypeDescriptionFont;
ctx.fillStyle = sAnnotationColor;
ctx.fillText(node.typeDescription, node.left, y + nAnnotationTextHeight);
ctx.stroke();
y += nAnnotationTextHeight + nAnnotationLineDistance;
}
if (annotation && bShowAnnotations) {
/*
ctx.clearRect(node.left - 10, y - 1, 500 / *node.totalWidth* /, nAnnotationTextHeight + 5);
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.font = sAnnotationFont;
ctx.fillStyle = sAnnotationColor;
ctx.fillText(annotation, node.left, y + nAnnotationTextHeight);
ctx.stroke();
*/
for (i = 0; i < Nodes[nodeIndex].annotationLines.length; i++) {
ctx.beginPath();
//ctx.strokeStyle = "black";
ctx.font = sAnnotationFont;
ctx.fillStyle = sAnnotationColor;
ctx.fillText(Nodes[nodeIndex].annotationLines[i], node.left, y + nAnnotationTextHeight);
ctx.stroke();
y += nAnnotationTextHeight + nAnnotationLineDistance;
}
}
}
function DrawOctagonShape(ctx, left, top, width, height, corner)
{
var right = left + width;
var bottom = top + height;
ctx.moveTo(left + corner, top);
ctx.lineTo(right - corner, top);
ctx.lineTo(right, top + corner);
ctx.lineTo(right, bottom - corner);
ctx.lineTo(right - corner, bottom);
ctx.lineTo(left + corner, bottom);
ctx.lineTo(left, bottom - corner);
ctx.lineTo(left, top + corner);
ctx.lineTo(left + corner, top);
}
function DrawOctagonWithShadow(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
ctx.beginPath();
ctx.fillStyle = sShadowColor;
DrawOctagonShape(ctx, node.left + nShadowOffset, node.top + nShadowOffset, nSequenceWidth, nSequenceHeight, nSequenceCornerSize);
ctx.fill();
ctx.beginPath();
if (nodeIndex == nLastClickedNodeIndex)
ctx.fillStyle = sSelectedNodeBackgroundColor;
else
ctx.fillStyle = sNodeBackgroundColor;
DrawOctagonShape(ctx, node.left, node.top, nSequenceWidth, nSequenceHeight, nSequenceCornerSize);
ctx.fill();
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sLineColor; //"black";
DrawOctagonShape(ctx, node.left, node.top, nSequenceWidth, nSequenceHeight, nSequenceCornerSize);
ctx.stroke();
}
function DrawPoints(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
var xx = node.right + nPointsDistance * 2; // + nMinHorLineLength;
var yy = node.verCenter - nPointsHalfSize;
ctx.fillStyle = sPointsColor;
for (i = 4; i > 0; i--) {
ctx.beginPath();
ctx.fillRect(xx, yy, nPointsSize, nPointsSize);
ctx.stroke();
xx += nPointsSize + nPointsDistance;
}
}
function DrawSequenceNode(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
var right = node.right;
DrawOctagonWithShadow(ctx, nodeIndex);
var dx = nSequenceWidth / 7;
var yy = node.verCenter;
var d = dx * 0.40;
var dd = d * 2;
var xx = node.left + dx * 2;
ctx.fillStyle = sLineColor; //"black";
ctx.beginPath();
ctx.arc(xx, yy, d, 0, 2*Math.PI);
ctx.stroke();
xx += dx * 1.5;
ctx.beginPath();
ctx.arc(xx, yy, d, 0, 2*Math.PI);
ctx.stroke();
xx += dx * 1.5;
ctx.beginPath();
ctx.arc(xx, yy, d, 0, 2*Math.PI);
ctx.stroke();
DrawAnnotation(ctx, nodeIndex);
if (node.firstChildIndex) {
DrawExpander(ctx, node.expHorCenter, node.verCenter, node.expanded);
right += nExpanderSize;
}
return right;
}
function DrawChoiceNode(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
var right = node.right;
DrawOctagonWithShadow(ctx, nodeIndex);
var dx = nSequenceWidth / 6;
var dx2 = dx * 0.66;
var xx = node.left + dx;
var dy = Math.round(nSequenceHeight / 5) + 0.5;
var yy = node.verCenter;
var top2 = yy - dy;
var bottom2 = yy + dy;
ctx.beginPath();
ctx.moveTo(xx, yy);
xx += dx;
ctx.lineTo(xx, yy);
xx += dx;
ctx.lineTo(xx, top2 + 0.5);
ctx.stroke();
var d = dx * 0.33;
var dd = d * 2;
xx += dx - 1;
ctx.fillStyle = sLineColor;
ctx.beginPath();
ctx.arc(xx, top2 - 1, d, 0, 2*Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(xx + dx2 - 0.5, yy, d, 0, 2*Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(xx, bottom2 + 1, d, 0, 2*Math.PI);
ctx.stroke();
DrawAnnotation(ctx, nodeIndex);
if (node.firstChildIndex) {
DrawExpander(ctx, node.expHorCenter, node.verCenter, node.expanded);
right += nExpanderSize;
}
return right;
}
/*
Nodes[0].left = x;
Nodes[0].top = y;
Nodes[0].right = x + nNodeWidth;
Nodes[0].bottom = y + nNodeHeight;
Nodes[0].width = nNodeWidth;
Nodes[0].verCenter = y + nHalfNodeHeight;
Nodes[0].name = "FundsXML4";
Nodes[0].annotation = "Root element of FundsXML 4.0 schema";
Nodes[0].expanded = true;
*/
function DrawElementNode(ctx, nodeIndex)
{
var node = Nodes[nodeIndex];
//var nNodeWidth = node.right - node.left;
//var nNodeHeight = node.bottom - node.top;
var right = node.right;
var rectLeft = node.left + 0.5;
var rectTop = node.top + 0.5;
var rectHeight = node.height - 0.5; //nNodeHeight
var rectWidth = node.width - 0.5;
if (node.maxOccurs > 1 || node.maxOccurs < 0) {
// draw shadow
ctx.beginPath();
ctx.fillStyle = sShadowColor;
ctx.fillRect(node.left + nMultipleNodeOffset + nShadowOffset, node.top + nMultipleNodeOffset + nShadowOffset, node.width + 0.5, node.height);
ctx.stroke();
// draw background for main node rectangle
ctx.beginPath();
ctx.fillStyle = sNodeBackgroundColor; //"#FFFFFF";
ctx.fillRect(rectLeft + nMultipleNodeOffset, rectTop + nMultipleNodeOffset, node.width, node.height);
ctx.stroke();
// draw main node rectangle
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sLineColor; //"black";
if (node.minOccurs == 0)
ctx.setLineDash([4, 4]); // [5,3] ... dashes are 5px and spaces are 3px
ctx.rect(rectLeft + nMultipleNodeOffset, rectTop + nMultipleNodeOffset, rectWidth, rectHeight);
ctx.stroke();
}
else {
// draw shadow
ctx.beginPath();
/*if (nodeIndex == nLastClickedNodeIndex)
ctx.fillStyle = sSelectedShadowColor;
else*/
ctx.fillStyle = sShadowColor;
ctx.fillRect(node.left + nShadowOffset, node.top + nShadowOffset, node.width + 0.5, node.height);
ctx.stroke();
}
// draw background for main node rectangle
ctx.beginPath();
if (nodeIndex == nLastClickedNodeIndex)
ctx.fillStyle = sSelectedNodeBackgroundColor;
else
ctx.fillStyle = sNodeBackgroundColor; //"#FFFFFF";
ctx.fillRect(rectLeft, rectTop, node.width, node.height);
ctx.stroke();
// draw main node rectangle
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sLineColor; //"black";
if (node.minOccurs == 0)
ctx.setLineDash([4,4]); // [5,3] ... dashes are 5px and spaces are 3px
ctx.rect(rectLeft, rectTop, rectWidth, rectHeight);
ctx.stroke();
ctx.setLineDash([]);
//ctx.shadowBlur = 0;
ctx.beginPath();
ctx.font = sNodeNameFont; //"10pt Arial";
ctx.fillStyle = sNodeNameColor; //"black";
ctx.fillText(node.name, node.left + nNodeTextPadding, node.top + nNodeTextHeight + nNodeTextPadding);
ctx.stroke();
if (Nodes[nodeIndex].attributes) {
var i, yy = node.top + nNodeTextHeight + nNodeTextPadding * 2;
if (node.showAttributes) {
DrawLine(ctx, rectLeft, yy, node.right, yy);
//DrawAttrExpander(ctx, node.right - nExpanderSize, yy, node.showAttributes);
yy += nAttributeVerPadding;
for (i = 0; i < Nodes[nodeIndex].attributes.length; i++) {
ctx.beginPath();
if (node.attributes[i].use == "required")
ctx.font = sMandatoryAttributeNameFont;
else
ctx.font = sOptionalAttributeNameFont;
ctx.fillStyle = sAttributeNameColor;
ctx.fillText(node.attributes[i].name, node.left + nNodeTextPadding, yy + nNodeTextHeight);
ctx.stroke();
yy += nAttributeLineHeight;
}
}
else
DrawAttrExpander(ctx, node.right - nExpanderSize, yy, node.showAttributes);
}
// typeDescription
DrawAnnotation(ctx, nodeIndex);
if (node.firstChildIndex) {
DrawExpander(ctx, node.right, node.verCenter, node.expanded);
right += nExpanderHalfSize;
}
else {
if (node.recursiveType || node.typeName == "xs:anyType" || node.baseTypeName == "xs:anyType")
DrawPoints(ctx, nodeIndex);
}
return right;
}
function DrawLine(ctx, x1, y1, x2, y2)
{
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = sLineColor; //"black";
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function IsMultiple(maxOccurs)
{
return (maxOccurs > 1 || maxOccurs < 0);
}
function SetNodeSize(ctx, nodeIndex, recursive)
{
var typeWidth = 0;
var annotationWidth = 0;
//if (Nodes[nodeIndex].type == NodeTypeChoice || Nodes[nodeIndex].type == NodeTypeSequence) {
if (!IsRealNode(Nodes[nodeIndex].type)) {
Nodes[nodeIndex].height = nSequenceHeight;
Nodes[nodeIndex].width = nSequenceWidth;
}
else {
var height = nNodeHeight;
ctx.font = sNodeNameFont;
var width = ctx.measureText(Nodes[nodeIndex].name).width + nNodeTextPadding * 2;
if (Nodes[nodeIndex].firstChildIndex)
width += nExpanderHalfSize;
if (Nodes[nodeIndex].attributes) {
width += nExpanderSize;
if (Nodes[nodeIndex].showAttributes) {
var i, width2 = 0;
for (i = 0; i < Nodes[nodeIndex].attributes.length; i++) {
if (Nodes[nodeIndex].attributes[i].use == "required")
ctx.font = sMandatoryAttributeNameFont;
else
ctx.font = sOptionalAttributeNameFont;
width2 = Math.max(width2, ctx.measureText(Nodes[nodeIndex].attributes[i].name).width);
}
height += Nodes[nodeIndex].attributes.length * nAttributeLineHeight + nAttributeVerPadding * 2;
width = Math.max(width, width2 + nNodeTextPadding * 2);
}
}
Nodes[nodeIndex].height = Math.round(height);
Nodes[nodeIndex].width = Math.round(width);
}
var sText = Nodes[nodeIndex].typeDescription;
if (sText && sText.length > 0) {
ctx.font = sTypeDescriptionFont;
typeWidth = ctx.measureText(sText).width;
}
sText = Nodes[nodeIndex].annotation;
if (sText && sText.length > 0) {
ctx.font = sAnnotationFont;
var totalTextWidth = ctx.measureText(sText).width;
var annotationLines = new Array();
var nChars = 0, nPartWidth = 0, nChars2 = 0, nPartWidth2 = 0;
var sPart = "", sPart2 = "", chr = " ";
while (totalTextWidth > nMaxAnnotationWidth) {
nChars = Math.round((sText.length * nMaxAnnotationWidth) / totalTextWidth);
sPart = sText.substr(0, nChars);
nPartWidth = ctx.measureText(sPart).width;
// find longest part of text fitting into maximum width
if (nPartWidth < nMaxAnnotationWidth) {
nChars2 = nChars + 1;
sPart2 = sText.substr(0, nChars2);
nPartWidth2 = ctx.measureText(sPart2).width;
while (nPartWidth2 <= nMaxAnnotationWidth) {
nChars = nChars2;
sPart = sPart2;
nPartWidth = nPartWidth2;
nChars2 = nChars + 1;
sPart2 = sText.substr(0, nChars2);
nPartWidth2 = ctx.measureText(sPart2).width;
}
}
if (nPartWidth > nMaxAnnotationWidth) {
nChars2 = nChars - 1;
sPart2 = sText.substr(0, nChars2);
nPartWidth2 = ctx.measureText(sPart2).width;
while (nPartWidth2 > nMaxAnnotationWidth) {
nChars = nChars2;
sPart = sPart2;
nPartWidth = nPartWidth2;
nChars2 = nChars - 1;
sPart2 = sText.substr(0, nChars2);
nPartWidth2 = ctx.measureText(sPart2).width;
}
}
// search for delimiter
nChars2 = nChars;
chr = sText.substr(nChars, 1);
while (nChars2 > 10 && sTextDelimeters.indexOf(chr) < 0) {
nChars2--;
chr = sText.substr(nChars2, 1);
}
if (sTextDelimeters.indexOf(chr) >= 0) {
// cut at delimiter
sPart = sText.substr(0, nChars2);
annotationLines.push(sPart);
sText = sText.substr(nChars2 + 1, 999);
}
else {
// cut at maximum and insert minus sign
nChars2 = nChars - 1;
sPart = sText.substr(0, nChars2) + "-";
annotationLines.push(sPart);
sText = sText.substr(nChars2, 999);
}
totalTextWidth = ctx.measureText(sText).width;
}
annotationLines.push(sText);
for (i = 0; i < annotationLines.length; i++)
annotationWidth = Math.max(annotationWidth, ctx.measureText(annotationLines[i]).width);
Nodes[nodeIndex].annotationLines = annotationLines;
Nodes[nodeIndex].footerHeight = Math.round((nAnnotationTextHeight + nAnnotationLineDistance) * annotationLines.length);
}
else {
Nodes[nodeIndex].footerHeight = 0;
Nodes[nodeIndex].footerWidth = 0;
}
Nodes[nodeIndex].footerWidth = Math.round(Math.max(typeWidth, annotationWidth));
var totalHeight = Nodes[nodeIndex].height + Nodes[nodeIndex].footerHeight;
if (IsMultiple(Nodes[nodeIndex].maxOccurs))
totalHeight += nMultipleNodeOffset;
if (Nodes[nodeIndex].typeDescription)
totalHeight += nAnnotationTextHeight + nAnnotationLineDistance;
if (totalHeight > 0)
totalHeight += nAnnotationDistance - nAnnotationLineDistance;
Nodes[nodeIndex].totalHeight = totalHeight;
if (recursive) {
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
SetNodeSize(ctx, nextNodeIndex, recursive);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
}
function CurrentTotalHeight(nodeIndex)
{
var bAddBaseDistance = false;
var totalHeight = Nodes[nodeIndex].height;
if (IsMultiple(Nodes[nodeIndex].maxOccurs))
totalHeight += nMultipleNodeOffset;
if (Nodes[nodeIndex].typeDescription && bShowTypeInfo) {
totalHeight += nAnnotationTextHeight + nAnnotationLineDistance;
bAddBaseDistance = true;
}
if (Nodes[nodeIndex].annotation && bShowAnnotations) {
totalHeight += Nodes[nodeIndex].footerHeight;
bAddBaseDistance = true;
}
if (bAddBaseDistance)
totalHeight += nAnnotationDistance - nAnnotationLineDistance;
return totalHeight;
}
function SetNodeSizes()
{
var canvas = document.getElementById("tree");
var ctx = canvas.getContext("2d");
ctx.font = sNodeNameFont;
SetNodeSize(ctx, rootNodeIndex, true);
}
function GetTreeHeight(nodeIndex)
{
var nodeHeight = CurrentTotalHeight(nodeIndex); //Nodes[nodeIndex].totalHeight;
var childrenHeight = 0 - nVerNodeDistance;
var result = nodeHeight;
if (Nodes[nodeIndex].expanded) {
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
childrenHeight += GetTreeHeight(nextNodeIndex) + nVerNodeDistance;
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
if (childrenHeight > 0) {
Nodes[nodeIndex].childrenHeight = childrenHeight;
result = childrenHeight;
}
return result;
}
function SetVerNodePosition(nodeIndex, y)
{
var verPosition = y;
var nHalfHeight = Nodes[nodeIndex].height / 2;
var firstChildIndex = Nodes[nodeIndex].firstChildIndex;
if (firstChildIndex && Nodes[nodeIndex].expanded) {
var nextNodeIndex = firstChildIndex;
var previousNodeIndex;
var childNodes = 0;
while (nextNodeIndex) {
childNodes++;
verPosition = SetVerNodePosition(nextNodeIndex, verPosition);
previousNodeIndex = nextNodeIndex;
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
Nodes[nodeIndex].verCenter = Math.round((Nodes[firstChildIndex].verCenter + Nodes[previousNodeIndex].verCenter) / 2);
Nodes[nodeIndex].top = Nodes[nodeIndex].verCenter - nHalfHeight;
Nodes[nodeIndex].bottom = Nodes[nodeIndex].top + Nodes[nodeIndex].height;
verPosition = Math.max(verPosition, Nodes[nodeIndex].top + CurrentTotalHeight(nodeIndex)/*Nodes[nodeIndex].totalHeight*/ + nVerNodeDistance);
}
else {
Nodes[nodeIndex].top = y;
Nodes[nodeIndex].verCenter = y + nHalfHeight;
Nodes[nodeIndex].bottom = y + Nodes[nodeIndex].height;
verPosition += CurrentTotalHeight(nodeIndex)/*Nodes[nodeIndex].totalHeight*/ + nVerNodeDistance;
nSchemaWidth = Math.max(nSchemaWidth, Nodes[nodeIndex].left + Nodes[nodeIndex].totalWidth);
}
return verPosition;
}
function SetVerNodePositions()
{
nSchemaHeight = 0;
nSchemaWidth = 0;
nSchemaHeight = SetVerNodePosition(rootNodeIndex, nSchemaBorder);
}
function ChildNodeCount(nodeIndex)
{
var result = 0;
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
result++;
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
return result;
}
function SetHorNodePosition(nodeIndex, x, recursive, visible)
{
var nodeType = Nodes[nodeIndex].type;
var firstChildIndex = Nodes[nodeIndex].firstChildIndex;
Nodes[nodeIndex].left = x;
var width = Nodes[nodeIndex].width;
var right = x + width;
Nodes[nodeIndex].right = right;
Nodes[nodeIndex].expHorCenter = -999;
Nodes[nodeIndex].visible = visible;
if (firstChildIndex)
if (nodeType == NodeTypeChoice || nodeType == NodeTypeSequence) {
Nodes[nodeIndex].expHorCenter = right + nExpanderHalfSize;
width += nExpanderSize;
}
else {
Nodes[nodeIndex].expHorCenter = right;
width += nExpanderHalfSize;
}
Nodes[nodeIndex].totalWidth = Math.max(width + nMinHorLineLength, Nodes[nodeIndex].footerWidth - nSequenceWidth);
if ((nodeType == NodeTypeChoice || nodeType == NodeTypeSequence) && ChildNodeCount(nodeIndex) > 1)
Nodes[nodeIndex].totalWidth += nMinHorLineLength;
var nextHorPos = x + Nodes[nodeIndex].totalWidth;
//if (Nodes[nodeIndex].expanded) {
var nextNodeIndex = firstChildIndex;
var childrenVisible = visible && Nodes[nodeIndex].expanded;
while (nextNodeIndex) {
SetHorNodePosition(nextNodeIndex, nextHorPos, recursive, childrenVisible);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
//}
}
function CalcNodePositions()
{
nSchemaHeight = 0;
nSchemaWidth = 0;
// Calculate height of all visible nodes including their visible child nodes
GetTreeHeight(rootNodeIndex);
// Calculate vertical position of all visible nodes
SetVerNodePositions();
// Calculate horizontal position of all visible nodes
SetHorNodePosition(rootNodeIndex, nSchemaBorder, true);
}
function DrawNode(ctx, nodeIndex, recursive)
{
var node = Nodes[nodeIndex];
var nodeName = node.name;
var nodeType = node.type;
var right = node.right;
if (nodeType == NodeTypeChoice)
right = DrawChoiceNode(ctx, nodeIndex);
else
if (nodeType == NodeTypeSequence)
right = DrawSequenceNode(ctx, nodeIndex);
else
right = DrawElementNode(ctx, nodeIndex);
if (recursive && node.expanded) {
var childNodes = ChildNodeCount(nodeIndex);
var nextNodeIndex = node.firstChildIndex;
var x = node.left + node.totalWidth;
var y1 = node.verCenter;
var y2 = node.verCenter;
if (childNodes > 1)
x -= nMinHorLineLength;
DrawLine(ctx, right, node.verCenter, x, node.verCenter);
while (nextNodeIndex) {
if (childNodes > 1) {
var y = Nodes[nextNodeIndex].verCenter;
DrawLine(ctx, x, y, Nodes[nextNodeIndex].left, y);
y1 = Math.min(y1, y);
y2 = Math.max(y2, y);
}
DrawNode(ctx, nextNodeIndex, recursive);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
if (childNodes > 1)
DrawLine(ctx, x, y1, x, y2);
}
}
function GetMaxChildWidth(nodeIndex)
{
var result = 0;
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
result = Math.max(result, Nodes[nextNodeIndex].totalWidth);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
return result;
}
function ExpandChoiceNodes(nodeIndex)
{
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
if (Nodes[nextNodeIndex].type == NodeTypeChoice)
Nodes[nextNodeIndex].expanded = true;
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
function MakeVisibleAndUpdate(x, y)
{
canvasContainerScrollLeft = canvasContainer.scrollLeft; //.scrollLeftMax
canvasContainerScrollTop = canvasContainer.scrollTop; //.scrollTopMax
MakeVisible(x, y);
canvasContainer.scrollLeft = Math.min(canvasContainerScrollLeft, canvas.width - canvasContainerWidth);
canvasContainer.scrollTop = Math.min(canvasContainerScrollTop, canvas.height - canvasContainerHeight);
}
function MoveNodeToCenter(nodeIndex)
{
canvasContainerScrollLeft = Nodes[nodeIndex].left + Nodes[nodeIndex].width - canvasContainerWidth * 0.8;
canvasContainerScrollTop = Nodes[nodeIndex].top + Nodes[nodeIndex].height - canvasContainerHeight * 0.5;
canvasContainer.scrollLeft = Math.max(Math.min(canvasContainerScrollLeft, canvas.width - canvasContainerWidth), 0);
canvasContainer.scrollTop = Math.max(Math.min(canvasContainerScrollTop, canvas.height - canvasContainerHeight), 0);
}
function DrawTree()
{
// set height of canvas container to window height (= full screen)
var canvasHeight = window.innerHeight - (schemaOptions.offsetHeight + searchResultDiv.offsetHeight);
canvasContainer.style.height = canvasHeight + "px"; //document.offsetHeight;
// make complete canvas container visible
//document.body.scrollTop = canvasContainer.offsetTop + 1;
document.body.scrollTop = schemaOptions.offsetTop + 1;
canvasContainerWidth = canvasContainer.clientWidth;
canvasContainerHeight = canvasContainer.clientHeight;
//var canvas = document.getElementById("tree");
var ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
//DrawSizeRuler(ctx, 5, 5, 50);
DrawNode(ctx, rootNodeIndex, true);
// make sure last clicked/expanded node is visible
canvasContainerScrollLeft = canvasContainer.scrollLeft; //.scrollLeftMax
canvasContainerScrollTop = canvasContainer.scrollTop; //.scrollTopMax
if (nSchemaWidth <= canvasContainerWidth) {
canvasContainerScrollLeft = 0;
canvasContainer.scrollLeft = canvasContainerScrollLeft;
}
if (nSchemaHeight <= canvasContainerHeight) {
canvasContainerScrollTop = 0;
canvasContainer.scrollTop = canvasContainerScrollTop;
}
if (nLastClickedNodeIndex) {
if (nLastExpandedNodeIndex) {
var maxChildWidth = GetMaxChildWidth(nLastExpandedNodeIndex) + 40;
var halfTreeHeight = Math.min(GetTreeHeight(nLastExpandedNodeIndex), canvasContainerHeight) / 2;
//var halfTreeHeight = Math.min(Nodes[nLastExpandedNodeIndex].childrenHeight, canvasContainerHeight) / 2;
var x = Nodes[nLastExpandedNodeIndex].left + Nodes[nLastExpandedNodeIndex].totalWidth + maxChildWidth;
MakeVisible(x, Nodes[nLastExpandedNodeIndex].verCenter + halfTreeHeight + 80);
MakeVisible(x, Nodes[nLastExpandedNodeIndex].verCenter - halfTreeHeight);
nLastExpandedNodeIndex = null;
}
if (nLastCollapsedNodeIndex) {
var x = Nodes[nLastClickedNodeIndex].left + Nodes[nLastClickedNodeIndex].totalWidth - canvasContainerWidth * 0.8;
MakeVisible(x, Nodes[nLastClickedNodeIndex].top - canvasContainerHeight * 0.5);
MakeVisible(x, Nodes[nLastClickedNodeIndex].top + CurrentTotalHeight(nLastClickedNodeIndex)/*Nodes[nLastClickedNodeIndex].totalHeight*/ + 80);
nLastCollapsedNodeIndex = null;
}
MakeVisible(Nodes[nLastClickedNodeIndex].left, Nodes[nLastClickedNodeIndex].top);
canvasContainer.scrollLeft = Math.min(canvasContainerScrollLeft, canvas.width - canvasContainerWidth);
canvasContainer.scrollTop = Math.min(canvasContainerScrollTop, canvas.height - canvasContainerHeight);
}
/*
var container = document.getElementById("canvas-container");
var rect = canvas.getBoundingClientRect(); // 10/48/10012/5050
var scrollTop = container.scrollTop;
tracePar.innerHTML = "BoundingClientRect=" + rect.left + "/" + rect.top;
tracePar.innerHTML = tracePar.innerHTML + "/" + rect.right + "/" + rect.bottom;
tracePar.innerHTML = tracePar.innerHTML + " , ScrollPosition=" + container.scrollLeft + "/" + container.scrollTop;
tracePar.innerHTML = tracePar.innerHTML + " , ContainerSize=" + container.clientWidth + "/" + container.clientHeight;
// ContainerSize=1228/733
tracePar.innerHTML = tracePar.innerHTML + " , CanvasSize=" + canvas.clientWidth + "/" + canvas.clientHeight;
if (nLastClickedNodeIndex) {
var node = Nodes[nLastClickedNodeIndex];
tracePar.innerHTML = tracePar.innerHTML + " , LastClickedNode=" + node.left + "/" + node.top + "/" + node.right + "/" + node.bottom;
}
// BoundingClientRect=-1264/-1296.5/1238/1205.5 , ScrollPosition=1274/1275.5 , ContainerSize=1228/733 ,
// CanvasSize=2500/2500 , LastClickedNode=2358/1772/2458/1796
//window.scrollTo(300, 500);
*/
/*
var x = 20.0;
var y = 20.0;
ctx.font = "bold 10pt Arial";
var sText = "FundsXML4";
var nTextHeight = nNodeTextHeight; // ctx.measureText(sText).height;
var nTextWidth = ctx.measureText(sText).width;
//alert("nTextWidth=" + nTextWidth + " , nTextHeight=" + nTextHeight);
var nNodeWidth = Math.round(nTextWidth + nNodeTextPadding * 2 + nExpanderHalfSize);
ctx.fillText(sText, x + nNodeTextPadding, y + nTextHeight + nNodeTextPadding);
ctx.lineWidth = nLineWidth; // 0.75; // 0.5; // "1";
/ * if (bRootNodeExpanded)
ctx.strokeStyle = "red";
else * /
ctx.strokeStyle = sLineColor; //"blue";
ctx.rect(x + 0.5, y + 0.5, nNodeWidth - 0.5, nNodeHeight - 0.5); // nTextHeight + nNodeTextPadding * 2 - 0.5);
ctx.stroke();
Nodes[0].left = x;
Nodes[0].top = y;
Nodes[0].right = x + nNodeWidth;
Nodes[0].bottom = y + nNodeHeight;
Nodes[0].width = nNodeWidth;
Nodes[0].verCenter = y + nHalfNodeHeight;
Nodes[0].name = "FundsXML4";
Nodes[0].annotation = "Root element of FundsXML 4.0 schema";
Nodes[0].expanded = true;
var yy = Nodes[0].bottom + nNodeTextPadding;
sText = "Root element of FundsXML 4.0 schema";
nTextHeight = nNodeTextHeight;
nTextWidth = ctx.measureText(sText).width;
//alert("nTextWidth=" + nTextWidth + " , nTextHeight=" + nTextHeight);
ctx.beginPath();
ctx.strokeStyle = "black";
//ctx.font = "8pt Arial";
ctx.font = "11px Arial";
ctx.fillText(sText, x, yy + nTextHeight);
ctx.stroke();
x += nNodeWidth;
y += nHalfNodeHeight;
DrawExpander(ctx, x, y, false);
x += nExpanderHalfSize;
var nLineLength = 50;
/ *
ctx.beginPath();
ctx.lineWidth = nLineWidth;
ctx.strokeStyle = "black";
ctx.moveTo(x, y);
ctx.lineTo(x + nLineLength, y);
ctx.stroke();
* /
DrawLine(ctx, x, y, x + nLineLength, y);
x += nLineLength;
DrawSequenceNode(ctx, x, y);
x += nSequenceWidth + nExpanderHalfSize;
DrawExpander(ctx, x, y, true);
x += nExpanderHalfSize;
DrawLine(ctx, x, y, x + nLineLength, y);
x += nLineLength;
Nodes.push({});
Nodes[1].left = x;
Nodes[1].top = y - nHalfNodeHeight;
Nodes[1].right = x + nNodeWidth;
Nodes[1].bottom = y + nHalfNodeHeight;
Nodes[1].width = nNodeWidth;
Nodes[1].verCenter = y;
Nodes[1].name = "ControlData";
Nodes[1].annotation = "Attributes of the xml document";
Nodes[1].expanded = true;
DrawNode(ctx, Nodes[1]);
x += nNodeWidth + nExpanderHalfSize;
DrawLine(ctx, x, y, x + nLineLength, y);
x += nLineLength;
DrawChoiceNode(ctx, x, y);
x += nSequenceWidth + nExpanderHalfSize;
DrawExpander(ctx, x, y, false);
x += nExpanderHalfSize;
*/
}
function getCursorPosition(canvas, event)
{
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
//console.log("x: " + x + " y: " + y);
alert("x: " + x + " [" + Nodes[0].left + " - " + Nodes[0].right + "] / y: " + y + " [" + Nodes[0].top + " - " + Nodes[0].bottom + "]");
}
function getObjectAtCursor(canvas, event)
{
var result;
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
//console.log("x: " + x + " y: " + y);
for (i = 0; i < Nodes.length; i++)
if (x >= Nodes[i].left && x <= Nodes[i].right + nExpanderHalfSize && y >= Nodes[i].top && y <= Nodes[i].bottom + nExpanderHalfSize)
result = i;
return result;
}
var nodeDetails = document.getElementById('node-details');
var NodeDetailsName = document.getElementById("nd-name");
var NodeDetailsAttr = document.getElementById("nd-attr");
var NodeDetailsType = document.getElementById("nd-type");
var NodeDetailsPattern = document.getElementById("nd-pattern");
var NodeDetailsAnno = document.getElementById("nd-anno");
var NodeDetailsEnum = document.getElementById("nd-enum");
var NodeDetailsXPath = document.getElementById("nd-xpath");
function ShowNodeDetails(nodeIndex)
{
var node = Nodes[nodeIndex];
var clientRect = canvas.getBoundingClientRect();
var i, txt;
var xOffset = -20;
var yOffset = nNodeTextHeight + nNodeTextPadding + 2;
var x = node.left + xOffset + clientRect.left;
var y = node.top + yOffset + clientRect.top + document.body.scrollTop;
//var y = node.top + node.bottom + clientRect.top - 5;
nodeDetails.style.left = x + "px";
nodeDetails.style.top = y + "px";
/*
document.body.scrollTop = canvasContainer.offsetTop + 1;
<tr><td class="node-column">Name</td><td class="node-name" id="nd-name">SampleNodeName</td></tr>
<tr><td class="node-column">Attr</td><td class="attributes" id="nd-attr"><b>AttrOne:</b> TypeInfo<br/><b>AttributeTwo:</b> TypeInfo</td></tr>
<tr><td class="node-column">Type</td><td class="type-description" id="nd-type">Type Description</td></tr>
<tr><td class="node-column">Descr</td><td class="annotation" id="nd-anno">First line of annotation text<br/>second line of annotation text<br/>third line</td></tr>
<tr><td class="node-column">Enum</td><td class="enumeration" id="nd-enum">FIRST<br/>SECOND<br/>THIRD<br/>FOURTH</td></tr>
<tr><td class="node-column">XPath</td><td class="xpath" id="nd-xpath">/FundsXML4/Funds/Fund/FundDynamicData/TotalAssetValues/TotalAssetValue</td></tr>
*/
NodeDetailsName.innerHTML = node.name;
if (Nodes[nodeIndex].attributes) {
txt = "<b>" + node.attributes[0].name + ": </b>" + node.attributes[0].type + " [" + node.attributes[0].use + "]";
for (i = 1; i < node.attributes.length; i++) {
txt += "<br/><b>" + node.attributes[i].name + ": </b> " + node.attributes[i].type;
if (node.attributes[i].use)
txt += " <b>[" + node.attributes[i].use + "]</b>";
}
}
else
txt = "";
NodeDetailsAttr.innerHTML = txt;
NodeDetailsType.innerHTML = node.typeDescription;
if (node.pattern)
txt = node.pattern;
else
txt = "";
NodeDetailsPattern.innerHTML = txt;
if (node.annotation) {
txt = node.annotationLines[0];
for (i = 1; i < node.annotationLines.length; i++) {
txt += "<br/>" + node.annotationLines[i];
}
}
else
txt = "";
NodeDetailsAnno.innerHTML = txt;
if (node.enumeration && node.enumeration[0]) {
// calculate average length of enumerations
var len = node.enumeration[0].length;
for (i = 1; i < node.enumeration.length; i++)
len += node.enumeration[i].length;
len = len / node.enumeration.length;
if (len > 5) {
// fill enumeration block
txt = node.enumeration[0];
for (i = 1; i < node.enumeration.length; i++) {
txt += "<br/>" + node.enumeration[i];
}
}
else {
txt = node.enumeration[0];
len = txt.length;
for (i = 1; i < node.enumeration.length; i++) {
if (len + node.enumeration[i].length > 40) {
txt += "<br/>" + node.enumeration[i];
len = node.enumeration[i].length;
}
else {
txt += ", " + node.enumeration[i];
len += 2 + node.enumeration[i].length;
}
}
}
}
else
txt = "";
NodeDetailsEnum.innerHTML = txt;
//txt = "/FundsXML4/.../" + node.name;
txt = XPath(nodeIndex);
NodeDetailsXPath.innerHTML = txt;
nodeDetails.style.display = "block";
var xx = x + nodeDetails.offsetWidth - clientRect.left;
var yy = y + nodeDetails.offsetHeight - clientRect.top;
MakeVisibleAndUpdate(xx, yy);
// make sure node details window is displayed completely
clientRect = canvas.getBoundingClientRect();
x = node.left + xOffset + clientRect.left;
y = node.top + yOffset + clientRect.top + document.body.scrollTop;
nodeDetails.style.left = x + "px";
nodeDetails.style.top = y + "px";
//nodeDetails.style.display = "block";
setTimeout(function () { nodeDetails.style.display = "block"; }, 50);
}
function NodeClicked(nodeIndex, showNodeDetails)
{
nLastClickedNodeIndex = nodeIndex;
nLastExpandedNodeIndex = null;
if (nodeIndex) {
var firstChildIndex = Nodes[nodeIndex].firstChildIndex;
if (firstChildIndex) {
if (Nodes[nodeIndex].expanded) {
Nodes[nodeIndex].expanded = false;
nLastCollapsedNodeIndex = nodeIndex;
}
else {
Nodes[nodeIndex].expanded = true;
nLastExpandedNodeIndex = nodeIndex;
var nodeType = Nodes[firstChildIndex].type;
if ((nodeType == NodeTypeChoice || nodeType == NodeTypeSequence) && Nodes[firstChildIndex].firstChildIndex) {
Nodes[firstChildIndex].expanded = true;
nLastExpandedNodeIndex = firstChildIndex;
}
ExpandChoiceNodes(nLastExpandedNodeIndex);
}
SetVerNodePositions();
//DrawTree();
}
else {
if (nodeDetails.style.display == "none" && showNodeDetails)
ShowNodeDetails(nodeIndex);
else
nodeDetails.style.display = "none";
}
}
else
nodeDetails.style.display = "none";
DrawTree();
}
function ClickDetected(event)
{
var nodeIndex = getObjectAtCursor(canvas, event);
NodeClicked(nodeIndex, true);
}
/*
function RightClickDetected(event)
{
var canvas = document.getElementById("tree");
//getCursorPosition(canvas, event);
var nodeIndex = getObjectAtCursor(canvas, event);
nLastClickedNodeIndex = nodeIndex;
if (nodeIndex) {
nodeDetails.style.left = event.clientX + "px"; // "600px";
nodeDetails.style.top = event.clientY + "px";
nodeDetails.style.display = "block";
}
else
nodeDetails.style.display = "none";
}
function openModal() {
document.getElementById('node-details').style.display = "block";
}
function closeModal() {
document.getElementById('node-details').style.display = "none";
}
*/
function ContainerOnScroll()
{
nodeDetails.style.display = "none";
}
/*
function myFunction(value1,value2,value3)
{
var ResultObject = {};
ResultObject["result1"] = value1 + value2;
ResultObject["result2"] = value1 * value3;
return ResultObject;
}
var ResultObject = myFunction(1,2,3);
*/
//DrawTree();
var elem = document.getElementById('tree');
elem.addEventListener('click', ClickDetected);
//elem.addEventListener('contextmenu', RightClickDetected);
//elem.addEventListener('dblclick', RightClickDetected);
elem = document.getElementById('canvas-container');
elem.addEventListener('scroll', ContainerOnScroll);
//oncontextmenu = "javascript:alert('success!');return false;"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Search functions
function SearchSubTree(nodeIndex)
{
var matching = false;
if (IsRealNode(Nodes[nodeIndex].type)) {
var nodeName = Nodes[nodeIndex].name;
if (nodeName && nodeName.toLowerCase().search(lastSearchText) >= 0)
matching = true;
}
var annotation = Nodes[nodeIndex].annotation;
if (!matching && annotation)
if (annotation.toLowerCase().search(lastSearchText) >= 0)
matching = true;
if (matching) {
if (SearchResults.length >= nMaxSearchResults)
bTooManySearchResults = true;
else
SearchResults.push(nodeIndex);
}
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex && !bTooManySearchResults) {
SearchSubTree(nextNodeIndex);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
function SearchButtonPressed()
{
var searchResultElement;
var nodeIndex, i;
var bDisplayResultTable = false;
lastSearchText = searchText.value.trim().toLowerCase();
SearchResults = new Array();
bTooManySearchResults = false;
searchResultDiv.scrollTop = 0;
if (lastSearchText.length > 2) {
SearchSubTree(rootNodeIndex);
bDisplayResultTable = true;
}
for (i = 0; i < SearchResults.length; i++) {
searchResultElement = document.getElementById('SearchResult' + (i + 1));
nodeIndex = SearchResults[i];
searchResultElement.innerHTML = '' + XPath(nodeIndex).replace(/\//g, ' / '); // + ' [' + nodeIndex + ']';
}
for (i = SearchResults.length; i < nMaxSearchResults; i++) {
searchResultElement = document.getElementById('SearchResult' + (i + 1));
searchResultElement.innerHTML = '';
}
if (bTooManySearchResults)
tooManyResults.innerHTML = 'Too many results found';
else
tooManyResults.innerHTML = '';
if (bDisplayResultTable) {
if (SearchResults.length == 0)
firstSearchResult.innerHTML = 'No results found for this search text ...';
searchResultDiv.style.display = "block";
searchResetButton.style.display = "inline-block";
}
else {
searchResultDiv.style.display = "none";
searchResetButton.style.display = "none";
}
DrawTree();
}
// Detect enter key pressed within search text input field
searchText.addEventListener("keyup", function (event) {
event.preventDefault();
if (event.keyCode == 13)
SearchButtonPressed();
});
function SetAllNodesCollapsed(nodeIndex)
{
Nodes[nodeIndex].expanded = false;
var nextNodeIndex = Nodes[nodeIndex].firstChildIndex;
while (nextNodeIndex) {
SetAllNodesCollapsed(nextNodeIndex);
nextNodeIndex = Nodes[nextNodeIndex].nextIndex;
}
}
function SetPathExpanded(nodeIndex)
{
if (Nodes[nodeIndex].firstChildIndex)
Nodes[nodeIndex].expanded = true;
var parentIndex = Nodes[nodeIndex].parentIndex;
if (parentIndex)
SetPathExpanded(parentIndex);
}
function SearchResultClicked(index)
{
if (index >= 0 && index < SearchResults.length) {
var nodeIndex = SearchResults[index];
SetAllNodesCollapsed(rootNodeIndex);
SetPathExpanded(nodeIndex);
SetVerNodePositions();
MoveNodeToCenter(nodeIndex);
if (Nodes[nodeIndex].firstChildIndex)
Nodes[nodeIndex].expanded = false;
SetVerNodePositions();
NodeClicked(nodeIndex, false);
}
}
function SearchResetPressed()
{
searchText.value = '';
SearchResults = new Array();
searchResultDiv.style.display = "none";
searchResetButton.style.display = "none";
DrawTree();
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment