1/*************************************************************************** 2// Firma: Hehner Reus Systems GmbH 3// Projekt: com.cerno.basis 4// Datei: DOM.js 5// Erstellung: 02.07.2010 6// Verwendung: Hilfsfunktionen für den Umgang mit dem DOM. 7/***************************************************************************/ 8 9// TODO: Wenn zu den einzelnen Funktionen ausreichend Unit-Tests geschrieben 10// wurden, den strict-Modus aktivieren, um weiteren unschönen Effekten vorzubeugen. 11// "use strict"; 12 13class HRDOM 14{ 15 /** 16 * Funktion ergänzt zu dem übergebenen Objekt das Funktions-Objekt 17 * als Bearbeiter des als Zeichenkette angegebenen Event. 18 * 19 * @param elementOrId Das Element, zu dem ein EventListener hinzugefügt 20 * werden soll. Entweder direkt das Objekt oder dessen Id. 21 * Wird null übergeben, wird der Event an das window-Objekt geknüpft. 22 * @param eventName Der Name des Events, auf den gelauscht werden soll. 23 * Beispiele: "resize", "click", "select" (immer ohne das "on"!) 24 * @param listener Ein Object, dass das Event interface implementiert hat. Das kann ein Object mit einer 25 * handleEvent()-Methode oder eine Funktion sein, welche das Event bearbeiten soll. 26 * @param Weitere Konfigurationen. Wie etwa once: true, um einen Listener nur einmal zu nutzen und danach automatisch wieder zu entfernen. 27 */ 28 static addEventListener(elementOrId, eventName, listener, config={capture: false}) 29 { 30 try 31 { 32 if (eventName == null || typeof(eventName) != "string" || !listener || (typeof(listener) !== 'function' && typeof(listener.handleEvent) !== 'function')) 33 return; 34 35 var targetElement = null; 36 if (elementOrId != null && typeof(elementOrId) == "string") 37 targetElement = document.getElementById(elementOrId); 38 else if (elementOrId != null && typeof(elementOrId) == "object") 39 targetElement = elementOrId; 40 else if (elementOrId == null) 41 targetElement = window; 42 43 if (targetElement == null) 44 return; 45 46 if (targetElement.addEventListener) 47 { 48 targetElement.addEventListener(eventName, listener, config); 49 } 50 else if (targetElement.attachEvent) 51 { 52 targetElement.attachEvent("on" + eventName, listener); 53 } 54 } 55 catch (e) 56 { 57 if (typeof(HRLogError) === 'function') 58 HRLogError(e); 59 } 60 } 61 62 /** 63 * Funktion entfernt zu dem übergebenen Objekt das Funktions-Objekt 64 * als Bearbeiter des als Zeichenkette angegebenen Event. 65 * 66 * @param elementOrId Das Element, bei dem ein EventListener entfernt 67 * werden soll. Entweder direkt das Objekt oder dessen Id. 68 * Wird null übergeben, wird der Event vom window-Objekt entfernt. 69 * @param eventName Der Name des Events, auf den nicht mehr gelauscht werden soll. 70 * Beispiele: "resize", "click", "select" (immer ohne das "on"!) 71 * @param listener Ein Object, dass das Event interface implementiert hat. Das kann ein Object mit einer 72 * handleEvent()-Methode oder eine Funktion sein, welche das Event bearbeiten soll. 73 */ 74 static removeEventListener(elementOrId, eventName, listener) 75 { 76 try 77 { 78 if (eventName == null || typeof(eventName) != "string" || !listener || (typeof(listener) !== 'function' && typeof(listener.handleEvent) !== 'function')) 79 return; 80 81 var targetElement = null; 82 if (elementOrId != null && typeof(elementOrId) == "string") 83 targetElement = document.getElementById(elementOrId); 84 else if (elementOrId != null && typeof(elementOrId) == "object") 85 targetElement = elementOrId; 86 else if (elementOrId == null) 87 targetElement = window; 88 89 if (targetElement == null) 90 return; 91 92 if (targetElement.removeEventListener) 93 { 94 targetElement.removeEventListener(eventName, listener, false); 95 } 96 else if (targetElement.attachEvent) 97 { 98 targetElement.detachEvent("on" + eventName, listener); 99 } 100 } 101 catch (e) 102 { 103 if (typeof(HRLogError) === 'function') 104 HRLogError(e); 105 } 106 } 107 108 /** 109 * Fügt die übergebene Funktion dem onload-Event der 110 * Seite hinzu. 111 * 112 * @param onLoadFunction die JavaScript-Funktion, die 113 * beim onload-Event zusätzlich aufgerufen wird. 114 */ 115 static addOnLoad(onLoadFunction) 116 { 117 if (window.addEventListener) 118 { 119 window.addEventListener("load", onLoadFunction, false); 120 } 121 else if (window.attachEvent) 122 { 123 window.attachEvent("onload", onLoadFunction); 124 } 125 else 126 window.onload = onLoadFunction; 127 } 128 129 /** 130 * Fügt die übergebene Funktion dem ajax-onload-Event der Seite hinzu. 131 * 132 * @param sender Das Element, welches das Event getriggert hat. 133 * @param onLoadFunction die JavaScript-Funktion, die beim onload-Event zusätzlich aufgerufen wird. 134 */ 135 static addOnAjaxLoad(sender, onLoadFunction) 136 {
137 try 138 { 139 if (sender && typeof(sender) === 'string') 140 { 141 sender = document.getElementById(sender); 142 } 143 if (sender && HREventManager && typeof(HREventManager.addListener) === 'function') 144 HREventManager.addListener(sender, 'ajax-load', onLoadFunction, {useStandard: false, notifiedByParents: true}); 145 } 146 catch (e) 147 { 148 if (typeof(HRLogError) === 'function') 149 HRLogError(e); 150 } 151 } 152 153 /** 154 * Hiermit kann ein Element durch ein anderes Element "gewrappt" werden. 155 * 156 * @param element Das zu wrappende Element 157 * @param wrapper Der Wrapper 158 */ 159 static wrap(element, wrapper) 160 { 161 try 162 { 163 if (element && wrapper && element.parentNode) 164 { 165 element.parentNode.insertBefore(wrapper, element); 166 wrapper.appendChild(element); 167 } 168 } 169 catch (e) 170 { 171 if (typeof(HRLogError) === 'function') 172 HRLogError(e); 173 } 174 } 175 176 /** 177 * Analogon zur Methode insertBefore: Fügt ein Element hinter ein anderes Element ein. 178 * 179 * Anmerkung: Aktuell (10.03.2020) gibt es keine insertAfter-Standardfunktion. 180 * Quelle: https://stackoverflow.com/questions/4793604/how-to-insert-an-element-after-another-element-in-javascript-without-using-a-lib 181 * 182 * @param element Das einzufügende Element 183 * @param referenceElement Das Element, hinter welches das Element eingefügt werden soll. 184 */ 185 static insertAfter(element, referenceElement) 186 { 187 try 188 { 189 // 190 // Falls das Referenz-Element das letzte Element sein sollte, ist nextSibling null, doch insertBefore 191 // deckt diesen Fall bereits ab und fügt das Element als letztes Element der Nodelist ein. 192 // 193 if (referenceElement.parentNode) 194 referenceElement.parentNode.insertBefore(element, referenceElement.nextSibling); 195 } 196 catch (e) 197 { 198 if (typeof(HRLogError) === 'function') 199 HRLogError(e); 200 } 201 } 202 203 /** 204 * Fügt das übergebene Element als erstes Kind in den übergebenen Parentknoten ein. 205 * 206 * @param element Das einzufügende Element. 207 * @param parent Der Parent-Knoten, in den das Kind eingefügt werden soll. 208 */ 209 static insertAsFirstChild(element, parent) 210 { 211 try 212 { 213 // 214 // Falls das Referenz-Element das letzte Element sein sollte, ist nextSibling null, doch insertBefore 215 // deckt diesen Fall bereits ab und fügt das Element als letztes Element der Nodelist ein. 216 // 217 if (parent.firstChild) 218 parent.insertBefore(element, parent.firstChild); 219 else 220 parent.appendChild(element); 221 } 222 catch (e) 223 { 224 if (typeof(HRLogError) === 'function') 225 HRLogError(e); 226 } 227 } 228 229 /** 230 * Entfernt alle Kinder des übergebenen DOM-Elements. 231 * 232 * @param element Der Knoten, dessen Kinder entfernt werden sollen. 233 */ 234 static removeAllChildren(element) 235 { 236 try 237 { 238 if (element) 239 { 240 while (element.firstChild) 241 { 242 element.removeChild(element.lastChild); 243 } 244 } 245 } 246 catch (e) 247 { 248 if (typeof(HRLogError) === 'function') 249 HRLogError(e); 250 } 251 } 252 253 /** 254 * Kopiert den übergebenen Text in die Zwischenablage. 255 * 256 * @param txt Der zu kopierende Text. 257 */ 258 static copyToClipboard(txt) 259 { 260 try 261 { 262 if (!txt) 263 txt = ''; 264 265 // Aus Sicherheitsgründen ist das clipboard-Objekt nur für https verfügbar... 266 if (navigator.clipboard && typeof(navigator.clipboard.writeText) === 'function') 267 navigator.clipboard.writeText(txt); 268 else 269 { 270 // ... andernfalls bieten wir zunächst einfach das alte Workaround mit window-Prompt an. 271 window.prompt("Bitte kopieren Sie folgenden Text in die Zwischenablage (Strg+C):", txt); 272 } 273 } 274 catch (e) 275 { 276 if (typeof(HRLogError) === 'function') 277 HRLogError(e); 278 } 279 } 280 281 /** 282 * Gibt an, ob das Element fokussierbar ist. 283 * 284 * @param el Element 285 * @return True, Element ist fokussierbar. 286 */ 287 static isFocusable(el) 288 { 289 if (el) 290 { 291 // Sichtbarkeit prüfen: Elemente müssen sichtbar sein. 292 if (el.style.display !== 'none' && el.style.visibility !== 'hidden' && !el.disabled && el.offsetParent !== null) 293 { 294 // Nur solche Elemente, die einen Tabindex haben. 295 if (parseInt(el.tabIndex) >= 0) 296 { 297 // Keine a-Tags mit ungültigen Eigenschaften oder hidden fields. 298 if ((el.tagName === 'A' && (el.rel === 'ignore' || !el.href)) || (el.tagName === 'INPUT' && el.type === 'hidden')) 299 return false;
300 301 return true; 302 } 303 } 304 } 305 306 return false; 307 } 308 309 /** 310 * Ermittelt das erste fokussierbare Element unterhalb eines gegebenen HTML-Elements. 311 * 312 * @param el Das zu prüfende Element. 313 * @return Gibt das erste fokussierbare Element zurück oder null, falls keines gefunden werden konnte. 314 */ 315 static getFirstFocusableDescendant(el) 316 { 317 let focusableDescendant = null; 318 319 try 320 { 321 if (el) 322 { 323 for (let i = 0; i < el.children.length; i++) 324 { 325 if (!focusableDescendant) 326 { 327 if (this.isFocusable(el.children[i])) 328 return el.children[i]; 329 else 330 focusableDescendant = this.getFirstFocusableDescendant(el.children[i]); 331 } 332 } 333 } 334 } 335 catch (e) 336 { 337 if (typeof(HRLogError) === 'function') 338 HRLogError(e); 339 } 340 341 return focusableDescendant; 342 } 343 344 /** 345 * Ermittelt das letzte fokussierbare Element unterhalb eines gegebenen HTML-Elements. 346 * 347 * @param el Das zu prüfende Element. 348 * @return Gibt das erste fokussierbare Element zurück oder null, falls keines gefunden werden konnte. 349 */ 350 static getLastFocusableDescendant(el) 351 { 352 let focusableDescendant = null; 353 354 try 355 { 356 if (el) 357 { 358 for (let i = el.children.length-1; i >= 0 ; i--) 359 { 360 if (!focusableDescendant) 361 { 362 if (this.isFocusable(el.children[i])) 363 return el.children[i]; 364 else 365 focusableDescendant = this.getLastFocusableDescendant(el.children[i]); 366 } 367 } 368 } 369 } 370 catch (e) 371 { 372 if (typeof(HRLogError) === 'function') 373 HRLogError(e); 374 } 375 376 return focusableDescendant; 377 } 378 379 /** 380 * Sorgt dafür, dass der Tab-Fokus in dem übergebenen HTML-Container-Element gefangen bleibt. 381 * 382 * @param el Das Container-Element (z.B. ein div), unter dem der Fokus gefangen sein soll. 383 */ 384 static trapFocus(el) 385 { 386 try 387 { 388 const firstEl = this.getFirstFocusableDescendant(el); 389 const lastEl = this.getLastFocusableDescendant(el); 390 if (firstEl && lastEl) 391 { 392 if (lastEl !== firstEl) 393 { 394 this.addEventListener(firstEl, 'keydown', (event) => { 395 if (event.shiftKey && event.key === 'Tab') 396 { 397 lastEl.focus(); 398 event.preventDefault(); 399 } 400 }); 401 402 this.addEventListener(lastEl, 'keydown', (event) => { 403 if (!event.shiftKey && event.key === 'Tab') 404 { 405 firstEl.focus(); 406 event.preventDefault(); 407 } 408 }); 409 } 410 else // Nur ein fokussierbares Element vorhanden. 411 { 412 this.addEventListener(firstEl, 'keydown', (event) => { 413 if (event.key === 'Tab') 414 { 415 firstEl.focus(); 416 event.preventDefault(); 417 } 418 }); 419 } 420 } 421 } 422 catch (e) 423 { 424 if (typeof(HRLogError) === 'function') 425 HRLogError(e); 426 } 427 } 428 429 /** 430 * Prüft, ob das aktuelle window-Objekt in einem i-Frame geladen wird. 431 * 432 * @returns true, falls es in einem i-Frame geladen wird. 433 */ 434 static inIframe() 435 { 436 try 437 { 438 return window.self !== window.top; 439 } 440 catch (e) 441 { 442 return true; 443 } 444 } 445 446 /** 447 * Erzeugt eine für uns statistisch ausreichend wahrscheinliche eindeutige ID. 448 */ 449 static uniqueID() 450 { 451 return Math.floor(Math.random() * Date.now()); 452 } 453 454 /** 455 * Fügt die übergebene Funktion dem browserspezifischen Event für die Beendigung der 456 * Transition bezüglich des übergebenen Elements hinzu. D.h. man kann eine Callback- 457 * Funktion für das Ende einer CSS-Transition angeben. 458 * 459 * @param element Das Element, auf welches die Transition angewendet wird. 460 * @param onTransitionEndedFunction Die auszuführende Funktion nach Beendigung der Transition. 461 */ 462 static addTransitionEndedEventListener(element, onTransitionEndedFunction) 463 {
464 try 465 { 466 // 467 // Ermittelt den korrekten Eventnamens des "transitioned"-Events zum aktuellen Browser. 468 // 469 const transitions = { 470 "transition" : "transitionend", 471 "OTransition" : "oTransitionEnd", 472 "MozTransition" : "transitionend", 473 "WebkitTransition": "webkitTransitionEnd" 474 }; 475 476 let eventName; 477 for (let transition in transitions) 478 { 479 if (document.body.style[transition] != undefined) 480 eventName = transitions[transition]; 481 } 482 483 if (eventName) 484 HREventManager.addListener(element, eventName, onTransitionEndedFunction, {unique: true}); 485 } 486 catch (e) 487 { 488 if (typeof(HRLogError) === 'function') 489 HRLogError(e); 490 } 491 } 492 493 /** 494 * Prüft, ob ein Javascript-Include zu der übergebenen URL im HTML-Head existiert. 495 * 496 * @param url Die zu ladende externe Ressource. 497 * @param searchDOM true, falls der Include im gesamten DOM gesucht werden soll. Default: Sucht nur im Head. 498 * @return true, falls es den Include gibt. 499 */ 500 static containsScriptInclude(url, searchDOM) 501 { 502 var found = false; 503 504 try 505 { 506 if (url) 507 { 508 var scripts; 509 if (searchDOM) 510 scripts = document.getElementsByTagName('script'); 511 else 512 { 513 var head = document.getElementsByTagName('head')[0]; 514 scripts = head.getElementsByTagName('script'); 515 } 516 if (scripts) 517 { 518 var l = scripts.length; 519 for (let i = 0; i < l && !found; i++) 520 { 521 if (scripts[i].src && scripts[i].src.length > 0 && url.indexOf(scripts[i].src) >= 0) 522 { 523 found = true; 524 break; 525 } 526 } 527 } 528 } 529 } 530 catch (e) 531 { 532 if (typeof(HRLogError) === 'function') 533 HRLogError(e); 534 } 535 536 return found; 537 } 538 539 /** 540 * Erzeugt, falls noch nicht vorhanden, einen Javascript-Include auf ein externes Javascript-File im HTML-Head der Seite. Das Laden erfolgt asynchron. 541 * 542 * @param url Die zu ladende externe Ressource. 543 * @param onLoadFunction CallBack-Funktion, die aufgerufen wird, wenn das Script vollständig geladen wurde. 544 * @param searchDOM true, falls der Include im gesamten DOM gesucht werden soll. Default: Sucht nur im Head. 545 * 546 * @return true, falls es zuvor noch keinen solchen Include gab. 547 */ 548 static appendScriptIncludeToHead(url, onLoadFunction, searchDOM) 549 { 550 var found = this.containsScriptInclude(url, searchDOM); 551 552 if (url) 553 { 554 var head = document.getElementsByTagName('head')[0]; 555 if (!found) 556 { 557 // 558 // Im Head das neue Script erzeugen. 559 // 560 var script = document.createElement('script'); 561 script.async = true; 562 script.src = url; 563 564 if (onLoadFunction && typeof(onLoadFunction) === 'function') 565 { 566 script.onload = function() { 567 try 568 { 569 onLoadFunction(); 570 } 571 catch(e) 572 { 573 if (typeof(HRLogError) === 'function') 574 HRLogError(e); 575 } 576 }; 577 } 578 head.appendChild(script); 579 } 580 else if (onLoadFunction && typeof(onLoadFunction) === 'function') 581 onLoadFunction(); 582 } 583 584 return !found; 585 } 586 587 /** 588 * Prüft, ob ein CSS-Link-Include zu der übergebenen URL im HTML-Head existiert. 589 * 590 * @param url Die zu ladende externe Ressource. 591 * @param searchDOM true, falls der Include im gesamten DOM gesucht werden soll. Default: Sucht nur im Head. 592 * @return true, falls es den Include gibt. 593 */ 594 static containsCSSLinkInclude(url, searchDOM) 595 { 596 let found = false;
597 598 try 599 { 600 if (url) 601 { 602 let links; 603 if (searchDOM) 604 links = document.getElementsByTagName('link'); 605 else 606 { 607 const head = document.getElementsByTagName('head')[0]; 608 links = head.getElementsByTagName('link'); 609 } 610 if (links) 611 { 612 let i = 0; 613 const l = links.length; 614 for (i = 0; i < l && !found; i++) 615 { 616 if (links[i].href && links[i].href.length > 0 && url.indexOf(links[i].href) >= 0) 617 { 618 found = true; 619 break; 620 } 621 } 622 } 623 } 624 } 625 catch (e) 626 { 627 if (typeof(HRLogError) === 'function') 628 HRLogError(e); 629 } 630 631 return found; 632 } 633 634 /** 635 * Erzeugt, falls noch nicht vorhanden, einen Link-Include auf ein externes CSS-Styling. 636 * 637 * @param url Die URL zum externen Styling. 638 * @param searchDOM true, falls der Include im gesamten DOM gesucht werden soll. Default: Sucht nur im Head. 639 * 640 * @return true, falls es zuvor noch keinen solchen Include gab. 641 */ 642 static appendCSSLinkIncludeToHead(url, searchDOM) 643 { 644 let found = this.containsCSSLinkInclude(url, searchDOM); 645 if (url) 646 { 647 const head = document.getElementsByTagName('head')[0]; 648 if (!found) 649 { 650 // Im Head den neuen Link erzeugen. 651 const link = document.createElement('link'); 652 link.rel = 'stylesheet'; 653 link.href = url; 654 head.appendChild(link); 655 } 656 } 657 658 return !found; 659 } 660 661 /** 662 * Dient dem Mischen der Default-Konfiguration mit der vom Nutzer eingegeben Konfiguration. 663 * Sollte der Nutzer eine Konfiguration getätigt haben, so wird die Default-Konfig. mit diesem 664 * Wert überschrieben. 665 * 666 * @param defaultConfig Die Default-Konfiguration. 667 * @param userConfig Die vom Nutzer eingegebene Konfiguration. 668 * 669 * @returns config Die neue Konfiguration oder null, falls etwas schiefgegangen ist. 670 */ 671 static mergeConfigs(defaultConfig, userConfig) 672 { 673 const config = defaultConfig; 674 try 675 { 676 if (userConfig == null) 677 { 678 return defaultConfig; 679 } 680 else if (defaultConfig == null) 681 { 682 return userConfig; 683 } 684 else 685 { 686 for (let key in userConfig) 687 { 688 config[key] = userConfig[key]; 689 } 690 } 691 } 692 catch(error) 693 { 694 return null; 695 } 696 return config; 697 } 698 699 /** 700 * Funktion gibt die Scrolltiefe in Prozent zurück. 701 * Wird ein maximaler Wert übergeben, wird die Scrolltiefe 702 * nur zurückgegeben, wenn dieser überschritten wurde. 703 * Ansonsten wird der maximale Wert zurückgegeben. 704 * 705 * @param maxValue Der maximale Wert (optional) 706 * @return Die Scrolltiefe oder der maximale Wert 707 */ 708 static getScrollPercent(maxValue) 709 { 710 try 711 { 712 if (maxValue == null) 713 maxValue = 0; 714 var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; 715 var windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || document.body.offsetHeight; 716 var pageHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight); 717 var scrollBottom = windowHeight + scrollTop; 718 var scrollPercent = Math.round(scrollBottom * 100 / pageHeight); 719 if (scrollPercent > maxValue && scrollPercent <= 100) 720 return scrollPercent; 721 return maxValue; 722 } 723 catch (e) 724 { 725 if (typeof(HRLogError) == 'function') 726 HRLogError(e); 727 } 728 return 0; 729 } 730 731 /** 732 * Liefert zu der übergebenen Id das passende Element-Objekt, 733 * allerdings nur, wenn das gesuchte Element ein Parent (oder 734 * Grandparent, usw.) des übergebenen Elements ist. 735 * 736 * @param startElement Das Element dessen Parent mit der übergebenen id gesucht ist. 737 * @param idToFind Die Id, die das ParentElement haben muss. 738 * @returns 739 */ 740 static getParentElementById(startElement, idToFind) 741 { 742 if (startElement && idToFind && typeof(idToFind) === 'string' && idToFind.length > 0) 743 return startElement.closest(`#${idToFind}`); 744 745 return null; 746 } 747 748 /** 749 * Prüft, ob unter ein Start-Element ein gewisses Parent-Element hat. 750 * 751 * @param startElement Das Element, von dem aus mit der Suche gestartet werden soll. 752 * @param parentToFind Das zu ermittelnde Parent-Element.
753 * @return Das gesuchte Parent-Element oder null, falls dieses nicht gefunden wurde. 754 */ 755 static isParentElement(startElement, parentToFind) 756 { 757 let elemFound = null; 758 759 if (startElement && parentToFind) 760 { 761 let parentElem = startElement.parentNode; 762 let saveCount = 0; 763 while (elemFound == null && parentElem != null && parentElem.tagName && parentElem.tagName.toLowerCase() != "html" && saveCount < 100) 764 { 765 saveCount++; 766 if (parentElem == parentToFind) 767 elemFound = parentElem; 768 else 769 parentElem = parentElem.parentNode; 770 } 771 } 772 773 return elemFound; 774 } 775 776 /** 777 * Setzt den Wert einer Radiobutton-Gruppe. Wenn der Wert 778 * nicht existiert, wird die Gruppe zurückgesetzt. 779 * 780 * @param radiobuttons Eine Radiobutton-Gruppe, genauer ein Array mit Radiobuttons des selben Namens. 781 * @param value Der Wert desjenigen Radiobuttons, der angehakt werden soll. 782 */ 783 static checkRadioByValue(radiobuttons, value) 784 { 785 try 786 { 787 if (radiobuttons) 788 { 789 const radioLength = radiobuttons.length; 790 if (radioLength) 791 { 792 for (let i = 0; i < radioLength; i++) 793 { 794 radiobuttons[i].checked = false; 795 if (radiobuttons[i].value == value.toString()) 796 radiobuttons[i].checked = true; 797 } 798 } 799 else 800 radiobuttons.checked = (radiobuttons.value == value.toString()); 801 } 802 } 803 catch (e) 804 { 805 if (typeof(HRLogError) === 'function') 806 HRLogError(e); 807 } 808 } 809 810 /** 811 * Gibt aus einer Radiobutton-Gruppe den ausgewählten 812 * Wert zurück. 813 * 814 * @param radioObj Die Radiobutton-Gruppe 815 * @return Der ausgewählte Wert oder null, wenn kein Element 816 * ausgewählt wurde oder keine Radiobuttons existieren 817 */ 818 static getCheckedValue(radioObj) 819 { 820 try 821 { 822 if (radioObj) 823 { 824 var radioLength = radioObj.length; 825 if (radioLength) 826 { 827 for (let i = 0; i < radioLength; i++) 828 { 829 if (radioObj[i].checked) 830 return radioObj[i].value; 831 } 832 } 833 else if (radioObj.checked) 834 return radioObj.value; 835 } 836 } 837 catch (e) 838 { 839 if (typeof(HRLogError) === 'function') 840 HRLogError(e); 841 } 842 843 return null; 844 } 845 846 /** 847 * Ermittelt unter den Radioboxen des übergebenen Namens den Wert der ausgewählten Box. 848 * 849 * @param name Der Name der relevanten Radioboxen. 850 * @erturn Der Wert der ausgewählten Radiobox oder eine leere Zeichenkette, falls keine Radiobox ausgewählt wurde. 851 */ 852 static getSelectedRadioboxValue(name) 853 { 854 return getCheckedValue(document.getElementsByName(name)); 855 } 856 857 /** 858 * Schreibt die übergebene Zeichenkette in den Body. 859 * Kann insbesondere als Debugging-Hilfsmittel genutzt werden. 860 * 861 * @param string Die im Body darzustellende Zeichenkette. 862 * @return Das am Body hängende Div mit der Zeichenkette. 863 */ 864 static printToBody(string) 865 { 866 let tmpDiv = document.getElementById('hr_tmp_div'); 867 if (!tmpDiv) 868 { 869 tmpDiv = document.createElement('div'); 870 document.body.appendChild(tmpDiv); 871 tmpDiv.id = 'hr_tmp_div'; 872 } 873 tmpDiv.appendChild(document.createTextNode(string)); 874 tmpDiv.appendChild(document.createElement('br')); 875 876 return tmpDiv; 877 } 878 879 /** 880 * Getter für den Wert eines Formularelements (Eingabefeld, Radiobutton, Checkbox, Dropdown). 881 * 882 * @param elementName Der Name des Formularelements, dessen Wert ermittelt werden soll. 883 * @param formname Der Name des Formulars, unter dem das Element gesucht werden soll. 884 * @returns der Wert des gesuchten Formularelements oder eine leere Zeichenkette, falls das 885 * Element nicht gefunden werden konnte. 886 */ 887 static getFormValueByName(elementName, formname) 888 {
889 try 890 { 891 var theForm = null; 892 if (!elementName || elementName == "") 893 return ""; 894 895 if (document.forms.length > 0) 896 { 897 if (formname && formname != "") 898 theForm = document.forms[formname]; 899 900 if (theForm == null) 901 theForm = document.forms[0]; 902 903 var element = theForm.elements[elementName]; 904 if (!element) // Vielleicht wurde auch eine ElementId angegeben... 905 element = document.getElementById(element); 906 907 if (!element) 908 return ""; 909 910 if (element.length && element.length > 0) 911 { 912 if (element[0] == null || typeof(element[0].type) != "string" || (element[0].type.toLowerCase() != "hidden" && element[0].type.toLowerCase() != "text")) 913 { 914 for (let i = 0; element[i]; i++) 915 { 916 if (element[i].checked || element[i].selected) 917 return element[i].value; 918 } 919 } 920 else 921 { 922 return element[0].value; 923 } 924 } 925 else if (element.type.toLowerCase() == "radio" || element.type.toLowerCase() == "checkbox") 926 { 927 if (element.checked && element.value) 928 return element.value; 929 } 930 else if (element.value) 931 { 932 return element.value; 933 } 934 } 935 } 936 catch (except) 937 { 938 } 939 940 return ""; 941 } 942 943 /** 944 * Kopiert alle Attribute eines DOM-Elements zu einem anderen DOM-Element. 945 * 946 * @param source Das HTML-Element, dessen Attribute kopiert werden sollen. 947 * @param target Das HTML-Element, das die kopierten Attribute erhalten soll. 948 */ 949 static copyAttributes(source, target) 950 { 951 Array.from(source.attributes).forEach(attr => { 952 target.setAttribute(attr.name, attr.value); 953 }); 954 } 955 956 /** 957 * Prüft, ob zwei gegebene Objekte gleich sind. Methode kann benutzt werden, um zwei Objekte zu 958 * vergleichen, die nicht auf die selbe Memory location zeigen. 959 * 960 * @param obj1 Das erste zu prüfende Objekt. 961 * @param obj2 Das zweite zu prüfende Objekt. 962 * @return true, falls die Objekte gleiche Eigenschaften mit übereinstimmenden Werten haben. 963 */ 964 static isEqual(obj1, obj2) 965 { 966 if (obj1 === obj2) 967 return true; 968 969 if (!obj1 || !obj2) 970 return false; 971 972 const entries1 = Object.entries(obj1); 973 const entries2 = Object.entries(obj2); 974 975 if (entries1.length !== entries2.length) 976 return false; 977 978 return entries1.every(([key, value]) => 979 obj2.hasOwnProperty(key) && obj2[key] === value); 980 }; 981 982 /** 983 * Setzt den Wert eines HTML-Elements. Hier wird auch die 984 * Ausgabe vom Edit-In-Place berücksichtigt. 985 * 986 * @param el Das Element oder ein CSS-Selektor zum Element. 987 * @param value Der zu setzende Wert. 988 */ 989 static setValue(el, value) 990 { 991 // Wenn el ein Selector-String ist, das Element finden. 992 if (typeof el === "string") 993 el = document.querySelector(el); 994 995 if (!el) 996 return; 997 998 // Prüfen, ob Element überhaupt value besitzt. 999 if (!("value" in el)) 1000 return; 1001 1002 // Wert des Elements setzen. 1003 el.value = value; 1004 1005 // Falls Edit-in-Place vorhanden ist, dann Ausgabe aktualisieren. 1006 const outputSpan = el.parentNode.querySelector('.edit-in-place-plain-text'); 1007 if (outputSpan) 1008 outputSpan.textContent = value; 1009 }; 1010} 1011 1012/** 1013 * @see HRDOM.addEventListener(elementOrId, eventName, listener) 1014 * 1015 * @deprecaded. 1016 */ 1017function HRAddEventListener(elementOrId, eventName, listener) 1018{ 1019 HRDOM.addEventListener(elementOrId, eventName, listener); 1020} 1021 1022/** 1023 * @see HRDOM.removeEventListener(elementOrId, eventName, listener) 1024 * 1025 * @deprecaded. 1026 */ 1027function HRRemoveEventListener(elementOrId, eventName, listener) 1028{ 1029 HRDOM.removeEventListener(elementOrId, eventName, listener); 1030} 1031 1032/** 1033 * @see HRDOM.addOnLoad(onLoadFunction) 1034 * 1035 * @deprecaded. 1036 */ 1037function HRAddOnLoad(onLoadFunction) 1038{ 1039 HRDOM.addOnLoad(onLoadFunction); 1040} 1041 1042/** 1043 * @see HRDOM.addOnLoad(onLoadFunction) 1044 * 1045 * @deprecaded. 1046 */ 1047const HRAddOnAjaxLoad = function(sender, onLoadFunction) 1048{ 1049 HRDOM.addOnAjaxLoad(sender, onLoadFunction); 1050} 1051 1052/** 1053 * @see HRDOM.addTransitionEnded(element, onTransitionEndedFunction) 1054 * 1055 * @deprecaded. 1056 */ 1057function HRAddTransitionEnded(element, onTransitionEndedFunction) 1058{ 1059 HRDOM.addTransitionEndedEventListener(element, onTransitionEndedFunction); 1060} 1061 1062/** 1063 * @see HRDOM.getCookieValue(name) 1064 * 1065 * @deprecaded. 1066 */ 1067function HRGetCookieValue(name) 1068{ 1069 return HRDOM.getCookieValue(name); 1070} 1071 1072/** 1073 * @see HRDOM.getScrollPercent(maxValue) 1074 * 1075 * @deprecaded. 1076 */ 1077function HRGetScrollPercent(maxValue) 1078{ 1079 return HRDOM.getScrollPercent(maxValue); 1080} 1081 1082/** 1083 * @see HRDOM.mergeConfigs(defaultConfig, userConfig) 1084 * 1085 * @deprecaded. 1086 */ 1087function HRMergeConfigs(defaultConfig, userConfig) 1088{ 1089 return HRDOM.mergeConfigs(defaultConfig, userConfig); 1090} 1091 1092/** 1093 * @see HRDOM.wrap(element, wrapper) 1094 * 1095 * @deprecaded. 1096 */
1097function HRWrap(element, wrapper) 1098{ 1099 HRDOM.wrap(element, wrapper); 1100} 1101 1102/** 1103 * @see HRDOM.insertAfter(element, referenceElement) 1104 * 1105 * @deprecaded. 1106 */ 1107function HRInsertAfter(element, referenceElement) 1108{ 1109 HRDOM.insertAfter(element, referenceElement); 1110} 1111 1112/** 1113 * @see HRDOM.insertAsFirstChild(element, parent) 1114 * 1115 * @deprecaded. 1116 */ 1117function HRInsertAsFirstChild(element, parent) 1118{ 1119 HRDOM.insertAsFirstChild(element, parent); 1120} 1121 1122/** 1123 * @see HRDOM.removeAllChildren(element) 1124 * 1125 * @deprecaded. 1126 */ 1127function HRRemoveAllChildren(element) 1128{ 1129 HRDOM.removeAllChildren(element); 1130} 1131 1132/** 1133 * @see HRDOM.containsScriptInclude(url, searchDOM) 1134 * 1135 * @deprecaded. 1136 */ 1137function HRContainsScriptInclude(url, searchDOM) 1138{ 1139 return HRDOM.containsScriptInclude(url, searchDOM); 1140} 1141 1142/** 1143 * @see HRDOM.appendScriptIncludeToHead(url, onLoadFunction, searchDOM) 1144 * 1145 * @deprecaded. 1146 */ 1147function HRAppendScriptIncludeToHead(url, onLoadFunction, searchDOM) 1148{ 1149 return HRDOM.appendScriptIncludeToHead(url, onLoadFunction, searchDOM); 1150} 1151 1152/** 1153 * @see HRDOM.getParentElementById(startElement, idToFind) 1154 * 1155 * @deprecaded. 1156 */ 1157function HRGetParentElementById(startElement, idToFind) 1158{ 1159 return HRDOM.getParentElementById(startElement, idToFind); 1160} 1161 1162/** 1163 * @see HRDOM.isParentElement(startElement, parentToFind) 1164 * 1165 * @deprecaded. 1166 */ 1167function HRIsParentElement(startElement, parentToFind) 1168{ 1169 return HRDOM.isParentElement(startElement, parentToFind); 1170} 1171 1172/** 1173 * @see HRDOM.getSelectedRadioboxValue(name) 1174 * 1175 * @deprecaded. 1176 */ 1177function HRGetSelectedRadioboxValue(name) 1178{ 1179 return HRDOM.getSelectedRadioboxValue(name); 1180} 1181 1182/** 1183 * @see HRDOM.getFormValueByName(elementName, formname) 1184 * 1185 * @deprecaded. 1186 */ 1187function HRGetFormValueByName(elementName, formname) 1188{ 1189 return HRDOM.getFormValueByName(elementName, formname) 1190}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.