define(["options", "jquery", "nav"], function (options, $, navConfig) {
/**
* The path of the output directory, relative to the current HTML file.
* @type {String}
*/
var path2root = null;
$(document).ready ( function() {
// Register the click handler for the TOC
var topicRefExpandBtn = $(".wh_publication_toc .wh-expand-btn");
topicRefExpandBtn.click(toggleTocExpand);
/* Toggle expand/collapse on enter and space */
topicRefExpandBtn.keypress(handleKeyEvent);
});
/**
* Retrieves the path of the output directory, relative to the current HTML file.
*
* @returns {*} the path of the output directory, relative to the current HTML file.
*/
function getPathToRoot() {
if (path2root == null) {
path2root = $('meta[name="wh-path2root"]').attr("content");
if (path2root == null || path2root == undefined) {
path2root = "";
}
}
return path2root;
};
/*
* Toggles expand/collapse on enter and space
*/
function handleKeyEvent(event) {
// Enter & Spacebar events
if ( event.which === 13 || event.which === 32) {
event.preventDefault();
toggleTocExpand.call(this);
}
}
function toggleTocExpand() {
var topicRef = $(this).closest(".topicref");
var state = topicRef.attr(navConfig.attrs.state);
var parentLi = $(this).closest('li');
var titleLink = $(this).siblings(".title").children("a");
var titleLinkID = titleLink.attr("id");
if (state == null) {
// Do nothing
} else if (state == navConfig.states.pending) {
// Do nothing
} else if (state == navConfig.states.notReady) {
topicRef.attr(navConfig.attrs.state, navConfig.states.pending);
parentLi.attr('aria-expanded', 'true');
$(this).attr("aria-labelledby", navConfig.btnIds.pending + " " + titleLinkID);
retrieveChildNodes(topicRef);
} else if (state == navConfig.states.expanded) {
topicRef.attr(navConfig.attrs.state, navConfig.states.collapsed);
$(this).attr("aria-labelledby", navConfig.btnIds.expand + " " + titleLinkID);
parentLi.attr('aria-expanded', 'false');
} else if (state == navConfig.states.collapsed) {
topicRef.attr(navConfig.attrs.state, navConfig.states.expanded);
$(this).attr("aria-labelledby", navConfig.btnIds.collapse + " " + titleLinkID);
parentLi.attr('aria-expanded', 'true');
}
};
/**
* Loads the JS file containing the list of child nodes for the current topic node.
* Builds the list of child topics element nodes based on the retrieved data.
*
* @param topicRefSpan The topicref 'span' element of the current node from TOC / Menu.
*/
function retrieveChildNodes(topicRefSpan) {
var tocId = $(topicRefSpan).attr(navConfig.attrs.tocID);
if (tocId != null) {
var jsonHref = navConfig.jsonBaseDir + "/" + tocId;
require(
[jsonHref],
function(data) {
if (data != null) {
var topics = data.topics;
var topicLi = topicRefSpan.closest('li');
var topicsUl = createTopicsList(topics);
var topicsUlParent = $('
');
topicsUl.forEach(function(topic){
topicsUlParent.append(topic);
});
topicLi.append(topicsUlParent);
var titleLink = topicRefSpan.find(".title > a");
var titleLinkID = titleLink.attr("id");
var expandBtn = topicRefSpan.children('.wh-expand-btn');
expandBtn.attr("aria-labelledby", navConfig.btnIds.collapse + " " + titleLinkID);
topicRefSpan.attr(navConfig.attrs.state, navConfig.states.expanded);
} else {
topicRefSpan.attr(navConfig.attrs.state, navConfig.states.leaf);
}
}
);
}
}
/**
* Creates the ul
element containing the child topic nodes of the current topic.
*
* @param topics The array of containing info about the child topics.
*
* @returns {*|jQuery|HTMLElement} the li
elements representing the child topic nodes of the current topic.
*/
function createTopicsList(topics) {
var topicsArray = [];
topics.forEach(function(topic) {
var topicLi = createTopicLi(topic);
topicsArray.push(topicLi);
});
return topicsArray;
};
/**
* Creates the li
element containing a topic node.
*
* @param topic The info about the topic node.
*
* @returns {*|jQuery|HTMLElement} the li
element containing a topic node.
*/
function createTopicLi(topic) {
var li = $("");
li.attr('role', 'treeitem');
if (hasChildren(topic)) {
li.attr('aria-expanded', 'false');
}
// .topicref span
var topicRefSpan = createTopicRefSpan(topic);
// append the topicref node in parent
li.append(topicRefSpan);
return li;
};
/**
* Creates the element containing the title and the link to the topic associated to a node in the menu or the TOC.
*
* @param topic The JSON object containing the info about the associated node.
*
* @returns {*|jQuery|HTMLElement} the topic title 'span' element.
*/
function createTopicRefSpan(topic) {
var isExternalReference = topic.scope == 'external';
// .topicref span
var topicRefSpan = $("");
topicRefSpan.addClass("topicref");
if (topic.outputclass != null) {
topicRefSpan.addClass(topic.outputclass);
}
// WH-1820 Copy the Ditaval "pass through" attributes.
var dataAttributes = topic.attributes;
if (typeof dataAttributes !== 'undefined') {
var attrsNames = Object.keys(dataAttributes);
attrsNames.forEach(function(attr) {
topicRefSpan.attr(attr, dataAttributes[attr]);
});
}
topicRefSpan.attr(navConfig.attrs.tocID, topic.tocID);
// Current node state
var containsChildren = hasChildren(topic);
if (containsChildren) {
// This state means that the child topics should be retrieved later.
topicRefSpan.attr(navConfig.attrs.state, navConfig.states.notReady);
} else {
topicRefSpan.attr(navConfig.attrs.state, navConfig.states.leaf);
}
var expandBtn = $("", {
class: "wh-expand-btn",
role: "button"
});
if(containsChildren) {
expandBtn.attr("aria-labelledby", navConfig.btnIds.expand + " " + getTopicLinkID(topic));
expandBtn.attr("tabindex", "0");
}
expandBtn.click(toggleTocExpand);
expandBtn.keypress(handleKeyEvent);
topicRefSpan.append(expandBtn);
// Topic ref link
var linkHref = '';
if (topic.href != null && topic.href != 'javascript:void(0)') {
if (!isExternalReference) {
linkHref += getPathToRoot();
}
linkHref += topic.href;
}
var link = $("", {
href: linkHref,
html: topic.title
});
// WH-2368 Update the relative links
var pathToRoot = getPathToRoot();
var linksInLink = link.find("a[href]");
linksInLink.each(function () {
var href = $(this).attr("href");
if (!(href.startsWith("http:") || href.startsWith("https:"))) {
$(this).attr("href", pathToRoot + href);
}
});
var imgsInLink = link.find("img[src]");
imgsInLink.each(function () {
var src = $(this).attr("src");
if (!(src.startsWith("http:") || src.startsWith("https:"))) {
$(this).attr("src", pathToRoot + src);
}
});
link.attr("id", getTopicLinkID(topic));
if (isExternalReference) {
link.attr("target", "_blank");
}
var titleSpan = $("", {
class: "title"
});
titleSpan.append(link);
// Topic ref short description
if (topic.shortdesc != null) {
var tooltipSpan = $("", {
class: "wh-tooltip",
html: topic.shortdesc
});
/* WH-1518: Check if the tooltip has content. */
if (tooltipSpan.find('.shortdesc:empty').length == 0) {
// Update the relative links
var links = tooltipSpan.find("a[href]");
links.each(function () {
var href = $(this).attr("href");
if (!(href.startsWith("http:") || href.startsWith("https:"))) {
$(this).attr("href", pathToRoot + href);
}
});
var imgs = tooltipSpan.find("img[src]");
imgs.each(function () {
var src = $(this).attr("src");
if (!(src.startsWith("http:") || src.startsWith("https:"))) {
$(this).attr("src", pathToRoot + src);
}
});
titleSpan.append(tooltipSpan);
}
}
topicRefSpan.append(titleSpan);
return topicRefSpan;
}
function getTopicLinkID(topic) {
return topic.tocID + "-link";
}
function hasChildren(topic) {
// If the "topics" property is not specified then it means that children should be loaded from the
// module referenced in the "next" property
var children = topic.topics;
var hasChildren;
if (children != null && children.length == 0) {
hasChildren = false;
} else {
hasChildren = true;
}
return hasChildren;
}
});