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