1 2// Submenu öffnen per Klick oder Tastatur 3document.querySelectorAll('.dropdown-submenu > a').forEach(function (trigger) { 4 trigger.addEventListener('click', function (e) { 5 e.preventDefault(); 6 // verhindert Bubbling, also document.addEventListener('click'... s.u. 7 e.stopPropagation(); 8 9 const parent = this.parentElement; 10 const expanded = this.getAttribute('aria-expanded') === 'true'; 11 12 // Alle anderen schlieÃen 13 document.querySelectorAll('.dropdown-submenu').forEach(function (el) { 14 el.classList.remove('show'); 15 el.querySelector('a').setAttribute('aria-expanded', 'false'); 16 }); 17 // Dieses öffnen 18 if (!expanded) { 19 parent.classList.add('show'); 20 this.setAttribute('aria-expanded', 'true'); 21 } 22 23 }); 24 25 // Tastaturbedienung (optional erweitert) 26 trigger.addEventListener('keydown', function (e) { 27 if (e.key === 'Enter' || e.key === ' ') { 28 e.preventDefault(); 29 this.click(); 30 } else if (e.key === 'Escape') { 31 this.setAttribute('aria-expanded', 'false'); 32 this.parentElement.classList.remove('show'); 33 this.focus(); 34 } 35 }); 36}); 37 38// Submenus schlieÃen beim Klick auÃerhalb und resize 39function closeAllSubmenus() { 40 document.querySelectorAll('.dropdown-submenu').forEach(function (submenu) { 41 submenu.classList.remove('show'); 42 submenu.querySelector('a').setAttribute('aria-expanded', 'false'); 43 }); 44} 45 46function closeAllMenus() { 47 document.querySelectorAll('.dropdown-menu').forEach(function (submenu) { 48 submenu.classList.remove('show'); 49 submenu.querySelector('a').setAttribute('aria-expanded', 'false'); 50 }); 51} 52 53document.addEventListener('click', closeAllSubmenus); 54window.addEventListener('resize', closeAllSubmenus); 55window.addEventListener('resize', closeAllMenus); 56 57/* Positionierung Menu Desktop */ 58if (window.innerWidth > 768) { 59 document.querySelectorAll('a.dropdown-toggle').forEach(el => { 60 ['mouseenter', 'click', 'keydown'].forEach(evt => { 61 el.addEventListener(evt, e => { 62 let offsetLeft = el.getBoundingClientRect().left; 63 let parent = el.parentElement; 64 let bottomY = parent.getBoundingClientRect().bottom; 65 66 // Suche das erste '.dropdown-menu' innerhalb dieses Parents 67 let parallelMenu = parent.querySelector('.dropdown-menu'); 68 69 let menu3 = el.closest('.dropdown-submenu'); 70 let menu1 = el.closest('.nav-item'); 71 let navbar = el.closest('.navbar'); 72 73 if (menu3) { 74 75 let menu3breite = menu3.querySelector('.dropdown-menu').getBoundingClientRect().width; 76 let distanceToRight1 = window.innerWidth - menu1.getBoundingClientRect().right - 20; 77 if (distanceToRight1 < menu3breite) 78 parallelMenu.style.left = "-" + menu3breite + "px"; 79 else 80 parallelMenu.style.left = "100%"; 81 } else { 82 83 // zweite Ebene 84 parallelMenu.style.top = `50px`; 85 let offsetLeft = menu1.getBoundingClientRect().left - navbar.getBoundingClientRect().left; 86 // links 87 if (offsetLeft < 20) 88 offsetLeft = 20; 89 // rechts 90 let widthParallelMenu = parallelMenu.getBoundingClientRect().width; 91 let widthNavbar = navbar.getBoundingClientRect().width; 92 if (widthParallelMenu > 0) { 93 let ueberlappung = offsetLeft + widthParallelMenu - widthNavbar; 94 if (ueberlappung > 0) 95 offsetLeft -= (ueberlappung + 20); 96 parallelMenu.style.left = offsetLeft + `px`; 97 } 98 } 99 100 }); 101 }); 102 }); 103 104 /* Chevrons für wischen */ 105 document.querySelector('.scroll-left').addEventListener('click', () => { 106 document.querySelector('.nav-wrapper').scrollBy({ left: -150, behavior: 'smooth' }); 107 }); 108 109 document.querySelector('.scroll-right').addEventListener('click', () => { 110 document.querySelector('.nav-wrapper').scrollBy({ left: 150, behavior: 'smooth' }); 111 }); 112 113 /* Chevron visibility */ 114 const scrollArea = document.querySelector('.nav-wrapper'); 115 const btnLeft = document.querySelector('.scroll-left'); 116 const btnRight = document.querySelector('.scroll-right'); 117 118 function updateChevronVisibility() { 119 const scrollLeft = scrollArea.scrollLeft; 120 const scrollWidth = scrollArea.scrollWidth; 121 const clientWidth = scrollArea.clientWidth; 122 123 124 // Linker Pfeil: nur zeigen, wenn gescrollt wurde 125 if (scrollLeft > 0) { 126 btnLeft.classList.remove('d-none'); 127 } else { 128 btnLeft.classList.add('d-none'); 129 } 130 131 // Rechter Pfeil: nur zeigen, wenn noch Platz zum Scrollen rechts 132 if (scrollLeft + clientWidth < scrollWidth - 1) { 133 btnRight.classList.remove('d-none'); 134 } else { 135 btnRight.classList.add('d-none'); 136 } 137 138 // Alle anderen Submenus schlieÃen 139 document.querySelectorAll('.nav-wrapper .show').forEach(el => { 140 el.classList.remove('show'); 141 }); 142 } 143 144 // Scrollbuttons 145 btnLeft.addEventListener('click', () => { 146 scrollArea.scrollBy({ left: -150, behavior: 'smooth' }); 147 }); 148 149 btnRight.addEventListener('click', () => { 150 // letztes Element nicht verschlucken 151 const remainingScroll = scrollArea.scrollWidth - scrollArea.clientWidth - scrollArea.scrollLeft; 152 const scrollAmount = Math.min(150, remainingScroll); 153 scrollArea.scrollBy({ left: scrollAmount, behavior: 'smooth' }); 154 }); 155 156 // Update Sichtbarkeit beim Scrollen 157 scrollArea.addEventListener('scroll', updateChevronVisibility); 158 159 // Initial prüfen nach Laden 160 window.addEventListener('load', updateChevronVisibility); 161 window.addEventListener('resize', updateChevronVisibility); 162 163 // zweimal auf den Toggler Klicken -> die Seite aufrufen 164 /*let lastClickedDropdown = null; 165 document.querySelectorAll('.dropdown-toggle').forEach(item => { 166 item.addEventListener('click', function (e) { 167 if (lastClickedDropdown === this) { 168 // Zweiter Klick auf dasselbe Element â weiterleiten 169 window.location.href = this.getAttribute('href'); 170 } else { 171 // Erster Klick â nur merken 172 lastClickedDropdown = this; 173 } 174 }); 175 }); 176 177 document.querySelectorAll('.dropdown-toggle').forEach(item => { 178 item.addEventListener('mouseover', function (e) { 179 if (window.matchMedia("(pointer: fine)").matches) { 180 lastClickedDropdown = this; 181 } 182 }); 183 });*/ 184 185} 186 187 188 189// Workaround barrierefreies Menu: 190// bei # 0 soll kein tabindex=-1 gesetzt werden. 191const target = document.getElementById('mmenu0'); 192 193if (target) { 194 // Direkt entfernen, falls schon da 195 if (target.getAttribute('tabindex') === '-1') { 196 target.removeAttribute('tabindex'); 197 } 198 199 // Beobachte spätere Ãnderungen 200 const observer = new MutationObserver(mutations => { 201 mutations.forEach(mutation => { 202 if ( 203 mutation.type === 'attributes' && 204 mutation.attributeName === 'tabindex' && 205 target.getAttribute('tabindex') === '-1' 206 ) { 207 target.removeAttribute('tabindex'); 208 } 209 }); 210 }); 211 212 observer.observe(target, { 213 attributes: true 214 }); 215} 216 217/* Startmenu Barrierefrei */ 218document.addEventListener("DOMContentLoaded", () => { 219 const skipMenu = document.getElementById("skip-menu"); 220 const buttons = skipMenu.querySelectorAll("button"); 221 222 // Mausklick abfangen 223 let hasClicked = false;
224 document.addEventListener("mousedown", () => { 225 hasClicked = true; 226 }); 227 228 229 let menuActive = false; 230 let firstUse = false; 231 232 const scrollbox = document.getElementById("mmenu0"); 233 if (scrollbox) { 234 scrollbox.querySelectorAll("li").forEach(li => { 235 li.setAttribute("tabindex", "-1"); 236 }) 237 } 238 239 document.addEventListener("keydown", (e) => { 240 if (!menuActive && !firstUse && !hasClicked && e.key === "Tab") { 241 // Nicht auslösen, wenn der Fokus bereits auf einem interaktiven Element liegt 242 const targetTagName = e.target.tagName.toLowerCase(); 243 if (["input", "textarea", "select", "button", "a"].includes(targetTagName)) { 244 return; 245 } 246 247 e.preventDefault(); 248 skipMenu.hidden = false; 249 buttons[0].focus(); 250 menuActive = true; 251 firstUse = true; 252 } 253 }); 254 255 buttons.forEach((btn) => { 256 btn.addEventListener("keydown", (e) => { 257 if (e.key === "Enter") { 258 const targetId = btn.dataset.target; 259 const target = document.getElementById(targetId); 260 261 if (target) { 262 target.setAttribute("tabindex", "-1"); 263 target.focus({ preventScroll: false }); 264 } 265 skipMenu.hidden = true; 266 menuActive = false; 267 } 268 }); 269 }); 270}); 271 272 273 274document.addEventListener("keyup", function (e) { 275 console.log("key:", e.key, " | code:", e.code); 276 // Prüfen ob ArrowUp gedrückt wurde 277 if (e.code === "Escape") { 278 const active = document.activeElement; // aktuell fokussiertes Element 279 // Prüfen ob es ein erstes Submenu-Item ist 280 if (e.target.parentElement.matches(".dropdown-menu li")) { 281 // Zum übergeordneten Menüpunkt springen 282 const target_a = active.closest(".dropdown-menu").previousElementSibling; 283 target_a.parentElement.classList.remove('show'); 284 target_a.setAttribute('aria-expanded', 'false'); 285 target_a.focus(); 286 } 287 } 288}); 289 290// beim Klicken auf "Navigationsmenu" wird das Mobile Menu geöffnet 291(() => { 292 const btnRight = document.querySelector('#start-link-to-menu'); 293 const navbar = document.querySelector('#navbarNavDropdown'); 294 295 if (!btnRight || !navbar) return; 296 297 // Funktion zum Umschalten nur bei < 768px 298 function toggleMenuIfMobile() { 299 if (window.innerWidth < 768) { 300 navbar.classList.toggle('collapse'); 301 } 302 } 303 304 // Maus-Klick 305 btnRight.addEventListener('click', toggleMenuIfMobile); 306 307 // Tastatur-Eingabe (Tab + Enter oder Space) 308 btnRight.addEventListener('keydown', (event) => { 309 if (event.key === 'Enter' || event.key === ' ') { 310 event.preventDefault(); 311 toggleMenuIfMobile(); 312 } 313 }); 314})(); 315 316// Keine Ãberlappungen des Menüs mit Navbar 317function positionFixedSidebars() { 318 if (window.innerWidth > 768) { 319 const navbar = document.querySelector('#navbarNavDropdown'); 320 if (!navbar) return; 321 const navbarBottom = navbar.getBoundingClientRect().bottom; 322 // Liste aller möglichen Sidebars 323 const sidebars = ['#wt6_sidebar1', '#wt6_sidebar2']; 324 325 sidebars.forEach(selector => { 326 const el = document.querySelector(selector); 327 if (el) { 328 el.style.top = `${navbarBottom + 30}px`; 329 el.style.display = "block"; 330 } 331 }); 332 } 333} 334 335// Beim Laden und bei Resize neu ausrichten 336window.addEventListener('DOMContentLoaded', positionFixedSidebars); 337window.addEventListener('resize', positionFixedSidebars); 338//Get the button 339let mybutton = document.getElementById("btn-back-to-top"); 340 341function scrollFunction() { 342 if ( 343 document.body.scrollTop > 20 || 344 document.documentElement.scrollTop > 20 345 ) { 346 mybutton.style.display = "block"; 347 } else { 348 mybutton.style.display = "none"; 349 } 350} 351// When the user clicks on the button, scroll to the top of the document 352mybutton.addEventListener("click", backToTop); 353 354 355function backToTop() { 356 document.body.scrollTop = 0; 357 document.documentElement.scrollTop = 0; 358} 359 360/* PAF_OBSOLETE function wtCheckMenu() { 361 let menu = document.getElementById('navbarNavDropdown'); 362 let menuSize = menu.getElementsByClassName('navbar-nav')[0].clientWidth; 363 let buttonSize = menu.parentNode.getElementsByClassName('buttons-navbar')[0].clientWidth; 364 let parentSize = menu.parentNode.clientWidth; 365 let usableSpace = parentSize - buttonSize - 50; 366 menu.style.visibility = (usableSpace>menuSize)?"visible":"hidden"; 367} */ 368 369window.onscroll = function () { 370 scrollFunction(); 371}; 372 373/*PAF-OBSOLETE 374window.onload = function() { 375 wtCheckMenu(); 376} 377window.onresize = function() { 378 wtCheckMenu(); 379} */ 380 381function wtToggleCopyright(elem) { 382 if( elem.style.width == 'auto' ) { 383 elem.style.width = '30px'; 384 elem.style.height = '27px'; 385 } else { 386 elem.style.width = 'auto'; 387 elem.style.height = 'auto'; 388 } 389} 390 391function wtToggleActive(elem) {
392 let cn = elem.className; 393 if( cn.match(/ active/) ) { 394 cn = cn.replace(/ active/,""); 395 } else { 396 cn += " active"; 397 } 398 elem.className = cn; 399} 400 401/*function wtTrimDropdown() { 402 let menu = document.getElementById('navbarNavDropdown'); 403 let dropdowns = menu.getElementsByClassName('dropdown-menu'); 404 let wh = window.innerHeight; 405 for( let i=0; i<dropdowns.length; i++) { 406 dropdowns[i].style.display = 'block'; 407 let dr = dropdowns[i].getBoundingClientRect(); 408 dropdowns[i].style.display = ''; 409 if( dr.bottom>wh ) { 410 dropdowns[i].style.height = (wh-dr.top)+"px"; 411 } else { 412 dropdowns[i].style.height = ''; 413 } 414 } 415}*/ 416 417function wtSetMenuCategory( category ) { 418 document.cookie = "wt_menu_category="+(category)+";path=/;SameSite=Lax"; 419 window.location.reload(); 420} 421 422function wtShowCategoryMenus() { 423 let co = wt_getCookieValue('wt_menu_category'); 424 if( co ) { 425 let menuitems = document.getElementsByClassName('wt_menu_'+(co) ); 426 for( let i=0; i<menuitems.length; i++) { 427 menuitems[i].style.display = 'inline'; 428 } 429 let mitem = document.getElementById('wt_catmenu_'+(co)); 430 if( mitem ) { mitem.style.borderBottomWidth = "5px"; } 431 let tbitems = document.getElementsByClassName('wt_catmenu_tb'); 432 for( let i=0; i<tbitems.length; i++) { 433 if( tbitems[i].id == 'wt_catmenu_tb_'+(co) ) { 434 tbitems[i].className = 'wt_catmenu_tb active text-white small'; 435 if( tbitems[i].innerHTML.match(/Profi/) ) { 436 tbitems[i].parentNode.parentNode.parentNode.style.backgroundColor = '#002060'; 437 } 438 } else { 439 tbitems[i].className = 'wt_catmenu_tb inactive text-white small'; 440 } 441 } 442 } 443} 444 445window.addEventListener('load', wtShowCategoryMenus ); 446var SignaturPads = {}; 447 448document.addEventListener("DOMContentLoaded", function () { 449 var signaturePads = document.querySelectorAll("canvas.signature-pad"); 450 451 signaturePads.forEach(function (canvas) { 452 SignaturPads[canvas.id] = new SignaturePad(canvas, { 453 backgroundColor: "rgb(255, 255, 255)" 454 }); 455 456 var formField = canvas.closest(".form-field-signatur-pad"); 457 var input = formField.querySelector("input.is-invalid"); 458 if (input) { 459 canvas.classList.add("border-danger"); 460 } 461 }); 462 463 var forms = document.querySelectorAll("form"); 464 forms.forEach(function (form) { 465 form.addEventListener("submit", function (event) { 466 var signaturePads = form.querySelectorAll("canvas.signature-pad"); 467 signaturePads.forEach(function (canvas) { 468 var SignaturPad = SignaturPads[canvas.id]; 469 if (!SignaturPad.isEmpty()) { 470 var data = SignaturPad.toDataURL("image/png"); 471 var blob = dataURLToBlob(data); 472 var file = new File([blob], canvas.id + ".png", { 473 type: "image/png", 474 lastModified: new Date().getTime(), 475 }); 476 var container = new DataTransfer(); 477 container.items.add(file); 478 var fileInputElement = document.getElementById(canvas.getAttribute("data-target")); 479 fileInputElement.files = container.files; 480 } 481 }); 482 }); 483 }); 484}); 485 486function clearSignaturPad(SignaturPad) { 487 var SignaturPadInstance = SignaturPads[SignaturPad]; 488 SignaturPadInstance.clear(); 489} 490 491function dataURLToBlob(dataURL) { 492 var parts = dataURL.split(";base64,"); 493 var contentType = parts[0].split(":")[1]; 494 var raw = window.atob(parts[1]); 495 var rawLength = raw.length; 496 var uInt8Array = new Uint8Array(rawLength); 497 498 for (var i = 0; i < rawLength; ++i) { 499 uInt8Array[i] = raw.charCodeAt(i); 500 } 501 502 return new Blob([uInt8Array], { type: contentType }); 503} 504/*! 505 * Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad 506 * (c) 2020 Szymon Nowak | Released under the MIT license 507 */ 508 509(function (global, factory) { 510 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 511 typeof define === 'function' && define.amd ? define(factory) : 512 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SignaturePad = factory()); 513}(this, (function () { 'use strict'; 514 515 var Point = (function () { 516 function Point(x, y, time) { 517 this.x = x; 518 this.y = y; 519 this.time = time || Date.now(); 520 } 521 Point.prototype.distanceTo = function (start) { 522 return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2)); 523 }; 524 Point.prototype.equals = function (other) { 525 return this.x === other.x && this.y === other.y && this.time === other.time; 526 }; 527 Point.prototype.velocityFrom = function (start) { 528 return this.time !== start.time 529 ? this.distanceTo(start) / (this.time - start.time) 530 : 0; 531 }; 532 return Point; 533 }()); 534 535 var Bezier = (function () { 536 function Bezier(startPoint, control2, control1, endPoint, startWidth, endWidth) { 537 this.startPoint = startPoint; 538 this.control2 = control2; 539 this.control1 = control1; 540 this.endPoint = endPoint; 541 this.startWidth = startWidth; 542 this.endWidth = endWidth; 543 } 544 Bezier.fromPoints = function (points, widths) { 545 var c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2; 546 var c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1; 547 return new Bezier(points[1], c2, c3, points[2], widths.start, widths.end); 548 }; 549 Bezier.calculateControlPoints = function (s1, s2, s3) { 550 var dx1 = s1.x - s2.x; 551 var dy1 = s1.y - s2.y; 552 var dx2 = s2.x - s3.x; 553 var dy2 = s2.y - s3.y;
554 var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 }; 555 var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 }; 556 var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); 557 var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2); 558 var dxm = m1.x - m2.x; 559 var dym = m1.y - m2.y; 560 var k = l2 / (l1 + l2); 561 var cm = { x: m2.x + dxm * k, y: m2.y + dym * k }; 562 var tx = s2.x - cm.x; 563 var ty = s2.y - cm.y; 564 return { 565 c1: new Point(m1.x + tx, m1.y + ty), 566 c2: new Point(m2.x + tx, m2.y + ty) 567 }; 568 }; 569 Bezier.prototype.length = function () { 570 var steps = 10; 571 var length = 0; 572 var px; 573 var py; 574 for (var i = 0; i <= steps; i += 1) { 575 var t = i / steps; 576 var cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x); 577 var cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y); 578 if (i > 0) { 579 var xdiff = cx - px; 580 var ydiff = cy - py; 581 length += Math.sqrt(xdiff * xdiff + ydiff * ydiff); 582 } 583 px = cx; 584 py = cy; 585 } 586 return length; 587 }; 588 Bezier.prototype.point = function (t, start, c1, c2, end) { 589 return (start * (1.0 - t) * (1.0 - t) * (1.0 - t)) 590 + (3.0 * c1 * (1.0 - t) * (1.0 - t) * t) 591 + (3.0 * c2 * (1.0 - t) * t * t) 592 + (end * t * t * t); 593 }; 594 return Bezier; 595 }()); 596 597 function throttle(fn, wait) { 598 if (wait === void 0) { wait = 250; } 599 var previous = 0; 600 var timeout = null; 601 var result; 602 var storedContext; 603 var storedArgs; 604 var later = function () { 605 previous = Date.now(); 606 timeout = null; 607 result = fn.apply(storedContext, storedArgs); 608 if (!timeout) { 609 storedContext = null; 610 storedArgs = []; 611 } 612 }; 613 return function wrapper() { 614 var args = []; 615 for (var _i = 0; _i < arguments.length; _i++) { 616 args[_i] = arguments[_i]; 617 } 618 var now = Date.now(); 619 var remaining = wait - (now - previous); 620 storedContext = this; 621 storedArgs = args; 622 if (remaining <= 0 || remaining > wait) { 623 if (timeout) { 624 clearTimeout(timeout); 625 timeout = null; 626 } 627 previous = now; 628 result = fn.apply(storedContext, storedArgs); 629 if (!timeout) { 630 storedContext = null; 631 storedArgs = []; 632 } 633 } 634 else if (!timeout) { 635 timeout = window.setTimeout(later, remaining); 636 } 637 return result; 638 }; 639 } 640 641 var SignaturePad = (function () { 642 function SignaturePad(canvas, options) { 643 var _this = this; 644 if (options === void 0) { options = {}; } 645 this.canvas = canvas; 646 this.options = options; 647 this._handleMouseDown = function (event) { 648 if (event.which === 1) { 649 _this._mouseButtonDown = true; 650 _this._strokeBegin(event); 651 } 652 }; 653 this._handleMouseMove = function (event) { 654 if (_this._mouseButtonDown) { 655 _this._strokeMoveUpdate(event); 656 } 657 }; 658 this._handleMouseUp = function (event) { 659 if (event.which === 1 && _this._mouseButtonDown) { 660 _this._mouseButtonDown = false; 661 _this._strokeEnd(event); 662 } 663 }; 664 this._handleTouchStart = function (event) { 665 event.preventDefault(); 666 if (event.targetTouches.length === 1) { 667 var touch = event.changedTouches[0]; 668 _this._strokeBegin(touch); 669 } 670 }; 671 this._handleTouchMove = function (event) { 672 event.preventDefault(); 673 var touch = event.targetTouches[0]; 674 _this._strokeMoveUpdate(touch); 675 }; 676 this._handleTouchEnd = function (event) { 677 var wasCanvasTouched = event.target === _this.canvas; 678 if (wasCanvasTouched) { 679 event.preventDefault(); 680 var touch = event.changedTouches[0]; 681 _this._strokeEnd(touch); 682 } 683 }; 684 this.velocityFilterWeight = options.velocityFilterWeight || 0.7; 685 this.minWidth = options.minWidth || 0.5; 686 this.maxWidth = options.maxWidth || 2.5; 687 this.throttle = ('throttle' in options ? options.throttle : 16); 688 this.minDistance = ('minDistance' in options 689 ? options.minDistance 690 : 5); 691 this.dotSize = 692 options.dotSize || 693 function dotSize() { 694 return (this.minWidth + this.maxWidth) / 2; 695 }; 696 this.penColor = options.penColor || 'black'; 697 this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)'; 698 this.onBegin = options.onBegin; 699 this.onEnd = options.onEnd; 700 this._strokeMoveUpdate = this.throttle 701 ? throttle(SignaturePad.prototype._strokeUpdate, this.throttle) 702 : SignaturePad.prototype._strokeUpdate; 703 this._ctx = canvas.getContext('2d'); 704 this.clear(); 705 this.on(); 706 } 707 SignaturePad.prototype.clear = function () { 708 var _a = this, ctx = _a._ctx, canvas = _a.canvas; 709 ctx.fillStyle = this.backgroundColor; 710 ctx.clearRect(0, 0, canvas.width, canvas.height); 711 ctx.fillRect(0, 0, canvas.width, canvas.height); 712 this._data = []; 713 this._reset(); 714 this._isEmpty = true; 715 }; 716 SignaturePad.prototype.fromDataURL = function (dataUrl, options, callback) { 717 var _this = this; 718 if (options === void 0) { options = {}; } 719 var image = new Image(); 720 var ratio = options.ratio || window.devicePixelRatio || 1; 721 var width = options.width || this.canvas.width / ratio; 722 var height = options.height || this.canvas.height / ratio; 723 this._reset(); 724 image.onload = function () { 725 _this._ctx.drawImage(image, 0, 0, width, height); 726 if (callback) { 727 callback(); 728 } 729 }; 730 image.onerror = function (error) { 731 if (callback) { 732 callback(error); 733 } 734 }; 735 image.src = dataUrl; 736 this._isEmpty = false;
737 }; 738 SignaturePad.prototype.toDataURL = function (type, encoderOptions) { 739 if (type === void 0) { type = 'image/png'; } 740 switch (type) { 741 case 'image/svg+xml': 742 return this._toSVG(); 743 default: 744 return this.canvas.toDataURL(type, encoderOptions); 745 } 746 }; 747 SignaturePad.prototype.on = function () { 748 this.canvas.style.touchAction = 'none'; 749 this.canvas.style.msTouchAction = 'none'; 750 if (window.PointerEvent) { 751 this._handlePointerEvents(); 752 } 753 else { 754 this._handleMouseEvents(); 755 if ('ontouchstart' in window) { 756 this._handleTouchEvents(); 757 } 758 } 759 }; 760 SignaturePad.prototype.off = function () { 761 this.canvas.style.touchAction = 'auto'; 762 this.canvas.style.msTouchAction = 'auto'; 763 this.canvas.removeEventListener('pointerdown', this._handleMouseDown); 764 this.canvas.removeEventListener('pointermove', this._handleMouseMove); 765 document.removeEventListener('pointerup', this._handleMouseUp); 766 this.canvas.removeEventListener('mousedown', this._handleMouseDown); 767 this.canvas.removeEventListener('mousemove', this._handleMouseMove); 768 document.removeEventListener('mouseup', this._handleMouseUp); 769 this.canvas.removeEventListener('touchstart', this._handleTouchStart); 770 this.canvas.removeEventListener('touchmove', this._handleTouchMove); 771 this.canvas.removeEventListener('touchend', this._handleTouchEnd); 772 }; 773 SignaturePad.prototype.isEmpty = function () { 774 return this._isEmpty; 775 }; 776 SignaturePad.prototype.fromData = function (pointGroups) { 777 var _this = this; 778 this.clear(); 779 this._fromData(pointGroups, function (_a) { 780 var color = _a.color, curve = _a.curve; 781 return _this._drawCurve({ color: color, curve: curve }); 782 }, function (_a) { 783 var color = _a.color, point = _a.point; 784 return _this._drawDot({ color: color, point: point }); 785 }); 786 this._data = pointGroups; 787 }; 788 SignaturePad.prototype.toData = function () { 789 return this._data; 790 }; 791 SignaturePad.prototype._strokeBegin = function (event) { 792 var newPointGroup = { 793 color: this.penColor, 794 points: [] 795 }; 796 if (typeof this.onBegin === 'function') { 797 this.onBegin(event); 798 } 799 this._data.push(newPointGroup); 800 this._reset(); 801 this._strokeUpdate(event); 802 }; 803 SignaturePad.prototype._strokeUpdate = function (event) { 804 if (this._data.length === 0) { 805 this._strokeBegin(event); 806 return; 807 } 808 var x = event.clientX; 809 var y = event.clientY; 810 var point = this._createPoint(x, y); 811 var lastPointGroup = this._data[this._data.length - 1]; 812 var lastPoints = lastPointGroup.points; 813 var lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1]; 814 var isLastPointTooClose = lastPoint 815 ? point.distanceTo(lastPoint) <= this.minDistance 816 : false; 817 var color = lastPointGroup.color; 818 if (!lastPoint || !(lastPoint && isLastPointTooClose)) { 819 var curve = this._addPoint(point); 820 if (!lastPoint) { 821 this._drawDot({ color: color, point: point }); 822 } 823 else if (curve) { 824 this._drawCurve({ color: color, curve: curve }); 825 } 826 lastPoints.push({ 827 time: point.time, 828 x: point.x, 829 y: point.y 830 }); 831 } 832 }; 833 SignaturePad.prototype._strokeEnd = function (event) { 834 this._strokeUpdate(event); 835 if (typeof this.onEnd === 'function') { 836 this.onEnd(event); 837 } 838 }; 839 SignaturePad.prototype._handlePointerEvents = function () { 840 this._mouseButtonDown = false;
vendor: 9,032 bytes, lines 841-1033
841 this.canvas.addEventListener('pointerdown', this._handleMouseDown); 842 this.canvas.addEventListener('pointermove', this._handleMouseMove); 843 document.addEventListener('pointerup', this._handleMouseUp); 844 }; 845 SignaturePad.prototype._handleMouseEvents = function () { 846 this._mouseButtonDown = false; 847 this.canvas.addEventListener('mousedown', this._handleMouseDown); 848 this.canvas.addEventListener('mousemove', this._handleMouseMove); 849 document.addEventListener('mouseup', this._handleMouseUp); 850 }; 851 SignaturePad.prototype._handleTouchEvents = function () { 852 this.canvas.addEventListener('touchstart', this._handleTouchStart); 853 this.canvas.addEventListener('touchmove', this._handleTouchMove); 854 this.canvas.addEventListener('touchend', this._handleTouchEnd); 855 }; 856 SignaturePad.prototype._reset = function () { 857 this._lastPoints = []; 858 this._lastVelocity = 0; 859 this._lastWidth = (this.minWidth + this.maxWidth) / 2; 860 this._ctx.fillStyle = this.penColor; 861 }; 862 SignaturePad.prototype._createPoint = function (x, y) { 863 var rect = this.canvas.getBoundingClientRect(); 864 return new Point(x - rect.left, y - rect.top, new Date().getTime()); 865 }; 866 SignaturePad.prototype._addPoint = function (point) { 867 var _lastPoints = this._lastPoints; 868 _lastPoints.push(point); 869 if (_lastPoints.length > 2) { 870 if (_lastPoints.length === 3) { 871 _lastPoints.unshift(_lastPoints[0]); 872 } 873 var widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2]); 874 var curve = Bezier.fromPoints(_lastPoints, widths); 875 _lastPoints.shift(); 876 return curve; 877 } 878 return null; 879 }; 880 SignaturePad.prototype._calculateCurveWidths = function (startPoint, endPoint) { 881 var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) + 882 (1 - this.velocityFilterWeight) * this._lastVelocity; 883 var newWidth = this._strokeWidth(velocity); 884 var widths = { 885 end: newWidth, 886 start: this._lastWidth 887 }; 888 this._lastVelocity = velocity; 889 this._lastWidth = newWidth; 890 return widths; 891 }; 892 SignaturePad.prototype._strokeWidth = function (velocity) { 893 return Math.max(this.maxWidth / (velocity + 1), this.minWidth); 894 }; 895 SignaturePad.prototype._drawCurveSegment = function (x, y, width) { 896 var ctx = this._ctx; 897 ctx.moveTo(x, y); 898 ctx.arc(x, y, width, 0, 2 * Math.PI, false); 899 this._isEmpty = false; 900 }; 901 SignaturePad.prototype._drawCurve = function (_a) { 902 var color = _a.color, curve = _a.curve; 903 var ctx = this._ctx; 904 var widthDelta = curve.endWidth - curve.startWidth; 905 var drawSteps = Math.floor(curve.length()) * 2; 906 ctx.beginPath(); 907 ctx.fillStyle = color; 908 for (var i = 0; i < drawSteps; i += 1) { 909 var t = i / drawSteps; 910 var tt = t * t; 911 var ttt = tt * t; 912 var u = 1 - t; 913 var uu = u * u; 914 var uuu = uu * u; 915 var x = uuu * curve.startPoint.x; 916 x += 3 * uu * t * curve.control1.x; 917 x += 3 * u * tt * curve.control2.x; 918 x += ttt * curve.endPoint.x; 919 var y = uuu * curve.startPoint.y; 920 y += 3 * uu * t * curve.control1.y; 921 y += 3 * u * tt * curve.control2.y; 922 y += ttt * curve.endPoint.y; 923 var width = Math.min(curve.startWidth + ttt * widthDelta, this.maxWidth); 924 this._drawCurveSegment(x, y, width); 925 } 926 ctx.closePath(); 927 ctx.fill(); 928 }; 929 SignaturePad.prototype._drawDot = function (_a) { 930 var color = _a.color, point = _a.point; 931 var ctx = this._ctx; 932 var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize; 933 ctx.beginPath(); 934 this._drawCurveSegment(point.x, point.y, width); 935 ctx.closePath(); 936 ctx.fillStyle = color; 937 ctx.fill(); 938 }; 939 SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) { 940 for (var _i = 0, pointGroups_1 = pointGroups; _i < pointGroups_1.length; _i++) { 941 var group = pointGroups_1[_i]; 942 var color = group.color, points = group.points; 943 if (points.length > 1) { 944 for (var j = 0; j < points.length; j += 1) { 945 var basicPoint = points[j]; 946 var point = new Point(basicPoint.x, basicPoint.y, basicPoint.time); 947 this.penColor = color; 948 if (j === 0) { 949 this._reset(); 950 } 951 var curve = this._addPoint(point); 952 if (curve) { 953 drawCurve({ color: color, curve: curve }); 954 } 955 } 956 } 957 else { 958 this._reset(); 959 drawDot({ 960 color: color, 961 point: points[0] 962 }); 963 } 964 } 965 }; 966 SignaturePad.prototype._toSVG = function () { 967 var _this = this; 968 var pointGroups = this._data; 969 var ratio = Math.max(window.devicePixelRatio || 1, 1); 970 var minX = 0; 971 var minY = 0; 972 var maxX = this.canvas.width / ratio; 973 var maxY = this.canvas.height / ratio; 974 var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 975 svg.setAttribute('width', this.canvas.width.toString()); 976 svg.setAttribute('height', this.canvas.height.toString()); 977 this._fromData(pointGroups, function (_a) { 978 var color = _a.color, curve = _a.curve; 979 var path = document.createElement('path'); 980 if (!isNaN(curve.control1.x) && 981 !isNaN(curve.control1.y) && 982 !isNaN(curve.control2.x) && 983 !isNaN(curve.control2.y)) { 984 var attr = "M " + curve.startPoint.x.toFixed(3) + "," + curve.startPoint.y.toFixed(3) + " " + 985 ("C " + curve.control1.x.toFixed(3) + "," + curve.control1.y.toFixed(3) + " ") + 986 (curve.control2.x.toFixed(3) + "," + curve.control2.y.toFixed(3) + " ") + 987 (curve.endPoint.x.toFixed(3) + "," + curve.endPoint.y.toFixed(3)); 988 path.setAttribute('d', attr); 989 path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3)); 990 path.setAttribute('stroke', color); 991 path.setAttribute('fill', 'none'); 992 path.setAttribute('stroke-linecap', 'round'); 993 svg.appendChild(path); 994 } 995 }, function (_a) { 996 var color = _a.color, point = _a.point; 997 var circle = document.createElement('circle'); 998 var dotSize = typeof _this.dotSize === 'function' ? _this.dotSize() : _this.dotSize; 999 circle.setAttribute('r', dotSize.toString()); 1000 circle.setAttribute('cx', point.x.toString()); 1001 circle.setAttribute('cy', point.y.toString()); 1002 circle.setAttribute('fill', color); 1003 svg.appendChild(circle); 1004 }); 1005 var prefix = 'data:image/svg+xml;base64,'; 1006 var header = '<svg' + 1007 ' xmlns="http://www.w3.org/2000/svg"' + 1008 ' xmlns:xlink="http://www.w3.org/1999/xlink"' + 1009 (" viewBox=\"" + minX + " " + minY + " " + maxX + " " + maxY + "\"") + 1010 (" width=\"" + maxX + "\"") + 1011 (" height=\"" + maxY + "\"") + 1012 '>'; 1013 var body = svg.innerHTML; 1014 if (body === undefined) { 1015 var dummy = document.createElement('dummy'); 1016 var nodes = svg.childNodes; 1017 dummy.innerHTML = ''; 1018 for (var i = 0; i < nodes.length; i += 1) { 1019 dummy.appendChild(nodes[i].cloneNode(true)); 1020 } 1021 body = dummy.innerHTML; 1022 } 1023 var footer = '</svg>'; 1024 var data = header + body + footer; 1025 return prefix + btoa(data); 1026 }; 1027 return SignaturePad; 1028 }()); 1029 1030 return SignaturePad; 1031 1032}))); 1033//# sourceMappingURL=signature_pad.umd.js.map
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.