7e5ead2016-01-20Pontus Östlund /* jshint undef: true, unused: true */
6c86912016-04-30Pontus Östlund /* globals window, document, requestAnimationFrame */
7e5ead2016-01-20Pontus Östlund /* exported PikeDoc */ var PikeDoc = null; if (!window.console) {
8992682016-04-29Henrik Grubbström (Grubba)  window.console = { log: function(){}, error: function(){} };
7e5ead2016-01-20Pontus Östlund } /* Encapsulate so we don't clutter the global scope */
0e3f092016-04-19Henrik Grubbström (Grubba) (function(window, document) {
7e5ead2016-01-20Pontus Östlund 'use strict';
0780872016-10-04Pontus Östlund var doDebug = false; var isdebug = document.location.search.indexOf('debug=1') > -1 || doDebug; var wdebug = isdebug ? window.console.log : function(){};
7e5ead2016-01-20Pontus Östlund // The scroll position at which the navbar sticks. This actually gets // calculated dynamically upon page load. var stickyScrollBreak = 70,
0e3f092016-04-19Henrik Grubbström (Grubba)  // Window width when we go to mobile mode mobileBreakPoint = 800, // The navbar to the left, HTMLElement navbar, innerNavbar, // Content wrapper, HTMLElement content,
8992682016-04-29Henrik Grubbström (Grubba)  // The page footer footer,
0e3f092016-04-19Henrik Grubbström (Grubba)  // The height of the navbar navbarHeight, // The height of the window windowHeight, // The height of the header headerHeight, // The height of the footer footerHeight, // The menu hamburger when in mobile mode burger, // Optimization® objectKeys = Object.keys, // Functions to run when DOM is ready onDOMReadyQueue = [];
7e5ead2016-01-20Pontus Östlund  // Hide the navbox when on the start page where the prev and next links // doesn't lead anywhere function maybeHideNavbox() { var navbox = document.getElementsByClassName('navbox')[0]; var prev = navbox.getElementsByClassName('prev')[0]; var next = navbox.getElementsByClassName('next')[0]; prev = prev.getAttribute('href'); next = next.getAttribute('href'); if (!next && !prev) { navbox.style.display = 'none'; hideTopLink(); } } // And if on the start page hide the Top link in the side navbar function hideTopLink() { var top = document.getElementsByClassName('top head'); top[0].style.display = 'none'; } // Called when DOM is ready function onPageLoad() {
0780872016-10-04Pontus Östlund  var versionElems, dateElems, i, max;
0e3f092016-04-19Henrik Grubbström (Grubba) 
7e5ead2016-01-20Pontus Östlund  maybeHideNavbox(); navbar = document.getElementsByClassName('navbar')[0]; content = document.getElementsByClassName('content')[0];
8992682016-04-29Henrik Grubbström (Grubba)  footer = document.getElementsByTagName('footer')[0]; footerHeight = footer.offsetHeight;
7e5ead2016-01-20Pontus Östlund  windowHeight = window.outerHeight; headerHeight = document.getElementsByTagName('header')[0].offsetHeight; navbarHeight = windowHeight - content.offsetTop - footerHeight; innerNavbar = document.getElementById('navbar'); burger = document.getElementById('burger');
0e3f092016-04-19Henrik Grubbström (Grubba)  // When the doc is compiled with FLAG_NO_DYNAMIC the version and publish date
0780872016-10-04Pontus Östlund  // will not be written to the pages but inserted with JS. If the NO_DYNAMIC // symbol is true we need to put the version and pubdate in the elements with
0e3f092016-04-19Henrik Grubbström (Grubba)  // attributes data-id="version" and data-id="date".
0780872016-10-04Pontus Östlund  if (PikeDoc.NO_DYNAMIC) {
0e3f092016-04-19Henrik Grubbström (Grubba)  versionElems = document.querySelectorAll('[data-id="version"]'); dateElems = document.querySelectorAll('[data-id="date"]');
0780872016-10-04Pontus Östlund  max = Math.max(versionElems.length, dateElems.length);
0e3f092016-04-19Henrik Grubbström (Grubba) 
0780872016-10-04Pontus Östlund  for (i = 0; i < max; i++) { if (versionElems[i] !== undefined) { versionElems[i].innerHTML = PikeDoc.VERSION; } if (dateElems[i] !== undefined) { dateElems[i].innerHTML = PikeDoc.PUBDATE; }
0e3f092016-04-19Henrik Grubbström (Grubba)  } }
7e5ead2016-01-20Pontus Östlund  stickyScrollBreak = headerHeight; } var iAmSticky;
0e3f092016-04-19Henrik Grubbström (Grubba) // Invoked when DOM is ready, and use as callback for onscroll.
7e5ead2016-01-20Pontus Östlund function onPageScroll() { // If scrollY is larger than the sticky position ... if (window.scrollY > stickyScrollBreak) { // ... see if we're already sticky and return if so ... if (iAmSticky) { return; } // ... or else set to sticky. iAmSticky = true;
8992682016-04-29Henrik Grubbström (Grubba)  content.style.minHeight = (windowHeight - headerHeight) + 'px';
7e5ead2016-01-20Pontus Östlund  navbar.classList.add('sticky'); } // If scrollY is less than the sticky position ... else { // ... see if we're explicitly non-sticky and return if so ... if (iAmSticky === false) { return; } // ... else set to explicitly non-sticky iAmSticky = false; navbar.classList.remove('sticky'); content.style.minHeight = 0; } } var iAmScrolled; function onMobilePageScroll() { if (window.scrollY > 1) { if (iAmScrolled) { return; } iAmScrolled = true; document.body.classList.add('scrolled'); } else { if (iAmScrolled === false) { return; } iAmScrolled = false; document.body.classList.remove('scrolled'); } } function onBurgerClick() { document.body.classList.toggle('menu-open'); return false; } function setMobileMode() { document.removeEventListener('scroll', onPageScroll);
0e3f092016-04-19Henrik Grubbström (Grubba)  document.addEventListener('scroll', onMobilePageScroll, false);
7e5ead2016-01-20Pontus Östlund  burger.removeEventListener('click', onBurgerClick);
0e3f092016-04-19Henrik Grubbström (Grubba)  burger.addEventListener('click', onBurgerClick, false);
7e5ead2016-01-20Pontus Östlund  navbar.classList.remove('sticky'); iAmSticky = false; } function setDesktopMode() { document.removeEventListener('scroll', onMobilePageScroll);
0e3f092016-04-19Henrik Grubbström (Grubba)  document.addEventListener('scroll', onPageScroll, false);
7e5ead2016-01-20Pontus Östlund  burger.removeEventListener('click', onBurgerClick); document.body.classList.remove('menu-open'); } var iAmMobile = false; function onWindowResize() { if (document.body.offsetWidth < mobileBreakPoint) { if (iAmMobile) { return; } iAmMobile = true; document.body.classList.add('mobile'); setMobileMode(); } else { if (iAmMobile === false) { return; } iAmMobile = false; document.body.classList.remove('mobile'); setDesktopMode(); } } // We only care about fairly modern browsers if (document.addEventListener) { // Fire when the DOM is ready
0e3f092016-04-19Henrik Grubbström (Grubba)  document.addEventListener('DOMContentLoaded', function() {
7e5ead2016-01-20Pontus Östlund  onPageLoad(); cacheFactory.setMenu(); PikeDoc.domReady(true); onWindowResize();
0e3f092016-04-19Henrik Grubbström (Grubba)  window.addEventListener('resize', onWindowResize, false); document.addEventListener('scroll', iAmMobile ? onMobilePageScroll : onPageScroll, false); }, false);
7e5ead2016-01-20Pontus Östlund } // During a session each generated menu is cached locally in a sessionStorage // (if available). This one handles that. var cacheFactory = (function() {
8992682016-04-29Henrik Grubbström (Grubba)  // Don't use cache if the page isn't served through a server. // The cache seems buggy as hell when the pages are view directly from // the file system. var cache = document.location.hostname && window.sessionStorage;
7e5ead2016-01-20Pontus Östlund  var m, isChecked = false;
0e3f092016-04-19Henrik Grubbström (Grubba) 
7e5ead2016-01-20Pontus Östlund  function init() {
0e3f092016-04-19Henrik Grubbström (Grubba)  if (m || PikeDoc.current.link === 'index.html') { return true; }
0780872016-10-04Pontus Östlund  if (!cache || (isChecked && !m)) {
0e3f092016-04-19Henrik Grubbström (Grubba)  return false;
7e5ead2016-01-20Pontus Östlund  }
0e3f092016-04-19Henrik Grubbström (Grubba) 
8992682016-04-29Henrik Grubbström (Grubba)  m = cache.getItem(PikeDoc.current.link);
7e5ead2016-01-20Pontus Östlund  isChecked = true;
0e3f092016-04-19Henrik Grubbström (Grubba) 
8992682016-04-29Henrik Grubbström (Grubba)  if (m) { m = JSON.parse(m); var ok = validateDate(m.time); if (!ok) { isChecked = false; cache.removeItem(PikeDoc.current.link); }
0780872016-10-04Pontus Östlund 
8992682016-04-29Henrik Grubbström (Grubba)  return ok; }
0780872016-10-04Pontus Östlund  return false;
7e5ead2016-01-20Pontus Östlund  }
0e3f092016-04-19Henrik Grubbström (Grubba)  function validateDate(time) { return getPubDate() < new Date(time); } function getPubDate() {
0780872016-10-04Pontus Östlund  return new Date(PikeDoc.GENERATED*1000);
0e3f092016-04-19Henrik Grubbström (Grubba)  }
7e5ead2016-01-20Pontus Östlund  function store() { if (cache) {
0e3f092016-04-19Henrik Grubbström (Grubba)  var obj = {
6c86912016-04-30Pontus Östlund  time: Date.now(),
0e3f092016-04-19Henrik Grubbström (Grubba)  value: innerNavbar.innerHTML }; cache.setItem(PikeDoc.current.link||'root', JSON.stringify(obj));
7e5ead2016-01-20Pontus Östlund  } } function setMenu() {
8992682016-04-29Henrik Grubbström (Grubba)  if (m && validateDate(m.time)) {
6c86912016-04-30Pontus Östlund  //window.console.log('Set menu');
0e3f092016-04-19Henrik Grubbström (Grubba)  innerNavbar.innerHTML = m.value;
6c86912016-04-30Pontus Östlund  requestAnimationFrame(function() { innerNavbar.querySelector('.sidebar').classList.remove('init'); });
7e5ead2016-01-20Pontus Östlund  } } return { hasCache: init, store: store, setMenu: setMenu }; }()); // Create a document element // // @param string name // Tag name // @param object|string attr // If a string treated as a text node, otherwise as tag attributes // @param string text function createElem(name, attr, text) { var e = document.createElement(name); if (attr && typeof attr === 'object') { objectKeys(attr).forEach(function(k) { e.setAttribute(k, attr[k]); }); } else if (typeof attr === 'string') { e.appendChild(document.createTextNode(attr)); } if (text) { e.appendChild(document.createTextNode(text)); } return e; } var helpers = (function() { // Returns basedir of `path` function basedir(path) { var i = path.lastIndexOf('/'); if (i < 1) return ''; return path.substring(0, i); } // Check if `other` starts with `prefix` function hasPrefix(prefix, other) { return other.substring(0, prefix.length) === prefix; } function adjustLink(link) { var reldir = basedir(PikeDoc.current.link); var dots = ''; while (reldir !== '' && !hasPrefix(link, reldir + '/')) { dots += '../'; reldir = basedir(reldir); } return dots + link.substring(reldir.length); } // Merge two sets of nodes. If a node exists in both `oldNodes` and // `newNodes` the latter will overwrite the former. function mergeChildren(oldNodes, newNodes) { var hash = {}; oldNodes.forEach(function(n) { hash[n.name] = n; }); newNodes.forEach(function(n) { var j = hash[n.name]; if (j) j = n; else hash[n.name] = n; }); return objectKeys(hash).map(function(k) { return hash[k]; }) .sort(function(a, b) { return (a.name > b.name) - (b.name > a.name); }); } return { basedir: basedir, hasPrefix: hasPrefix, adjustLink: adjustLink, mergeChildren: mergeChildren }; }());
0e3f092016-04-19Henrik Grubbström (Grubba) // Main object for generating the navigation
7e5ead2016-01-20Pontus Östlund PikeDoc = (function() { var symbols = [], symbolsMap = {}, endInherits = [], inheritList = [], isDomReady = false, isAllLoaded = false, isInline = true, current; function Symbol(name) { this.name = name; this._children = {}; this.children = []; } Symbol.prototype = { addChildren: function(type, children) { this._children[type] = children; return this; }, finish: function() { var my = this;
0e3f092016-04-19Henrik Grubbström (Grubba)  // window.console.log('### Symbol.finish(', this.name, ')');
7e5ead2016-01-20Pontus Östlund  objectKeys(this._children).forEach(function(k) { my.children = my.children.concat(my._children[k]); }); lowSetInherit(); }, setInherited: function() { this.children.forEach(function(c) { c.inherited = 1; }); } }; function lowSetInherit() { endInherits = endInherits.filter(function(a) { var ss = symbolsMap[a]; if (ss) { ss.setInherited(); return false; } return true; }); } /* This is called from the generated javascripts (index.js) that's being * loaded on the fly. * * @param string name * The name of the symbol (Namespace, module e.t.c) * @param boolean isInline * Is this being called from a script loaded directly in the page * or being called from a loaded script. */ function registerSymbol(name, isInline) { // Only the parent namespace/module/class is loaded inline, and we don't // care about that one. Also, when on the TOP page the navigation is // written to the page, so we don't care for that either. if (isInline || !name) { return new Symbol(name); } var s = new Symbol(name); symbols.push(s);
6c86912016-04-30Pontus Östlund  //window.console.log(' + Register symbol: ', name);
7e5ead2016-01-20Pontus Östlund  symbolsMap[name] = s; return s; } function endInherit(which) { endInherits.push(which); } function addInherit(which) { inheritList = inheritList.concat(which); } var types = {}; function finish() {
0e3f092016-04-19Henrik Grubbström (Grubba)  // window.console.log('finish(', endInherits.length, ')');
7e5ead2016-01-20Pontus Östlund  if (endInherits.length === 0) { var merge = helpers.mergeChildren; objectKeys(symbolsMap).forEach(function(k) { var ch = symbolsMap[k]._children; objectKeys(ch).forEach(function(sk) { types[sk] = merge(types[sk]||[], ch[sk]); }); }); isAllLoaded = true; maybeRenderNavbar(); } } var jsMap = {};
0e3f092016-04-19Henrik Grubbström (Grubba)  var scriptQueue = 0;
8992682016-04-29Henrik Grubbström (Grubba) 
7e5ead2016-01-20Pontus Östlund  function loadScript(link, namespace, inherits) {
0780872016-10-04Pontus Östlund  wdebug('load: ', link);
7e5ead2016-01-20Pontus Östlund  if (cacheFactory.hasCache()) { return; } link = helpers.adjustLink(link); // Already loaded if (jsMap[link]) {
0780872016-10-04Pontus Östlund  wdebug('Already loaded: ', link);
7e5ead2016-01-20Pontus Östlund  return; }
0780872016-10-04Pontus Östlund  wdebug('+++ Load:', link);
0e3f092016-04-19Henrik Grubbström (Grubba) 
7e5ead2016-01-20Pontus Östlund  jsMap[link] = true; if (inherits) { addInherit(inherits); }
0e3f092016-04-19Henrik Grubbström (Grubba)  scriptQueue += 1;
7e5ead2016-01-20Pontus Östlund  var s = createElem('script', { src: link });
0e3f092016-04-19Henrik Grubbström (Grubba)  //s.async = false;
7e5ead2016-01-20Pontus Östlund  document.head.appendChild(s); (function(scr, ns) { scr.addEventListener('load', function() {
0e3f092016-04-19Henrik Grubbström (Grubba)  scriptQueue -= 1;
7e5ead2016-01-20Pontus Östlund  if (ns) { if (ns === true) { finish(); } else { endInherit(ns); } }
0e3f092016-04-19Henrik Grubbström (Grubba)  else { finish(); } }, false);
7e5ead2016-01-20Pontus Östlund  }(s, namespace)); } function domReady() { isDomReady = true;
0e3f092016-04-19Henrik Grubbström (Grubba)  onDOMReadyQueue.forEach(function(f) { if (typeof f === 'function') { f(); } });
7e5ead2016-01-20Pontus Östlund  maybeRenderNavbar(); } function lowNavbar(container, heading, nodes, suffix) {
6c86912016-04-30Pontus Östlund  if (!nodes || !nodes.length) {
7e5ead2016-01-20Pontus Östlund  return;
6c86912016-04-30Pontus Östlund  }
7e5ead2016-01-20Pontus Östlund 
0e3f092016-04-19Henrik Grubbström (Grubba)  var curlnk = PikeDoc.current.link;
7e5ead2016-01-20Pontus Östlund  var adjlnk = helpers.adjustLink;
0e3f092016-04-19Henrik Grubbström (Grubba)  var c = container; var div = createElem('div', { style: 'margin-left:0.5em' });
7e5ead2016-01-20Pontus Östlund  nodes.forEach(function(n) { var name, tnode, tmp; name = n.name + suffix; tnode = document.createTextNode(name); if (!n.inherited) { tnode = createElem('b', name); }
0e3f092016-04-19Henrik Grubbström (Grubba)  if (n.link !== curlnk) {
7e5ead2016-01-20Pontus Östlund  tmp = createElem('a', { href: adjlnk(n.link) }); tmp.appendChild(tnode); tnode = tmp; }
6c86912016-04-30Pontus Östlund  if (n.modifiers) { n.modifiers.forEach(function(mod) { if (n.name !== 'create') { tnode.classList.add('mod-' + mod); } }); }
7e5ead2016-01-20Pontus Östlund  div.appendChild(tnode); }); c.appendChild(createElem('b', { class: 'heading' }, heading)); c.appendChild(div); } /* Render the left navigation bar. */ function navbar() {
6c86912016-04-30Pontus Östlund  var s = createElem('div', { class: 'sidebar init' });
8992682016-04-29Henrik Grubbström (Grubba)  // If the cache already has set the menu, then clear it. The cache is // almost certainly run before this method. var old = innerNavbar.querySelectorAll('.sidebar'); var i, tmp; if (old.length) {
0780872016-10-04Pontus Östlund  wdebug('Clear cached menu and regenerate', old);
8992682016-04-29Henrik Grubbström (Grubba)  for (i = 0; i < old.length; i++) { tmp = old[i]; tmp.parentNode.removeChild(tmp); } }
7e5ead2016-01-20Pontus Östlund  innerNavbar.appendChild(s); lowNavbar(s, 'Modules', types.module, ''); lowNavbar(s, 'Classes', types.class, ''); lowNavbar(s, 'Enums', types.enum, ''); lowNavbar(s, 'Directives', types.directive, ''); lowNavbar(s, 'Methods', types.method, '()'); lowNavbar(s, 'Operators', types.operator, '()'); lowNavbar(s, 'Members', types.member, '()'); lowNavbar(s, 'Namespaces', types.namespace, '::'); lowNavbar(s, 'Appendices', types.appendix, ''); cacheFactory.store(); } function maybeRenderNavbar() {
0780872016-10-04Pontus Östlund  wdebug('maybeRenderNavbar(', isAllLoaded, isDomReady, scriptQueue, ')');
0e3f092016-04-19Henrik Grubbström (Grubba)  if (isAllLoaded && isDomReady && scriptQueue === 0) {
7e5ead2016-01-20Pontus Östlund  navbar();
6c86912016-04-30Pontus Östlund  requestAnimationFrame(function() { innerNavbar.querySelector('.sidebar').classList.remove('init'); });
7e5ead2016-01-20Pontus Östlund  } }
0e3f092016-04-19Henrik Grubbström (Grubba)  (function() { // If the refdoc lives in pike.lysator.liu.se we add some custom Google // searchability. if (document.location.hostname === 'pike.lysator.liu.se' || document.location.hostname === 'pike.local') // for dev purposes { onDOMReadyQueue.push(function() { // When this is run on pike.lysator.liu.se the script below will replace // the content of #version with a search field. Since the script below // is loaded async there might be the case where the version is // briefly shown before it's replaced, which will produce an unpleasant // flicker. This hack will minimize that "unpleasantry". var v = document.getElementById('version'); if (!v.classList.contains('search')) { v.innerHTML = ''; } }); var s = document.getElementsByTagName('script')[0]; var el = createElem('script', { src: '/assets/js/local/refdoc-search.min.js', async: true }); s.parentNode.insertBefore(el, s);
8992682016-04-29Henrik Grubbström (Grubba)  var el2 = createElem('script', { src: '/assets/js/local/disqus.min.js', async: true }); s.parentNode.insertBefore(el2, s);
0e3f092016-04-19Henrik Grubbström (Grubba)  var f = createElem('link', {
8992682016-04-29Henrik Grubbström (Grubba)  href: '/assets/img/favicon.png',
0e3f092016-04-19Henrik Grubbström (Grubba)  rel: 'shortcut icon' }); document.head.appendChild(f); } }());
7e5ead2016-01-20Pontus Östlund  return { registerSymbol: registerSymbol, endInherit: endInherit, loadScript: loadScript, domReady: domReady, isInline: isInline, current: current,
0780872016-10-04Pontus Östlund  finish: finish
7e5ead2016-01-20Pontus Östlund  }; }());
0780872016-10-04Pontus Östlund // This is explicitly set to false in the HTML page if the docs are generated // with inlined Pike version and timestamp. PikeDoc.FLAG_NO_DYNAMIC = true;
0e3f092016-04-19Henrik Grubbström (Grubba) }(window, document));