blob: 0fac5748aad82548fce91716576cd5d9999ece79 [file] [edit]
"use strict";
function Menu() {
this.$toggle = document.getElementById('menu-toggle');
this.$menu = document.getElementById('menu');
this.$searchBox = document.getElementById('menu-search-box');
this.$searchResults = document.getElementById('menu-search-results');
this.initSearch();
this.$toggle.addEventListener('click', this.toggle.bind(this));
this.$searchBox.addEventListener('keydown', function (e) {
if (e.keyCode === 191 && e.target.value.length === 0) {
e.preventDefault();
e.stopPropagation();
} else if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
this.selectResult();
}
}.bind(this));
this.$searchBox.addEventListener('keyup', debounce(function (e) {
e.stopPropagation();
this.search(e.target.value);
}.bind(this)));
var tocItems = this.$menu.querySelectorAll('#menu-toc li');
for (var i = 0; i < tocItems.length; i++) {
var $item = tocItems[i];
$item.addEventListener('click', function($item, event) {
$item.classList.toggle('active');
event.stopPropagation();
}.bind(null, $item));
}
var tocLinks = this.$menu.querySelectorAll('#menu-toc li > a');
for (var i = 0; i < tocLinks.length; i++) {
var $link = tocLinks[i];
$link.addEventListener('click', function(event) {
this.toggle();
event.stopPropagation();
}.bind(this));
}
}
Menu.prototype.toggle = function () {
this.$menu.classList.toggle('active');
}
Menu.prototype.show = function () {
this.$menu.classList.add('active');
}
Menu.prototype.hide = function () {
this.$menu.classList.remove('active');
}
Menu.prototype.isVisible = function() {
return this.$menu.classList.contains('active');
}
Menu.prototype.initSearch = function () {
var $biblio = document.getElementById('menu-search-biblio');
if (!$biblio) {
this.biblio = {};
} else {
this.biblio = JSON.parse($biblio.textContent);
}
this.biblio.ops = this.biblio.filter(function (e) { return e.type === 'op' });
this.biblio.clauses = this.biblio.filter(function (e) { return e.type === 'clause' });
this.biblio.productions = this.biblio.filter(function (e) { return e.type === 'production' });
document.addEventListener('keydown', function (e) {
if (e.keyCode === 191) {
e.preventDefault();
e.stopPropagation();
if(this.isVisible()) {
this._closeAfterSearch = false;
} else {
this._closeAfterSearch = true;
this.show();
}
this.show();
this.$searchBox.focus();
}
}.bind(this))
}
Menu.prototype.search = function (needle) {
if (needle.length < 2) {
this.hideSearch();
} else {
this.showSearch();
}
needle = needle.toLowerCase();
var results = {};
var seenClauses = {};
results.ops = this.biblio.ops.filter(function(op) {
return fuzzysearch(needle, op.aoid.toLowerCase());
});
results.ops.forEach(function(op) {
seenClauses[op.refId] = true;
});
results.productions = this.biblio.productions.filter(function(prod) {
return fuzzysearch(needle, prod.name.toLowerCase());
});
results.clauses = this.biblio.clauses.filter(function(clause) {
return !seenClauses[clause.id] && (clause.number.indexOf(needle) === 0 || fuzzysearch(needle, clause.title.toLowerCase()));
});
if (results.length > 50) {
results = results.slice(0, 50);
}
this.displayResults(results);
}
Menu.prototype.displayResults = function (results) {
var totalResults = Object.keys(results).reduce(function (sum, record) { return sum + record.length }, 0);
if (totalResults > 0) {
this.$searchResults.classList.remove('no-results');
var html = '<ul>';
results.ops.forEach(function (op) {
html += '<li class=menu-search-result-op><a href="#' + op.refId + '">' + op.aoid + '</a></li>'
});
results.productions.forEach(function (prod) {
html += '<li class=menu-search-result-prod><a href="#' + prod.id + '">' + prod.name + '</a></li>'
});
results.clauses.forEach(function (clause) {
html += '<li class=menu-search-result-clause><a href="#' + clause.id + '">' + clause.number + ' ' + clause.title + '</a></li>'
})
html += '</ul>'
this.$searchResults.innerHTML = html;
} else {
this.$searchResults.classList.add('no-results');
}
}
Menu.prototype.hideSearch = function () {
this.$searchResults.classList.add('inactive');
}
Menu.prototype.showSearch = function () {
this.$searchResults.classList.remove('inactive');
}
Menu.prototype.selectResult = function () {
var $first = this.$searchResults.querySelector('li:first-child a');
if ($first) {
document.location = $first.getAttribute('href');
}
this.$searchBox.value = '';
this.$searchBox.blur();
this.hideSearch();
if (this._closeAfterSearch) {
this.hide();
}
}
function init() {
var menu = new Menu();
}
document.addEventListener('DOMContentLoaded', init);
function debounce(fn) {
var timeout;
return function() {
var args = arguments;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function() {
timeout = null;
fn.apply(this, args);
}.bind(this), 150);
}
}
// The following license applies to the fuzzysearch function
// The MIT License (MIT)
// Copyright © 2015 Nicolas Bevacqua
// 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.
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var CLAUSE_NODES = ['EMU-CLAUSE', 'EMU-INTRO', 'EMU-ANNEX'];
function findLocalReferences ($elem) {
var name = $elem.innerHTML;
var references = [];
var parentClause = $elem.parentNode;
while (parentClause && CLAUSE_NODES.indexOf(parentClause.nodeName) === -1) {
parentClause = parentClause.parentNode;
}
if(!parentClause) return;
var vars = parentClause.querySelectorAll('var');
for (var i = 0; i < vars.length; i++) {
var $var = vars[i];
if ($var.innerHTML === name) {
references.push($var);
}
}
return references;
}
function toggleFindLocalReferences($elem) {
var references = findLocalReferences($elem);
if ($elem.classList.contains('referenced')) {
references.forEach(function ($reference) {
$reference.classList.remove('referenced');
});
} else {
references.forEach(function ($reference) {
$reference.classList.add('referenced');
});
}
}
function installFindLocalReferences () {
document.addEventListener('click', function (e) {
if (e.target.nodeName === 'VAR') {
toggleFindLocalReferences(e.target);
}
});
}
document.addEventListener('DOMContentLoaded', installFindLocalReferences);