blob: 64be9682e9136ae200bc627bddf3b4eb1c570c85 [file] [log] [blame]
function LoadData ()
{
gTypeNames = [];
ComplexTypeNames = [];
SimpleTypeNames = [];
for (var sName in Data)
{
gTypeNames.push(sName);
switch(Data[sName].type)
{
case "complex-type":
ComplexTypeNames.push(sName);
break;
case "simple-type":
SimpleTypeNames.push(sName);
break;
}
}
document.getElementById("message").innerHTML = "there are " + ComplexTypeNames.length + " complex types and "
+ SimpleTypeNames.length +" simple types";
}
function InitializeSearch ()
{
CurrentTypeName = "";
TypeHistory = Array();
LoadData();
ShowType("A:ST_Overlap");
}
function CheckInput (aField, aEvent)
{
switch(aEvent.keyCode)
{
case 38:
--selection_index;
if (selection_index < 0)
selection_index = matches.length-1;
break;
case 40:
++selection_index;
if (selection_index >= matches.length)
selection_index = 0;
break;
default:
matches = GetMatches(aField.value);
selection_index = 0;
}
ShowMatches(matches, selection_index);
}
function GetMatches (sPattern)
{
var aLcPatterns = sPattern.toLowerCase().split(/\s+/);
var nTypeCount = gTypeNames.length;
var aMatches = [];
for (index=0; index<nTypeCount; ++index)
{
var sTypeName = gTypeNames[index];
var aParts = new Array(sTypeName);
var sLcTypeName = sTypeName.toLowerCase();
var bIsMatch = true;
var nSearchStart = 0;
for (nPatternIndex=0; nPatternIndex<aLcPatterns.length && bIsMatch; ++nPatternIndex)
{
var sPattern = aLcPatterns[nPatternIndex];
var nMatchStart = sLcTypeName.indexOf(sPattern, nSearchStart);
if (nMatchStart >= 0)
{
var nMatchEnd = nMatchStart + sPattern.length;
aParts.push(sTypeName.substring(nSearchStart, nMatchStart));
aParts.push(sTypeName.substring(nMatchStart, nMatchEnd));
nSearchStart = nMatchEnd;
}
else
{
// Only some patterns are matched.
bIsMatch = false;
}
}
if (bIsMatch)
{
if (nMatchEnd < sTypeName.length-1)
aParts.push(sTypeName.substring(nMatchEnd));
aMatches.push(aParts);
}
}
return aMatches;
}
/** Show the matching types.
* As there can be a great many matching types, some sort of abbreviation is necessary.
* Format all matches into lines of n entries.
* Show the line containing the selected match and the ones before and after.
* Show also the number of ommited matches.
*/
function ShowMatches (aMatches, nSelectionIndex)
{
var sText = "";
var nHalfRange = 10;
var nMatchesPerLine = 5;
var nLineCount = Math.floor((aMatches.length+nMatchesPerLine-1) / nMatchesPerLine);
var nLineOfSelection = Math.floor(nSelectionIndex / nMatchesPerLine);
var nFirstDisplayedLine = nLineOfSelection>0 ? nLineOfSelection-1 : 0;
var nLastDisplayedLine = nLineOfSelection<nLineCount-1 ? nLineOfSelection+1 : nLineCount-1;
for (nLineIndex=nFirstDisplayedLine; nLineIndex<=nLastDisplayedLine; ++nLineIndex)
{
var nLineStartIndex = nLineIndex * nMatchesPerLine;
var nLineEndIndex = nLineStartIndex + nMatchesPerLine - 1;
if (nLineEndIndex >= aMatches.length)
nLineEndIndex = aMatches.length-1;
sText += "<tr>"
for (nIndex=nLineStartIndex; nIndex<=nLineEndIndex; ++nIndex)
{
var aMatch = aMatches[nIndex];
var sTypeName = aMatch[0];
var sMatch = "";
for (nPartIndex=1; nPartIndex<aMatch.length; ++nPartIndex)
{
if ((nPartIndex%2)==0)
sMatch += "<span class=\"match-highlight\">"+aMatch[nPartIndex]+"</span>";
else
sMatch += aMatch[nPartIndex];
}
sText += "<td>"
if (nIndex == nSelectionIndex)
{
sText += " <span class=\"typelink current-match\">" + sMatch + "</span>";
}
else
{
sText += " " + GetTypeLink(sMatch, sTypeName, -1);
}
sText += "</td>"
}
sText += "</tr>";
}
if (nFirstDisplayedLine > 0)
sText = "<tr><td>["+(nFirstDisplayedLine*nMatchesPerLine)+" matches] ...</td><tr>" + sText;
if (nLastDisplayedLine+1 < nLineCount)
sText += "<tr><td>... ["+((nLineCount-nLastDisplayedLine-1)*nMatchesPerLine)+" matches]</td></tr>";
document.getElementById('matches').innerHTML = "<table>"+sText+"</table>";
if (aMatches.length == 0)
{
document.getElementById('match-count').innerHTML = "no match:";
}
else
{
if (aMatches.length == 1)
document.getElementById('match-count').innerHTML = "single match:";
else
document.getElementById('match-count').innerHTML = aMatches.length+" matches:";
ShowType(aMatches[nSelectionIndex][0]);
}
}
function GetTopLevelNodeForTypeName(sTypeName)
{
if (sTypeName in Data)
return Data[sTypeName];
else
alert(sTypeName +" is not a known complex type, simple type, or group");
}
/** Show the specified type.
* When nHistoryIndex is not -1 then the history is shortened to that (before that) index.
*/
function ShowType (sTypeName, nHistoryIndex)
{
if (nHistoryIndex == -1)
{
if (CurrentTypeName != "")
{
TypeHistory.push(CurrentTypeName);
ShowHistory();
}
}
else
{
TypeHistory = TypeHistory.slice(0,nHistoryIndex);
ShowHistory();
}
CurrentTypeName = sTypeName;
var aElement = document.getElementById('result');
// Remove the old content.
while(aElement.childNodes.length > 0)
aElement.removeChild(aElement.firstChild);
// Create the new content.
var list = CreateDomTreeForType(GetTopLevelNodeForTypeName(sTypeName), "ul");
// Show the new content.
aElement.appendChild(list);
}
/** Create a dom sub tree for the given OOXML type that is ready for insertion into the global DOM tree.
*/
function CreateDomTreeForType (aNode, sType)
{
var aEntry = document.createElement(sType);
if (typeof aNode==='undefined')
{
aEntry.innerHTML = "undefined node";
}
else if (typeof aNode.type==='undefined')
{
aEntry.innerHTML = "unknown type";
}
else
{
switch(aNode.type)
{
case "attribute":
aEntry.innerHTML = CreateValueTable([
"attribute",
"type:", GetTypeLink(aNode["value-type"], aNode["value-type"], -1),
"use:", aNode.use]);
break;
case "attribute-reference":
aEntry.innerHTML = CreateReference(aNode["referenced-attribute"]);
break;
case "builtin":
aEntry.innerHTML = CreateValueTable(
["builtin",
"name:", aNode['builtin-type']
]);
break;
case "complex-type":
aEntry.innerHTML = aNode.type + " " + aNode.name;
break;
case "complex-type-reference":
aEntry.innerHTML = CreateReference(aNode["referenced-complex-type"]);
break;
case "group":
aEntry.innerHTML = aNode.type + " " + aNode.name;
break;
case "group-reference":
aEntry.innerHTML = CreateReference("group", aNode["referenced-group"]);
break;
case "element":
aEntry.innerHTML = "element <b>" + aNode["tag"] + "</b> -> " + GetTypeLink(aNode["result-type"], aNode["result-type"], -1);
break;
case "occurrence":
aEntry.innerHTML = aNode.minimum +" -> " + aNode.maximum;
break;
case "restriction":
aEntry.innerHTML = CreateRestrictionRepresentation(aNode);
break;
case "sequence":
aEntry.innerHTML = "sequence";
break;
case "simple-type":
aEntry.innerHTML = aNode.type + " " + aNode.name;
break;
case "simple-type-reference":
aEntry.innerHTML = CreateReference("simple-type", aNode["referenced-simple-type"]);
break;
default:
aEntry.innerHTML = aNode.type;
break;
}
// Add nodes for attributes.
var aAttributes= aNode["attributes"];
if ( ! (typeof aAttributes==='undefined' || aAttributes.length == 0))
{
var aAttributeList = document.createElement("ul");
aEntry.appendChild(aAttributeList);
for (var nIndex=0; nIndex<aAttributes.length; ++nIndex)
{
var aAttributeEntry = CreateDomTreeForType(aAttributes[nIndex], "li");
aAttributeList.appendChild(aAttributeEntry);
}
}
// Add nodes for children.
var aChildren = aNode["children"];
if ( ! (typeof aChildren==='undefined' || aChildren.length == 0))
{
var aChildrenList = document.createElement("ul");
aEntry.appendChild(aChildrenList);
for (var nIndex=0; nIndex<aChildren.length; ++nIndex)
{
var aChildrenEntry = CreateDomTreeForType(aChildren[nIndex], "li");
aChildrenList.appendChild(aChildrenEntry);
}
}
}
return aEntry;
}
function GetTypeLink (sText, sTarget, nIndex)
{
return "<span class=\"typelink\" id=\""+sTarget+"\" onclick=\"ShowType('"+sTarget+"',"+nIndex+")\">"+sText+"</span>";
}
function CreateValueTable (aValues)
{
var sResult = "<table class=\"value-table\"><tr><td>"+aValues[0]+"</td><td>"+aValues[1]+"</td><td>"+aValues[2]+"</td></tr>";
for (nIndex=3; nIndex<aValues.length; nIndex+=2)
{
sResult += "<tr><td></td><td>"+aValues[nIndex]+"</td><td>"+aValues[nIndex+1]+"</td></tr>";
}
sResult += "</table>";
return sResult;
}
function CreateReference (sWhat, sTypeName)
{
return "reference to "+sWhat+" "+GetTypeLink(sTypeName, sTypeName, -1) + " "
+CreateButton(
sTypeName,
"show",
"ToggleTypeReferenceExpansion('"+sTypeName+"')")
+"<br><span id=\"expansion-"+sTypeName+"\"></span>";
}
function CreateButton (sId, sText, sExpandAction)
{
return "<span class=\"button\" id=\"button-"+sId+"\" onClick=\""+sExpandAction+"\">"+sText+"</span>";
}
function ToggleTypeReferenceExpansion(sTypeName)
{
var aButton = document.getElementById("button-"+sTypeName);
var aExpansion = document.getElementById("expansion-"+sTypeName);
if (aButton.innerHTML == "show")
{
aExpansion.appendChild(CreateDomTreeForType(Data[sTypeName], "span"));
aButton.innerHTML = "hide";
}
else
{
aExpansion.innerHTML = "";
aButton.innerHTML = "show";
}
}
function ShowHistory ()
{
var aElement = document.getElementById('history');
var sContent = "History:";
for (nIndex=0; nIndex<TypeHistory.length; ++nIndex)
{
if (nIndex == 0)
sContent += " ";
else
sContent += ", ";
sContent += GetTypeLink(TypeHistory[nIndex], TypeHistory[nIndex], nIndex);
}
aElement.innerHTML = sContent;
}
function CreateRestrictionRepresentation (aNode)
{
var aTableData = ["restriction", "based on:", GetTypeLink(aNode['base-type'], aNode['base-type'], -1)];
AddValue(aNode, "enumeration", aTableData);
AddValue(aNode, "pattern", aTableData);
AddValue(aNode, "length", aTableData);
return CreateValueTable(aTableData);
}
function AddValue (aMap, sKey, aTableData)
{
if (sKey in aMap)
{
aTableData.push(sKey+":");
aTableData.push(aMap[sKey]);
}
}