webhelp.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. define(["options", 'util', 'jquery', 'jquery.highlight'], function(options, util, $) {
  2. // Add some Bootstrap classes when document is ready
  3. var highlighted = false;
  4. $(document).ready(function () {
  5. var scrollPosition = $(window).scrollTop();
  6. handleSideTocPosition(scrollPosition);
  7. handlePageTocPosition(scrollPosition);
  8. $(window).scroll(function() {
  9. scrollPosition = handleSideTocPosition(scrollPosition);
  10. scrollPosition = handlePageTocPosition(scrollPosition);
  11. });
  12. $(window).resize(function(){
  13. $("#wh_publication_toc").removeAttr('style');
  14. scrollPosition = handleSideTocPosition(scrollPosition);
  15. scrollPosition = handlePageTocPosition(scrollPosition);
  16. });
  17. // Show/hide the button which expands/collapse the subtopics
  18. // if there are at least two subtopics in a topic
  19. var countSubtopics = $('.topic.nested1').length;
  20. var countSections = $('section.section .title').length;
  21. if(countSubtopics > 1 || countSections >1){
  22. $('.webhelp_expand_collapse_sections').show();
  23. }
  24. // WH-231
  25. // Expanding the side-toc
  26. $('.dots-before').click(function(){
  27. $(this).siblings('.hide-before').show();
  28. $(this).hide();
  29. });
  30. $('.dots-after').click(function(){
  31. $(this).siblings('.hide-after').show();
  32. $(this).hide();
  33. });
  34. // WH-2209
  35. var showZoomedImage = options.getBoolean("webhelp.show.full.size.image");
  36. if (showZoomedImage) {
  37. // Get the image and insert it inside the modal - use its "alt" text as a caption
  38. $.each( $('img.image:not([usemap])'), function (e) {
  39. var parentElement = $(this).parent().get(0).tagName;
  40. if(this.naturalWidth > this.width && parentElement.toLowerCase() != 'a'){
  41. $(this).addClass('zoom');
  42. }
  43. });
  44. $('.zoom').click(function(){
  45. $('#modal_img_large').css("display","block");
  46. $("#modal-img").attr('src',$(this).attr('src') );
  47. $("#caption").html( $(this).attr('alt') );
  48. });
  49. }
  50. // When the user clicks on (x), close the modal
  51. $(".modal .close").click(function(){
  52. $(".modal").css("display","none");
  53. });
  54. $(document).keyup(function(e) {
  55. if (e.keyCode == 27 && $('#modal_img_large').is(":visible")) { // escape key maps to keycode `27`
  56. $(".modal").css("display","none");
  57. }
  58. });
  59. // Navigational links and print
  60. $('#topic_navigation_links .navprev>a').addClass("oxy-icon oxy-icon-arrow-left");
  61. $('#topic_navigation_links .navnext>a').addClass("oxy-icon oxy-icon-arrow-right");
  62. $('.wh_print_link button').addClass('oxy-icon oxy-icon-print');
  63. // Hide sideTOC when it is empty
  64. var sideToc = $('#wh_publication_toc');
  65. var pageToc = $('#wh_topic_toc');
  66. if (sideToc !== undefined) {
  67. var sideTocChildren = sideToc.find('*');
  68. if (sideTocChildren.length == 0) {
  69. sideToc.css('display', 'none');
  70. // The topic content should span on all 12 columns
  71. sideToc.removeClass('col-lg-4 col-md-4 col-sm-4 col-xs-12');
  72. var topicContentParent = $('.wh_topic_content').parent();
  73. if (topicContentParent !== undefined && pageToc == undefined) {
  74. topicContentParent.removeClass(' col-lg-8 col-md-8 col-sm-8 col-xs-12 ');
  75. topicContentParent.addClass(' col-lg-12 col-md-12 col-sm-12 col-xs-12 ');
  76. }
  77. } else {
  78. /* WH-1518: Check if the tooltip has content. */
  79. var emptyShortDesc = sideToc.find('.topicref .wh-tooltip .shortdesc:empty');
  80. if (emptyShortDesc.length > 0) {
  81. var tooltip = emptyShortDesc.closest('.wh-tooltip');
  82. tooltip.remove();
  83. }
  84. }
  85. }
  86. // WH-1518: Hide the Breadcrumb tooltip if it is empty.
  87. var breadcrumb = $('.wh_breadcrumb');
  88. var breadcrumbShortDesc = breadcrumb.find('.topicref .wh-tooltip .shortdesc:empty');
  89. if (breadcrumbShortDesc.length > 0) {
  90. var tooltip = breadcrumbShortDesc.closest('.wh-tooltip');
  91. tooltip.remove();
  92. }
  93. var $allAccordionHeaders = $(".wh_main_page_toc .wh_main_page_toc_accordion_header");
  94. var $allAccordionButtons = $(".wh_main_page_toc .wh_main_page_toc_accordion_header .header-button");
  95. $allAccordionHeaders.click(function(event) {
  96. $headerButton = $(this).find('.header-button');
  97. if ($(this).hasClass('expanded')) {
  98. $(this).removeClass("expanded");
  99. $headerButton.attr('aria-expanded', 'false');
  100. } else {
  101. $allAccordionHeaders.removeClass("expanded");
  102. $(this).addClass("expanded");
  103. $allAccordionButtons.attr('aria-expanded', 'false');
  104. $headerButton.attr('aria-expanded', 'true');
  105. }
  106. event.stopImmediatePropagation();
  107. return false;
  108. });
  109. /* Toggle expand/collapse on enter and space */
  110. $allAccordionButtons.keypress(function( event ) {
  111. // Enter & Spacebar events
  112. if ( event.which === 13 || event.which === 32) {
  113. event.preventDefault();
  114. var $parentHeader = $(this).closest('.wh_main_page_toc_accordion_header');
  115. if ($parentHeader.hasClass('expanded')) {
  116. $parentHeader.removeClass("expanded");
  117. $(this).attr('aria-expanded', 'false');
  118. } else {
  119. $allAccordionHeaders.removeClass("expanded");
  120. $parentHeader.addClass("expanded");
  121. $allAccordionButtons.attr('aria-expanded', 'false');
  122. $(this).attr('aria-expanded', 'true');
  123. }
  124. }
  125. return false;
  126. });
  127. $(".wh_main_page_toc a").click(function(event) {
  128. event.stopImmediatePropagation();
  129. });
  130. highlightSearchTerm();
  131. /*
  132. * Codeblock copy to clipboard action
  133. */
  134. $('.codeblock').mouseover(function(){
  135. // WH-1806
  136. var item = $('<span class="copyTooltip wh-tooltip-container" data-tooltip-position="left"/>');
  137. if ( $(this).find('.copyTooltip').length == 0 ){
  138. $(this).prepend(item);
  139. $('.codeblock .copyTooltip').click(function(){
  140. var txt = $(this).closest(".codeblock").text();
  141. if(!txt || txt == ''){
  142. return;
  143. }
  144. copyTextToClipboard(txt, $(this));
  145. });
  146. }
  147. });
  148. $('.codeblock').mouseleave(function(){
  149. $(this).find('.copyTooltip').remove();
  150. });
  151. /**
  152. * @description Copy the text to the clipboard
  153. */
  154. function copyTextToClipboard(text, copyTooltipSpan) {
  155. var textArea = document.createElement("textarea");
  156. textArea.style.position = 'fixed';
  157. textArea.value = text;
  158. document.body.appendChild(textArea);
  159. textArea.select();
  160. try {
  161. var successful = document.execCommand('copy');
  162. // WH-1806
  163. if (copyTooltipSpan.find('.wh-tooltip').length == 0) {
  164. var tooltipContainer = $(
  165. '<span>' +
  166. ' <span class="wh-tooltip"><p class="wh-tooltip-content">Copied to clipboard</p></span>' +
  167. '</span>'
  168. );
  169. copyTooltipSpan.prepend(tooltipContainer);
  170. copyTooltipSpan.mouseleave(function() {
  171. tooltipContainer.remove();
  172. });
  173. setTimeout(function(){ tooltipContainer.remove();}, 3000);
  174. }
  175. } catch (err) {
  176. // Unable to copy
  177. if (copyTooltipSpan.find('.wh-tooltip').length == 0) {
  178. var tooltipContainer = $(
  179. '<span>' +
  180. ' <span class="wh-tooltip"><p class="wh-tooltip-content">Oops, unable to copy</p></span>' +
  181. '</span>'
  182. );
  183. copyTooltipSpan.mouseleave(function() {
  184. tooltipContainer.remove();
  185. });
  186. copyTooltipSpan.prepend(tooltipContainer);
  187. setTimeout(function(){ tooltipContainer.remove(); }, 3000);
  188. }
  189. // WH-1806
  190. //$('.copyTooltip').tooltip({title: 'Oops, unable to copy', trigger: "click"});
  191. util.debug('Oops, unable to copy codeblock content!', err)
  192. }
  193. document.body.removeChild(textArea);
  194. }
  195. /**
  196. * Check to see if the window is top if not then display button
  197. */
  198. $(window).scroll(function(){
  199. if ($(this).scrollTop() > 5) {
  200. $('#go2top').fadeIn('fast');
  201. } else {
  202. $('#go2top').fadeOut('fast');
  203. }
  204. });
  205. /**
  206. * Click event to scroll to top
  207. */
  208. $('#go2top').click(function(){
  209. $('html, body').animate({scrollTop : 0},800);
  210. return false;
  211. });
  212. });
  213. /**
  214. * @description Handle the vertical position of the side toc
  215. */
  216. function handleSideTocPosition(scrollPosition) {
  217. var scrollPosition = scrollPosition !== undefined ? scrollPosition : 0;
  218. var $sideToc = $(".wh_publication_toc");
  219. var $sideTocID = $("#wh_publication_toc");
  220. var $navSection = $(".wh_tools");
  221. var bottomNavOffset = 0;
  222. var $slideSection = $('#wh_topic_body');
  223. var topOffset = 20;
  224. var visibleAreaHeight = parseInt($(window).height()) - parseInt($(".wh_footer").outerHeight());
  225. if ($sideToc.length > 0 && $slideSection.length > 0) {
  226. var minVisibleOffset = $(window).scrollTop();
  227. var tocHeight = parseInt($sideToc.height()) + parseInt($sideToc.css("padding-top")) + parseInt($sideToc.css("padding-bottom")) + parseInt($sideToc.css("margin-top")) + parseInt($sideToc.css("margin-bottom"));
  228. var tocWidth = parseInt($sideTocID.outerWidth()) - parseInt($sideTocID.css("padding-left")) - parseInt($sideTocID.css("padding-right"));
  229. var tocXNav = parseInt($slideSection.offset().left) - tocWidth;
  230. if (scrollPosition > $(window).scrollTop()) {
  231. if ($sideToc.offset().top < $sideToc.parent().offset().top) {
  232. $sideToc.css('position', 'inherit');
  233. }
  234. } else {
  235. if (tocHeight > $(window).height()) {
  236. $sideToc.css('position', 'inherit');
  237. }
  238. }
  239. if ($navSection.length > 0) {
  240. bottomNavOffset = parseInt($navSection.offset().top) + parseInt($navSection.height()) + parseInt($navSection.css("padding-top")) + parseInt($navSection.css("padding-bottom")) + parseInt($navSection.css("margin-top")) + parseInt($navSection.css("margin-bottom"));
  241. }
  242. if (bottomNavOffset > minVisibleOffset) {
  243. minVisibleOffset = bottomNavOffset;
  244. }
  245. if (tocHeight <= visibleAreaHeight) {
  246. var cHeight = parseInt($('.wh_content_area').height());
  247. if (parseInt(minVisibleOffset - topOffset) <= $(window).scrollTop() && parseInt($(window).width()) > 767) {
  248. $('.wh_content_area').css('min-height', cHeight+'px');
  249. $sideToc.css("top", topOffset + "px").css("width", tocWidth + "px").css("position", "fixed").css("z-index", "999");
  250. } else {
  251. $sideToc.removeAttr('style');
  252. }
  253. } else {
  254. $sideToc.removeAttr('style');
  255. }
  256. scrollPosition = $(window).scrollTop();
  257. }
  258. return $(window).scrollTop();
  259. }
  260. /**
  261. * @description Highlight the current node in the page toc section on page scroll or clicking on Topic TOC items
  262. */
  263. function pageTocHighlightNode(scrollPosition) {
  264. var scrollPosition = scrollPosition !== undefined ? Math.round(scrollPosition) : 0;
  265. var topOffset = 150;
  266. var hash = location.hash != undefined ? location.hash : "";
  267. var hashOffTop = $(hash).offset() != undefined ? $(hash).offset().top : 0;
  268. var elemHashTop = hash != "" ? Math.round(hashOffTop) : 0;
  269. if( hash.substr(1) != '' && elemHashTop >= scrollPosition && (elemHashTop <= (scrollPosition + topOffset)) ){
  270. $('#wh_topic_toc a').removeClass('current_node');
  271. $('#wh_topic_toc a[data-tocid = "'+ hash.substr(1) + '"]').addClass('current_node');
  272. } else {
  273. $.each( $('.wh_topic_content .title'), function (e) {
  274. var currentId = $(this).parent().attr('id');
  275. var elemTop = Math.round($(this).offset().top);
  276. if( elemTop >= scrollPosition && (elemTop <= (scrollPosition + topOffset)) ){
  277. $('#wh_topic_toc a').removeClass('current_node');
  278. $('#wh_topic_toc a[data-tocid = "'+ currentId + '"]').addClass('current_node');
  279. }
  280. });
  281. }
  282. return $(window).scrollTop();
  283. }
  284. /**
  285. * @description Handle the vertical position of the page toc
  286. */
  287. function handlePageTocPosition(scrollPosition) {
  288. scrollPosition = scrollPosition !== undefined ? scrollPosition : 0;
  289. var $pageTOCID = $("#wh_topic_toc");
  290. var $pageTOC = $(".wh_topic_toc");
  291. var $navSection = $(".wh_tools");
  292. var bottomNavOffset = 0;
  293. var topOffset = 33;
  294. var $contentBody = $(".wh_topic_content");
  295. if ($pageTOC.length > 0) {
  296. pageTocHighlightNode(scrollPosition);
  297. var visibleAreaHeight = parseInt($(window).height()) - parseInt($(".wh_footer").outerHeight());
  298. var tocHeight = parseInt($pageTOC.height()) + parseInt($pageTOC.css("padding-top")) + parseInt($pageTOC.css("padding-bottom")) + parseInt($pageTOC.css("margin-top")) + parseInt($pageTOC.css("margin-bottom"));
  299. var tocWidth = parseInt($pageTOCID.outerWidth()) - parseInt($pageTOCID.css("padding-left")) - parseInt($pageTOCID.css("padding-right"));
  300. var minVisibleOffset = $(window).scrollTop();
  301. if ($navSection.length > 0) {
  302. bottomNavOffset = parseInt($navSection.offset().top) + parseInt($navSection.height()) + parseInt($navSection.css("padding-top")) + parseInt($navSection.css("padding-bottom")) + parseInt($navSection.css("margin-top")) + parseInt($navSection.css("margin-bottom"));
  303. }
  304. if (bottomNavOffset > minVisibleOffset) {
  305. minVisibleOffset = bottomNavOffset;
  306. }
  307. if ((tocHeight+topOffset) < visibleAreaHeight && (bottomNavOffset-topOffset) < $(window).scrollTop() && (tocHeight+topOffset) < $contentBody.height()) {
  308. if (parseInt(minVisibleOffset - topOffset) <= $(window).scrollTop() && parseInt($(window).width()) > 767) {
  309. $pageTOC.css("top", "20px").css("position", "fixed").css("width", tocWidth + "px").css("height", tocHeight + "px");
  310. } else {
  311. $pageTOC.removeAttr('style');
  312. }
  313. } else {
  314. $pageTOC.removeAttr('style');
  315. }
  316. }
  317. }
  318. /**
  319. * @description Highlight searched words
  320. */
  321. function highlightSearchTerm() {
  322. util.debug("highlightSearchTerm()");
  323. if (highlighted) {
  324. return;
  325. }
  326. try {
  327. var $body = $('.wh_topic_content');
  328. var $relatedLinks = $('.wh_related_links');
  329. var $childLinks = $('.wh_child_links');
  330. // Test if highlighter library is available
  331. if (typeof $body.removeHighlight != 'undefined') {
  332. $body.removeHighlight();
  333. $relatedLinks.removeHighlight();
  334. var hlParameter = util.getParameter('hl');
  335. if (hlParameter != undefined) {
  336. var jsonString = decodeURIComponent(String(hlParameter));
  337. util.debug("jsonString: ", jsonString);
  338. if (jsonString !== undefined && jsonString != "") {
  339. var words = jsonString.split(',');
  340. util.debug("words: ", words);
  341. for (var i = 0; i < words.length; i++) {
  342. util.debug('highlight(' + words[i] + ');');
  343. $body.highlight(words[i]);
  344. $relatedLinks.highlight(words[i]);
  345. $childLinks.highlight(words[i]);
  346. }
  347. }
  348. }
  349. } else {
  350. // JQuery highlights library is not loaded
  351. }
  352. }
  353. catch (e) {
  354. util.debug (e);
  355. }
  356. highlighted = true;
  357. }
  358. /*
  359. * Hide the highlight of the search results
  360. */
  361. $('.wh_hide_highlight').click(function(){
  362. $('.highlight').addClass('wh-h');
  363. $('.wh-h').toggleClass('highlight');
  364. $(this).toggleClass('hl-close');
  365. });
  366. /*
  367. * Show the highlight button only if 'hl' parameter is found
  368. */
  369. if( util.getParameter('hl')!= undefined ){
  370. $('.wh_hide_highlight').show();
  371. }
  372. var isTouchEnabled = false;
  373. try {
  374. if (document.createEvent("TouchEvent")) {
  375. isTouchEnabled = true;
  376. }
  377. } catch (e) {
  378. util.debug(e);
  379. }
  380. /**
  381. * Open the link from top_menu when the current group is expanded.
  382. *
  383. * Apply the events also on the dynamically generated elements.
  384. */
  385. $(document).on('click', ".wh_top_menu li", function (event) {
  386. $(".wh_top_menu li").removeClass('active');
  387. $(this).addClass('active');
  388. $(this).parents('li').addClass('active');
  389. event.stopImmediatePropagation();
  390. });
  391. $(document).on('click', '.wh_top_menu a', function (event) {
  392. var pointerType;
  393. if (typeof event.pointerType !== "undefined") {
  394. pointerType = event.pointerType;
  395. }
  396. if ($(window).width() < 767 || isTouchEnabled || pointerType == "touch") {
  397. var areaExpanded = $(this).closest('li');
  398. var isActive = areaExpanded.hasClass('active');
  399. var hasChildren = areaExpanded.hasClass('has-children');
  400. if (isActive || !hasChildren) {
  401. window.location = $(this).attr("href");
  402. event.preventDefault();
  403. event.stopImmediatePropagation();
  404. return false;
  405. } else {
  406. event.preventDefault();
  407. }
  408. } else {
  409. return true;
  410. }
  411. });
  412. });