1d7d00a41SKrystof Tulinger/* 2d7d00a41SKrystof Tulinger * CDDL HEADER START 3d7d00a41SKrystof Tulinger * 4d7d00a41SKrystof Tulinger * The contents of this file are subject to the terms of the 5d7d00a41SKrystof Tulinger * Common Development and Distribution License (the "License"). 6d7d00a41SKrystof Tulinger * You may not use this file except in compliance with the License. 7d7d00a41SKrystof Tulinger * 8d7d00a41SKrystof Tulinger * See LICENSE.txt included in this distribution for the specific 9d7d00a41SKrystof Tulinger * language governing permissions and limitations under the License. 10d7d00a41SKrystof Tulinger * 11d7d00a41SKrystof Tulinger * When distributing Covered Code, include this CDDL HEADER in each 12d7d00a41SKrystof Tulinger * file and include the License file at LICENSE.txt. 13d7d00a41SKrystof Tulinger * If applicable, add the following below this CDDL HEADER, with the 14d7d00a41SKrystof Tulinger * fields enclosed by brackets "[]" replaced with your own identifying 15d7d00a41SKrystof Tulinger * information: Portions Copyright [yyyy] [name of copyright owner] 16d7d00a41SKrystof Tulinger * 17d7d00a41SKrystof Tulinger * CDDL HEADER END 18d7d00a41SKrystof Tulinger */ 19d7d00a41SKrystof Tulinger 20d7d00a41SKrystof Tulinger/* 21d7d00a41SKrystof Tulinger * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. 22d7d00a41SKrystof Tulinger * Portions Copyright 2011 Jens Elkner. 23d7d00a41SKrystof Tulinger * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>. 24587e9867SKrystof Tulinger * Portions Copyright (c) 2022, Krystof Tulinger <k.tulinger@seznam.cz>. 25d7d00a41SKrystof Tulinger */ 26d7d00a41SKrystof Tulinger 27d7d00a41SKrystof Tulinger/** 28d7d00a41SKrystof Tulinger * Spaces plugin. 29d7d00a41SKrystof Tulinger * 30d7d00a41SKrystof Tulinger * Inserts a dummy space between line number and the text so that on copy-paste 31d7d00a41SKrystof Tulinger * the white space is preserved. 32d7d00a41SKrystof Tulinger * 33d7d00a41SKrystof Tulinger * Internally listens on scroll events and autofills the spaces only for the visible 34d7d00a41SKrystof Tulinger * elements. 35d7d00a41SKrystof Tulinger * 36d7d00a41SKrystof Tulinger * IMPORTANT: This plugin is strictly dependent on ascending order of lines 37d7d00a41SKrystof Tulinger * and on their attribute "name". It performs a binary search which boosts performance 38d7d00a41SKrystof Tulinger * of this plugin for really long files. 39d7d00a41SKrystof Tulinger * 40d7d00a41SKrystof Tulinger * @author Krystof Tulinger 41d7d00a41SKrystof Tulinger */ 42d7d00a41SKrystof Tulinger(function (w, $) { 43d7d00a41SKrystof Tulinger const spaces = function () { 44d7d00a41SKrystof Tulinger const inner = { 45d7d00a41SKrystof Tulinger defaults: { 46d7d00a41SKrystof Tulinger interval: 750, 47d7d00a41SKrystof Tulinger selector: "a.l, a.hl", 48d7d00a41SKrystof Tulinger $parent: null, 49d7d00a41SKrystof Tulinger callback: function () { 50d7d00a41SKrystof Tulinger if (!$(this).hasClass("selected")) { 51d7d00a41SKrystof Tulinger $(this).addClass("selected"); 52d7d00a41SKrystof Tulinger $(this).text($(this).text() + " "); 53d7d00a41SKrystof Tulinger } 54d7d00a41SKrystof Tulinger } 55d7d00a41SKrystof Tulinger }, 56d7d00a41SKrystof Tulinger options: {}, 57d7d00a41SKrystof Tulinger $collection: $(), 58d7d00a41SKrystof Tulinger initialized: false, 59d7d00a41SKrystof Tulinger lock: false, 60d7d00a41SKrystof Tulinger binarySearch: function (array, key, compare) { 61d7d00a41SKrystof Tulinger let lo = 0; 62d7d00a41SKrystof Tulinger let hi = array.length - 1; 63d7d00a41SKrystof Tulinger while (lo <= hi) { 64d7d00a41SKrystof Tulinger const mid = ((lo + hi) >> 1); 65d7d00a41SKrystof Tulinger const cmp = compare(array[mid], key); 66d7d00a41SKrystof Tulinger if (cmp === 0) { 67d7d00a41SKrystof Tulinger return mid; 68d7d00a41SKrystof Tulinger } else if (cmp < 0) { 69d7d00a41SKrystof Tulinger lo = mid + 1; 70d7d00a41SKrystof Tulinger } else { 71d7d00a41SKrystof Tulinger hi = mid - 1; 72d7d00a41SKrystof Tulinger } 73d7d00a41SKrystof Tulinger } 74d7d00a41SKrystof Tulinger return -1; 75d7d00a41SKrystof Tulinger }, 76d7d00a41SKrystof Tulinger handleScrollEvent: function () { 77d7d00a41SKrystof Tulinger inner.lock = false; 78d7d00a41SKrystof Tulinger 79d7d00a41SKrystof Tulinger const myOffset = inner.$collection.first().offset() ? inner.$collection.first().offset().top : 0; 80d7d00a41SKrystof Tulinger const myHeight = inner.$collection.first().height() || 0; 81d7d00a41SKrystof Tulinger const parentOffset = inner.options.$parent.offset() ? inner.options.$parent.offset().top : 0; 82d7d00a41SKrystof Tulinger const parentHeight = inner.options.$parent.height() || 0; 83d7d00a41SKrystof Tulinger 84d7d00a41SKrystof Tulinger const expectations = { 85d7d00a41SKrystof Tulinger // the first element in viewport 86d7d00a41SKrystof Tulinger start: Math.floor(Math.abs(Math.min(myOffset - parentOffset, 0)) / myHeight), 87d7d00a41SKrystof Tulinger // the last element in viewport 88d7d00a41SKrystof Tulinger end: Math.ceil((Math.abs(Math.min(myOffset - parentOffset, 0)) + parentHeight) / myHeight) 89d7d00a41SKrystof Tulinger }; 90d7d00a41SKrystof Tulinger 91d7d00a41SKrystof Tulinger const indices = { 92d7d00a41SKrystof Tulinger start: 0, 93d7d00a41SKrystof Tulinger end: inner.$collection.length 94d7d00a41SKrystof Tulinger }; 95d7d00a41SKrystof Tulinger 96d7d00a41SKrystof Tulinger const cmp = function (a, key) { 97d7d00a41SKrystof Tulinger return $(a).attr("name") - key; // comparing the "name" attribute with the desired value 98d7d00a41SKrystof Tulinger }; 99d7d00a41SKrystof Tulinger 100d7d00a41SKrystof Tulinger 101d7d00a41SKrystof Tulinger indices.start = inner.binarySearch(inner.$collection, expectations.start, cmp); 102d7d00a41SKrystof Tulinger indices.end = inner.binarySearch(inner.$collection, expectations.end, cmp); 103d7d00a41SKrystof Tulinger 104d7d00a41SKrystof Tulinger /** cutoffs */ 105d7d00a41SKrystof Tulinger indices.start = Math.max(0, indices.start); 106d7d00a41SKrystof Tulinger indices.start = Math.min(inner.$collection.length - 1, indices.start); 107d7d00a41SKrystof Tulinger 108d7d00a41SKrystof Tulinger if (indices.end === -1) { 109d7d00a41SKrystof Tulinger indices.end = inner.$collection.length - 1; 110d7d00a41SKrystof Tulinger } 111d7d00a41SKrystof Tulinger indices.end = Math.min(inner.$collection.length - 1, indices.end); 112d7d00a41SKrystof Tulinger 113d7d00a41SKrystof Tulinger /** calling callback for every element in the viewport */ 114d7d00a41SKrystof Tulinger for (var i = indices.start; i <= indices.end; i++) { 115d7d00a41SKrystof Tulinger inner.options.callback.apply(inner.$collection[i]); 116d7d00a41SKrystof Tulinger } 117d7d00a41SKrystof Tulinger }, 118d7d00a41SKrystof Tulinger init: function () { 119d7d00a41SKrystof Tulinger 120d7d00a41SKrystof Tulinger if (inner.initialized) { 121d7d00a41SKrystof Tulinger return; 122d7d00a41SKrystof Tulinger } 123d7d00a41SKrystof Tulinger 124d7d00a41SKrystof Tulinger inner.$collection = inner.options.$parent.find(inner.options.selector); 125d7d00a41SKrystof Tulinger 126d7d00a41SKrystof Tulinger if (inner.$collection.length <= 0) { 127d7d00a41SKrystof Tulinger return; 128d7d00a41SKrystof Tulinger } 129d7d00a41SKrystof Tulinger 130d7d00a41SKrystof Tulinger const scrollHandler = function (e) { 131d7d00a41SKrystof Tulinger if (inner.lock) { 132d7d00a41SKrystof Tulinger return; 133d7d00a41SKrystof Tulinger } 134d7d00a41SKrystof Tulinger inner.lock = true; 135d7d00a41SKrystof Tulinger setTimeout(inner.handleScrollEvent, inner.options.interval); 136d7d00a41SKrystof Tulinger }; 137d7d00a41SKrystof Tulinger // fire the event if user has not scrolled 138d7d00a41SKrystof Tulinger inner.options.$parent.scroll(scrollHandler).resize(scrollHandler).scroll(); 139d7d00a41SKrystof Tulinger inner.initialized = true; 140d7d00a41SKrystof Tulinger } 141d7d00a41SKrystof Tulinger }; 142d7d00a41SKrystof Tulinger 143d7d00a41SKrystof Tulinger this.init = function (options) { 144d7d00a41SKrystof Tulinger inner.options = $.extend({}, inner.defaults, {$parent: $("#content")}, options); 145d7d00a41SKrystof Tulinger inner.init(); 146d7d00a41SKrystof Tulinger return this; 147d7d00a41SKrystof Tulinger }; 148d7d00a41SKrystof Tulinger }; 149d7d00a41SKrystof Tulinger 150d7d00a41SKrystof Tulinger $.spaces = new ($.extend(spaces, $.spaces ? $.spaces : {}))(); 151d7d00a41SKrystof Tulinger})(window, window.jQuery); 152d7d00a41SKrystof Tulinger 153d7d00a41SKrystof Tulinger/** 154d7d00a41SKrystof Tulinger * Offseting the target anchors by the height of the fixed header. 155d7d00a41SKrystof Tulinger * Code taken from http://jsfiddle.net/ianclark001/rkocah23/. 156d7d00a41SKrystof Tulinger * 157d7d00a41SKrystof Tulinger * If this is not used, clicking on a anchor 158d7d00a41SKrystof Tulinger * with a hash target (href="#some-id") will 159d7d00a41SKrystof Tulinger * lead to incorrect positioning at the top of the page. 160d7d00a41SKrystof Tulinger */ 161d7d00a41SKrystof Tulinger(function (document, history, location) { 162d7d00a41SKrystof Tulinger const HISTORY_SUPPORT = !!(history && history.pushState); 163d7d00a41SKrystof Tulinger 164d7d00a41SKrystof Tulinger const anchorScrolls = { 165d7d00a41SKrystof Tulinger ANCHOR_REGEX: /^#[^ ]+$/, 166d7d00a41SKrystof Tulinger OFFSET_HEIGHT_PX: 90, 167d7d00a41SKrystof Tulinger 168d7d00a41SKrystof Tulinger /** 169d7d00a41SKrystof Tulinger * Establish events, and fix initial scroll position if a hash is provided. 170d7d00a41SKrystof Tulinger */ 171d7d00a41SKrystof Tulinger init: function () { 172d7d00a41SKrystof Tulinger this.scrollToCurrent(); 173d7d00a41SKrystof Tulinger $(window).on('hashchange', $.proxy(this, 'scrollToCurrent')); 174d7d00a41SKrystof Tulinger $('body').on('click', 'a', $.proxy(this, 'delegateAnchors')); 175d7d00a41SKrystof Tulinger }, 176d7d00a41SKrystof Tulinger 177d7d00a41SKrystof Tulinger /** 178d7d00a41SKrystof Tulinger * Return the offset amount to deduct from the normal scroll position. 179d7d00a41SKrystof Tulinger * Modify as appropriate to allow for dynamic calculations 180d7d00a41SKrystof Tulinger */ 181d7d00a41SKrystof Tulinger getFixedOffset: function () { 182d7d00a41SKrystof Tulinger return this.OFFSET_HEIGHT_PX; 183d7d00a41SKrystof Tulinger }, 184d7d00a41SKrystof Tulinger 185d7d00a41SKrystof Tulinger /** 186d7d00a41SKrystof Tulinger * If the provided href is an anchor which resolves to an element on the 187d7d00a41SKrystof Tulinger * page, scroll to it. 188d7d00a41SKrystof Tulinger * @param {String} href 189d7d00a41SKrystof Tulinger * @return {Boolean} - Was the href an anchor. 190d7d00a41SKrystof Tulinger */ 191d7d00a41SKrystof Tulinger scrollIfAnchor: function (href, pushToHistory) { 192d7d00a41SKrystof Tulinger if (!this.ANCHOR_REGEX.test(href)) { 193d7d00a41SKrystof Tulinger return false; 194d7d00a41SKrystof Tulinger } 195d7d00a41SKrystof Tulinger 196d7d00a41SKrystof Tulinger let match = document.getElementById(href.slice(1)); 197d7d00a41SKrystof Tulinger if (!match) { 198d7d00a41SKrystof Tulinger /** 199d7d00a41SKrystof Tulinger * Match the elements with name="href", take the first match 200d7d00a41SKrystof Tulinger */ 201d7d00a41SKrystof Tulinger match = document.getElementsByName(href.slice(1)); 202d7d00a41SKrystof Tulinger match = match.length > 0 ? match[0] : null; 203d7d00a41SKrystof Tulinger } 204d7d00a41SKrystof Tulinger 205d7d00a41SKrystof Tulinger if (match) { 206d7d00a41SKrystof Tulinger const anchorOffset = $(match.nextElementSibling).offset().top - this.getFixedOffset(); 207d7d00a41SKrystof Tulinger $('html, body').animate({scrollTop: anchorOffset}); 208d7d00a41SKrystof Tulinger 209d7d00a41SKrystof Tulinger location.hash = href; 210d7d00a41SKrystof Tulinger 211d7d00a41SKrystof Tulinger // Add the state to history as-per normal anchor links 212d7d00a41SKrystof Tulinger if (HISTORY_SUPPORT && pushToHistory) { 213d7d00a41SKrystof Tulinger history.pushState({}, document.title, location.pathname + location.search + href); 214d7d00a41SKrystof Tulinger } 215d7d00a41SKrystof Tulinger } 216d7d00a41SKrystof Tulinger 217d7d00a41SKrystof Tulinger return !!match; 218d7d00a41SKrystof Tulinger }, 219d7d00a41SKrystof Tulinger 220d7d00a41SKrystof Tulinger /** 221d7d00a41SKrystof Tulinger * Attempt to scroll to the current location's hash. 222d7d00a41SKrystof Tulinger */ 223d7d00a41SKrystof Tulinger scrollToCurrent: function (e) { 224d7d00a41SKrystof Tulinger if (this.scrollIfAnchor(window.location.hash) && e) { 225d7d00a41SKrystof Tulinger e.preventDefault(); 226d7d00a41SKrystof Tulinger } 227d7d00a41SKrystof Tulinger }, 228d7d00a41SKrystof Tulinger 229d7d00a41SKrystof Tulinger /** 230d7d00a41SKrystof Tulinger * If the click event's target was an anchor, fix the scroll position. 231d7d00a41SKrystof Tulinger */ 232d7d00a41SKrystof Tulinger delegateAnchors: function (e) { 233d7d00a41SKrystof Tulinger const elem = e.target; 234d7d00a41SKrystof Tulinger 235d7d00a41SKrystof Tulinger if (this.scrollIfAnchor(elem.getAttribute('href'), true)) { 236d7d00a41SKrystof Tulinger e.preventDefault(); 237d7d00a41SKrystof Tulinger } 238d7d00a41SKrystof Tulinger } 239d7d00a41SKrystof Tulinger }; 240d7d00a41SKrystof Tulinger 241d7d00a41SKrystof Tulinger 242d7d00a41SKrystof Tulinger $(document).ready($.proxy(anchorScrolls, 'init')); 243d7d00a41SKrystof Tulinger})(window.document, window.history, window.location); 244d7d00a41SKrystof Tulinger 245d7d00a41SKrystof Tulinger(function(window, $) { 246d7d00a41SKrystof Tulinger const hash = function () { 247d7d00a41SKrystof Tulinger const inner = { 248d7d00a41SKrystof Tulinger self: this, 249d7d00a41SKrystof Tulinger initialized: false, 250d7d00a41SKrystof Tulinger highlighted: [], 251d7d00a41SKrystof Tulinger defaults: { 252d7d00a41SKrystof Tulinger highlightedClass: 'target', 253d7d00a41SKrystof Tulinger linkSelectorTemplate: '{parent} a[name={n}]', 254d7d00a41SKrystof Tulinger clickSelector: '{parent} a.l, {parent} a.hl', 255d7d00a41SKrystof Tulinger parent: 'div#src', 256d7d00a41SKrystof Tulinger autoScroll: true, 257d7d00a41SKrystof Tulinger autoScrollDuration: 500 258d7d00a41SKrystof Tulinger }, 259d7d00a41SKrystof Tulinger options: {}, 260d7d00a41SKrystof Tulinger bindClickHandler: function() { 261d7d00a41SKrystof Tulinger $(inner.format(inner.options.clickSelector, {parent: inner.options.parent})).click(function (e) { 262d7d00a41SKrystof Tulinger if(e.shiftKey) { 263d7d00a41SKrystof Tulinger // shift pressed 264d7d00a41SKrystof Tulinger const val = inner.toInt($(this).attr("name")); 265d7d00a41SKrystof Tulinger if (!val) { 266d7d00a41SKrystof Tulinger return false; 267d7d00a41SKrystof Tulinger } 268d7d00a41SKrystof Tulinger 269d7d00a41SKrystof Tulinger const l = inner.getLinesParts(window.location.hash); 270d7d00a41SKrystof Tulinger 271d7d00a41SKrystof Tulinger if (l.length == 2) { 272d7d00a41SKrystof Tulinger window.location.hash = "#" + Math.min(l[0], val) + "-" + Math.max(val, l[1]); 273d7d00a41SKrystof Tulinger } else if (l.length == 1) { 274d7d00a41SKrystof Tulinger window.location.hash = "#" + Math.min(l[0], val) + "-" + Math.max(l[0], val); 275d7d00a41SKrystof Tulinger } 276d7d00a41SKrystof Tulinger return false; 277d7d00a41SKrystof Tulinger } 278d7d00a41SKrystof Tulinger return true; 279d7d00a41SKrystof Tulinger }); 280d7d00a41SKrystof Tulinger }, 281d7d00a41SKrystof Tulinger 282d7d00a41SKrystof Tulinger getHashParts: function (hash) { 283d7d00a41SKrystof Tulinger if (!hash || hash === "") { 284d7d00a41SKrystof Tulinger return hash; 285d7d00a41SKrystof Tulinger } 286d7d00a41SKrystof Tulinger return (hash = hash.split("#")).length > 1 ? hash[1] : ""; 287d7d00a41SKrystof Tulinger }, 288d7d00a41SKrystof Tulinger 289d7d00a41SKrystof Tulinger getLinesParts: function ( hashPart ) { 290d7d00a41SKrystof Tulinger hashPart = inner.getHashParts(hashPart); 291d7d00a41SKrystof Tulinger if (!hashPart || hashPart === "") { 292d7d00a41SKrystof Tulinger return hashPart; 293d7d00a41SKrystof Tulinger } 294d7d00a41SKrystof Tulinger const s = hashPart.split("-"); 295d7d00a41SKrystof Tulinger if (s.length > 1 && inner.toInt(s[0]) && inner.toInt(s[1])) { 296d7d00a41SKrystof Tulinger return [inner.toInt(s[0]), inner.toInt(s[1])]; 297d7d00a41SKrystof Tulinger } 298d7d00a41SKrystof Tulinger if (s.length > 0 && inner.toInt(s[0])) { 299d7d00a41SKrystof Tulinger return [inner.toInt(s[0])]; 300d7d00a41SKrystof Tulinger } 301d7d00a41SKrystof Tulinger return []; 302d7d00a41SKrystof Tulinger }, 303d7d00a41SKrystof Tulinger 304d7d00a41SKrystof Tulinger lines: function (urlPart) { 305d7d00a41SKrystof Tulinger const p = inner.getLinesParts(urlPart); 306d7d00a41SKrystof Tulinger if (p.length == 2) { 307d7d00a41SKrystof Tulinger let l = []; 308d7d00a41SKrystof Tulinger for (let i = Math.min(p[0],p[1]); i <= Math.max(p[0], p[1]); i++) { 309d7d00a41SKrystof Tulinger l.push(i); 310d7d00a41SKrystof Tulinger } 311d7d00a41SKrystof Tulinger return l; 312d7d00a41SKrystof Tulinger } else if (p.length == 1){ 313d7d00a41SKrystof Tulinger return [p[0]]; 314d7d00a41SKrystof Tulinger } 315d7d00a41SKrystof Tulinger return []; 316d7d00a41SKrystof Tulinger }, 317d7d00a41SKrystof Tulinger 318d7d00a41SKrystof Tulinger reload: function(e){ 319d7d00a41SKrystof Tulinger for (let i = 0; i < inner.highlighted.length; i++) { 320d7d00a41SKrystof Tulinger // remove color 321d7d00a41SKrystof Tulinger inner.highlighted[i].removeClass(inner.options.highlightedClass); 322d7d00a41SKrystof Tulinger } 323d7d00a41SKrystof Tulinger inner.highlighted = []; 324d7d00a41SKrystof Tulinger 325d7d00a41SKrystof Tulinger const lines = inner.lines(window.location.hash); 326d7d00a41SKrystof Tulinger 327d7d00a41SKrystof Tulinger if (lines.length < 1) { 328d7d00a41SKrystof Tulinger // not a case of line highlighting 329d7d00a41SKrystof Tulinger return; 330d7d00a41SKrystof Tulinger } 331d7d00a41SKrystof Tulinger for (let j = 0; j < lines.length; j++) { 332d7d00a41SKrystof Tulinger // color 333d7d00a41SKrystof Tulinger const slc = inner.format(inner.options.linkSelectorTemplate, { "parent": inner.options.parent, 334d7d00a41SKrystof Tulinger "n": lines[j] } ); 335d7d00a41SKrystof Tulinger const el = $(slc).addClass(inner.options.highlightedClass); 336d7d00a41SKrystof Tulinger inner.highlighted.push(el); 337d7d00a41SKrystof Tulinger } 338d7d00a41SKrystof Tulinger }, 339d7d00a41SKrystof Tulinger format: function(format) { 340d7d00a41SKrystof Tulinger let args = Array.prototype.slice.call(arguments, 1); 341d7d00a41SKrystof Tulinger args = args.length > 0 ? typeof args[0] === "object" ? args[0] : args : args; 342d7d00a41SKrystof Tulinger return format.replace(/{([a-zA-Z0-9_-]+)}/g, function(match, number) { 343d7d00a41SKrystof Tulinger return typeof args[number] != 'undefined' ? args[number] : match; 344d7d00a41SKrystof Tulinger }); 345d7d00a41SKrystof Tulinger }, 346d7d00a41SKrystof Tulinger toInt: function (string) { 347d7d00a41SKrystof Tulinger return parseInt(string, 10); 348d7d00a41SKrystof Tulinger }, 349d7d00a41SKrystof Tulinger scroll: function (){ 350d7d00a41SKrystof Tulinger if (!inner.options.autoScroll) { 351d7d00a41SKrystof Tulinger return; 352d7d00a41SKrystof Tulinger } 353d7d00a41SKrystof Tulinger const lines = inner.getLinesParts(window.location.hash); 354d7d00a41SKrystof Tulinger if (lines.length > 0) { 355d7d00a41SKrystof Tulinger const line = lines[0]; // first line 356d7d00a41SKrystof Tulinger const $line = $(inner.format(inner.options.linkSelectorTemplate, { 357d7d00a41SKrystof Tulinger parent: inner.options.parent, 358d7d00a41SKrystof Tulinger n: line 359d7d00a41SKrystof Tulinger })); 360d7d00a41SKrystof Tulinger if ($line.length > 0) { 361d7d00a41SKrystof Tulinger // if there is such element identified with the line number 362d7d00a41SKrystof Tulinger // we can scroll to it 363d7d00a41SKrystof Tulinger $('html, body').animate({ 364d7d00a41SKrystof Tulinger scrollTop: $(inner.format(inner.options.linkSelectorTemplate, { 365d7d00a41SKrystof Tulinger parent: inner.options.parent, 366d7d00a41SKrystof Tulinger n: line 367d7d00a41SKrystof Tulinger })).offset().top - $(inner.options.parent).offset().top 368d7d00a41SKrystof Tulinger }, inner.options.autoScrollDuration); 369d7d00a41SKrystof Tulinger } 370d7d00a41SKrystof Tulinger } 371d7d00a41SKrystof Tulinger } 372d7d00a41SKrystof Tulinger }; // inner 373d7d00a41SKrystof Tulinger 374d7d00a41SKrystof Tulinger this.init = function (options) { 375d7d00a41SKrystof Tulinger if (inner.initialized) { 376d7d00a41SKrystof Tulinger return this; 377d7d00a41SKrystof Tulinger } 378d7d00a41SKrystof Tulinger inner.options = $.extend(inner.defaults, options, {}); 379d7d00a41SKrystof Tulinger 380d7d00a41SKrystof Tulinger $(window).on("hashchange", inner.reload); 381d7d00a41SKrystof Tulinger inner.reload(); 382d7d00a41SKrystof Tulinger inner.bindClickHandler(); 383d7d00a41SKrystof Tulinger inner.scroll(); 384d7d00a41SKrystof Tulinger inner.initialized = true; 385d7d00a41SKrystof Tulinger return this; 386d7d00a41SKrystof Tulinger }; 387d7d00a41SKrystof Tulinger }; 388d7d00a41SKrystof Tulinger $.hash = new ($.extend(hash, $.hash ? $.hash : {}))(); 389d7d00a41SKrystof Tulinger}) (window, window.jQuery); 390d7d00a41SKrystof Tulinger 391d7d00a41SKrystof Tulinger/** 392d7d00a41SKrystof Tulinger * General on-demand script downloader 393d7d00a41SKrystof Tulinger */ 394d7d00a41SKrystof Tulinger(function (window, document, $) { 395d7d00a41SKrystof Tulinger const script = function () { 396d7d00a41SKrystof Tulinger this.scriptsDownloaded = {}; 397d7d00a41SKrystof Tulinger this.defaults = { 398d7d00a41SKrystof Tulinger contextPath: window.contextPath 399d7d00a41SKrystof Tulinger }; 400d7d00a41SKrystof Tulinger 401d7d00a41SKrystof Tulinger this.options = $.extend(this.defaults, {}); 402d7d00a41SKrystof Tulinger 403d7d00a41SKrystof Tulinger this.loadScript = function (url) { 404d7d00a41SKrystof Tulinger if (!/^[a-z]{3,5}:\/\//.test(url)) { // dummy test for remote prefix 405d7d00a41SKrystof Tulinger url = this.options.contextPath + '/' + url; 406d7d00a41SKrystof Tulinger } 407d7d00a41SKrystof Tulinger if (url in this.scriptsDownloaded) { 408d7d00a41SKrystof Tulinger return this.scriptsDownloaded[url]; 409d7d00a41SKrystof Tulinger } 410d7d00a41SKrystof Tulinger this.scriptsDownloaded[url] = $.ajax({ 411d7d00a41SKrystof Tulinger url: url, 412d7d00a41SKrystof Tulinger dataType: 'script', 413d7d00a41SKrystof Tulinger cache: true, 414d7d00a41SKrystof Tulinger timeout: 10000 415d7d00a41SKrystof Tulinger }).fail(function () { 416d7d00a41SKrystof Tulinger console.debug('Failed to download "' + url + '" module'); 417d7d00a41SKrystof Tulinger }); 418d7d00a41SKrystof Tulinger return this.scriptsDownloaded[url]; 419d7d00a41SKrystof Tulinger }; 420d7d00a41SKrystof Tulinger }; 421d7d00a41SKrystof Tulinger $.script = new ($.extend(script, $.script ? $.script : {}))(); 422d7d00a41SKrystof Tulinger})(window, document, jQuery); 423d7d00a41SKrystof Tulinger 424d7d00a41SKrystof Tulinger/** 425d7d00a41SKrystof Tulinger * General window plugin 426d7d00a41SKrystof Tulinger * 427d7d00a41SKrystof Tulinger * This plugin allows you to create a new window inside the browser. The main 428d7d00a41SKrystof Tulinger * interface is create function. 429d7d00a41SKrystof Tulinger * 430d7d00a41SKrystof Tulinger * Usage: 431d7d00a41SKrystof Tulinger * $myWindow = $.window.create({ 432d7d00a41SKrystof Tulinger * // default options (later available via this.options) 433d7d00a41SKrystof Tulinger * project: 'abcd', // not existing in window options and will be filled 434d7d00a41SKrystof Tulinger * draggable: false, // override the window defaults 435d7d00a41SKrystof Tulinger * // callbacks for events 436d7d00a41SKrystof Tulinger * init: function ($window) { 437d7d00a41SKrystof Tulinger * // called when creating the new window 438d7d00a41SKrystof Tulinger * // you can modify the new window object - it's jquery object 439d7d00a41SKrystof Tulinger * // you must return the modified window object 440d7d00a41SKrystof Tulinger * }, 441d7d00a41SKrystof Tulinger * load: function ($window) { 442d7d00a41SKrystof Tulinger * // called when the page is successfully loaded 443d7d00a41SKrystof Tulinger * // you can attach some handlers and fill some options with DOM values 444d7d00a41SKrystof Tulinger * }, 445d7d00a41SKrystof Tulinger * update: function(data) { 446d7d00a41SKrystof Tulinger * // called when update is called on your window bypassing the data param 447d7d00a41SKrystof Tulinger * // you can modify the window content or other DOM content 448d7d00a41SKrystof Tulinger * } 449d7d00a41SKrystof Tulinger * }, { 450d7d00a41SKrystof Tulinger * // context object - can contain other helper variables and functions 451d7d00a41SKrystof Tulinger * // it's available in the callbacks as the 'this' variable 452d7d00a41SKrystof Tulinger * // the window itself is available as this.$window 453d7d00a41SKrystof Tulinger * modified: false, 454d7d00a41SKrystof Tulinger * modify: function () { 455d7d00a41SKrystof Tulinger * this.modified = true; 456d7d00a41SKrystof Tulinger * }, 457d7d00a41SKrystof Tulinger * }) 458d7d00a41SKrystof Tulinger * 459d7d00a41SKrystof Tulinger * The new $myWindow object is jQuery object - you can call jQuery functions on it. 460d7d00a41SKrystof Tulinger * It doesn't really make sense to call all of the jQuery functions however 461d7d00a41SKrystof Tulinger * some of them might be useful: toggle, hide, show and so on. 462d7d00a41SKrystof Tulinger * 463d7d00a41SKrystof Tulinger * The window object also provides some useful functions like 464d7d00a41SKrystof Tulinger * $myWindow.error(message) to display an error in this.$errors element or 465d7d00a41SKrystof Tulinger * $myWindow.update(data) to trigger your update callback with given data or 466d7d00a41SKrystof Tulinger * $myWindow.move(position) to move the window to the given position 467d7d00a41SKrystof Tulinger * if no position is given it may be determined from the mouse position 468d7d00a41SKrystof Tulinger * 469d7d00a41SKrystof Tulinger * For custom content in the window you can use body() function: 470d7d00a41SKrystof Tulinger * $myWindow.body().append($('<div>').addClass('important-div')) 471d7d00a41SKrystof Tulinger * 472d7d00a41SKrystof Tulinger * @author Kryštof Tulinger 473d7d00a41SKrystof Tulinger */ 474d7d00a41SKrystof Tulinger(function (browserWindow, document, $, $script) { 475d7d00a41SKrystof Tulinger const window = function () { 476d7d00a41SKrystof Tulinger const Inner = function (options, context) { 477d7d00a41SKrystof Tulinger const self = this; 478d7d00a41SKrystof Tulinger // private 479d7d00a41SKrystof Tulinger this.context = context; 480d7d00a41SKrystof Tulinger this.callbacks = { 481d7d00a41SKrystof Tulinger init: [], 482d7d00a41SKrystof Tulinger load: [], 483d7d00a41SKrystof Tulinger update: [] 484d7d00a41SKrystof Tulinger }; 485d7d00a41SKrystof Tulinger this.$window = undefined; 486d7d00a41SKrystof Tulinger this.$errors = undefined; 487d7d00a41SKrystof Tulinger this.clientX = 0; 488d7d00a41SKrystof Tulinger this.clientY = 0; 489d7d00a41SKrystof Tulinger this.pendingUpdates = []; 490d7d00a41SKrystof Tulinger 491d7d00a41SKrystof Tulinger /** 492d7d00a41SKrystof Tulinger * Default values for the window options. 493d7d00a41SKrystof Tulinger */ 494d7d00a41SKrystof Tulinger this.defaults = { 495d7d00a41SKrystof Tulinger title: 'Window', 496d7d00a41SKrystof Tulinger appendDraggable: '#content', 497d7d00a41SKrystof Tulinger draggable: true, 498d7d00a41SKrystof Tulinger draggableScript: 'js/jquery-ui-1.12.1-draggable.min.js', // relative to context 499d7d00a41SKrystof Tulinger contextPath: browserWindow.contextPath, 500d7d00a41SKrystof Tulinger parent: undefined, 501d7d00a41SKrystof Tulinger load: undefined, 502d7d00a41SKrystof Tulinger init: undefined, 503d7d00a41SKrystof Tulinger handlers: undefined 504d7d00a41SKrystof Tulinger }; 505d7d00a41SKrystof Tulinger 506d7d00a41SKrystof Tulinger this.options = $.extend({}, this.defaults, options); 507d7d00a41SKrystof Tulinger 508d7d00a41SKrystof Tulinger this.addCallback = function (name, callback, context) { 509d7d00a41SKrystof Tulinger context = context || this.getSelfContext; 510d7d00a41SKrystof Tulinger if (!this.callbacks || !$.isArray(this.callbacks[name])) { 511d7d00a41SKrystof Tulinger this.callbacks[name] = []; 512d7d00a41SKrystof Tulinger } 513d7d00a41SKrystof Tulinger this.callbacks[name].push({ 514d7d00a41SKrystof Tulinger 'callback': callback, 515d7d00a41SKrystof Tulinger 'context': context 516d7d00a41SKrystof Tulinger }); 517d7d00a41SKrystof Tulinger }; 518d7d00a41SKrystof Tulinger 519d7d00a41SKrystof Tulinger this.fire = function (name, args) { 520d7d00a41SKrystof Tulinger if (!this.callbacks || !$.isArray(this.callbacks[name])) { 521d7d00a41SKrystof Tulinger return; 522d7d00a41SKrystof Tulinger } 523d7d00a41SKrystof Tulinger 524d7d00a41SKrystof Tulinger for (let i = 0; i < this.callbacks[name].length; i++) { 525d7d00a41SKrystof Tulinger this.$window = (this.callbacks[name][i].callback.apply( 526d7d00a41SKrystof Tulinger this.callbacks[name][i].context.call(this), 527d7d00a41SKrystof Tulinger args || [this.$window])) || this.$window; 528d7d00a41SKrystof Tulinger } 529d7d00a41SKrystof Tulinger }; 530d7d00a41SKrystof Tulinger 531d7d00a41SKrystof Tulinger this.getContext = function () { 532d7d00a41SKrystof Tulinger return $.extend(this.context, {options: this.options}); 533d7d00a41SKrystof Tulinger }; 534d7d00a41SKrystof Tulinger 535d7d00a41SKrystof Tulinger this.getSelfContext = function () { 536d7d00a41SKrystof Tulinger return this; 537d7d00a41SKrystof Tulinger }; 538d7d00a41SKrystof Tulinger 539d7d00a41SKrystof Tulinger // private 540d7d00a41SKrystof Tulinger this.cropPosition = function($w, position) { 541d7d00a41SKrystof Tulinger const w = { 542d7d00a41SKrystof Tulinger height: $w.outerHeight(true), 543d7d00a41SKrystof Tulinger width: $w.outerWidth(true) 544d7d00a41SKrystof Tulinger }; 545d7d00a41SKrystof Tulinger const bw = { 546d7d00a41SKrystof Tulinger height: $(browserWindow).outerHeight(true), 547d7d00a41SKrystof Tulinger width: $(browserWindow).outerWidth(true), 548d7d00a41SKrystof Tulinger yOffset: 0, 549d7d00a41SKrystof Tulinger xOffset: 0 550d7d00a41SKrystof Tulinger }; 551d7d00a41SKrystof Tulinger position.top -= Math.max(0, position.top + w.height - bw.yOffset - bw.height + 20); 552d7d00a41SKrystof Tulinger position.left -= Math.max(0, position.left + w.width - bw.xOffset - bw.width + 20); 553d7d00a41SKrystof Tulinger return position; 554d7d00a41SKrystof Tulinger }; 555d7d00a41SKrystof Tulinger 556d7d00a41SKrystof Tulinger this.determinePosition = function () { 557d7d00a41SKrystof Tulinger const position = { 558d7d00a41SKrystof Tulinger top: this.clientY, 559d7d00a41SKrystof Tulinger left: this.clientX 560d7d00a41SKrystof Tulinger }; 561d7d00a41SKrystof Tulinger return this.cropPosition(this.$window, position); 562d7d00a41SKrystof Tulinger }; 563d7d00a41SKrystof Tulinger 564d7d00a41SKrystof Tulinger this.makeMeDraggable = function () { 565d7d00a41SKrystof Tulinger if (!$script || typeof $script.loadScript !== 'function') { 566d7d00a41SKrystof Tulinger console.log("The window plugin requires $.script plugin when draggable option is 'true'"); 567d7d00a41SKrystof Tulinger return; 568d7d00a41SKrystof Tulinger } 569d7d00a41SKrystof Tulinger 570d7d00a41SKrystof Tulinger $script.loadScript(this.options.draggableScript).done(function () { 571d7d00a41SKrystof Tulinger self.$window.draggable({ 572d7d00a41SKrystof Tulinger appendTo: self.options.draggableAppendTo || $('body'), 573d7d00a41SKrystof Tulinger helper: 'clone', 574d7d00a41SKrystof Tulinger start: function () { 575d7d00a41SKrystof Tulinger $(this).hide(); 576d7d00a41SKrystof Tulinger }, 577d7d00a41SKrystof Tulinger stop: function (e, ui) { 578d7d00a41SKrystof Tulinger $(this).show().offset(ui.offset).css('position', 'fixed'); 579d7d00a41SKrystof Tulinger }, 580d7d00a41SKrystof Tulinger create: function (e, ui) { 581d7d00a41SKrystof Tulinger $(this).css('position', 'fixed'); 582d7d00a41SKrystof Tulinger } 583d7d00a41SKrystof Tulinger }); 584d7d00a41SKrystof Tulinger }); 585d7d00a41SKrystof Tulinger }; 586d7d00a41SKrystof Tulinger 587d7d00a41SKrystof Tulinger this.addCallback('init', function ($window) { 588d7d00a41SKrystof Tulinger let $close; 589d7d00a41SKrystof Tulinger const $top = $("<div>").addClass('clearfix'). 590d7d00a41SKrystof Tulinger append($("<div>").addClass("pull-left").append($("<b>").text(this.options.title || "Window"))). 591d7d00a41SKrystof Tulinger append($("<div>").addClass('pull-right').append($close = $('<a href="#" class="minimize">x</a>'))); 592d7d00a41SKrystof Tulinger 593d7d00a41SKrystof Tulinger const $header = $("<div>").addClass('window-header').append($top); 594d7d00a41SKrystof Tulinger 595d7d00a41SKrystof Tulinger const $body = $("<div>").addClass("window-body").append(self.$errors = $('<div>').css('text-align', 'center')); 596d7d00a41SKrystof Tulinger 597d7d00a41SKrystof Tulinger $window = $("<div>"). 598d7d00a41SKrystof Tulinger addClass('window'). 599d7d00a41SKrystof Tulinger addClass('diff_navigation_style'). 600d7d00a41SKrystof Tulinger css('z-index', 15000). 601d7d00a41SKrystof Tulinger hide(). 602d7d00a41SKrystof Tulinger append($header). 603d7d00a41SKrystof Tulinger append($body); 604d7d00a41SKrystof Tulinger 605d7d00a41SKrystof Tulinger $close.click(function () { 606d7d00a41SKrystof Tulinger $window.hide(); 607d7d00a41SKrystof Tulinger return false; 608d7d00a41SKrystof Tulinger }); 609d7d00a41SKrystof Tulinger 610d7d00a41SKrystof Tulinger /** 611d7d00a41SKrystof Tulinger * Get the element for the window body. 612d7d00a41SKrystof Tulinger * This should be used to place your desired content. 613d7d00a41SKrystof Tulinger * 614d7d00a41SKrystof Tulinger * The returned object has a method {@code window()} 615d7d00a41SKrystof Tulinger * which returns the whole window. 616d7d00a41SKrystof Tulinger * 617d7d00a41SKrystof Tulinger * {@code $window} is equivalent to {@code $window.body().window()} 618d7d00a41SKrystof Tulinger * 619d7d00a41SKrystof Tulinger * @returns jQuery object of the window body 620d7d00a41SKrystof Tulinger */ 621d7d00a41SKrystof Tulinger $window.body = function () { 622d7d00a41SKrystof Tulinger $body.window = function () { 623d7d00a41SKrystof Tulinger return $window; 624d7d00a41SKrystof Tulinger }; 625d7d00a41SKrystof Tulinger return $body; 626d7d00a41SKrystof Tulinger }; 627d7d00a41SKrystof Tulinger 628d7d00a41SKrystof Tulinger /** 629d7d00a41SKrystof Tulinger * Display custom error message in the window 630d7d00a41SKrystof Tulinger * @param {string} msg message 631d7d00a41SKrystof Tulinger * @returns self 632d7d00a41SKrystof Tulinger */ 633d7d00a41SKrystof Tulinger $window.error = function (msg) { 634d7d00a41SKrystof Tulinger const $span = $("<p class='error'>" + msg + "</p>"). 635d7d00a41SKrystof Tulinger animate({opacity: "0.2"}, 3000); 636d7d00a41SKrystof Tulinger $span.hide('slow', function () { 637d7d00a41SKrystof Tulinger $span.remove(); 638d7d00a41SKrystof Tulinger }); 639d7d00a41SKrystof Tulinger self.$errors.html($span); 640d7d00a41SKrystof Tulinger return this; 641d7d00a41SKrystof Tulinger }; 642d7d00a41SKrystof Tulinger 643d7d00a41SKrystof Tulinger /** 644d7d00a41SKrystof Tulinger * Move the window to the position. If no position is given 645d7d00a41SKrystof Tulinger * it may be determined from the mouse position. 646d7d00a41SKrystof Tulinger * 647d7d00a41SKrystof Tulinger * @param {object} position object with top and left attributes 648d7d00a41SKrystof Tulinger * @returns self 649d7d00a41SKrystof Tulinger */ 650d7d00a41SKrystof Tulinger $window.move = function (position) { 651d7d00a41SKrystof Tulinger position = position || self.determinePosition(); 652d7d00a41SKrystof Tulinger return this.css(position); 653d7d00a41SKrystof Tulinger }; 654d7d00a41SKrystof Tulinger 655d7d00a41SKrystof Tulinger /** 656d7d00a41SKrystof Tulinger * Display or hide the window. 657d7d00a41SKrystof Tulinger * 658d7d00a41SKrystof Tulinger * We override this method from jquery to manually 659d7d00a41SKrystof Tulinger * trigger the hide() and show() methods 660d7d00a41SKrystof Tulinger * which may be used in the descendants. 661d7d00a41SKrystof Tulinger * 662d7d00a41SKrystof Tulinger * @returns self 663d7d00a41SKrystof Tulinger */ 664d7d00a41SKrystof Tulinger $window.toggle = function() { 665d7d00a41SKrystof Tulinger const action = this.is(':visible') ? this.hide : this.show; 666d7d00a41SKrystof Tulinger return action.apply(this, arguments); 667d7d00a41SKrystof Tulinger }; 668d7d00a41SKrystof Tulinger 669d7d00a41SKrystof Tulinger /** 670d7d00a41SKrystof Tulinger * Toggle and move the window to the current mouse position 671d7d00a41SKrystof Tulinger * 672d7d00a41SKrystof Tulinger * @returns self 673d7d00a41SKrystof Tulinger */ 674d7d00a41SKrystof Tulinger $window.toggleAndMove = function () { 675d7d00a41SKrystof Tulinger return $window.toggle().move(); 676d7d00a41SKrystof Tulinger }; 677d7d00a41SKrystof Tulinger 678d7d00a41SKrystof Tulinger /** 679d7d00a41SKrystof Tulinger * Update the window with given data. 680d7d00a41SKrystof Tulinger * 681d7d00a41SKrystof Tulinger * @param {mixed} data 682d7d00a41SKrystof Tulinger * @returns {undefined} 683d7d00a41SKrystof Tulinger */ 684d7d00a41SKrystof Tulinger $window.update = function (data) { 685d7d00a41SKrystof Tulinger if (this.loaded) { 686d7d00a41SKrystof Tulinger self.fire('update', [data]); 687d7d00a41SKrystof Tulinger } else { 688d7d00a41SKrystof Tulinger self.pendingUpdates.push({data: data}); 689d7d00a41SKrystof Tulinger } 690d7d00a41SKrystof Tulinger return this; 691d7d00a41SKrystof Tulinger }; 692d7d00a41SKrystof Tulinger 693d7d00a41SKrystof Tulinger // insert window into context 694d7d00a41SKrystof Tulinger this.context = $.extend(this.context, {$window: $window}); 695d7d00a41SKrystof Tulinger 696d7d00a41SKrystof Tulinger // set us as initialized 697d7d00a41SKrystof Tulinger $window.initialized = true; 698d7d00a41SKrystof Tulinger // set us as not loaded 699d7d00a41SKrystof Tulinger $window.loaded = false; 700d7d00a41SKrystof Tulinger 701d7d00a41SKrystof Tulinger return $window; 702d7d00a41SKrystof Tulinger }); 703d7d00a41SKrystof Tulinger 704d7d00a41SKrystof Tulinger this.addCallback('load', function ($window) { 705d7d00a41SKrystof Tulinger const that = this; 706d7d00a41SKrystof Tulinger $(document).mousemove(function (e) { 707d7d00a41SKrystof Tulinger that.clientX = e.clientX; 708d7d00a41SKrystof Tulinger that.clientY = e.clientY; 709d7d00a41SKrystof Tulinger }); 710d7d00a41SKrystof Tulinger $(document).keyup(function (e) { 711d7d00a41SKrystof Tulinger var key = e.keyCode; 712d7d00a41SKrystof Tulinger if (key === 27) { // esc 713d7d00a41SKrystof Tulinger that.$window.hide(); 714d7d00a41SKrystof Tulinger } 715d7d00a41SKrystof Tulinger return true; 716d7d00a41SKrystof Tulinger }); 717d7d00a41SKrystof Tulinger }); 718d7d00a41SKrystof Tulinger 719d7d00a41SKrystof Tulinger if (this.options.draggable) { 720d7d00a41SKrystof Tulinger this.addCallback('load', this.makeMeDraggable); 721d7d00a41SKrystof Tulinger } 722d7d00a41SKrystof Tulinger 723d7d00a41SKrystof Tulinger this.addCallback('load', function ($window) { 724d7d00a41SKrystof Tulinger this.$window.appendTo(this.options.parent ? $(this.options.parent) : $("body")); 725d7d00a41SKrystof Tulinger }); 726d7d00a41SKrystof Tulinger 727d7d00a41SKrystof Tulinger if (this.options.init && typeof this.options.init === 'function') { 728d7d00a41SKrystof Tulinger this.addCallback('init', this.options.init, this.getContext); 729d7d00a41SKrystof Tulinger } 730d7d00a41SKrystof Tulinger 731d7d00a41SKrystof Tulinger if (self.options.load && typeof self.options.load === 'function') { 732d7d00a41SKrystof Tulinger this.addCallback('load', this.options.load, this.getContext); 733d7d00a41SKrystof Tulinger } 734d7d00a41SKrystof Tulinger 735d7d00a41SKrystof Tulinger if (self.options.update && typeof self.options.update === 'function') { 736d7d00a41SKrystof Tulinger this.addCallback('update', this.options.update, this.getContext); 737d7d00a41SKrystof Tulinger } 738d7d00a41SKrystof Tulinger 739d7d00a41SKrystof Tulinger $(function () { 740d7d00a41SKrystof Tulinger self.fire('load'); 741d7d00a41SKrystof Tulinger self.$window.loaded = true; 742d7d00a41SKrystof Tulinger 743d7d00a41SKrystof Tulinger for (var i = 0; i < self.pendingUpdates.length; i++) { 744d7d00a41SKrystof Tulinger self.fire('update', [self.pendingUpdates[i].data]); 745d7d00a41SKrystof Tulinger } 746d7d00a41SKrystof Tulinger self.pendingUpdates = []; 747d7d00a41SKrystof Tulinger }); 748d7d00a41SKrystof Tulinger 749d7d00a41SKrystof Tulinger this.fire('init'); 750d7d00a41SKrystof Tulinger 751d7d00a41SKrystof Tulinger return this.$window; 752d7d00a41SKrystof Tulinger }; 753d7d00a41SKrystof Tulinger 754d7d00a41SKrystof Tulinger /** 755d7d00a41SKrystof Tulinger * Create a window. 756d7d00a41SKrystof Tulinger * 757d7d00a41SKrystof Tulinger * @param {hash} options containing default options and callbacks 758d7d00a41SKrystof Tulinger * @param {hash} context other helper variables and functions 759d7d00a41SKrystof Tulinger * @returns new window object 760d7d00a41SKrystof Tulinger */ 761d7d00a41SKrystof Tulinger this.create = function (options, context) { 762d7d00a41SKrystof Tulinger return new Inner(options, context); 763d7d00a41SKrystof Tulinger }; 764d7d00a41SKrystof Tulinger }; 765d7d00a41SKrystof Tulinger $.window = new ($.extend(window, $.window ? $.window : {}))(); 766d7d00a41SKrystof Tulinger})(window, document, jQuery, jQuery.script); 767d7d00a41SKrystof Tulinger 768d7d00a41SKrystof Tulinger/** 769d7d00a41SKrystof Tulinger * Intelligence window plugin. 770d7d00a41SKrystof Tulinger * 771d7d00a41SKrystof Tulinger * Reworked to use Jquery in 2016 772d7d00a41SKrystof Tulinger */ 773d7d00a41SKrystof Tulinger(function (browserWindow, document, $, $window) { 774d7d00a41SKrystof Tulinger if (!$window || typeof $window.create !== 'function') { 775d7d00a41SKrystof Tulinger console.log("The intelligenceWindow plugin requires $.window plugin"); 776d7d00a41SKrystof Tulinger return; 777d7d00a41SKrystof Tulinger } 778d7d00a41SKrystof Tulinger 779d7d00a41SKrystof Tulinger var intelliWindow = function () { 780d7d00a41SKrystof Tulinger this.initialised = false; 781d7d00a41SKrystof Tulinger this.init = function (options, context) { 782d7d00a41SKrystof Tulinger $.intelliWindow = $window.create($.extend({ 783d7d00a41SKrystof Tulinger title: 'Intelligence window', 784d7d00a41SKrystof Tulinger selector: 'a.intelliWindow-symbol', 785d7d00a41SKrystof Tulinger google_url: 'https://www.google.com/search?q=', 786d7d00a41SKrystof Tulinger project: undefined, 787d7d00a41SKrystof Tulinger init: function ($window) { 788d7d00a41SKrystof Tulinger let $highlight, $unhighlight, $unhighlightAll, $prev, $next; 789d7d00a41SKrystof Tulinger 790d7d00a41SKrystof Tulinger let $firstList = $("<ul>"). 791d7d00a41SKrystof Tulinger append($("<li>").append( 792d7d00a41SKrystof Tulinger $highlight = $('<a href="#" title="Highlight">' + 793d7d00a41SKrystof Tulinger '<span>Highlight</span> <b class="symbol-name"></b></a>'))). 794d7d00a41SKrystof Tulinger append($("<li>").append( 795d7d00a41SKrystof Tulinger $unhighlight = $('<a href="#" title="Unhighlight">' + 796d7d00a41SKrystof Tulinger '<span>Unhighlight</span> <b class="symbol-name"></b></a>'))). 797d7d00a41SKrystof Tulinger append($("<li>").append( 798d7d00a41SKrystof Tulinger $unhighlightAll = $('<a href="#" title="Unhighlight all">' + 799d7d00a41SKrystof Tulinger '<span>Unhighlight all</span></a>'))); 800d7d00a41SKrystof Tulinger 801d7d00a41SKrystof Tulinger this.bindOnClick($highlight, this.highlight); 802d7d00a41SKrystof Tulinger this.bindOnClick($unhighlight, this.unhighlight); 803d7d00a41SKrystof Tulinger this.bindOnClick($unhighlightAll, this.unhighlightAll); 804d7d00a41SKrystof Tulinger 805d7d00a41SKrystof Tulinger let $secondList = $("<ul>"). 806d7d00a41SKrystof Tulinger append($("<li>").append( 807d7d00a41SKrystof Tulinger $('<a class="search-defs" href="#" target="_blank">' + 808d7d00a41SKrystof Tulinger '<span>Search for definitions of</span> <b class="symbol-name"></b></a>'))). 809d7d00a41SKrystof Tulinger append($("<li>").append( 810d7d00a41SKrystof Tulinger $('<a class="search-refs" href="#" target="_blank">' + 811d7d00a41SKrystof Tulinger '<span>Search for references of</span> <b class="symbol-name"></b></a>'))). 812d7d00a41SKrystof Tulinger append($("<li>").append( 813d7d00a41SKrystof Tulinger $('<a class="search-full" href="#" target="_blank">' + 814d7d00a41SKrystof Tulinger '<span>Do a full search with</span> <b class="symbol-name"></b></a>'))). 815d7d00a41SKrystof Tulinger append($("<li>").append( 816d7d00a41SKrystof Tulinger $('<a class="search-files" href="#" target="_blank">' + 817d7d00a41SKrystof Tulinger '<span>Search for file names that contain</span> <b class="symbol-name"></b></a>'))); 818d7d00a41SKrystof Tulinger 819d7d00a41SKrystof Tulinger let $thirdList = $("<ul>"). 820d7d00a41SKrystof Tulinger append($("<li>").append( 821d7d00a41SKrystof Tulinger $('<a class="search-google" href="#" target="_blank">' + 822d7d00a41SKrystof Tulinger '<span>Google</span> <b class="symbol-name"></b></a>'))); 823d7d00a41SKrystof Tulinger 824d7d00a41SKrystof Tulinger let $controls = $('<div class="pull-right">'). 825d7d00a41SKrystof Tulinger append($next = $('<a href="#" title="next" class="pull-right">Next >></a>')). 826d7d00a41SKrystof Tulinger append('<span class="pull-right"> | </span>'). 827d7d00a41SKrystof Tulinger append($prev = $('<a href="#" title="prev" class="pull-right"><< Prev </a>')). 828d7d00a41SKrystof Tulinger append($('<div class="clearfix">')). 829d7d00a41SKrystof Tulinger append(this.$errors = $('<span class="clearfix">')); 830d7d00a41SKrystof Tulinger 831d7d00a41SKrystof Tulinger this.bindOnClick($next, this.scrollToNextElement, 1); 832d7d00a41SKrystof Tulinger this.bindOnClick($prev, this.scrollToNextElement, -1); 833d7d00a41SKrystof Tulinger 834d7d00a41SKrystof Tulinger return $window. 835d7d00a41SKrystof Tulinger attr('id', 'intelli_win'). 836d7d00a41SKrystof Tulinger addClass('intelli-window'). 837d7d00a41SKrystof Tulinger body(). 838d7d00a41SKrystof Tulinger append($controls). 839d7d00a41SKrystof Tulinger append($("<h2>").addClass('symbol-name')). 840d7d00a41SKrystof Tulinger append($("<span>").addClass('symbol-description')). 841d7d00a41SKrystof Tulinger append($("<hr>")). 842d7d00a41SKrystof Tulinger append($("<h5>").text("In current file")). 843d7d00a41SKrystof Tulinger append($firstList). 844d7d00a41SKrystof Tulinger append($("<h5>").text('In project "' + this.project + '"')). 845d7d00a41SKrystof Tulinger append($secondList). 846d7d00a41SKrystof Tulinger append($("<h5>").text("On Google")). 847d7d00a41SKrystof Tulinger append($thirdList). 848d7d00a41SKrystof Tulinger window(); 849d7d00a41SKrystof Tulinger }, 850d7d00a41SKrystof Tulinger load: function ($window) { 851d7d00a41SKrystof Tulinger const that = this; 852d7d00a41SKrystof Tulinger $(document).keypress(function (e) { 853d7d00a41SKrystof Tulinger if (textInputHasFocus()) { 854d7d00a41SKrystof Tulinger return true; 855d7d00a41SKrystof Tulinger } 856d7d00a41SKrystof Tulinger const key = e.which; 857d7d00a41SKrystof Tulinger switch (key) { 858d7d00a41SKrystof Tulinger case 49: // 1 859d7d00a41SKrystof Tulinger if (that.symbol) { 860d7d00a41SKrystof Tulinger that.$window.toggleAndMove(); 861d7d00a41SKrystof Tulinger } 862d7d00a41SKrystof Tulinger break; 863d7d00a41SKrystof Tulinger case 50: // 2 864d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 865d7d00a41SKrystof Tulinger that.highlight(that.symbol, 1); 866d7d00a41SKrystof Tulinger } 867d7d00a41SKrystof Tulinger break; 868d7d00a41SKrystof Tulinger case 51: // 3 869d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 870d7d00a41SKrystof Tulinger that.highlight(that.symbol, 2); 871d7d00a41SKrystof Tulinger } 872d7d00a41SKrystof Tulinger break; 873d7d00a41SKrystof Tulinger case 52: // 4 874d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 875d7d00a41SKrystof Tulinger that.highlight(that.symbol, 3); 876d7d00a41SKrystof Tulinger } 877d7d00a41SKrystof Tulinger break; 878d7d00a41SKrystof Tulinger case 53: // 5 879d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 880d7d00a41SKrystof Tulinger that.highlight(that.symbol, 4); 881d7d00a41SKrystof Tulinger } 882d7d00a41SKrystof Tulinger break; 883d7d00a41SKrystof Tulinger case 54: // 6 884d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 885d7d00a41SKrystof Tulinger that.highlight(that.symbol, 5); 886d7d00a41SKrystof Tulinger } 887d7d00a41SKrystof Tulinger break; 888*b802fcc7SKryštof Tulinger case 55: // 7 889d7d00a41SKrystof Tulinger if (that.symbol && that.unhighlight(that.symbol).length === 0) { 890d7d00a41SKrystof Tulinger that.highlight(that.symbol, 6); 891d7d00a41SKrystof Tulinger } 892d7d00a41SKrystof Tulinger break; 893*b802fcc7SKryštof Tulinger case 56: // 8 894d7d00a41SKrystof Tulinger that.unhighlightAll(); 895d7d00a41SKrystof Tulinger break; 896d7d00a41SKrystof Tulinger case 110: // n 897d7d00a41SKrystof Tulinger that.scrollToNextElement(1); 898d7d00a41SKrystof Tulinger break; 899d7d00a41SKrystof Tulinger case 98: // b 900d7d00a41SKrystof Tulinger that.scrollToNextElement(-1); 901d7d00a41SKrystof Tulinger break; 902d7d00a41SKrystof Tulinger default: 903d7d00a41SKrystof Tulinger } 904d7d00a41SKrystof Tulinger return true; 905d7d00a41SKrystof Tulinger }); 906d7d00a41SKrystof Tulinger this.getSymbols().mouseover(function () { 907d7d00a41SKrystof Tulinger that.changeSymbol($(this)); 908d7d00a41SKrystof Tulinger }); 909d7d00a41SKrystof Tulinger this.project = this.options.project || $("input[name='project']").val(); 910d7d00a41SKrystof Tulinger this.contextPath = browserWindow.contextPath; 911d7d00a41SKrystof Tulinger } 912d7d00a41SKrystof Tulinger }, options || {}), $.extend({ 913d7d00a41SKrystof Tulinger symbol: undefined, 914d7d00a41SKrystof Tulinger project: undefined, 915d7d00a41SKrystof Tulinger $symbols: undefined, 916d7d00a41SKrystof Tulinger $current: undefined, 917d7d00a41SKrystof Tulinger $last_highlighted_current: $(), 918d7d00a41SKrystof Tulinger $search_defs: undefined, 919d7d00a41SKrystof Tulinger $search_refs: undefined, 920d7d00a41SKrystof Tulinger $search_full: undefined, 921d7d00a41SKrystof Tulinger $search_files: undefined, 922d7d00a41SKrystof Tulinger $search_google: undefined, 923d7d00a41SKrystof Tulinger changeSymbol: function ($el) { 924d7d00a41SKrystof Tulinger this.$current = $el; 925d7d00a41SKrystof Tulinger this.$last_highlighted_current = $el.hasClass("symbol-highlighted") ? $el : this.$last_highlighted_current; 926d7d00a41SKrystof Tulinger this.symbol = $el.text(); 927d7d00a41SKrystof Tulinger this.place = $el.data("definition-place"); 928d7d00a41SKrystof Tulinger this.$window.find('.hidden-on-start').show(); 929d7d00a41SKrystof Tulinger this.$window.find(".symbol-name").text(this.symbol); 930d7d00a41SKrystof Tulinger this.$window.find(".symbol-description").text(this.getSymbolDescription(this.place)); 931d7d00a41SKrystof Tulinger this.modifyLinks(); 932d7d00a41SKrystof Tulinger }, 933d7d00a41SKrystof Tulinger modifyLinks: function () { 934d7d00a41SKrystof Tulinger this.$search_defs = this.$search_defs || this.$window.find('.search-defs'); 935d7d00a41SKrystof Tulinger this.$search_refs = this.$search_refs || this.$window.find('.search-refs'); 936d7d00a41SKrystof Tulinger this.$search_full = this.$search_full || this.$window.find('.search-full'); 937d7d00a41SKrystof Tulinger this.$search_files = this.$search_files || this.$window.find('.search-files'); 938d7d00a41SKrystof Tulinger this.$search_google = this.$search_google || this.$window.find('.search-google'); 939d7d00a41SKrystof Tulinger 940d7d00a41SKrystof Tulinger this.$search_defs.attr('href', this.getSearchLink('defs')); 941d7d00a41SKrystof Tulinger this.$search_refs.attr('href', this.getSearchLink('refs')); 942d7d00a41SKrystof Tulinger this.$search_full.attr('href', this.getSearchLink('full')); 943d7d00a41SKrystof Tulinger this.$search_files.attr('href', this.getSearchLink('path')); 944d7d00a41SKrystof Tulinger this.$search_google.attr('href', this.options.google_url + this.symbol); 945d7d00a41SKrystof Tulinger }, 946d7d00a41SKrystof Tulinger getSearchLink: function (query) { 947d7d00a41SKrystof Tulinger return this.options.contextPath + '/search?' + query + '=' + this.symbol + '&project=' + this.project; 948d7d00a41SKrystof Tulinger }, 949d7d00a41SKrystof Tulinger getSymbolDescription: function (place) { 950d7d00a41SKrystof Tulinger switch (place) { 951d7d00a41SKrystof Tulinger case "def": 952d7d00a41SKrystof Tulinger return "A declaration or definition."; 953d7d00a41SKrystof Tulinger case "defined-in-file": 954d7d00a41SKrystof Tulinger return "A symbol declared or defined in this file."; 955d7d00a41SKrystof Tulinger case "undefined-in-file": 956d7d00a41SKrystof Tulinger return "A symbol declared or defined elsewhere."; 957d7d00a41SKrystof Tulinger default: 958d7d00a41SKrystof Tulinger // should not happen 959d7d00a41SKrystof Tulinger return "Something I have no idea about."; 960d7d00a41SKrystof Tulinger } 961d7d00a41SKrystof Tulinger }, 962d7d00a41SKrystof Tulinger getSymbols: function () { 963d7d00a41SKrystof Tulinger return (this.$symbols = this.$symbols || $(this.options.selector)); 964d7d00a41SKrystof Tulinger }, 965d7d00a41SKrystof Tulinger highlight: function (symbol, color) { 966d7d00a41SKrystof Tulinger if (this.$current.text() === symbol) { 967d7d00a41SKrystof Tulinger this.$last_highlighted_current = this.$current; 968d7d00a41SKrystof Tulinger } 969d7d00a41SKrystof Tulinger return this.getSymbols().filter(function () { 970d7d00a41SKrystof Tulinger return $(this).text() === symbol; 971d7d00a41SKrystof Tulinger }).addClass('symbol-highlighted').addClass('hightlight-color-' + (color || 1)); 972d7d00a41SKrystof Tulinger }, 973d7d00a41SKrystof Tulinger unhighlight: function (symbol) { 974d7d00a41SKrystof Tulinger if (this.$last_highlighted_current && 975d7d00a41SKrystof Tulinger this.$last_highlighted_current.text() === symbol && 976d7d00a41SKrystof Tulinger this.$last_highlighted_current.hasClass('symbol-highlighted')) { 977d7d00a41SKrystof Tulinger const i = this.getSymbols().index(this.$last_highlighted_current); 978d7d00a41SKrystof Tulinger this.$last_highlighted_jump = this.getSymbols().slice(0, i).filter('.symbol-highlighted').last(); 979d7d00a41SKrystof Tulinger } 980d7d00a41SKrystof Tulinger return this.getSymbols().filter(".symbol-highlighted").filter(function () { 981d7d00a41SKrystof Tulinger return $(this).text() === symbol; 982d7d00a41SKrystof Tulinger }).removeClass('symbol-highlighted') 983d7d00a41SKrystof Tulinger .removeClass(function (index, className) { 984d7d00a41SKrystof Tulinger return (className.match(/(^|\s)hightlight-color-\S+/g) || []).join(' '); 985d7d00a41SKrystof Tulinger }); 986d7d00a41SKrystof Tulinger }, 987d7d00a41SKrystof Tulinger unhighlightAll: function () { 988d7d00a41SKrystof Tulinger this.$last_highlighted_current = undefined; 989d7d00a41SKrystof Tulinger return this.getSymbols().filter(".symbol-highlighted"). 990d7d00a41SKrystof Tulinger removeClass("symbol-highlighted"). 991d7d00a41SKrystof Tulinger removeClass(function (index, className) { 992d7d00a41SKrystof Tulinger return (className.match (/(^|\s)hightlight-color-\S+/g) || []).join(' '); 993d7d00a41SKrystof Tulinger }); 994d7d00a41SKrystof Tulinger }, 995d7d00a41SKrystof Tulinger scrollTop: function ($el) { 996d7d00a41SKrystof Tulinger if (this.options.scrollTop) { 997d7d00a41SKrystof Tulinger this.options.scrollTop($el); 998d7d00a41SKrystof Tulinger } else { 999d7d00a41SKrystof Tulinger $('html, body').stop().animate({ 1000d7d00a41SKrystof Tulinger scrollTop: $el.offset().top - $("#src").offset().top 1001d7d00a41SKrystof Tulinger }, 500); 1002d7d00a41SKrystof Tulinger } 1003d7d00a41SKrystof Tulinger }, 1004d7d00a41SKrystof Tulinger scrollToNextElement: function (direction) { 1005d7d00a41SKrystof Tulinger const UP = -1; 1006d7d00a41SKrystof Tulinger const DOWN = 1; 1007d7d00a41SKrystof Tulinger const $highlighted = this.getSymbols().filter(".symbol-highlighted"); 1008d7d00a41SKrystof Tulinger let $el = $highlighted.length && this.$last_highlighted_current ? this.$last_highlighted_current : this.$current; 1009d7d00a41SKrystof Tulinger const indexOfCurrent = this.getSymbols().index($el); 1010d7d00a41SKrystof Tulinger 1011d7d00a41SKrystof Tulinger switch (direction) { 1012d7d00a41SKrystof Tulinger case DOWN: 1013d7d00a41SKrystof Tulinger $el = this.getSymbols().slice(indexOfCurrent + 1); 1014d7d00a41SKrystof Tulinger if ($highlighted.length) { 1015d7d00a41SKrystof Tulinger $el = $el.filter('.symbol-highlighted'); 1016d7d00a41SKrystof Tulinger } 1017d7d00a41SKrystof Tulinger if (!$el.length) { 1018d7d00a41SKrystof Tulinger this.$window.error("This is the last occurence!"); 1019d7d00a41SKrystof Tulinger return; 1020d7d00a41SKrystof Tulinger } 1021d7d00a41SKrystof Tulinger $el = $el.first(); 1022d7d00a41SKrystof Tulinger break; 1023d7d00a41SKrystof Tulinger case UP: 1024d7d00a41SKrystof Tulinger $el = this.getSymbols().slice(0, indexOfCurrent); 1025d7d00a41SKrystof Tulinger if ($highlighted.length) { 1026d7d00a41SKrystof Tulinger $el = $el.filter('.symbol-highlighted'); 1027d7d00a41SKrystof Tulinger } 1028d7d00a41SKrystof Tulinger if (!$el.length) { 1029d7d00a41SKrystof Tulinger this.$window.error("This is the first occurence!"); 1030d7d00a41SKrystof Tulinger return; 1031d7d00a41SKrystof Tulinger } 1032d7d00a41SKrystof Tulinger $el = $el.last(); 1033d7d00a41SKrystof Tulinger break; 1034d7d00a41SKrystof Tulinger default: 1035d7d00a41SKrystof Tulinger this.$window.error("Unknown direction"); 1036d7d00a41SKrystof Tulinger return; 1037d7d00a41SKrystof Tulinger } 1038d7d00a41SKrystof Tulinger 1039d7d00a41SKrystof Tulinger this.scrollTop($el); 1040d7d00a41SKrystof Tulinger this.changeSymbol($el); 1041d7d00a41SKrystof Tulinger }, 1042d7d00a41SKrystof Tulinger bindOnClick: function ($el, callback, param) { 1043d7d00a41SKrystof Tulinger const that = this; 1044d7d00a41SKrystof Tulinger $el.click(function (e) { 1045d7d00a41SKrystof Tulinger e.preventDefault(); 1046d7d00a41SKrystof Tulinger callback.call(that, param || that.symbol); 1047d7d00a41SKrystof Tulinger return false; 1048d7d00a41SKrystof Tulinger }); 1049d7d00a41SKrystof Tulinger } 1050d7d00a41SKrystof Tulinger }, context || {})); 1051d7d00a41SKrystof Tulinger return $.intelliWindow; 1052d7d00a41SKrystof Tulinger }; 1053d7d00a41SKrystof Tulinger }; 1054d7d00a41SKrystof Tulinger $.intelliWindow = new ($.extend(intelliWindow, $.intelliWindow ? $.intelliWindow : {}))(); 1055d7d00a41SKrystof Tulinger})(window, document, jQuery, jQuery.window); 1056d7d00a41SKrystof Tulinger 1057d7d00a41SKrystof Tulinger/** 1058d7d00a41SKrystof Tulinger * Messages window plugin. 1059d7d00a41SKrystof Tulinger * 1060d7d00a41SKrystof Tulinger * @author Kryštof Tulinger 1061d7d00a41SKrystof Tulinger */ 1062d7d00a41SKrystof Tulinger(function (browserWindow, document, $, $window) { 1063d7d00a41SKrystof Tulinger if (!$window || typeof $window.create !== 'function') { 1064d7d00a41SKrystof Tulinger console.log("The messagesWindow plugin requires $.window plugin"); 1065d7d00a41SKrystof Tulinger return; 1066d7d00a41SKrystof Tulinger } 1067d7d00a41SKrystof Tulinger 1068d7d00a41SKrystof Tulinger const messagesWindow = function () { 1069d7d00a41SKrystof Tulinger this.init = function (options, context) { 1070d7d00a41SKrystof Tulinger $.messagesWindow = $window.create($.extend({ 1071d7d00a41SKrystof Tulinger title: 'Messages Window', 1072d7d00a41SKrystof Tulinger draggable: false, 1073d7d00a41SKrystof Tulinger init: function ($window) { 1074d7d00a41SKrystof Tulinger return $window. 1075d7d00a41SKrystof Tulinger attr('id', 'messages_win'). 1076d7d00a41SKrystof Tulinger addClass('messages-window'). 1077d7d00a41SKrystof Tulinger addClass('diff_navigation_style'). 1078d7d00a41SKrystof Tulinger css({top: '150px', right: '20px'}). 1079d7d00a41SKrystof Tulinger body(). 1080d7d00a41SKrystof Tulinger append(this.$messages = $("<div>")). 1081d7d00a41SKrystof Tulinger window(); 1082d7d00a41SKrystof Tulinger }, 1083d7d00a41SKrystof Tulinger load: function ($window) { 1084d7d00a41SKrystof Tulinger $window.mouseenter(function () { 1085d7d00a41SKrystof Tulinger $window.show(); 1086d7d00a41SKrystof Tulinger }).mouseleave(function () { 1087d7d00a41SKrystof Tulinger $window.hide(); 1088d7d00a41SKrystof Tulinger }); 1089d7d00a41SKrystof Tulinger 1090d7d00a41SKrystof Tulinger // simulate show/toggle and move 1091d7d00a41SKrystof Tulinger $.each(['show', 'toggle'], function () { 1092d7d00a41SKrystof Tulinger const old = $window[this]; 1093d7d00a41SKrystof Tulinger $window[this] = function () { 1094d7d00a41SKrystof Tulinger return old.call($window).move(); 1095d7d00a41SKrystof Tulinger }; 1096d7d00a41SKrystof Tulinger }); 1097d7d00a41SKrystof Tulinger }, 1098d7d00a41SKrystof Tulinger update: function (data) { 1099d7d00a41SKrystof Tulinger this.$messages.empty(); 1100d7d00a41SKrystof Tulinger for (let tag of data) { 1101d7d00a41SKrystof Tulinger if (!tag || tag.messages.length === 0) { 1102d7d00a41SKrystof Tulinger continue; 1103d7d00a41SKrystof Tulinger } 1104d7d00a41SKrystof Tulinger this.$messages.append($("<h5>"). 1105d7d00a41SKrystof Tulinger addClass('message-group-caption'). 1106d7d00a41SKrystof Tulinger text(tag.tag.charAt(0).toUpperCase() + tag.tag.slice(1))); 1107d7d00a41SKrystof Tulinger const $ul = $("<ul>").addClass('message-group limited'); 1108d7d00a41SKrystof Tulinger for (let j = 0; j < tag.messages.length; j++) { 1109d7d00a41SKrystof Tulinger if (!tag.messages[j]) { 1110d7d00a41SKrystof Tulinger continue; 1111d7d00a41SKrystof Tulinger } 1112d7d00a41SKrystof Tulinger $ul.append( 1113d7d00a41SKrystof Tulinger $('<li>'). 1114d7d00a41SKrystof Tulinger addClass('message-group-item'). 1115d7d00a41SKrystof Tulinger addClass(tag.messages[j].messageLevel). 1116d7d00a41SKrystof Tulinger attr('title', 'Expires on ' + tag.messages[j].expiration). 1117d7d00a41SKrystof Tulinger html(tag.messages[j].created + ': ' + tag.messages[j].text) 1118d7d00a41SKrystof Tulinger ); 1119d7d00a41SKrystof Tulinger } 1120d7d00a41SKrystof Tulinger this.$messages.append($ul); 1121d7d00a41SKrystof Tulinger } 1122d7d00a41SKrystof Tulinger } 1123d7d00a41SKrystof Tulinger }, options || {}), $.extend({ 1124d7d00a41SKrystof Tulinger $messages: $() 1125d7d00a41SKrystof Tulinger }, context || {})); 1126d7d00a41SKrystof Tulinger return $.messagesWindow; 1127d7d00a41SKrystof Tulinger }; 1128d7d00a41SKrystof Tulinger }; 1129d7d00a41SKrystof Tulinger $.messagesWindow = new ($.extend(messagesWindow, $.messagesWindow ? $.messagesWindow : {}))(); 1130d7d00a41SKrystof Tulinger})(window, document, jQuery, jQuery.window); 1131d7d00a41SKrystof Tulinger 1132d7d00a41SKrystof Tulinger/** 1133d7d00a41SKrystof Tulinger * Scopes window plugin. 1134d7d00a41SKrystof Tulinger * 1135d7d00a41SKrystof Tulinger * @author Kryštof Tulinger 1136d7d00a41SKrystof Tulinger */ 1137d7d00a41SKrystof Tulinger(function (browserWindow, document, $, $window) { 1138d7d00a41SKrystof Tulinger if (!$window || typeof $window.create !== 'function') { 1139d7d00a41SKrystof Tulinger console.log("The scopesWindow plugin requires $.window plugin"); 1140d7d00a41SKrystof Tulinger return; 1141d7d00a41SKrystof Tulinger } 1142d7d00a41SKrystof Tulinger 1143d7d00a41SKrystof Tulinger const scopesWindow = function () { 1144d7d00a41SKrystof Tulinger this.init = function (options, context) { 1145d7d00a41SKrystof Tulinger $.scopesWindow = $window.create($.extend({ 1146d7d00a41SKrystof Tulinger title: 'Scopes Window', 1147d7d00a41SKrystof Tulinger draggable: false, 1148d7d00a41SKrystof Tulinger init: function ($window) { 1149d7d00a41SKrystof Tulinger return $window. 1150d7d00a41SKrystof Tulinger attr('id', 'scopes_win'). 1151d7d00a41SKrystof Tulinger addClass('scopes-window'). 1152d7d00a41SKrystof Tulinger addClass('diff_navigation_style'). 1153d7d00a41SKrystof Tulinger css({top: '150px', right: '20px'}). 1154d7d00a41SKrystof Tulinger body(). 1155d7d00a41SKrystof Tulinger append(this.$scopes = $("<div>")). 1156d7d00a41SKrystof Tulinger window(); 1157d7d00a41SKrystof Tulinger }, 1158d7d00a41SKrystof Tulinger load: function ($window) { 1159d7d00a41SKrystof Tulinger $window.hide().css('top', $("#content").offset().top + 10 + 'px'); 1160d7d00a41SKrystof Tulinger 1161d7d00a41SKrystof Tulinger // override the hide and show to throw an event and run 1162d7d00a41SKrystof Tulinger // scope_on_scroll() for update 1163d7d00a41SKrystof Tulinger $.each(['hide', 'show'], function () { 1164d7d00a41SKrystof Tulinger const event = this; 1165d7d00a41SKrystof Tulinger const old = $window[event]; 1166d7d00a41SKrystof Tulinger $window[event] = function () { 1167d7d00a41SKrystof Tulinger var $toReturn = old.call($window).trigger(event); 1168d7d00a41SKrystof Tulinger if (!scope_on_scroll || typeof scope_on_scroll !== 'function') { 1169d7d00a41SKrystof Tulinger console.debug("[scopesWindow]: The scope_on_scroll() is not a function at this point."); 1170d7d00a41SKrystof Tulinger return $toReturn; 1171d7d00a41SKrystof Tulinger } 1172d7d00a41SKrystof Tulinger scope_on_scroll(); 1173d7d00a41SKrystof Tulinger return $toReturn; 1174d7d00a41SKrystof Tulinger }; 1175d7d00a41SKrystof Tulinger }); 1176d7d00a41SKrystof Tulinger 1177d7d00a41SKrystof Tulinger $('.scopes-toggle').click(function () { 1178d7d00a41SKrystof Tulinger $window.toggle(); 1179d7d00a41SKrystof Tulinger return false; 1180d7d00a41SKrystof Tulinger }); 1181d7d00a41SKrystof Tulinger }, 1182d7d00a41SKrystof Tulinger update: function (data) { 1183d7d00a41SKrystof Tulinger if(!this.$window.is(':visible') && !this.$window.data('shown-once')) { 1184d7d00a41SKrystof Tulinger this.$window.show().data('shown-once', true); 1185d7d00a41SKrystof Tulinger } 1186d7d00a41SKrystof Tulinger this.$scopes.empty(); 1187d7d00a41SKrystof Tulinger this.$scopes.html(this.buildLink(data.id, data.link)); 1188d7d00a41SKrystof Tulinger this.$window.trigger('update'); 1189d7d00a41SKrystof Tulinger } 1190d7d00a41SKrystof Tulinger }, options || {}), $.extend({ 1191d7d00a41SKrystof Tulinger $scopes: $(), 1192d7d00a41SKrystof Tulinger buildLink: function (href, name) { 1193d7d00a41SKrystof Tulinger return $('<a>').attr('href', '#' + href).attr('title', name).html(name); 1194d7d00a41SKrystof Tulinger } 1195d7d00a41SKrystof Tulinger }, context || {})); 1196d7d00a41SKrystof Tulinger return $.scopesWindow; 1197d7d00a41SKrystof Tulinger }; 1198d7d00a41SKrystof Tulinger }; 1199d7d00a41SKrystof Tulinger $.scopesWindow = new ($.extend(scopesWindow, $.scopesWindow ? $.scopesWindow : {}))(); 1200d7d00a41SKrystof Tulinger})(window, document, jQuery, jQuery.window); 1201d7d00a41SKrystof Tulinger 1202d7d00a41SKrystof Tulinger/** 1203d7d00a41SKrystof Tulinger * Navigate window plugin. 1204d7d00a41SKrystof Tulinger * 1205d7d00a41SKrystof Tulinger * @author Kryštof Tulinger 1206d7d00a41SKrystof Tulinger */ 1207d7d00a41SKrystof Tulinger(function (browserWindow, document, $, $window) { 1208d7d00a41SKrystof Tulinger if (!$window || typeof $window.create !== 'function') { 1209d7d00a41SKrystof Tulinger console.log("The navigateWindow plugin requires $.window plugin"); 1210d7d00a41SKrystof Tulinger return; 1211d7d00a41SKrystof Tulinger } 1212d7d00a41SKrystof Tulinger 1213d7d00a41SKrystof Tulinger const navigateWindow = function () { 1214d7d00a41SKrystof Tulinger this.init = function (options, context) { 1215d7d00a41SKrystof Tulinger $.navigateWindow = $window.create($.extend({ 1216d7d00a41SKrystof Tulinger title: 'Navigate Window', 1217d7d00a41SKrystof Tulinger draggable: false, 1218d7d00a41SKrystof Tulinger init: function ($window) { 1219d7d00a41SKrystof Tulinger return $window. 1220d7d00a41SKrystof Tulinger attr('id', 'navigate_win'). 1221d7d00a41SKrystof Tulinger addClass('navigate-window'). 1222d7d00a41SKrystof Tulinger addClass('diff_navigation_style'). 1223d7d00a41SKrystof Tulinger addClass('diff_navigation_style'). 1224d7d00a41SKrystof Tulinger css({top: '150px', right: '20px', height: this.defaultHeight + 'px'}). 1225d7d00a41SKrystof Tulinger body(). 1226d7d00a41SKrystof Tulinger append(this.$content). 1227d7d00a41SKrystof Tulinger window(); 1228d7d00a41SKrystof Tulinger }, 1229d7d00a41SKrystof Tulinger load: function ($window) { 1230d7d00a41SKrystof Tulinger const that = this; 1231d7d00a41SKrystof Tulinger $window.css('top', this.getTopOffset() + 10 + 'px'); 1232d7d00a41SKrystof Tulinger 1233d7d00a41SKrystof Tulinger if ($.scopesWindow && $.scopesWindow.initialized) { 1234d7d00a41SKrystof Tulinger $.scopesWindow.on('show', function () { 1235d7d00a41SKrystof Tulinger setTimeout(function () { 1236d7d00a41SKrystof Tulinger that.updatePosition($window); 1237d7d00a41SKrystof Tulinger }, 100); 1238d7d00a41SKrystof Tulinger }).on('hide', function () { 1239d7d00a41SKrystof Tulinger that.updatePosition($window); 1240d7d00a41SKrystof Tulinger }).on('update', function () { 1241d7d00a41SKrystof Tulinger that.updatePosition($window); 1242d7d00a41SKrystof Tulinger }); 1243d7d00a41SKrystof Tulinger 1244d7d00a41SKrystof Tulinger if ($.scopesWindow.is(':visible')) { 1245d7d00a41SKrystof Tulinger setTimeout(function () { 1246d7d00a41SKrystof Tulinger that.updatePosition($window); 1247d7d00a41SKrystof Tulinger }, 100); 1248d7d00a41SKrystof Tulinger } 1249d7d00a41SKrystof Tulinger } 1250d7d00a41SKrystof Tulinger 1251d7d00a41SKrystof Tulinger if ($('[data-navigate-window-enabled="true"]').length) { 1252d7d00a41SKrystof Tulinger $window.show(); 1253d7d00a41SKrystof Tulinger } 1254d7d00a41SKrystof Tulinger 1255d7d00a41SKrystof Tulinger // override and show to throw an event and update position 1256d7d00a41SKrystof Tulinger $.each(['show'], function () { 1257d7d00a41SKrystof Tulinger const event = this; 1258d7d00a41SKrystof Tulinger const old = $window[event]; 1259d7d00a41SKrystof Tulinger $window[event] = function () { 1260d7d00a41SKrystof Tulinger return that.updatePosition(old.call($window).trigger(event)); 1261d7d00a41SKrystof Tulinger }; 1262d7d00a41SKrystof Tulinger }); 1263d7d00a41SKrystof Tulinger 1264d7d00a41SKrystof Tulinger $(browserWindow).resize(function () { 1265d7d00a41SKrystof Tulinger that.updatePosition($window); 1266d7d00a41SKrystof Tulinger }); 1267d7d00a41SKrystof Tulinger that.updatePosition($window); 1268d7d00a41SKrystof Tulinger }, 1269d7d00a41SKrystof Tulinger update: function (data) { 1270d7d00a41SKrystof Tulinger let $ul; 1271d7d00a41SKrystof Tulinger this.$content.empty(); 1272d7d00a41SKrystof Tulinger for (let i = 0; i < data.length; i++) { 1273d7d00a41SKrystof Tulinger this.$content.append($('<h4>').text(data[i][0])); 1274d7d00a41SKrystof Tulinger if (data[i][2].length === 0) { 1275d7d00a41SKrystof Tulinger continue; 1276d7d00a41SKrystof Tulinger } 1277d7d00a41SKrystof Tulinger this.$content.append($ul = $('<ul>')); 1278d7d00a41SKrystof Tulinger for (let j = 0; j < data[i][2].length; j++) { 1279d7d00a41SKrystof Tulinger $ul.append($('<li>').append(this.buildLink(data[i][2][j][1], data[i][2][j][0], data[i][1]))); 1280d7d00a41SKrystof Tulinger } 1281d7d00a41SKrystof Tulinger } 1282d7d00a41SKrystof Tulinger this.updatePosition(this.$window); 1283d7d00a41SKrystof Tulinger } 1284d7d00a41SKrystof Tulinger }, options || { 1285d7d00a41SKrystof Tulinger }), $.extend({ 1286d7d00a41SKrystof Tulinger $content: $('<div>'), 1287d7d00a41SKrystof Tulinger defaultHeight: 480, 1288d7d00a41SKrystof Tulinger buildLink: function (href, name, c) { 1289d7d00a41SKrystof Tulinger return $('<a>').attr('href', '#' + href).attr('title', this.escapeHtml(name)).addClass(c).html(this.escapeHtml(name)).click(lnshow); 1290d7d00a41SKrystof Tulinger }, 1291d7d00a41SKrystof Tulinger getTopOffset: function () { 1292d7d00a41SKrystof Tulinger return $("#content").offset().top; 1293d7d00a41SKrystof Tulinger }, 1294d7d00a41SKrystof Tulinger updatePosition: function ($w) { 1295d7d00a41SKrystof Tulinger if (!$w.is(':visible')) { 1296d7d00a41SKrystof Tulinger /** 1297d7d00a41SKrystof Tulinger * If the window is not visible then this 1298d7d00a41SKrystof Tulinger * function is expensive as 1299d7d00a41SKrystof Tulinger * <a href="http://api.jquery.com/outerheight/">documented</a> 1300d7d00a41SKrystof Tulinger * under additional notes. 1301d7d00a41SKrystof Tulinger */ 1302d7d00a41SKrystof Tulinger return $w; 1303d7d00a41SKrystof Tulinger } 1304d7d00a41SKrystof Tulinger 1305d7d00a41SKrystof Tulinger const a = {}; 1306d7d00a41SKrystof Tulinger a.top = this.getTopOffset() + 10; 1307d7d00a41SKrystof Tulinger if ($.scopesWindow && 1308d7d00a41SKrystof Tulinger $.scopesWindow.initialized && 1309d7d00a41SKrystof Tulinger $.scopesWindow.is(':visible')) { 1310d7d00a41SKrystof Tulinger a.top = $.scopesWindow.position().top + $.scopesWindow.outerHeight() + 20; 1311d7d00a41SKrystof Tulinger } 1312d7d00a41SKrystof Tulinger a.height = Math.min(parseFloat($w.css('max-height')) || this.defaultHeight, $(browserWindow).outerHeight() - a.top - ($w.outerHeight(true) - $w.height()) - 20); 1313d7d00a41SKrystof Tulinger 1314d7d00a41SKrystof Tulinger if (a.height == $w.height() && a.top == this.getTopOffset()) { 1315d7d00a41SKrystof Tulinger return $w; 1316d7d00a41SKrystof Tulinger } 1317d7d00a41SKrystof Tulinger 1318d7d00a41SKrystof Tulinger if (this.$content.children().length === 0) { 1319d7d00a41SKrystof Tulinger // the window is empty 1320d7d00a41SKrystof Tulinger delete a.height; 1321d7d00a41SKrystof Tulinger } 1322d7d00a41SKrystof Tulinger 1323d7d00a41SKrystof Tulinger return $w.stop().animate(a); 1324d7d00a41SKrystof Tulinger }, 1325d7d00a41SKrystof Tulinger escapeHtml: function (html) { 1326d7d00a41SKrystof Tulinger return html.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 1327d7d00a41SKrystof Tulinger } 1328d7d00a41SKrystof Tulinger }, context || {})); 1329d7d00a41SKrystof Tulinger return $.navigateWindow; 1330d7d00a41SKrystof Tulinger }; 1331d7d00a41SKrystof Tulinger }; 1332d7d00a41SKrystof Tulinger $.navigateWindow = new ($.extend(navigateWindow, $.navigateWindow ? $.navigateWindow : {}))(); 1333d7d00a41SKrystof Tulinger})(window, document, jQuery, jQuery.window); 1334d7d00a41SKrystof Tulinger 1335d7d00a41SKrystof Tulingerfunction init_scopes() { 1336d7d00a41SKrystof Tulinger $.scopesWindow.init(); 1337d7d00a41SKrystof Tulinger $(window).scroll(scope_on_scroll); 1338d7d00a41SKrystof Tulinger} 1339d7d00a41SKrystof Tulinger 1340d7d00a41SKrystof Tulingerfunction init_results_autohide() { 1341d7d00a41SKrystof Tulinger $("#sbox input[type='submit']").click(function (e) { 1342d7d00a41SKrystof Tulinger $("#footer").not(".main_page").hide(); // footer 1343d7d00a41SKrystof Tulinger $("#results > .message-group").hide(); // messages 1344d7d00a41SKrystof Tulinger $("#results > p.suggestions").hide(); // suggestions 1345d7d00a41SKrystof Tulinger $("#results > p.pagetitle").hide(); // description 1346d7d00a41SKrystof Tulinger $("#results > p.slider").hide(); // pagination 1347d7d00a41SKrystof Tulinger $("#results > h3").hide(); // error 1348d7d00a41SKrystof Tulinger $("#results > table, #results > ul").hide(); // results + empty 1349d7d00a41SKrystof Tulinger $("#results > table + p, #results > ul + p").hide(); // results + empty timing 1350d7d00a41SKrystof Tulinger }); 1351d7d00a41SKrystof Tulinger} 1352d7d00a41SKrystof Tulinger 1353d7d00a41SKrystof Tulingerfunction init_searchable_option_list() { 1354d7d00a41SKrystof Tulinger function init_sol_on_type_combobox() { 1355d7d00a41SKrystof Tulinger const $type = $('#type'); 1356d7d00a41SKrystof Tulinger if ($type.length === 0) { 1357d7d00a41SKrystof Tulinger return; 1358d7d00a41SKrystof Tulinger } 1359d7d00a41SKrystof Tulinger /** 1360d7d00a41SKrystof Tulinger * Has to be here because otherwise the offset() 1361d7d00a41SKrystof Tulinger * takes the original long <select> box and the max-height 1362d7d00a41SKrystof Tulinger * does not work then. 1363d7d00a41SKrystof Tulinger */ 1364d7d00a41SKrystof Tulinger $type.searchableOptionList({ 1365d7d00a41SKrystof Tulinger texts: { 1366d7d00a41SKrystof Tulinger searchplaceholder: 'Click here to restrict the file type' 1367d7d00a41SKrystof Tulinger }, 1368d7d00a41SKrystof Tulinger maxHeight: $type.offset().top + 'px', 1369d7d00a41SKrystof Tulinger /** 1370d7d00a41SKrystof Tulinger * Defined in menu.jsp just next to the original <select> 1371d7d00a41SKrystof Tulinger */ 1372d7d00a41SKrystof Tulinger resultsContainer: $("#type-select-container") 1373d7d00a41SKrystof Tulinger }); 1374d7d00a41SKrystof Tulinger } 1375d7d00a41SKrystof Tulinger const searchableOptionListOptions = { 1376d7d00a41SKrystof Tulinger maxHeight: '300px', 1377d7d00a41SKrystof Tulinger showSelectionBelowList: false, 1378d7d00a41SKrystof Tulinger showSelectAll: false, 1379d7d00a41SKrystof Tulinger maxShow: 30, 1380d7d00a41SKrystof Tulinger resultsContainer: $("#ltbl"), 1381d7d00a41SKrystof Tulinger numSelectedItem: $("#nn"), 1382d7d00a41SKrystof Tulinger quickDeleteForm: $("#sbox"), 1383d7d00a41SKrystof Tulinger quickDeletePermit: checkIsOnSearchPage, 1384d7d00a41SKrystof Tulinger texts: { 1385d7d00a41SKrystof Tulinger searchplaceholder: 'Click here to select project(s)' 1386d7d00a41SKrystof Tulinger }, 1387d7d00a41SKrystof Tulinger events: { 1388d7d00a41SKrystof Tulinger onInitialized: function () { 1389d7d00a41SKrystof Tulinger if ($.messagesWindow.initialized) { 1390d7d00a41SKrystof Tulinger this.$selectionContainer.find("[data-messages]").mouseenter(function () { 1391d7d00a41SKrystof Tulinger var data = $(this).data('messages') || []; 1392d7d00a41SKrystof Tulinger $.messagesWindow.update(data); 1393d7d00a41SKrystof Tulinger $.messagesWindow.show(); 1394d7d00a41SKrystof Tulinger }).mouseleave(function (e) { 1395d7d00a41SKrystof Tulinger $.messagesWindow.hide(); 1396d7d00a41SKrystof Tulinger }); 1397d7d00a41SKrystof Tulinger } 1398d7d00a41SKrystof Tulinger }, 1399d7d00a41SKrystof Tulinger // override the default onScroll positioning event if necessary 1400d7d00a41SKrystof Tulinger onScroll: function () { 1401d7d00a41SKrystof Tulinger 1402d7d00a41SKrystof Tulinger const posY = this.$input.offset().top - this.config.scrollTarget.scrollTop() + this.$input.outerHeight() + 1; 1403d7d00a41SKrystof Tulinger let selectionContainerWidth = this.$innerContainer.outerWidth(false) - parseInt(this.$selectionContainer.css('border-left-width'), 10) - parseInt(this.$selectionContainer.css('border-right-width'), 10); 1404d7d00a41SKrystof Tulinger 1405d7d00a41SKrystof Tulinger if (this.$innerContainer.css('display') !== 'block') { 1406d7d00a41SKrystof Tulinger // container has a certain width 1407d7d00a41SKrystof Tulinger // make selection container a bit wider 1408d7d00a41SKrystof Tulinger selectionContainerWidth = Math.ceil(selectionContainerWidth * 1.2); 1409d7d00a41SKrystof Tulinger } else { 1410d7d00a41SKrystof Tulinger // no border radius on top 1411d7d00a41SKrystof Tulinger this.$selectionContainer.css('border-top-right-radius', 'initial'); 1412d7d00a41SKrystof Tulinger 1413d7d00a41SKrystof Tulinger if (this.$actionButtons) { 1414d7d00a41SKrystof Tulinger this.$actionButtons.css('border-top-right-radius', 'initial'); 1415d7d00a41SKrystof Tulinger } 1416d7d00a41SKrystof Tulinger } 1417d7d00a41SKrystof Tulinger 1418d7d00a41SKrystof Tulinger this.$selectionContainer. 1419d7d00a41SKrystof Tulinger css('top', Math.floor(posY)). 1420d7d00a41SKrystof Tulinger css('left', Math.floor(this.$container.offset().left)). 1421d7d00a41SKrystof Tulinger css('width', selectionContainerWidth); 1422d7d00a41SKrystof Tulinger }, 1423d7d00a41SKrystof Tulinger onRendered: init_sol_on_type_combobox 1424d7d00a41SKrystof Tulinger } 1425d7d00a41SKrystof Tulinger }; 1426d7d00a41SKrystof Tulinger 1427d7d00a41SKrystof Tulinger const $project = $('#project'); 1428d7d00a41SKrystof Tulinger if ($project.length === 1) { 1429d7d00a41SKrystof Tulinger $project.searchableOptionList(searchableOptionListOptions); 1430d7d00a41SKrystof Tulinger } else { 1431d7d00a41SKrystof Tulinger init_sol_on_type_combobox(); 1432d7d00a41SKrystof Tulinger } 1433d7d00a41SKrystof Tulinger} 1434d7d00a41SKrystof Tulinger 1435d7d00a41SKrystof Tulingerfunction init_history_input() { 1436d7d00a41SKrystof Tulinger $('input[data-revision-path]').click(function () { 1437d7d00a41SKrystof Tulinger const $this = $(this); 1438d7d00a41SKrystof Tulinger $("a.more").each(function () { 1439d7d00a41SKrystof Tulinger $(this).attr('href', setParameter($(this).attr('href'), 'r1', $this.data('revision-1'))); 1440d7d00a41SKrystof Tulinger $(this).attr('href', setParameter($(this).attr('href'), 'r2', $this.data('revision-2'))); 1441d7d00a41SKrystof Tulinger }); 1442d7d00a41SKrystof Tulinger 1443d7d00a41SKrystof Tulinger const $revisions = $('input[data-revision-path]'); 1444d7d00a41SKrystof Tulinger 1445d7d00a41SKrystof Tulinger // change the correct revision on every element 1446d7d00a41SKrystof Tulinger // (every element keeps a track which revision is selected) 1447d7d00a41SKrystof Tulinger $revisions.filter("[data-diff-revision='r1']").data('revision-2', $this.data('revision-2')); 1448d7d00a41SKrystof Tulinger $revisions.filter("[data-diff-revision='r2']").data('revision-1', $this.data('revision-1')); 1449d7d00a41SKrystof Tulinger 1450d7d00a41SKrystof Tulinger // set the correct revision for the form submission 1451d7d00a41SKrystof Tulinger $("#input_" + $this.data('diff-revision')).val($this.data('revision-path')); 1452d7d00a41SKrystof Tulinger 1453d7d00a41SKrystof Tulinger // enable all input 1454d7d00a41SKrystof Tulinger $revisions.prop('disabled', false); 1455d7d00a41SKrystof Tulinger // uncheck all input in my column 1456d7d00a41SKrystof Tulinger $revisions.filter("[data-diff-revision='" + $this.data('diff-revision') + "']").prop('checked', false); 1457d7d00a41SKrystof Tulinger // set me as checked 1458d7d00a41SKrystof Tulinger $this.prop('checked', true); 1459d7d00a41SKrystof Tulinger 1460d7d00a41SKrystof Tulinger // disable from top to r2 1461d7d00a41SKrystof Tulinger let index = Math.max($revisions.index($("input[data-revision-path][data-diff-revision='r2']:checked")), 0); 1462d7d00a41SKrystof Tulinger $revisions.slice(0, index).filter("[data-diff-revision='r1']").prop('disabled', true); 1463d7d00a41SKrystof Tulinger 1464d7d00a41SKrystof Tulinger // disable from bottom to r1 1465d7d00a41SKrystof Tulinger index = Math.max($revisions.index($("input[data-revision-path][data-diff-revision='r1']:checked")), index); 1466d7d00a41SKrystof Tulinger $revisions.slice(index + 1).filter("[data-diff-revision='r2']").prop('disabled', true); 1467d7d00a41SKrystof Tulinger }); 1468d7d00a41SKrystof Tulinger} 1469d7d00a41SKrystof Tulinger 1470d7d00a41SKrystof Tulingerfunction init_tablesorter() { 1471d7d00a41SKrystof Tulinger $("#dirlist").tablesorter({ 1472d7d00a41SKrystof Tulinger sortList: [[0, 0]], 1473d7d00a41SKrystof Tulinger cancelSelection: true, 1474d7d00a41SKrystof Tulinger sortReset : true, 1475d7d00a41SKrystof Tulinger sortRestart : true, 1476d7d00a41SKrystof Tulinger sortInitialOrder: "desc", 1477d7d00a41SKrystof Tulinger headers: { 1478d7d00a41SKrystof Tulinger 1: { 1479d7d00a41SKrystof Tulinger sorter: 'text', 1480d7d00a41SKrystof Tulinger sortInitialOrder: "asc" 1481d7d00a41SKrystof Tulinger }, 1482d7d00a41SKrystof Tulinger 3: { 1483d7d00a41SKrystof Tulinger sorter: 'dates' 1484d7d00a41SKrystof Tulinger }, 1485d7d00a41SKrystof Tulinger 4: { 1486d7d00a41SKrystof Tulinger sorter: 'groksizes' 1487d7d00a41SKrystof Tulinger } 1488d7d00a41SKrystof Tulinger } 1489d7d00a41SKrystof Tulinger }); 1490d7d00a41SKrystof Tulinger} 1491d7d00a41SKrystof Tulinger 1492d7d00a41SKrystof Tulingerfunction init_markdown_converter() { 1493d7d00a41SKrystof Tulinger let converter = null; 1494d7d00a41SKrystof Tulinger $('[data-markdown]').each(function () { 1495d7d00a41SKrystof Tulinger var $that = $(this); 1496d7d00a41SKrystof Tulinger $.script.loadScript('webjars/xss/1.0.8/dist/xss.min.js').done(function () { 1497d7d00a41SKrystof Tulinger $.script.loadScript('webjars/showdown/1.9.1/dist/showdown.min.js').done(function () { 1498d7d00a41SKrystof Tulinger $that.find('.markdown-content[data-markdown-download]').each(function () { 1499d7d00a41SKrystof Tulinger var $dataMarkdownDownloadEl = $(this); 1500d7d00a41SKrystof Tulinger if (converter === null) { 1501d7d00a41SKrystof Tulinger converter = new showdown.Converter(); 1502d7d00a41SKrystof Tulinger converter.setOption('tables', true); 1503d7d00a41SKrystof Tulinger converter.setOption('strikethrough', true); 1504d7d00a41SKrystof Tulinger converter.setOption('tasklists', true); 1505d7d00a41SKrystof Tulinger converter.setOption('simplifiedAutoLink', true); 1506d7d00a41SKrystof Tulinger converter.setOption('parseImgDimension', true); 1507d7d00a41SKrystof Tulinger converter.setOption('literalMidWordUnderscores', true); 1508d7d00a41SKrystof Tulinger } 1509d7d00a41SKrystof Tulinger 1510d7d00a41SKrystof Tulinger $.ajax({ 1511d7d00a41SKrystof Tulinger url: $(this).data('markdown-download'), 1512d7d00a41SKrystof Tulinger dataType: 'text', 1513d7d00a41SKrystof Tulinger timeout: 5000, 1514d7d00a41SKrystof Tulinger mimeType: 'text/plain' 1515d7d00a41SKrystof Tulinger }).done(function (payload) { 1516d7d00a41SKrystof Tulinger $dataMarkdownDownloadEl.html(filterXSS(converter.makeHtml(payload))).show(); 1517d7d00a41SKrystof Tulinger $that.addClass('markdown').find('[data-markdown-original]').hide(); 1518d7d00a41SKrystof Tulinger }); 1519d7d00a41SKrystof Tulinger }); 1520d7d00a41SKrystof Tulinger }); 1521d7d00a41SKrystof Tulinger }); 1522d7d00a41SKrystof Tulinger }); 1523d7d00a41SKrystof Tulinger} 1524d7d00a41SKrystof Tulinger 1525d7d00a41SKrystof Tulingerwindow.onload = function () { 1526d7d00a41SKrystof Tulinger for (let i in document.pageReady) { 1527d7d00a41SKrystof Tulinger document.pageReady[i](); 1528d7d00a41SKrystof Tulinger } 1529d7d00a41SKrystof Tulinger}; 1530d7d00a41SKrystof Tulinger 1531d7d00a41SKrystof Tulinger$(document).ready(function () { 1532d7d00a41SKrystof Tulinger for (let i in this.domReady) { 1533d7d00a41SKrystof Tulinger document.domReady[i](); 1534d7d00a41SKrystof Tulinger } 1535d7d00a41SKrystof Tulinger 1536d7d00a41SKrystof Tulinger /** 1537d7d00a41SKrystof Tulinger * Initialize scope scroll event to display scope information correctly when 1538d7d00a41SKrystof Tulinger * the element comes into the viewport. 1539d7d00a41SKrystof Tulinger */ 1540d7d00a41SKrystof Tulinger $('#src').each(function () { 1541d7d00a41SKrystof Tulinger init_scopes(); 1542d7d00a41SKrystof Tulinger }); 1543d7d00a41SKrystof Tulinger 1544d7d00a41SKrystof Tulinger /** 1545d7d00a41SKrystof Tulinger * Initialize table sorter on every directory listing. 1546d7d00a41SKrystof Tulinger */ 1547d7d00a41SKrystof Tulinger init_tablesorter(); 1548d7d00a41SKrystof Tulinger 1549d7d00a41SKrystof Tulinger /** 1550d7d00a41SKrystof Tulinger * Initialize intelligence window plugin. Presence of #contextpath indicates 1551d7d00a41SKrystof Tulinger * that we use the code view. 1552d7d00a41SKrystof Tulinger */ 1553d7d00a41SKrystof Tulinger $("#contextpath").each(function () { 1554d7d00a41SKrystof Tulinger $.intelliWindow.init(); 1555d7d00a41SKrystof Tulinger return false; 1556d7d00a41SKrystof Tulinger }); 1557d7d00a41SKrystof Tulinger 1558d7d00a41SKrystof Tulinger /** 1559d7d00a41SKrystof Tulinger * Initialize the messages plugin to display 1560d7d00a41SKrystof Tulinger * message onhover on every affected element. 1561d7d00a41SKrystof Tulinger */ 1562d7d00a41SKrystof Tulinger $.messagesWindow.init(); 1563d7d00a41SKrystof Tulinger 1564d7d00a41SKrystof Tulinger /** 1565d7d00a41SKrystof Tulinger * Attaches a onhover listener to display messages for affected elements. 1566d7d00a41SKrystof Tulinger */ 1567d7d00a41SKrystof Tulinger if ($.messagesWindow.initialized) { 1568d7d00a41SKrystof Tulinger $("[data-messages]").mouseenter(function () { 1569d7d00a41SKrystof Tulinger const data = $(this).data('messages') || []; 1570d7d00a41SKrystof Tulinger $.messagesWindow.update(data); 1571d7d00a41SKrystof Tulinger $.messagesWindow.show(); 1572d7d00a41SKrystof Tulinger }).mouseleave(function (e) { 1573d7d00a41SKrystof Tulinger $.messagesWindow.hide(); 1574d7d00a41SKrystof Tulinger }); 1575d7d00a41SKrystof Tulinger } 1576d7d00a41SKrystof Tulinger 1577d7d00a41SKrystof Tulinger /** 1578d7d00a41SKrystof Tulinger * Initialize spaces plugin which automatically inserts a single space between 1579d7d00a41SKrystof Tulinger * the line number and the following text. It strongly relies on the fact 1580d7d00a41SKrystof Tulinger * that the line numbers are stored in 'name' attribute on each line link. 1581d7d00a41SKrystof Tulinger */ 1582d7d00a41SKrystof Tulinger $.spaces.init(); 1583d7d00a41SKrystof Tulinger 1584d7d00a41SKrystof Tulinger /** 1585d7d00a41SKrystof Tulinger * Initialize the window hash management. Mainly this allows users to select 1586d7d00a41SKrystof Tulinger * multiple lines of code and use that url to send it to somebody else. 1587d7d00a41SKrystof Tulinger */ 1588d7d00a41SKrystof Tulinger $.hash.init({parent: "pre"}); 1589d7d00a41SKrystof Tulinger 1590d7d00a41SKrystof Tulinger /** 1591d7d00a41SKrystof Tulinger * After hitting the search button, the results or projects are temporarily hidden 1592d7d00a41SKrystof Tulinger * until the new page is loaded. That helps to distinguish if search is being in process. 1593d7d00a41SKrystof Tulinger */ 1594d7d00a41SKrystof Tulinger init_results_autohide(); 1595d7d00a41SKrystof Tulinger 1596d7d00a41SKrystof Tulinger /** 1597d7d00a41SKrystof Tulinger * Initialize the new project picker 1598d7d00a41SKrystof Tulinger */ 1599d7d00a41SKrystof Tulinger init_searchable_option_list(); 1600d7d00a41SKrystof Tulinger 1601d7d00a41SKrystof Tulinger /** 1602d7d00a41SKrystof Tulinger * Initialize the history input picker. 1603d7d00a41SKrystof Tulinger * Checkboxes are automatically covered with a click event and automatically 1604d7d00a41SKrystof Tulinger * colored as disabled or checked. 1605d7d00a41SKrystof Tulinger * 1606d7d00a41SKrystof Tulinger * Also works for paging where it stores the actual selected revision range in the 1607d7d00a41SKrystof Tulinger * pagination links. 1608d7d00a41SKrystof Tulinger */ 1609d7d00a41SKrystof Tulinger init_history_input(); 1610d7d00a41SKrystof Tulinger 1611d7d00a41SKrystof Tulinger /** 1612d7d00a41SKrystof Tulinger * Initialize the markdown converter. 1613d7d00a41SKrystof Tulinger * 1614d7d00a41SKrystof Tulinger * WARNING: The converter is not XSS safe. If you're not sure about what 1615d7d00a41SKrystof Tulinger * could occur in the readmes then rather comment out this. 1616d7d00a41SKrystof Tulinger */ 1617d7d00a41SKrystof Tulinger init_markdown_converter(); 1618d7d00a41SKrystof Tulinger 1619d7d00a41SKrystof Tulinger restoreFocusAfterSearchSubmit(); 1620d7d00a41SKrystof Tulinger}); 1621d7d00a41SKrystof Tulinger 1622d7d00a41SKrystof Tulinger/** 1623d7d00a41SKrystof Tulinger * Get a parameter value from the URL. 1624d7d00a41SKrystof Tulinger * 1625d7d00a41SKrystof Tulinger * @param p the name of the parameter 1626d7d00a41SKrystof Tulinger * @return the decoded value of parameter p 1627d7d00a41SKrystof Tulinger */ 1628d7d00a41SKrystof Tulingerfunction getParameter(p) { 1629d7d00a41SKrystof Tulinger // First split up the parameter list. That is, transform from 1630d7d00a41SKrystof Tulinger // ?a=b&c=d 1631d7d00a41SKrystof Tulinger // to 1632d7d00a41SKrystof Tulinger // [ ["a", "b"], ["c","d"] ] 1633d7d00a41SKrystof Tulinger if (getParameter.params === undefined) { 1634d7d00a41SKrystof Tulinger getParameter.params = window.location.search.substr(1).split("&").map( 1635d7d00a41SKrystof Tulinger function (x) { return x.split("="); }); 1636d7d00a41SKrystof Tulinger } 1637d7d00a41SKrystof Tulinger const params = getParameter.params; 1638d7d00a41SKrystof Tulinger // Then look for the parameter. 1639d7d00a41SKrystof Tulinger for (let i in params) { 1640d7d00a41SKrystof Tulinger if (params[i][0] === p && params[i].length > 1) { 1641d7d00a41SKrystof Tulinger return decodeURIComponent(params[i][1]); 1642d7d00a41SKrystof Tulinger } 1643d7d00a41SKrystof Tulinger } 1644d7d00a41SKrystof Tulinger return undefined; 1645d7d00a41SKrystof Tulinger} 1646d7d00a41SKrystof Tulinger 1647d7d00a41SKrystof Tulinger/** 1648d7d00a41SKrystof Tulinger * Set parameter in the given url. 1649d7d00a41SKrystof Tulinger * @param string url 1650d7d00a41SKrystof Tulinger * @param string p parameter name 1651d7d00a41SKrystof Tulinger * @param string v parameter value 1652d7d00a41SKrystof Tulinger * @returns string the modified url 1653d7d00a41SKrystof Tulinger */ 1654d7d00a41SKrystof Tulingerfunction setParameter(url, p, v) { 1655d7d00a41SKrystof Tulinger const base = url.substr(0, url.indexOf('?')); 1656d7d00a41SKrystof Tulinger const params = url.substr(base.length + 1).split("&").map( 1657d7d00a41SKrystof Tulinger function (x) { 1658d7d00a41SKrystof Tulinger return x.split("="); 1659d7d00a41SKrystof Tulinger }); 1660d7d00a41SKrystof Tulinger let found = false; 1661d7d00a41SKrystof Tulinger for (let i in params) { 1662d7d00a41SKrystof Tulinger if (params[i][0] === p && params[i].length > 1) { 1663d7d00a41SKrystof Tulinger params[i][1] = encodeURIComponent(v); 1664d7d00a41SKrystof Tulinger found = true; 1665d7d00a41SKrystof Tulinger } 1666d7d00a41SKrystof Tulinger } 1667d7d00a41SKrystof Tulinger if (!found) { 1668d7d00a41SKrystof Tulinger params.push([p, encodeURIComponent(v)]); 1669d7d00a41SKrystof Tulinger } 1670d7d00a41SKrystof Tulinger 1671d7d00a41SKrystof Tulinger return base + '?' + params.map(function (x) { 1672d7d00a41SKrystof Tulinger return x[0] + '=' + x[1]; 1673d7d00a41SKrystof Tulinger }).join('&'); 1674d7d00a41SKrystof Tulinger} 1675d7d00a41SKrystof Tulinger 1676d7d00a41SKrystof Tulingerfunction domReadyMast() { 1677d7d00a41SKrystof Tulinger if (!window.location.hash) { 1678d7d00a41SKrystof Tulinger const h = getParameter("h"); 1679d7d00a41SKrystof Tulinger if (h && h !== "") { 1680d7d00a41SKrystof Tulinger window.location.hash = h; 1681d7d00a41SKrystof Tulinger } 1682d7d00a41SKrystof Tulinger } 1683d7d00a41SKrystof Tulinger if (document.annotate) { 1684d7d00a41SKrystof Tulinger $('a.r').tooltip({ 1685d7d00a41SKrystof Tulinger content: function () { 1686d7d00a41SKrystof Tulinger const element = $(this); 1687d7d00a41SKrystof Tulinger const title = element.attr("title") || ""; 1688d7d00a41SKrystof Tulinger const parts = title.split(/<br\/>(?=[a-zA-Z0-9]+:)/g); 1689d7d00a41SKrystof Tulinger if (parts.length <= 0) { 1690d7d00a41SKrystof Tulinger return ""; 1691d7d00a41SKrystof Tulinger } 1692d7d00a41SKrystof Tulinger const $el = $("<dl>"); 1693d7d00a41SKrystof Tulinger for (let i = 0; i < parts.length; i++) { 1694d7d00a41SKrystof Tulinger const definitions = parts[i].split(":"); 1695d7d00a41SKrystof Tulinger if (definitions.length < 2) { 1696d7d00a41SKrystof Tulinger continue; 1697d7d00a41SKrystof Tulinger } 1698d7d00a41SKrystof Tulinger $("<dt>").text(definitions.shift().trim()).appendTo($el); 1699d7d00a41SKrystof Tulinger const $dd = $("<dd>"); 1700d7d00a41SKrystof Tulinger $.each(definitions.join(":").split("<br/>"), function (i, el) { 1701d7d00a41SKrystof Tulinger $dd.append(escapeHtml(el.trim())); 1702d7d00a41SKrystof Tulinger $dd.append($("<br/>")); 1703d7d00a41SKrystof Tulinger }); 1704d7d00a41SKrystof Tulinger $dd.appendTo($el); 1705d7d00a41SKrystof Tulinger } 1706d7d00a41SKrystof Tulinger return $el; 1707d7d00a41SKrystof Tulinger } 1708d7d00a41SKrystof Tulinger }); 1709d7d00a41SKrystof Tulinger 1710d7d00a41SKrystof Tulinger $("#toggle-annotate-by-javascript").css('display', 'inline'); 1711d7d00a41SKrystof Tulinger $("#toggle-annotate").hide(); 1712d7d00a41SKrystof Tulinger } 1713d7d00a41SKrystof Tulinger} 1714d7d00a41SKrystof Tulinger 1715d7d00a41SKrystof Tulingerfunction pageReadyMast() { 1716d7d00a41SKrystof Tulinger} 1717d7d00a41SKrystof Tulinger 1718d7d00a41SKrystof Tulingerfunction domReadyMenu(minisearch) { 1719d7d00a41SKrystof Tulinger if (getSettingsValue('suggester-enabled') === 'false') { 1720d7d00a41SKrystof Tulinger return; 1721d7d00a41SKrystof Tulinger } 1722d7d00a41SKrystof Tulinger 1723d7d00a41SKrystof Tulinger $.ajax({ 1724d7d00a41SKrystof Tulinger // cannot use "/api/v1/configuration/suggester" because of security 1725d7d00a41SKrystof Tulinger url: window.contextPath + "/api/v1/suggest/config", 1726d7d00a41SKrystof Tulinger dataType: "json", 1727d7d00a41SKrystof Tulinger success: function(config) { 1728d7d00a41SKrystof Tulinger if (config.enabled) { 1729d7d00a41SKrystof Tulinger initAutocomplete(config, minisearch); 1730d7d00a41SKrystof Tulinger } 1731d7d00a41SKrystof Tulinger }, 1732d7d00a41SKrystof Tulinger error: function(xhr, ajaxOptions, error) { 1733d7d00a41SKrystof Tulinger console.log('Could not get autocomplete configuration, probably disabled'); 1734d7d00a41SKrystof Tulinger } 1735d7d00a41SKrystof Tulinger }); 1736d7d00a41SKrystof Tulinger} 1737d7d00a41SKrystof Tulinger 1738d7d00a41SKrystof Tulingerfunction initAutocomplete(config, minisearch) { 1739d7d00a41SKrystof Tulinger if (minisearch) { 1740d7d00a41SKrystof Tulinger initMinisearchAutocomplete(config); 1741d7d00a41SKrystof Tulinger } else { 1742d7d00a41SKrystof Tulinger initAutocompleteForField("full", "full", config); 1743d7d00a41SKrystof Tulinger initAutocompleteForField("defs", "defs", config); 1744d7d00a41SKrystof Tulinger initAutocompleteForField("refs", "refs", config); 1745d7d00a41SKrystof Tulinger initAutocompleteForField("path", "path", config); 1746d7d00a41SKrystof Tulinger initAutocompleteForField("hist", "hist", config); 1747d7d00a41SKrystof Tulinger } 1748d7d00a41SKrystof Tulinger} 1749d7d00a41SKrystof Tulinger 1750d7d00a41SKrystof Tulingerfunction initMinisearchAutocomplete(config) { 1751d7d00a41SKrystof Tulinger if (config.allowedFields && config.allowedFields.indexOf('full') < 0) { 1752d7d00a41SKrystof Tulinger return; 1753d7d00a41SKrystof Tulinger } 1754d7d00a41SKrystof Tulinger 1755d7d00a41SKrystof Tulinger let project = ''; 1756d7d00a41SKrystof Tulinger 1757d7d00a41SKrystof Tulinger var projectElem = $('#minisearch-project'); 1758d7d00a41SKrystof Tulinger if (projectElem) { 1759d7d00a41SKrystof Tulinger project = projectElem.val(); 1760d7d00a41SKrystof Tulinger } 1761d7d00a41SKrystof Tulinger 1762d7d00a41SKrystof Tulinger const pathElem = $('#minisearch-path'); 1763d7d00a41SKrystof Tulinger 1764d7d00a41SKrystof Tulinger initAutocompleteForField('search', 'full', config, function (input, field) { 1765d7d00a41SKrystof Tulinger const caretPos = input.caret(); 1766d7d00a41SKrystof Tulinger if (!(typeof caretPos === 'number')) { 1767d7d00a41SKrystof Tulinger console.error("Suggest: could not get caret position"); 1768d7d00a41SKrystof Tulinger return; 1769d7d00a41SKrystof Tulinger } 1770d7d00a41SKrystof Tulinger return { 1771d7d00a41SKrystof Tulinger projects: [project], 1772d7d00a41SKrystof Tulinger field: field, 1773d7d00a41SKrystof Tulinger full: input.val(), 1774d7d00a41SKrystof Tulinger path: pathElem.is(':checked') ? pathElem.val() : '', 1775d7d00a41SKrystof Tulinger caret: caretPos 1776d7d00a41SKrystof Tulinger }; 1777d7d00a41SKrystof Tulinger }, 'search'); 1778d7d00a41SKrystof Tulinger} 1779d7d00a41SKrystof Tulinger 1780d7d00a41SKrystof Tulingerfunction initAutocompleteForField(inputId, field, config, dataFunction, errorElemId) { 1781d7d00a41SKrystof Tulinger if (config.allowedFields && config.allowedFields.indexOf(field) < 0) { 1782d7d00a41SKrystof Tulinger return; 1783d7d00a41SKrystof Tulinger } 1784d7d00a41SKrystof Tulinger 1785d7d00a41SKrystof Tulinger let text; 1786d7d00a41SKrystof Tulinger let identifier; 1787d7d00a41SKrystof Tulinger let time; 1788d7d00a41SKrystof Tulinger let partialResult; 1789d7d00a41SKrystof Tulinger 1790d7d00a41SKrystof Tulinger const input = $("#" + inputId); 1791d7d00a41SKrystof Tulinger 1792d7d00a41SKrystof Tulinger if (!dataFunction) { 1793d7d00a41SKrystof Tulinger dataFunction = getAutocompleteMenuData; 1794d7d00a41SKrystof Tulinger } 1795d7d00a41SKrystof Tulinger if (!errorElemId) { 1796d7d00a41SKrystof Tulinger errorElemId = 'full'; 1797d7d00a41SKrystof Tulinger } 1798d7d00a41SKrystof Tulinger const errorElem = $('#' + errorElemId); 1799d7d00a41SKrystof Tulinger 1800d7d00a41SKrystof Tulinger input.autocomplete({ 1801d7d00a41SKrystof Tulinger source: function(request, response) { 1802d7d00a41SKrystof Tulinger $.ajax({ 1803d7d00a41SKrystof Tulinger url: window.contextPath + "/api/v1/suggest", 1804d7d00a41SKrystof Tulinger dataType: "json", 1805d7d00a41SKrystof Tulinger data: dataFunction(input, field), 1806d7d00a41SKrystof Tulinger success: function(data) { 1807d7d00a41SKrystof Tulinger hideError(errorElem); 1808d7d00a41SKrystof Tulinger 1809d7d00a41SKrystof Tulinger text = data.queryText; 1810d7d00a41SKrystof Tulinger identifier = data.identifier; 1811d7d00a41SKrystof Tulinger time = data.time; 1812d7d00a41SKrystof Tulinger partialResult = data.partialResult; 1813d7d00a41SKrystof Tulinger 1814d7d00a41SKrystof Tulinger response(data.suggestions); 1815d7d00a41SKrystof Tulinger }, 1816d7d00a41SKrystof Tulinger error: function(xhr, ajaxOptions, error) { 1817d7d00a41SKrystof Tulinger input.autocomplete("close"); 1818d7d00a41SKrystof Tulinger response(undefined); // to remove loading indicator 1819d7d00a41SKrystof Tulinger 1820d7d00a41SKrystof Tulinger showError(xhr.responseJSON.message, errorElem); 1821d7d00a41SKrystof Tulinger }, 1822d7d00a41SKrystof Tulinger statusCode: { 1823d7d00a41SKrystof Tulinger 404: function() { 1824d7d00a41SKrystof Tulinger response(); // do not show anything 1825d7d00a41SKrystof Tulinger } 1826d7d00a41SKrystof Tulinger } 1827d7d00a41SKrystof Tulinger }); 1828d7d00a41SKrystof Tulinger }, 1829d7d00a41SKrystof Tulinger create: function () { 1830d7d00a41SKrystof Tulinger $(this).data('ui-autocomplete')._renderItem = function (ul, item) { 1831d7d00a41SKrystof Tulinger const listItem = getSuggestionListItem(item, config); 1832d7d00a41SKrystof Tulinger 1833d7d00a41SKrystof Tulinger return listItem.appendTo(ul); 1834d7d00a41SKrystof Tulinger }; 1835d7d00a41SKrystof Tulinger 1836d7d00a41SKrystof Tulinger $(this).data('ui-autocomplete')._renderMenu = function (ul, items) { 1837d7d00a41SKrystof Tulinger const _this = this; 1838d7d00a41SKrystof Tulinger $.each(items, function(index, item) { 1839d7d00a41SKrystof Tulinger _this._renderItemData(ul, item); 1840d7d00a41SKrystof Tulinger }); 1841d7d00a41SKrystof Tulinger if (config.showTime) { 1842d7d00a41SKrystof Tulinger $("<li>", { 1843d7d00a41SKrystof Tulinger "class": "ui-state-disabled", 1844d7d00a41SKrystof Tulinger style: 'padding-left: 5px;', 1845d7d00a41SKrystof Tulinger text: time + ' ms' 1846d7d00a41SKrystof Tulinger }).appendTo(ul); 1847d7d00a41SKrystof Tulinger } 1848d7d00a41SKrystof Tulinger if (partialResult) { 1849d7d00a41SKrystof Tulinger $("<li>", { 1850d7d00a41SKrystof Tulinger "class": "ui-state-disabled", 1851d7d00a41SKrystof Tulinger style: 'padding-left: 5px;', 1852d7d00a41SKrystof Tulinger text: 'Partial result due to timeout' 1853d7d00a41SKrystof Tulinger }).appendTo(ul); 1854d7d00a41SKrystof Tulinger } 1855d7d00a41SKrystof Tulinger }; 1856d7d00a41SKrystof Tulinger }, 1857d7d00a41SKrystof Tulinger focus: function (event, ui) { 1858d7d00a41SKrystof Tulinger if (ui.item.selectable === false) { 1859d7d00a41SKrystof Tulinger event.preventDefault(); 1860d7d00a41SKrystof Tulinger return; 1861d7d00a41SKrystof Tulinger } 1862d7d00a41SKrystof Tulinger if (event.originalEvent.originalEvent.type.indexOf('key') === 0) { // replace value only on key events 1863d7d00a41SKrystof Tulinger replaceValueWithSuggestion(input, text, identifier, ui.item.phrase); 1864d7d00a41SKrystof Tulinger } 1865d7d00a41SKrystof Tulinger 1866d7d00a41SKrystof Tulinger event.preventDefault(); // to prevent the movement of the caret to the end 1867d7d00a41SKrystof Tulinger }, 1868d7d00a41SKrystof Tulinger select: function (event, ui) { 1869d7d00a41SKrystof Tulinger replaceValueWithSuggestion(input, text, identifier, ui.item.phrase); 1870d7d00a41SKrystof Tulinger 1871d7d00a41SKrystof Tulinger event.preventDefault(); // to prevent the movement of the caret to the end 1872d7d00a41SKrystof Tulinger }, 1873d7d00a41SKrystof Tulinger response: function (event, ui) { 1874d7d00a41SKrystof Tulinger if (!ui.content) { 1875d7d00a41SKrystof Tulinger // error occurred 1876d7d00a41SKrystof Tulinger return; 1877d7d00a41SKrystof Tulinger } 1878d7d00a41SKrystof Tulinger if (ui.content.length === 0 && !partialResult) { 1879d7d00a41SKrystof Tulinger const noMatchesFoundResult = {phrase: 'No matches found', selectable: false}; 1880d7d00a41SKrystof Tulinger ui.content.push(noMatchesFoundResult); 1881d7d00a41SKrystof Tulinger } 1882d7d00a41SKrystof Tulinger }, 1883d7d00a41SKrystof Tulinger minLength: config.minChars 1884d7d00a41SKrystof Tulinger }).click(function() { 1885d7d00a41SKrystof Tulinger $(this).autocomplete('search', $(this).val()); 1886d7d00a41SKrystof Tulinger }).keyup(function(e) { 1887d7d00a41SKrystof Tulinger if (e.keyCode === 37 || e.keyCode === 39) { // left or right arrow key 1888d7d00a41SKrystof Tulinger $(this).autocomplete('search', $(this).val()); 1889d7d00a41SKrystof Tulinger } 1890d7d00a41SKrystof Tulinger // try to refresh on empty input (error might go away) except when pressed esc key 1891d7d00a41SKrystof Tulinger if (input.val() === "" && e.keyCode !== 27) { 1892d7d00a41SKrystof Tulinger $(this).autocomplete('search', ' '); 1893d7d00a41SKrystof Tulinger } 1894d7d00a41SKrystof Tulinger }); 1895d7d00a41SKrystof Tulinger} 1896d7d00a41SKrystof Tulinger 1897d7d00a41SKrystof Tulingerfunction getAutocompleteMenuData(input, field) { 1898d7d00a41SKrystof Tulinger const caretPos = input.caret(); 1899d7d00a41SKrystof Tulinger if (!Number.isInteger(caretPos)) { 1900d7d00a41SKrystof Tulinger console.error("Suggest: could not get caret position"); 1901d7d00a41SKrystof Tulinger return; 1902d7d00a41SKrystof Tulinger } 1903d7d00a41SKrystof Tulinger return { 1904d7d00a41SKrystof Tulinger projects: getSelectedProjectNames(), 1905d7d00a41SKrystof Tulinger field: field, 1906d7d00a41SKrystof Tulinger full: $('#full').val(), 1907d7d00a41SKrystof Tulinger defs: $('#defs').val(), 1908d7d00a41SKrystof Tulinger refs: $('#refs').val(), 1909d7d00a41SKrystof Tulinger path: $('#path').val(), 1910d7d00a41SKrystof Tulinger hist: $('#hist').val(), 1911d7d00a41SKrystof Tulinger type: $('#type').val(), 1912d7d00a41SKrystof Tulinger caret: caretPos 1913d7d00a41SKrystof Tulinger }; 1914d7d00a41SKrystof Tulinger} 1915d7d00a41SKrystof Tulinger 1916d7d00a41SKrystof Tulingerfunction replaceValueWithSuggestion(input, queryText, identifier, suggestion) { 1917d7d00a41SKrystof Tulinger const pos = queryText.indexOf(identifier); 1918d7d00a41SKrystof Tulinger const phrase = escapeLuceneCharacters(suggestion); 1919d7d00a41SKrystof Tulinger input.val(queryText.replace(identifier, phrase)); 1920d7d00a41SKrystof Tulinger input.caret(pos + phrase.length); 1921d7d00a41SKrystof Tulinger} 1922d7d00a41SKrystof Tulinger 1923d7d00a41SKrystof Tulingerfunction showError(errorText, errorElem) { 1924d7d00a41SKrystof Tulinger const parent = errorElem.parent(); 1925d7d00a41SKrystof Tulinger 1926d7d00a41SKrystof Tulinger parent.css('position', 'relative'); 1927d7d00a41SKrystof Tulinger 1928d7d00a41SKrystof Tulinger let span = parent.find('#autocomplete-error')[0]; 1929d7d00a41SKrystof Tulinger if (!span) { 1930d7d00a41SKrystof Tulinger span = $("<span>", { 1931d7d00a41SKrystof Tulinger "class": "note-error important-note important-note-rounded", 1932d7d00a41SKrystof Tulinger style: "right: -10px; position: absolute; top: 0px;", 1933d7d00a41SKrystof Tulinger text: "!", 1934d7d00a41SKrystof Tulinger id: 'autocomplete-error' 1935d7d00a41SKrystof Tulinger }); 1936d7d00a41SKrystof Tulinger 1937d7d00a41SKrystof Tulinger span.appendTo(parent); 1938d7d00a41SKrystof Tulinger } else { 1939d7d00a41SKrystof Tulinger span = $(span); 1940d7d00a41SKrystof Tulinger span.off("mouseenter mouseleave"); 1941d7d00a41SKrystof Tulinger } 1942d7d00a41SKrystof Tulinger 1943d7d00a41SKrystof Tulinger span.hover(function() { // mouse in 1944d7d00a41SKrystof Tulinger $.messagesWindow.empty(); 1945d7d00a41SKrystof Tulinger $.messagesWindow.append(escapeHtml(errorText)); 1946d7d00a41SKrystof Tulinger $.messagesWindow.show(); 1947d7d00a41SKrystof Tulinger }, function() { // mouse out 1948d7d00a41SKrystof Tulinger $.messagesWindow.hide(); 1949d7d00a41SKrystof Tulinger }); 1950d7d00a41SKrystof Tulinger} 1951d7d00a41SKrystof Tulinger 1952d7d00a41SKrystof Tulingerfunction hideError(errorElem) { 1953d7d00a41SKrystof Tulinger const parent = errorElem.parent(); 1954d7d00a41SKrystof Tulinger const span = parent.find('#autocomplete-error')[0]; 1955d7d00a41SKrystof Tulinger if (span) { 1956d7d00a41SKrystof Tulinger span.remove(); 1957d7d00a41SKrystof Tulinger } 1958d7d00a41SKrystof Tulinger} 1959d7d00a41SKrystof Tulinger 1960d7d00a41SKrystof Tulingerfunction getSuggestionListItem(itemData, config) { 1961d7d00a41SKrystof Tulinger if (itemData.selectable === false) { 1962d7d00a41SKrystof Tulinger return $("<li>", { 1963d7d00a41SKrystof Tulinger "class": "ui-state-disabled", 1964d7d00a41SKrystof Tulinger text: itemData.phrase 1965d7d00a41SKrystof Tulinger }); 1966d7d00a41SKrystof Tulinger } 1967d7d00a41SKrystof Tulinger 1968d7d00a41SKrystof Tulinger const listItem = $("<li>", { 1969d7d00a41SKrystof Tulinger "class": "ui-menu-item", 1970d7d00a41SKrystof Tulinger style: "display: block;" 1971d7d00a41SKrystof Tulinger }); 1972d7d00a41SKrystof Tulinger const listItemChild = $("<div>", { 1973d7d00a41SKrystof Tulinger "class": "ui-menu-item-wrapper", 1974d7d00a41SKrystof Tulinger style: "height: 20px; padding: 0;", 1975d7d00a41SKrystof Tulinger tabindex: "-1" 1976d7d00a41SKrystof Tulinger }); 1977d7d00a41SKrystof Tulinger 1978d7d00a41SKrystof Tulinger listItemChild.appendTo(listItem); 1979d7d00a41SKrystof Tulinger 1980d7d00a41SKrystof Tulinger $("<span>", { 1981d7d00a41SKrystof Tulinger text: itemData.phrase, 1982d7d00a41SKrystof Tulinger style: "float: left; padding-left: 5px; max-height: 20px;" 1983d7d00a41SKrystof Tulinger }).appendTo(listItemChild); 1984d7d00a41SKrystof Tulinger 1985d7d00a41SKrystof Tulinger let projectInfoText = ""; 1986d7d00a41SKrystof Tulinger if (config.showProjects) { 1987d7d00a41SKrystof Tulinger if (itemData.projects.length > 1) { 1988d7d00a41SKrystof Tulinger projectInfoText = 'Found in ' + itemData.projects.length + ' projects'; 1989d7d00a41SKrystof Tulinger } else { 1990d7d00a41SKrystof Tulinger projectInfoText = itemData.projects[0]; 1991d7d00a41SKrystof Tulinger } 1992d7d00a41SKrystof Tulinger } 1993d7d00a41SKrystof Tulinger 1994d7d00a41SKrystof Tulinger let score = ""; 1995d7d00a41SKrystof Tulinger if (config.showScores) { 1996d7d00a41SKrystof Tulinger score = ' (' + itemData.score + ')'; 1997d7d00a41SKrystof Tulinger } 1998d7d00a41SKrystof Tulinger $("<span>", { 1999d7d00a41SKrystof Tulinger text: projectInfoText + score, 2000d7d00a41SKrystof Tulinger style: "float: right; color: #999999; font-style: italic; padding-right: 5px;" 2001d7d00a41SKrystof Tulinger }).appendTo(listItemChild); 2002d7d00a41SKrystof Tulinger 2003d7d00a41SKrystof Tulinger return listItem; 2004d7d00a41SKrystof Tulinger} 2005d7d00a41SKrystof Tulinger 2006d7d00a41SKrystof Tulingerfunction escapeLuceneCharacters(term) { 2007d7d00a41SKrystof Tulinger // must escape: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ 2008d7d00a41SKrystof Tulinger const pattern = /([\+\-\!\(\)\{\}\[\]\^\"\~\*\?\:\\]|&&|\|\|)/g; 2009d7d00a41SKrystof Tulinger 2010d7d00a41SKrystof Tulinger return term.replace(pattern, "\\$1"); 2011d7d00a41SKrystof Tulinger} 2012d7d00a41SKrystof Tulinger 2013d7d00a41SKrystof Tulingerfunction domReadyHistory() { 2014d7d00a41SKrystof Tulinger // start state should ALWAYS be: first row: r1 hidden, r2 checked ; 2015d7d00a41SKrystof Tulinger // second row: r1 clicked, (r2 hidden)(optionally) 2016d7d00a41SKrystof Tulinger // I cannot say what will happen if they are not like that, togglediffs 2017d7d00a41SKrystof Tulinger // will go mad ! 2018d7d00a41SKrystof Tulinger togglerevs(); 2019d7d00a41SKrystof Tulinger toggleProjectInfo(); 2020d7d00a41SKrystof Tulinger} 2021d7d00a41SKrystof Tulinger 2022d7d00a41SKrystof Tulingerfunction get_annotations() { 2023d7d00a41SKrystof Tulinger let link = window.location.pathname + "?a=true"; 2024d7d00a41SKrystof Tulinger if (document.rev && document.rev()) { 2025d7d00a41SKrystof Tulinger link += "&r=" + encodeURIComponent(document.rev()); 2026d7d00a41SKrystof Tulinger } 2027d7d00a41SKrystof Tulinger if (window.location.hash) { 2028d7d00a41SKrystof Tulinger // If a line is highlighted when "annotate" is clicked, we want to 2029d7d00a41SKrystof Tulinger // preserve the highlighting, but we don't want the page to scroll 2030d7d00a41SKrystof Tulinger // to the highlighted line. So put the line number in a URL parameter 2031d7d00a41SKrystof Tulinger // instead of in the hash. 2032d7d00a41SKrystof Tulinger link += "&h="; 2033d7d00a41SKrystof Tulinger link += window.location.hash.substring(1, window.location.hash.length); 2034d7d00a41SKrystof Tulinger } 2035d7d00a41SKrystof Tulinger window.location = link; 2036d7d00a41SKrystof Tulinger} 2037d7d00a41SKrystof Tulinger 2038d7d00a41SKrystof Tulingerfunction toggle_annotations() { 2039d7d00a41SKrystof Tulinger $(document.body).toggleClass("blame-hidden"); 2040d7d00a41SKrystof Tulinger} 2041d7d00a41SKrystof Tulinger 2042d7d00a41SKrystof Tulinger/** list.jsp */ 2043d7d00a41SKrystof Tulinger 2044d7d00a41SKrystof Tulinger/** 2045d7d00a41SKrystof Tulinger * Initialize defaults for list.jsp 2046d7d00a41SKrystof Tulinger */ 2047d7d00a41SKrystof Tulingerfunction pageReadyList() { 2048d7d00a41SKrystof Tulinger document.highlight_count = 0; 2049d7d00a41SKrystof Tulinger $.navigateWindow.init(); 2050d7d00a41SKrystof Tulinger if (typeof get_sym_list === 'function') { 2051d7d00a41SKrystof Tulinger $.navigateWindow.update(get_sym_list()); 2052d7d00a41SKrystof Tulinger } 2053d7d00a41SKrystof Tulinger $('#navigate').click(function () { 2054d7d00a41SKrystof Tulinger $.navigateWindow.toggle(); 2055d7d00a41SKrystof Tulinger return false; 2056d7d00a41SKrystof Tulinger }); 2057d7d00a41SKrystof Tulinger} 2058d7d00a41SKrystof Tulinger 2059d7d00a41SKrystof Tulinger/** 2060d7d00a41SKrystof Tulinger * Toggle the display of line numbers. 2061d7d00a41SKrystof Tulinger */ 2062d7d00a41SKrystof Tulingerfunction lntoggle() { 2063d7d00a41SKrystof Tulinger $(document.body).toggleClass("lines-hidden"); 2064d7d00a41SKrystof Tulinger $('.fold-space, .fold-icon, .unfold-icon').toggle(); 2065d7d00a41SKrystof Tulinger} 2066d7d00a41SKrystof Tulinger 2067d7d00a41SKrystof Tulingerfunction lnshow() { 2068d7d00a41SKrystof Tulinger $(document.body).removeClass("lines-hidden"); 2069d7d00a41SKrystof Tulinger $('.fold-space, .fold-icon, .unfold-icon').show(); 2070d7d00a41SKrystof Tulinger} 2071d7d00a41SKrystof Tulinger 2072d7d00a41SKrystof Tulinger/* ------ Highlighting ------ */ 2073d7d00a41SKrystof Tulinger 2074d7d00a41SKrystof Tulinger/** 2075d7d00a41SKrystof Tulinger * Highlight keywords by changing the style of matching tags. 2076d7d00a41SKrystof Tulinger */ 2077d7d00a41SKrystof Tulingerfunction highlightKeyword(keyword) { 2078d7d00a41SKrystof Tulinger const high_colors = [ "#ffff66", "#ffcccc", "#ccccff", "#99ff99", "#cc66ff" ]; 2079d7d00a41SKrystof Tulinger const pattern = "a:contains('" + keyword + "')"; 2080d7d00a41SKrystof Tulinger $(pattern).css({ 2081d7d00a41SKrystof Tulinger 'text-decoration' : 'underline', 2082d7d00a41SKrystof Tulinger 'background-color' : high_colors[document.highlight_count % high_colors.length], 2083d7d00a41SKrystof Tulinger 'font-weight' : 'bold' 2084d7d00a41SKrystof Tulinger }); 2085d7d00a41SKrystof Tulinger document.highlight_count++; 2086d7d00a41SKrystof Tulinger} 2087d7d00a41SKrystof Tulinger//Test: HighlightKeyword('timeval'); 2088d7d00a41SKrystof Tulinger 2089d7d00a41SKrystof Tulinger/** 2090d7d00a41SKrystof Tulinger * Highlight the text given as value of the element with the ID "input_highlight" . 2091d7d00a41SKrystof Tulinger * @see HighlightKeyword 2092d7d00a41SKrystof Tulinger */ 2093d7d00a41SKrystof Tulingerfunction add_highlight() { 2094d7d00a41SKrystof Tulinger const tbox = document.getElementById('input_highlight'); 2095d7d00a41SKrystof Tulinger highlightKeyword(tbox.value); 2096d7d00a41SKrystof Tulinger} 2097d7d00a41SKrystof Tulinger 2098d7d00a41SKrystof Tulingerfunction toggle_filelist() { 2099d7d00a41SKrystof Tulinger const $a = $('div.filelist'); 2100d7d00a41SKrystof Tulinger const $b = $('div.filelist-hidden'); 2101d7d00a41SKrystof Tulinger $a.toggle().toggleClass('filelist').toggleClass('filelist-hidden'); 2102d7d00a41SKrystof Tulinger $b.toggle().toggleClass('filelist').toggleClass('filelist-hidden'); 2103d7d00a41SKrystof Tulinger} 2104d7d00a41SKrystof Tulinger 2105d7d00a41SKrystof Tulingerfunction toggle_revtags() { 2106d7d00a41SKrystof Tulinger const $a = $('tr.revtags, span.revtags'); 2107d7d00a41SKrystof Tulinger const $b = $('tr.revtags-hidden, span.revtags-hidden'); 2108d7d00a41SKrystof Tulinger $a.toggle().toggleClass('revtags').toggleClass('revtags-hidden'); 2109d7d00a41SKrystof Tulinger $b.toggle().toggleClass('revtags').toggleClass('revtags-hidden'); 2110d7d00a41SKrystof Tulinger} 2111d7d00a41SKrystof Tulinger 2112d7d00a41SKrystof Tulinger/** 2113d7d00a41SKrystof Tulinger * Function to toggle message length presentation 2114d7d00a41SKrystof Tulinger */ 2115d7d00a41SKrystof Tulingerfunction toggleCommon(closestType) { 2116d7d00a41SKrystof Tulinger $(".rev-toggle-a").click(function() { 2117d7d00a41SKrystof Tulinger const toggleState = $(this).closest(closestType).attr("data-toggle-state"); 2118d7d00a41SKrystof Tulinger const thisCell = $(this).closest("td"); 2119d7d00a41SKrystof Tulinger 2120d7d00a41SKrystof Tulinger if (toggleState === "less") { 2121d7d00a41SKrystof Tulinger $(this).closest(closestType).attr("data-toggle-state", "more"); 2122d7d00a41SKrystof Tulinger thisCell.find(".rev-message-summary").addClass("rev-message-hidden"); 2123d7d00a41SKrystof Tulinger thisCell.find(".rev-message-full").removeClass("rev-message-hidden"); 2124d7d00a41SKrystof Tulinger $(this).html("... show less"); 2125d7d00a41SKrystof Tulinger } 2126d7d00a41SKrystof Tulinger else if (toggleState === "more") { 2127d7d00a41SKrystof Tulinger $(this).closest(closestType).attr("data-toggle-state", "less"); 2128d7d00a41SKrystof Tulinger thisCell.find(".rev-message-full").addClass("rev-message-hidden"); 2129d7d00a41SKrystof Tulinger thisCell.find(".rev-message-summary").removeClass("rev-message-hidden"); 2130d7d00a41SKrystof Tulinger $(this).html("show more ..."); 2131d7d00a41SKrystof Tulinger } 2132d7d00a41SKrystof Tulinger 2133d7d00a41SKrystof Tulinger return false; 2134d7d00a41SKrystof Tulinger }); 2135d7d00a41SKrystof Tulinger} 2136d7d00a41SKrystof Tulinger 2137d7d00a41SKrystof Tulinger/** 2138d7d00a41SKrystof Tulinger * Function to toggle revision message length for long revision messages 2139d7d00a41SKrystof Tulinger */ 2140d7d00a41SKrystof Tulingerfunction togglerevs() { 2141d7d00a41SKrystof Tulinger $(".rev-toggle-a").click(toggleCommon("p")); 2142d7d00a41SKrystof Tulinger} 2143d7d00a41SKrystof Tulinger/** 2144d7d00a41SKrystof Tulinger * Function to toggle project info message length 2145d7d00a41SKrystof Tulinger */ 2146d7d00a41SKrystof Tulingerfunction toggleProjectInfo() { 2147d7d00a41SKrystof Tulinger $(".rev-toggle-a").click(toggleCommon("span")); 2148d7d00a41SKrystof Tulinger} 2149d7d00a41SKrystof Tulinger 2150d7d00a41SKrystof Tulingerfunction selectAllProjects() { 2151d7d00a41SKrystof Tulinger if ($("#project").data(SearchableOptionList.prototype.DATA_KEY)) { 2152d7d00a41SKrystof Tulinger $("#project").searchableOptionList().selectAll(); 2153d7d00a41SKrystof Tulinger } else { 2154d7d00a41SKrystof Tulinger $("#project option").prop('selected', true); 2155d7d00a41SKrystof Tulinger } 2156d7d00a41SKrystof Tulinger} 2157d7d00a41SKrystof Tulinger 2158d7d00a41SKrystof Tulingerfunction invertAllProjects() { 2159d7d00a41SKrystof Tulinger if ($("#project").data(SearchableOptionList.prototype.DATA_KEY)) { 2160d7d00a41SKrystof Tulinger $("#project").searchableOptionList().invert(); 2161d7d00a41SKrystof Tulinger } else { 2162d7d00a41SKrystof Tulinger $("#project option").each(function () { 2163d7d00a41SKrystof Tulinger $(this).prop('selected', !$(this).prop('selected')); 2164d7d00a41SKrystof Tulinger }); 2165d7d00a41SKrystof Tulinger } 2166d7d00a41SKrystof Tulinger} 2167d7d00a41SKrystof Tulinger 2168d7d00a41SKrystof Tulingerfunction deselectAllProjects() { 2169d7d00a41SKrystof Tulinger if ($("#project").data(SearchableOptionList.prototype.DATA_KEY)) { 2170d7d00a41SKrystof Tulinger $("#project").searchableOptionList().deselectAll(); 2171d7d00a41SKrystof Tulinger } else { 2172d7d00a41SKrystof Tulinger $("#project option").prop('selected', false); 2173d7d00a41SKrystof Tulinger } 2174d7d00a41SKrystof Tulinger} 2175d7d00a41SKrystof Tulinger 2176d7d00a41SKrystof Tulingerfunction clearSearchFrom() { 2177d7d00a41SKrystof Tulinger $("#sbox input[type='text']").each(function () { 2178d7d00a41SKrystof Tulinger $(this).val(""); 2179d7d00a41SKrystof Tulinger }); 2180d7d00a41SKrystof Tulinger $("#type").searchableOptionList().selectRadio(""); 2181d7d00a41SKrystof Tulinger} 2182d7d00a41SKrystof Tulinger 2183d7d00a41SKrystof Tulingerfunction getSelectedProjectNames() { 2184d7d00a41SKrystof Tulinger try { 2185d7d00a41SKrystof Tulinger return $.map($("#project").searchableOptionList().getSelection().filter("[name='project']"), function (item) { 2186d7d00a41SKrystof Tulinger return $(item).attr("value"); 2187d7d00a41SKrystof Tulinger }); 2188d7d00a41SKrystof Tulinger } catch (e) { // happens when projects are not enabled 2189d7d00a41SKrystof Tulinger return []; 2190d7d00a41SKrystof Tulinger } 2191d7d00a41SKrystof Tulinger} 2192d7d00a41SKrystof Tulinger 2193d7d00a41SKrystof Tulinger/** 2194d7d00a41SKrystof Tulinger * Fold or unfold a function definition. 2195d7d00a41SKrystof Tulinger */ 2196d7d00a41SKrystof Tulingerfunction fold(id) { 2197d7d00a41SKrystof Tulinger $('#' + id + '_fold_icon'). 2198d7d00a41SKrystof Tulinger children(). 2199d7d00a41SKrystof Tulinger first(). 2200d7d00a41SKrystof Tulinger toggleClass('unfold-icon'). 2201d7d00a41SKrystof Tulinger toggleClass('fold-icon'); 2202d7d00a41SKrystof Tulinger $('#' + id + '_fold').toggle('fold'); 2203d7d00a41SKrystof Tulinger} 2204d7d00a41SKrystof Tulinger 2205d7d00a41SKrystof Tulingerlet scope_timeout = null; 2206d7d00a41SKrystof Tulinger/** 2207d7d00a41SKrystof Tulinger * Function that is called when the #content div element is scrolled. Checks 2208d7d00a41SKrystof Tulinger * if the top of the page is inside a function scope. If so, update the 2209d7d00a41SKrystof Tulinger * scope element to show the name of the function and a link to its definition. 2210d7d00a41SKrystof Tulinger */ 2211d7d00a41SKrystof Tulingerfunction scope_on_scroll() { 2212d7d00a41SKrystof Tulinger if($.scopesWindow && $.scopesWindow.initialized && !$.scopesWindow.is(':visible')) { 2213d7d00a41SKrystof Tulinger return; 2214d7d00a41SKrystof Tulinger } 2215d7d00a41SKrystof Tulinger if (scope_timeout !== null) { 2216d7d00a41SKrystof Tulinger clearTimeout(scope_timeout); 2217d7d00a41SKrystof Tulinger scope_timeout = null; 2218d7d00a41SKrystof Tulinger } 2219d7d00a41SKrystof Tulinger scope_timeout = setTimeout(function () { 2220d7d00a41SKrystof Tulinger const y = $('#whole_header').outerHeight() + 2; 2221d7d00a41SKrystof Tulinger const c = document.elementFromPoint(15, y + 1); 2222d7d00a41SKrystof Tulinger 2223d7d00a41SKrystof Tulinger if ($(c).is('.l, .hl')) { 2224d7d00a41SKrystof Tulinger const $par = $(c).closest('.scope-body, .scope-head'); 2225d7d00a41SKrystof Tulinger 2226d7d00a41SKrystof Tulinger if (!$par.length) { 2227d7d00a41SKrystof Tulinger return; 2228d7d00a41SKrystof Tulinger } 2229d7d00a41SKrystof Tulinger 2230d7d00a41SKrystof Tulinger const $head = $par.hasClass('scope-body') ? $par.prev() : $par; 2231d7d00a41SKrystof Tulinger const $sig = $head.children().first(); 2232d7d00a41SKrystof Tulinger if ($.scopesWindow.initialized) { 2233d7d00a41SKrystof Tulinger $.scopesWindow.update({ 2234d7d00a41SKrystof Tulinger 'id': $head.attr('id'), 2235d7d00a41SKrystof Tulinger 'link': $sig.html() 2236d7d00a41SKrystof Tulinger }); 2237d7d00a41SKrystof Tulinger } 2238d7d00a41SKrystof Tulinger } 2239d7d00a41SKrystof Tulinger scope_timeout = null; 2240d7d00a41SKrystof Tulinger }, 150); 2241d7d00a41SKrystof Tulinger} 2242d7d00a41SKrystof Tulinger 2243d7d00a41SKrystof Tulinger/** 2244d7d00a41SKrystof Tulinger * Determines whether current page is search page = list with queried documents. 2245d7d00a41SKrystof Tulinger * @returns true if on search page, false otherwise 2246d7d00a41SKrystof Tulinger */ 2247d7d00a41SKrystof Tulingerfunction isOnSearchPage() { 2248d7d00a41SKrystof Tulinger return $(document.documentElement).hasClass('search'); 2249d7d00a41SKrystof Tulinger} 2250d7d00a41SKrystof Tulinger 2251d7d00a41SKrystof Tulingerfunction checkIsOnSearchPage() { 2252d7d00a41SKrystof Tulinger if (isOnSearchPage()) { 2253d7d00a41SKrystof Tulinger $('#xrd').val("1"); // no redirect 2254d7d00a41SKrystof Tulinger return true; 2255d7d00a41SKrystof Tulinger } 2256d7d00a41SKrystof Tulinger return false; 2257d7d00a41SKrystof Tulinger} 2258d7d00a41SKrystof Tulinger 2259d7d00a41SKrystof Tulinger/** 2260d7d00a41SKrystof Tulinger * Preprocess the searched projects in the form with: 2261d7d00a41SKrystof Tulinger * 2262d7d00a41SKrystof Tulinger * <ol> 2263d7d00a41SKrystof Tulinger * <li>For all project search -> replace the projects with simple searchall parameter</li> 2264d7d00a41SKrystof Tulinger * <li>For group search -> replace all projects in a group by the group parameter</li> 2265d7d00a41SKrystof Tulinger * </ol> 2266d7d00a41SKrystof Tulinger * @param form the form containing the checkboxes 2267d7d00a41SKrystof Tulinger */ 2268d7d00a41SKrystof Tulingerfunction preprocess_searched_projects(form) { 2269d7d00a41SKrystof Tulinger const sol = $('#project').searchableOptionList(); 2270d7d00a41SKrystof Tulinger 2271d7d00a41SKrystof Tulinger const $sel = sol.$selectionContainer; 2272d7d00a41SKrystof Tulinger 2273d7d00a41SKrystof Tulinger /* 2274d7d00a41SKrystof Tulinger * For all project search check if all project checkbox are checked and then uncheck them (they 2275d7d00a41SKrystof Tulinger * would appear in the url) and add a hidden checkbox with searchall name. 2276d7d00a41SKrystof Tulinger */ 2277d7d00a41SKrystof Tulinger const allProjectsSearch = $.makeArray($sel.find('.sol-checkbox[name=project]')).every(function (checkbox) { 2278d7d00a41SKrystof Tulinger return $(checkbox).is(':checked'); 2279d7d00a41SKrystof Tulinger }); 2280d7d00a41SKrystof Tulinger 2281d7d00a41SKrystof Tulinger if (allProjectsSearch && $('#search_all_projects').length === 0) { 2282d7d00a41SKrystof Tulinger $sel.find('.sol-checkbox').prop('checked', false); 2283d7d00a41SKrystof Tulinger const $input = $('<input>'); 2284d7d00a41SKrystof Tulinger const $all = $input. 2285d7d00a41SKrystof Tulinger attr({ 2286d7d00a41SKrystof Tulinger id: 'search_all_projects', 2287d7d00a41SKrystof Tulinger type: 'checkbox', 2288d7d00a41SKrystof Tulinger value: true, 2289d7d00a41SKrystof Tulinger name: 'searchall' 2290d7d00a41SKrystof Tulinger }). 2291d7d00a41SKrystof Tulinger prop('checked', true). 2292d7d00a41SKrystof Tulinger css('display', 'none'); 2293d7d00a41SKrystof Tulinger $all.appendTo($(form)); 2294d7d00a41SKrystof Tulinger return; 2295d7d00a41SKrystof Tulinger } 2296d7d00a41SKrystof Tulinger 2297d7d00a41SKrystof Tulinger /* 2298d7d00a41SKrystof Tulinger * For selecting groups instead of projects, ommit the "Other" group. Loop over 2299d7d00a41SKrystof Tulinger * all project checkbox in a group and when all of them are checked, uncheck them (they 2300d7d00a41SKrystof Tulinger * would appear in the URL) and then check the group checkbox. 2301d7d00a41SKrystof Tulinger */ 2302d7d00a41SKrystof Tulinger $sel.find('.sol-optiongroup').each(function () { 2303d7d00a41SKrystof Tulinger const $el = $(this); 2304d7d00a41SKrystof Tulinger 2305d7d00a41SKrystof Tulinger // handle "Other" group for ungrouped projects 2306d7d00a41SKrystof Tulinger if ($el.find('.sol-optiongroup-label').text() === 'Other') { 2307d7d00a41SKrystof Tulinger $el.find('.sol-checkbox[name=group]').prop('checked', false); 2308d7d00a41SKrystof Tulinger return; 2309d7d00a41SKrystof Tulinger } 2310d7d00a41SKrystof Tulinger 2311d7d00a41SKrystof Tulinger const checkboxs = $el.find('.sol-option .sol-checkbox'); 2312d7d00a41SKrystof Tulinger for (let i = 0; i < checkboxs.length; i++) { 2313d7d00a41SKrystof Tulinger const checkbox = $(checkboxs[i]); 2314d7d00a41SKrystof Tulinger if (!checkbox.is(":checked")) { 2315d7d00a41SKrystof Tulinger return; 2316d7d00a41SKrystof Tulinger } 2317d7d00a41SKrystof Tulinger } 2318d7d00a41SKrystof Tulinger 2319d7d00a41SKrystof Tulinger $el.find('.sol-checkbox[name=group]').prop('checked', true); 2320d7d00a41SKrystof Tulinger for (let j = 0; j < checkboxs.length; j++) { 2321d7d00a41SKrystof Tulinger const cb = $(checkboxs[j]); 2322d7d00a41SKrystof Tulinger cb.prop('checked', false); 2323d7d00a41SKrystof Tulinger } 2324d7d00a41SKrystof Tulinger }); 2325d7d00a41SKrystof Tulinger} 2326d7d00a41SKrystof Tulinger 2327d7d00a41SKrystof Tulinger/** 2328d7d00a41SKrystof Tulinger * Handles submit on search form. 2329d7d00a41SKrystof Tulinger * 2330d7d00a41SKrystof Tulinger * If submit was initiated by pressing the return key when focus was 2331d7d00a41SKrystof Tulinger * in a text field then `si` attribute will be added to the form. 2332d7d00a41SKrystof Tulinger * 2333d7d00a41SKrystof Tulinger * @param {HTMLFormElement} form 2334d7d00a41SKrystof Tulinger */ 2335d7d00a41SKrystof Tulingerfunction searchSubmit(form) { 2336d7d00a41SKrystof Tulinger let submitInitiator = ''; 2337d7d00a41SKrystof Tulinger if (textInputHasFocus()) { 2338d7d00a41SKrystof Tulinger submitInitiator = document.activeElement.getAttribute('id'); 2339d7d00a41SKrystof Tulinger } 2340d7d00a41SKrystof Tulinger if (submitInitiator) { 2341d7d00a41SKrystof Tulinger const input = document.createElement('INPUT'); 2342d7d00a41SKrystof Tulinger input.setAttribute('name', 'si'); 2343d7d00a41SKrystof Tulinger input.value = submitInitiator; 2344d7d00a41SKrystof Tulinger input.type = 'hidden'; 2345d7d00a41SKrystof Tulinger form.appendChild(input); 2346d7d00a41SKrystof Tulinger } 2347d7d00a41SKrystof Tulinger 2348d7d00a41SKrystof Tulinger // replace all projects search with searchall parameter 2349d7d00a41SKrystof Tulinger // select groups instead of projects if all projects in one group are selected 2350d7d00a41SKrystof Tulinger preprocess_searched_projects(form); 2351d7d00a41SKrystof Tulinger} 2352d7d00a41SKrystof Tulinger 2353d7d00a41SKrystof Tulinger/** 2354d7d00a41SKrystof Tulinger * Restores focus on page load 2355d7d00a41SKrystof Tulinger * 2356d7d00a41SKrystof Tulinger * @see #searchSubmit 2357d7d00a41SKrystof Tulinger */ 2358d7d00a41SKrystof Tulingerfunction restoreFocusAfterSearchSubmit() { 2359d7d00a41SKrystof Tulinger const siParam = getParameter('si'); 2360d7d00a41SKrystof Tulinger if (siParam) { 2361d7d00a41SKrystof Tulinger const $input = $('input[type=text][id="' + siParam + '"]'); 2362d7d00a41SKrystof Tulinger if ($input.length === 1) { 2363d7d00a41SKrystof Tulinger $input[0].selectionStart = $input.val().length; 2364d7d00a41SKrystof Tulinger $input[0].selectionEnd = $input[0].selectionStart; 2365d7d00a41SKrystof Tulinger $input.focus(); 2366d7d00a41SKrystof Tulinger } 2367d7d00a41SKrystof Tulinger } 2368d7d00a41SKrystof Tulinger} 2369d7d00a41SKrystof Tulinger 2370d7d00a41SKrystof Tulinger/** 2371d7d00a41SKrystof Tulinger * @return {boolean} true if focus is on a input[type=text] element 2372d7d00a41SKrystof Tulinger */ 2373d7d00a41SKrystof Tulingerfunction textInputHasFocus() { 2374d7d00a41SKrystof Tulinger return !!document.activeElement && 2375d7d00a41SKrystof Tulinger document.activeElement.nodeName === 'INPUT' && 2376d7d00a41SKrystof Tulinger document.activeElement.type === 'text'; 2377d7d00a41SKrystof Tulinger} 2378d7d00a41SKrystof Tulinger 2379d7d00a41SKrystof Tulingerfunction escapeHtml(string) { // taken from https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery 2380d7d00a41SKrystof Tulinger const htmlEscapeMap = { 2381d7d00a41SKrystof Tulinger '&': '&', 2382d7d00a41SKrystof Tulinger '<': '<', 2383d7d00a41SKrystof Tulinger '>': '>', 2384d7d00a41SKrystof Tulinger '"': '"', 2385d7d00a41SKrystof Tulinger "'": ''', 2386d7d00a41SKrystof Tulinger '/': '/', 2387d7d00a41SKrystof Tulinger '`': '`', 2388d7d00a41SKrystof Tulinger '=': '=' 2389d7d00a41SKrystof Tulinger }; 2390d7d00a41SKrystof Tulinger return String(string).replace(/[&<>"'`=\/]/g, function (s) { 2391d7d00a41SKrystof Tulinger return htmlEscapeMap[s]; 2392d7d00a41SKrystof Tulinger }); 2393d7d00a41SKrystof Tulinger} 2394d7d00a41SKrystof Tulinger 2395d7d00a41SKrystof Tulinger/** 2396d7d00a41SKrystof Tulinger * Returns user-specific local settings for a provided key. 2397d7d00a41SKrystof Tulinger * @param key settings key 2398d7d00a41SKrystof Tulinger * @returns {string} settings value or {@code undefined} if not set 2399d7d00a41SKrystof Tulinger */ 2400d7d00a41SKrystof Tulingerfunction getSettingsValue(key) { 2401d7d00a41SKrystof Tulinger return localStorage.getItem(key); 2402d7d00a41SKrystof Tulinger} 2403d7d00a41SKrystof Tulinger 2404d7d00a41SKrystof Tulinger/** 2405d7d00a41SKrystof Tulinger * Event listener which stores user-specific settings change for an {@code input} element. 2406d7d00a41SKrystof Tulinger * @param el settings {@code input} element 2407d7d00a41SKrystof Tulinger */ 2408d7d00a41SKrystof Tulingerfunction onSettingsValueChange(el) { 2409d7d00a41SKrystof Tulinger let value = getSettingsInputValue(el); 2410d7d00a41SKrystof Tulinger localStorage.setItem(el.name, value); 2411d7d00a41SKrystof Tulinger} 2412d7d00a41SKrystof Tulinger 2413d7d00a41SKrystof Tulinger/** 2414d7d00a41SKrystof Tulinger * Decodes a settings value from a settings {@code input} element. 2415d7d00a41SKrystof Tulinger * @param el settings {@code input} element 2416d7d00a41SKrystof Tulinger * @returns {string|*} settings value 2417d7d00a41SKrystof Tulinger */ 2418d7d00a41SKrystof Tulingerfunction getSettingsInputValue(el) { 2419d7d00a41SKrystof Tulinger if (el.type === 'checkbox') { 2420d7d00a41SKrystof Tulinger if (el.checked) { 2421d7d00a41SKrystof Tulinger return el.dataset.checkedValue; 2422d7d00a41SKrystof Tulinger } else { 2423d7d00a41SKrystof Tulinger return el.dataset.uncheckedValue; 2424d7d00a41SKrystof Tulinger } 2425d7d00a41SKrystof Tulinger } else { 2426d7d00a41SKrystof Tulinger return el.value; 2427d7d00a41SKrystof Tulinger } 2428d7d00a41SKrystof Tulinger} 2429d7d00a41SKrystof Tulinger 2430d7d00a41SKrystof Tulinger/** 2431d7d00a41SKrystof Tulinger * Resets all settings elements with class {@code local-setting} to their default values. 2432d7d00a41SKrystof Tulinger */ 2433d7d00a41SKrystof Tulingerfunction resetAllSettings() { 2434d7d00a41SKrystof Tulinger for (const el of document.getElementsByClassName('local-setting')) { 2435d7d00a41SKrystof Tulinger setDefaultSettingsValue(el); 2436d7d00a41SKrystof Tulinger onSettingsValueChange(el); 2437d7d00a41SKrystof Tulinger } 2438d7d00a41SKrystof Tulinger} 2439d7d00a41SKrystof Tulinger 2440d7d00a41SKrystof Tulinger/** 2441d7d00a41SKrystof Tulinger * Sets a default value for a settings {@code input} element. 2442d7d00a41SKrystof Tulinger * @param el settings {@code input} element 2443d7d00a41SKrystof Tulinger */ 2444d7d00a41SKrystof Tulingerfunction setDefaultSettingsValue(el) { 2445d7d00a41SKrystof Tulinger setSettingsInputValue(el, el.dataset.defaultValue); 2446d7d00a41SKrystof Tulinger} 2447d7d00a41SKrystof Tulinger 2448d7d00a41SKrystof Tulinger/** 2449d7d00a41SKrystof Tulinger * Sets the settings {@code input} element value to the provided one. 2450d7d00a41SKrystof Tulinger * @param el element to change 2451d7d00a41SKrystof Tulinger * @param value value to set 2452d7d00a41SKrystof Tulinger */ 2453d7d00a41SKrystof Tulingerfunction setSettingsInputValue(el, value) { 2454d7d00a41SKrystof Tulinger if (el.type === 'checkbox') { 2455d7d00a41SKrystof Tulinger el.checked = el.dataset.checkedValue === value; 2456d7d00a41SKrystof Tulinger } else { 2457d7d00a41SKrystof Tulinger el.value = value; 2458d7d00a41SKrystof Tulinger } 2459d7d00a41SKrystof Tulinger} 2460d7d00a41SKrystof Tulinger 2461d7d00a41SKrystof Tulinger/** 2462d7d00a41SKrystof Tulinger * Initializes all settings elements with {@code local-setting} class. 2463d7d00a41SKrystof Tulinger */ 2464d7d00a41SKrystof Tulingerfunction initSettings() { 2465d7d00a41SKrystof Tulinger for (const el of document.getElementsByClassName('local-setting')) { 2466d7d00a41SKrystof Tulinger const value = getSettingsValue(el.name); 2467d7d00a41SKrystof Tulinger if (value) { 2468d7d00a41SKrystof Tulinger setSettingsInputValue(el, value); 2469d7d00a41SKrystof Tulinger } else { 2470d7d00a41SKrystof Tulinger setDefaultSettingsValue(el); 2471d7d00a41SKrystof Tulinger } 2472d7d00a41SKrystof Tulinger } 2473d7d00a41SKrystof Tulinger} 2474