1 2 3// TRANSLATE 4let translate = {}; 5let language = {}; 6let otherTranslate = {}; 7let publicConsts = {}; 8let stateNames = {}; 9let isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches && ($('html[data-darkmode="LIGHT"]').length <= 0) || ($('html[data-darkmode="DARK"]').length > 0); 10window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { 11 isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches && ($('html[data-darkmode="LIGHT"]').length <= 0) || ($('html[data-darkmode="DARK"]').length > 0); 12 setAppDarkMode(); 13 changeTheme($('html').data('color')); 14}); 15function toFloatInput(price) { 16 return numberFormat(price.toString().replace(',', '').replace('.', ','), 2, ',', '.'); 17} 18function numberFormat(price, decimalPlaces, decimalSeparator, thousandsSeparator) { 19 let value = parseFloat(price.replace('.', '').replace(',', '.')); 20 if (isNaN(value)) { 21 return "0,00"; 22 } 23 let negativ = false; 24 if (value < 0) { 25 negativ = true; 26 value *= -1; 27 } 28 let formatted = value.toFixed(decimalPlaces); 29 let number = Math.floor(formatted); 30 let decimal = Math.floor((formatted - number).toFixed(decimalPlaces) * Math.pow(10, decimalPlaces)); 31 decimal = decimal.toString(); 32 while (decimal.toString().length < decimalPlaces) { 33 decimal = '0' + decimal; 34 } 35 number = number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator); 36 number = number + decimalSeparator + decimal.toString().padEnd(decimalPlaces, "0"); 37 return (negativ ? '-' : '') + number; 38} 39$.scrollLock = (function scrollLockSimple() { 40 var locked = false; 41 var $body; 42 var previous; 43 44 function lock() { 45 if (!$body) 46 $body = $('body'); 47 previous = $body.css('overflow'); 48 $body.css('overflow', 'hidden'); 49 locked = true; 50 } 51 52 function unlock() { 53 $body.css('overflow', 'visible'); 54 locked = false; 55 } 56 return function scrollLock(on) { 57 if (arguments.length) { 58 if (on) 59 lock(); 60 else 61 unlock(); 62 } else { 63 if (locked) 64 unlock(); 65 else 66 lock(); 67 } 68 }; 69}()); 70 71let vh = window.innerHeight * 0.01; 72document.documentElement.style.setProperty('--vh', `${vh}px`); 73window.addEventListener('resize', () => { 74 let vh = window.innerHeight * 0.01; 75 document.documentElement.style.setProperty('--vh', `${vh}px`); 76}); 77 78function setAppDarkMode() { 79 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 80 var messageObj = { function: 'darkmode', isDarkMode: isDarkMode }; 81 var stringifiedMessageObj = JSON.stringify(messageObj); 82 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 83 } 84} 85function getTranslate() { 86 return new Promise((resolve, reject) => { 87 let lang = $('html').data('my-lang'); 88 if (lang == 'bz') 89 lang = 'de'; 90 $.getJSON("translate/" + lang + ".json?t=" + new Date().getTime(), function (data) { 91 language = $('html').data('my-lang'); 92 translate = data; 93 loadOtherLangs(lang); 94 resolve(true); 95 }).fail(function (e) { 96 console.log("error translate"); 97 resolve(false); 98 }); 99 }); 100 101} 102// translate wird erst im window.load-Handler geladen - Klicks davor (oder nach 103// fehlgeschlagenem Laden) liefen auf ein leeres translate-Objekt. 104async function ensureTranslate() { 105 if (Object.keys(translate).length === 0) { 106 await getTranslate(); 107 } 108} 109function getPublicConsts() { 110 return new Promise((resolve, reject) => { 111 $.getJSON("getpublicconsts", function (data) { 112 publicConsts = data; 113 resolve(true); 114 }).fail(function (e) { 115 console.log("error publicconsts"); 116 resolve(false); 117 }); 118 }); 119} 120function getStateNames() { 121 return new Promise((resolve, reject) => { 122 $.getJSON("getstatenames", function (data) { 123 stateNames = data; 124 resolve(true); 125 }).fail(function (e) { 126 console.log("error statenames"); 127 resolve(false); 128 }); 129 }); 130 131} 132function getStateTranslate(state) { 133 if (stateNames[state] !== undefined) { 134 return stateNames[state]; 135 } 136 if (translate[state] !== undefined) { 137 return translate[state]; 138 } 139 // z. B. STATE_TEST_1_OK: nicht in stateNames, nur unter translate['STATES'] 140 if (translate['STATES'] !== undefined && translate['STATES'][state] !== undefined) { 141 let name = translate['STATES'][state]; 142 if (language == 'bz' && otherTranslate['it'] !== undefined && otherTranslate['it']['STATES'] !== undefined && otherTranslate['it']['STATES'][state] !== undefined) { 143 name += ' - ' + otherTranslate['it']['STATES'][state]; 144 } 145 return name; 146 } 147 return state; 148} 149function loadOtherLangs(currLang) { 150 const allLang = ['de', 'it', 'en']; 151 allLang.forEach(function (lang) { 152 if (lang != currLang) { 153 $.getJSON("translate/" + lang + ".json?t=" + new Date().getTime(), function (data) {
154 otherTranslate[lang] = data 155 }).fail(function (e) { 156 console.log("error translate"); 157 }); 158 } 159 }); 160} 161// GENERAL 162function trackEventGoogleAnalytics(eventName, parameter = {}) { 163 try { 164 if (typeof gtag !== 'undefined') { 165 gtag('event', eventName, parameter); 166 } 167 } catch (error) { 168 console.log(error); 169 } 170 171} 172function trackEventFacebook(eventName, parameter = {}) { 173 try { 174 if (typeof fbq !== 'undefined') { 175 fbq('trackCustom', eventName, parameter); 176 return true; 177 } 178 } catch (error) { 179 console.log(error); 180 } 181 return false; 182} 183async function scrollToEl(el) { 184 return new Promise(function (resolve, reject) { 185 let top = $('.menu-top').outerHeight(); 186 if ($('.my-breadcrumbs-wrapper').length > 0) 187 top += $('.my-breadcrumbs-wrapper').outerHeight(); 188 $([document.documentElement, document.body]).animate({ 189 scrollTop: el.offset().top - top 190 }, 500).promise().done(function () { 191 resolve(true); 192 }); 193 }); 194} 195const levenshteinDistance = (str1 = '', str2 = '') => { 196 const track = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null)); 197 for (let i = 0; i <= str1.length; i += 1) { 198 track[0][i] = i; 199 } 200 for (let j = 0; j <= str2.length; j += 1) { 201 track[j][0] = j; 202 } 203 for (let j = 1; j <= str2.length; j += 1) { 204 for (let i = 1; i <= str1.length; i += 1) { 205 const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1; 206 track[j][i] = Math.min( 207 track[j][i - 1] + 1, 208 track[j - 1][i] + 1, 209 track[j - 1][i - 1] + indicator, 210 ); 211 } 212 } 213 return track[str2.length][str1.length]; 214}; 215initZoomist(); 216function initZoomist() { 217 if ($('.zoomist-img').length > 0) { 218 $('.zoomist-img').each(function (idx, zoomistElement) { 219 const myZoomist = new Zoomist(zoomistElement, { 220 zoomRatio: 0.1, 221 fill: "contain", 222 draggable: true, 223 wheelable: true, 224 pinchable: true, 225 bounds: true, 226 minRatio: 1, 227 maxRatio: 6, 228 slider: false, 229 // slider: { 230 // direction: "horizontal" 231 // }, 232 zoomer: false 233 }) 234 myZoomist.on('zoom', function (ratio) { 235 if (ratio <= 1) { 236 myZoomist.reset(); 237 238 } 239 }); 240 myZoomist.on('dragStart', function (transform, event) { 241 if (myZoomist.getZoomRatio() <= 1) { 242 myZoomist.reset() 243 } 244 }); 245 myZoomist.on('drag', function (transform, event) { 246 if (myZoomist.getZoomRatio() <= 1) { 247 myZoomist.reset() 248 } 249 }); 250 }) 251 252 } 253} 254$('.focus-after-load').find('[name]').focus(); 255initColor(); 256$(window).on('load', async function () { 257 await getPublicConsts(); 258 await getTranslate(); 259 await updateGb(null, false); 260 await saveFormCheckBeforeUnload(); 261 await initLocalStorageToForm(); 262 await initParamsToForm(); 263 await getStateNames(); 264 initDirIDParam(); 265 initMultipleTestSign(); 266 initMultipleInputValue(); 267 updateCartButton(); 268 initToasts(); 269 initTriggerClick(); 270 if (typeof initMyHandsontable !== "undefined") { 271 initMyHandsontable(); 272 } 273 if (typeof initializeTabulator !== "undefined") { 274 initializeTabulator(); 275 } 276 showCookieBanner(); 277}); 278 279function iosAcceptTracking() { 280 $('script[type="text/plain"][cookie-consent="tracking"],script[type="text/plain"][cookie-consent="targeting"]').each(function () { 281 var $script = $(this); 282 var newScript = document.createElement('script'); 283 newScript.type = 'text/javascript'; 284 if ($script.attr('src')) { 285 newScript.src = $script.attr('src'); 286 newScript.async = true; 287 } else { 288 newScript.text = $script.html(); 289 } 290 document.head.appendChild(newScript); 291 $script.remove(); 292 }); 293} 294async function showCookieBannerMobileApp() { 295 if ($('html').data('plt-android')) { 296 if (!translate['SETTINGS']) { 297 await getTranslate(); 298 } 299 if (typeof cookieconsent === 'undefined') { 300 return; 301 } 302 cookieconsent.run({ 303 "notice_banner_type": "simple", 304 "consent_type": "express", 305 "palette": "light", 306 "language": language, 307 "website_name": "APPEC", 308 "cookies_policy_url": translate['SETTINGS']['PRIVACY_LINK'], 309 "cookie_duration": 365 310 }); 311 } 312} 313function showCookieBanner() { 314 // cookieconsent.js wird z.B. von Firefox-Trackingschutz/Adblockern blockiert 315 if (typeof cookieconsent === 'undefined' || !translate['SETTINGS']) { 316 return; 317 } 318 if (typeof webkit === 'undefined') { 319 cookieconsent.run({ 320 "notice_banner_type": "simple", 321 "consent_type": "express", 322 "palette": "light", 323 "language": language, 324 "website_name": "APPEC", 325 "cookies_policy_url": translate['SETTINGS']['PRIVACY_LINK'], 326 "cookie_duration": 365 327 }); 328 } 329} 330function initToasts() { 331 showSaved(); 332 removeRefId(); 333 showUpdated(); 334 showDisconnected(); 335 showAccountConfirmed(); 336 showAccountDeleted(); 337 showNoArticleLeft(); 338 showPositiveMultipleTestAdded(); 339} 340window.onpopstate = history.onpushstate = function (e) { 341 initDirIDParam(); 342} 343function initMultipleInputValue() { 344 let IDs = localStorage.getItem('multiple_test_data'); 345 let multipleTestData = JSON.parse(IDs); 346 if ($('input[name="multiple_test_data"]').length > 0 && multipleTestData.length > 0) { 347 $('input[name="multiple_test_data"]').val(IDs); 348 $('form.check-before-unload').data('serialize', $('form.check-before-unload').seri
348alize()); 349 } 350} 351function initMultipleTestSign() { 352 let url_str = window.location.href; 353 let url = new URL(url_str); 354 let search_params = url.searchParams; 355 let multipletestMode = false; 356 let prevtest_id = 0; 357 let multipleTestDataKey = 0; 358 search_params.forEach(function (val, key) { 359 if (key == 'multipletest') { 360 multipletestMode = true; 361 } 362 if (key == 'key') { 363 multipleTestDataKey = val; 364 } 365 if (key == 'prevtest_id') { 366 prevtest_id = val; 367 } 368 }); 369 if (multipletestMode) { 370 let sign = localStorage.getItem('sign_img'); 371 if (sign) { 372 $('input[name="sign_image"]').val(sign); 373 if ($('.sign-img').length > 0) { 374 $('.sign-img').attr('src', sign); 375 } else { 376 let imgEl = document.createElement('img'); 377 imgEl.setAttribute('src', sign); 378 imgEl.className = 'sign-img'; 379 $('.sign-container').append(imgEl); 380 } 381 } 382 let IDs = localStorage.getItem('multiple_test_data'); 383 let multipleTestData = JSON.parse(IDs); 384 let prevMultipleTestDataKey = multipleTestDataKey - 1; 385 if (multipleTestData.length > prevMultipleTestDataKey && prevMultipleTestDataKey >= 0) { 386 if (prevtest_id > 0) { 387 multipleTestData[prevMultipleTestDataKey]['test_id'] = prevtest_id; 388 multipleTestData[prevMultipleTestDataKey]['test_added'] = true; 389 localStorage.setItem('multiple_test_data', JSON.stringify(multipleTestData)); 390 window.history.pushState('', document.title, removeParam('prevtest_id', url_str)); 391 } 392 if (multipleTestData[prevMultipleTestDataKey]['test_added'] && multipleTestData[prevMultipleTestDataKey]['test_id'] > 0) { 393 $('#prev-test').removeClass('hide-me').find('a').attr('href', 'articles/edittest?multipletest=1&id=' + multipleTestData[prevMultipleTestDataKey]['test_id'] + ' &key=' + prevMultipleTestDataKey); 394 } else { 395 $('#prev-test').removeClass('hide-me').find('a').attr('href', 'articles/edittest?multipletest=1&article_id=' + multipleTestData[prevMultipleTestDataKey]['id'] + '&key=' + prevMultipleTestDataKey); 396 } 397 } 398 resetFormCheckBeforeUnload(); 399 } 400} 401$(document).on('input', 'input[type="text"]', function (event) { 402 // Sonst wird special Char in DB gespeichert was zu fehler führt, hier eventuell weitere special Char entfernen 403 // console.log($(this).val($(this).val().replaceAll('"', "").replaceAll("'", ""))); 404}); 405function initDatePicker() { 406 if (translate['DATEPICKER']['DATE_FORMAT'] !== undefined) { 407 $('input.datepicker').Zebra_DatePicker({ 408 days: translate['DATEPICKER']['WEEKDAYS'], 409 format: translate['DATEPICKER']['DATE_FORMAT'], 410 lang_clear_date: translate['DATEPICKER']['CLEAR_DATE'], 411 months: translate['DATEPICKER']['MONTHS'], 412 open_on_focus: false, 413 readonly_element: $('html').data('plt-ios'), 414 show_other_months: false, 415 show_clear_date: true, 416 show_select_today: translate['DATEPICKER']['DATE_TODAY'], 417 strict: true, 418 //default_position: 'below', 419 show_icon: false, 420 onSelect: function (value) { 421 this.change() 422 }, 423 onClear: function (value) { 424 this.change() 425 } 426 }); 427 } 428} 429function checkDate(str) { 430 var date_regex = /^(0[1-9]|1\d|2\d|3[01])\.(0[1-9]|1[0-2])\.(19|20|21)\d{2}$/; 431 return (date_regex.test(str)); 432} 433$(document).on('focus', 'input[type="text"].datepicker', function (event) { 434 if ($(this).data('Zebra_DatePicker') == undefined) { 435 initDatePicker(); 436 } 437 $(this).parents('.input-container').removeClass('empty'); 438}); 439 440$(document).on('blur', 'input[type="text"].datepicker', function (event) { 441 const val = $(this).val(); 442 if (val) { 443 $(this).parents('.input-container').removeClass('empty'); 444 } else { 445 $(this).parents('.input-container').addClass('empty'); 446 } 447}); 448$(document).on('change', 'input[type="text"].datepicker', function (event) { 449 $(this).parents('.my-input').removeClass('error'); 450 const val = $(this).val(); 451 if (val) { 452 $(this).parents('.input-container').removeClass('empty') 453 if (!checkDate(val)) { 454 let inputWrapperEl = $(this).parents('.my-input'); 455 inputWrapperEl.addClass('error'); 456 inputWrapperEl.find('.input-error').text(translate['DATEPICKER']['INVALID_DATE']); 457 $(this).focus(); 458 } else { 459 if ($(this).attr('name') === 'from_date') { 460 $('input[name="to_date"]').data('Zebra_DatePicker').update({ direction: [val, moment().format("DD.MM.YYYY")] }); 461 } 462 } 463 } else { 464 $(this).parents('.input-container').addClass('empty'); 465 if ($(this).attr('name') === 'from_date') { 466 $('input[name="to_date"]').data('Zebra_DatePicker').update({ direction: [false, moment().format("DD.MM.YYYY")] }); 467 } 468 } 469}); 470function initColor() { 471 let tmpColor = $('html').data('color'); 472 if (/^#[0-9A-F]{6}$/i.test(tmpColor)) { 473 const hex = tmpColor; 474 const r = parseInt(hex.replace('#', '').substr(0, 2), 16); 475 const g = parseInt(hex.replace('#', '').substr(2, 2), 16); 476 const b = parseInt(hex.replace('#', '').substr(4, 2), 16); 477 if (!(r > 230 && g > 230 && b > 230)) { 478 changeTheme(tmpColor); 479 } 480 } else { 481 changeTheme('#3880ff'); 482 } 483} 484function initLocalStorageToForm() { 485 return new Promise(async (resolve, reject) => { 486 if ($('form.save-in-local-storage').length > 0) { 487 if ($('form.save-in-local-storage [name="edit"]').val() != '1') { 488 if ($('form.save-in-local-storage [name="is_ref_id"]').length <= 0) { 489 let tmpData = localStorage.getItem($('form.save-in-local-storage').attr('id')); 490 if (tmpData) { 491 let data = JSON.parse(tmpData); 492 if ($('form.save-in-local-storage').attr('id') == 'editmodel-form') { 493 let tmpArr = Object.entries(data).map(arr => arr[0]).filter(x => x.includes('checklist-id')); 494 for (let idx = 0; idx < tmpArr.length; idx++) {
495 const key = tmpArr[idx]; 496 let checklist = await addChecklist(false, false); 497 let tmpkey = 'question-' + key.replace(/^\D+/g, '') + '[]'; 498 let tmpkeyType = 'type-' + key.replace(/^\D+/g, '') + '[]'; 499 if (data[tmpkey]) { 500 let tmpQuestions = data[tmpkey]; 501 let tmpTypes = []; 502 if (data[tmpkeyType]) { 503 tmpTypes = data[tmpkeyType]; 504 } 505 for (let idx2 = 0; idx2 < tmpQuestions.length; idx2++) { 506 let type = 'radio'; 507 if (tmpTypes[idx2]) { 508 type = tmpTypes[idx2]; 509 } 510 await addNewQuestion($(checklist).find('.list'), tmpQuestions[idx2], type, false); 511 } 512 } 513 } 514 } 515 Object.entries(data).forEach(function ([key, val], idx) { 516 if (key != 'edit' && key != 'parent_dir_name' && key != 'parent_dir_id' && !key.includes('question-') && !key.includes('type-')) { 517 let inputEl = $('form.save-in-local-storage [name="' + key + '"]'); 518 if (inputEl.length > 0) { 519 inputEl.val(val).change(); 520 if (typeof val === 'string' || val instanceof String) { 521 if (val.startsWith('data:image/')) { 522 inputEl.parent().find('.prev-img').css('background-image', 'url(' + val + ')'); 523 } 524 } 525 } 526 } 527 }) 528 } 529 } 530 } 531 } 532 resolve(true); 533 }); 534} 535function initParamsToForm() { 536 return new Promise((resolve, reject) => { 537 let url_str = window.location.href; 538 let url = new URL(url_str); 539 let search_params = url.searchParams; 540 let params = {}; 541 search_params.forEach(function (val, key) { 542 params[key] = val; 543 $('[name="' + key + '"]').val(val); 544 if ($('[name="' + key + '"]').length > 0) { 545 window.history.pushState('', document.title, removeParam(key, url_str)); 546 url_str = window.location.href; 547 } 548 }); 549 resolve(true); 550 }); 551} 552function initTriggerClick() { 553 let url_str = window.location.href; 554 let url = new URL(url_str); 555 let search_params = url.searchParams; 556 if (search_params.has('triggerclick')) { 557 const triggerID = '#' + search_params.get('triggerclick'); 558 $(triggerID).trigger('click'); 559 window.history.pushState('', document.title, removeParam("triggerclick", url_str)); 560 } 561} 562function showSaved() { 563 let url_str = window.location.href; 564 let url = new URL(url_str); 565 let search_params = url.searchParams; 566 if (search_params.has('saved')) { 567 window.history.pushState('', document.title, removeParam("saved", url_str)); 568 presentToast(translate['SAVED'], 'fa-cloud', 'success', 2000); 569 } 570} 571function removeRefId() { 572 let url_str = window.location.href; 573 let url = new URL(url_str); 574 let search_params = url.searchParams; 575 if (search_params.has('ref_id')) { 576 window.history.pushState('', document.title, removeParam("ref_id", url_str)); 577 } 578} 579function showUpdated() { 580 let url_str = window.location.href; 581 let url = new URL(url_str); 582 let search_params = url.searchParams; 583 if (search_params.has('updated')) { 584 window.history.pushState('', document.title, removeParam("updated", url_str)); 585 presentToast(translate['MODEL']['UPDATED'], 'fa-cloud-arrow-down', 'success', 2000); 586 } 587} 588function showDisconnected() { 589 let url_str = window.location.href; 590 let url = new URL(url_str); 591 let search_params = url.searchParams; 592 if (search_params.has('disconnected')) { 593 window.history.pushState('', document.title, removeParam("disconnected", url_str)); 594 presentToast(translate['MODEL']['DISCONNECTED'], 'fa-check', 'success', 2000); 595 } 596} 597function showAccountDeleted() { 598 let url_str = window.location.href; 599 let url = new URL(url_str); 600 let search_params = url.searchParams; 601 if (search_params.has('shownoarticlesleft')) { 602 window.history.pushState('', document.title, removeParam("shownoarticlesleft", url_str)); 603 getAjaxPopUp('noarticlesleft'); 604 } 605} 606function showNoArticleLeft() { 607 let url_str = window.location.href; 608 let url = new URL(url_str); 609 let search_params = url.searchParams; 610 if (search_params.has('accountdeleted')) { 611 window.history.pushState('', document.title, removeParam("accountdeleted", url_str)); 612 presentToast(translate['SETTINGS']['ACCOUNT_DELTED_SUCCESSFUL'], 'fa-circle-check', 'success'); 613 } 614} 615function showPositiveMultipleTestAdded() { 616 let url_str = window.location.href; 617 let url = new URL(url_str); 618 let search_params = url.searchParams; 619 if (search_params.has('positivemultipletestadded')) { 620 let count = 0; 621 if (search_params.has('count')) { 622 count = search_params.get('count'); 623 window.history.pushState('', document.title, removeParam("count", url_str)); 624 url_str = window.location.href; 625 } 626 window.history.pushState('', document.title, removeParam("positivemultipletestadded", url_str)); 627 presentToast(translate['ARTICLE']['TOAST_POSITIVE_MULTIPLE_TEST_ADDED'].replace('##', count), 'fa-circle-check', 'success'); 628 } 629} 630 631function showAccountConfirmed() { 632 let url_str = window.location.href; 633 let url = new URL(url_str); 634 let search_params = url.searchParams; 635 if (search_params.has('accountconfirmed')) { 636 if (search_params.get('accountconfirmed') == '1') { 637 presentToast(translate['SETTINGS']['ACCOUNT_CONFIRMED'], 'fa-circle-check', 'success', 10000); 638 } else { 639 presentToast(translate[search_params.get('error')], 'fa-circle-exclamation', 'warning', 10000); 640 url_str = removeParam("error", url_str); 641 } 642 url_str = removeParam("accountconfirmed", url_str); 643 window.history.pushState('', document.title, url_str); 644 } 645} 646function removeParam(key, sourceURL) { 647 var rtn = sourceURL.split("?")[0], 648 param, 649 params_arr = [], 650 queryString = (sourceURL.indexOf("?") !== -1) ? sourceURL.split("?")[1] : ""; 651 if (queryString !== "") { 652 params_arr = queryString.split("&"); 653 for (var i = params_arr.length - 1; i >= 0; i -= 1) { 654 param = params_arr[i].split("=")[0]; 655 if (param === key) { 656 params_arr.splice(i, 1); 657 } 658 } 659 if (params_arr.length) rtn = rtn + "?" + params_arr.join("&"); 660 } 661 return rtn; 662} 663function replaceUrlParam(paramName, paramValue) { 664 let url = window.location.href; 665 if (paramValue == null) { 666 paramValue = ''; 667 } 668 var pattern = new RegExp('\\b(' + paramName + '=).*?(&|#|$)'); 669 if (url.search(pattern) >= 0) { 670 url = url.replace(pattern, '$1' + paramValue + '$2'); 671 } else { 672 url = url.replace(/[?#]$/, ''); 673 url = url + (url.indexOf('?') > 0 ? '&' : '?') + paramName + '=' + paramValue; 674 } 675 window.history.pushState('', document.title, url); 676} 677$(document).on('click', '.open-link', function (e) { 678 e.preventDefault(); 679 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 680 try { 681 let messageObj = { function: 'open_external_link', url: $(this).attr('href') }; 682 let stringifiedMessageObj = JSON.stringify(messageObj); 683 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 684 } catch (error) { 685 console.log(error); 686 } 687 } else { 688 window.open($(this).attr('href'), '_blank'); 689 } 690}); 691$(document).on('click', 'a[target="_blank"]', function (e) { 692 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 693 e.preventDefault(); 694 try { 695 let messageObj = { function: 'open_external_link', url: $(this).attr('href') }; 696 let stringifiedMessageObj = JSON.stringify(messageObj); 697 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 698 } catch (error) { 699 console.log(error); 700 } 701 } 702}); 703$(document).on('click', '[data-openlink]', function (e) { 704 if (!$('.my-table-list').hasClass('long-pressed')) { 705 let link = $(this).data('openlink'); 706 if (e.ctrlKey || e.metaKey) { 707 window.open(link, '_blank'); 708 } else { 709 window.open(link, '_self'); 710 } 711 } 712}); 713$(document).on('click', '.action-links a:not(.preview-attachment-in-lightbox):not([data-dir]):not(.get-bill-pdf), .preview-attachment-in-lightbox[download]', async function (e) { 714 e.preventDefault(); 715 e.stopImmediatePropagation(); 716 const openInNewTab = e.metaKey || e.ctrlKey; 717 if (typeof $(this).attr('download') == "undefined") { 718 let link = $(this).attr('href'); 719 window.open(link, openInNewTab ? '_blank' : '_self'); 720 if ($(this).attr('id') == 'export-test') { 721 exporttest($(this)); 722 } 723 } else { 724 await showLoading(); 725 $.ajax({ 726 url: $(this).attr('href') + '&for_ajax=1', 727 success: async function (result) { 728 try { 729 let data = JSON.parse(result); 730 if (typeof data === 'object') { 731 await downloadFile(data['base64'], data['filename'], data['mimetype']) 732 } else { 733 await hideLoading(); 734 console.log(result); 735 } 736 } catch (err) { 737 await hideLoading(); 738 console.log(err); 739 console.log(result); 740 } 741 }, 742 error: function (error) { 743 console.log(error); 744 } 745 }); 746 } 747}); 748$(document).on('click', '.my-table-list .list-item', function (e) { 749 if ($('.my-table-list').hasClass('long-pressed')) { 750 return; 751 } 752 if ($(e.target).closest('.select-col, .action-links').length > 0) { 753 return; 754 } 755 let firstActionLink = $(this).find('.action-links a').first(); 756 if (firstActionLink.length > 0) { 757 firstActionLink[0].click(); 758 } 759}); 760 761 762 763function setCookie(cname, cvalue, exdays = 0) { 764 if (exdays == 0) { 765 document.cookie = cname + "=" + cvalue + ";path=/"; 766 } else { 767 const d = new Date(); 768 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 769 let expires = "expires=" + d.toUTCString(); 770 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 771 } 772} 773 774function deleteCookie(cname) {
775 setCookie(cname, null, -100); 776 document.cookie = cname + "=" + ";expires=Thu, 01 Jan 1970 00:00:01 GMT"; 777} 778 779function getCookie(cname) { 780 let name = cname + "="; 781 let ca = document.cookie.split(';'); 782 for (let i = 0; i < ca.length; i++) { 783 let c = ca[i]; 784 while (c.charAt(0) == ' ') { 785 c = c.substring(1); 786 } 787 if (c.indexOf(name) == 0) { 788 return c.substring(name.length, c.length); 789 } 790 } 791 return ""; 792} 793let touchstartX = 0; 794let touchendX = 0; 795let canSwipeMenu = false; 796let hasMoved = false; // <-- neu 797 798$('body').on('touchstart', function (event) { 799 touchstartX = event.touches[0].clientX; 800 hasMoved = false; // reset bei jedem neuen Touchstart 801 802 if (!$('.menu-left').hasClass('open')) { 803 if (touchstartX < 70) { 804 canSwipeMenu = true; 805 } 806 } else { 807 canSwipeMenu = true; 808 } 809}); 810 811$('body').on('touchmove', function (event) { 812 if (canSwipeMenu) { 813 touchendX = event.touches[0].clientX; 814 hasMoved = true; // nur wenn es wirklich bewegt wurde 815 } 816}); 817 818$('body').on('touchend', function (event) { 819 if (canSwipeMenu && hasMoved) { // <-- nur wenn tatsächlich geswiped 820 let diff = touchstartX - touchendX; 821 822 if (!$('.menu-left').hasClass('open')) { 823 if (diff < -200) { 824 $('.menu-left').toggleClass('open'); 825 } 826 } else { 827 if (diff > 200) { 828 $('.menu-left').toggleClass('open'); 829 } 830 } 831 } 832 833 // Reset 834 canSwipeMenu = false;
835 hasMoved = false; 836}); 837 838$(document).on('keydown', function (e) { 839 let key = e.keyCode ? e.keyCode : e.which; 840 if ($('.my-popup').is(':visible')) { 841 if (key == 27) { 842 $('.my-popup').find('.close-popup').trigger('click'); 843 $('.my-popup').find('.close-and-remove-popup').trigger('click'); 844 } 845 } 846 if ($('#popup-pdf').is(':visible')) { 847 if (key == 27) { 848 $('#popup-pdf').find('.close').trigger('click'); 849 } 850 } 851 if ($('.my-action-sheet').is(':visible')) { 852 if (key == 27) { 853 closeMyActionSheet($('.my-action-sheet')); 854 } 855 }//cmd+s ctrl+s 856 if ((e.ctrlKey || e.metaKey) && e.which == 83) { 857 $('.ctrl-save').trigger('click'); 858 e.preventDefault(); 859 return false; 860 } 861}); 862async function showLoading(text = translate['LOADING']) { 863 $('#my-loading span.info-text').html(text); 864 if (!$('#my-loading').is(':visible')) { 865 await $('#my-loading').fadeIn(300).delay(500).promise(); 866 } 867 return true; 868} 869async function hideLoading(noAnimation = false) { 870 if (!noAnimation) { 871 await $('#my-loading').fadeOut(300).promise(); 872 } else { 873 await $('#my-loading').fadeOut(0).promise(); 874 } 875 return true; 876} 877 878$(window).resize(function () { 879 resetToastsPostions(); 880 if ($('.my-breadcrumbs').length > 0) { 881 changeBreadcrumbsView(); 882 } 883 if ($('#sign_canvas').length > 0) { 884 saveResizeAndRedisplaySignCanvas(); 885 } 886 if ($('#canvas_container').length > 0) { 887 initPDFViewer(); 888 } 889 if ($('.filter-wrapper').length > 0 || $('.my-breadcrumbs-wrapper').length > 0) { 890 setFilterWrapperSticky(); 891 } 892}); 893async function getSVG(link) { 894 return new Promise((resolve, reject) => { 895 $.ajax({ 896 url: link, 897 success: function (data) { 898 resolve(new XMLSerializer().serializeToString(data.documentElement)); 899 }, 900 error: function (error) { 901 console.log(error); 902 } 903 }); 904 }) 905} 906$(document).on('click', '.delete-filters', function (e) { 907 deleteCookie('article_filter'); 908 deleteCookie('tests_from_article_filter'); 909 deleteCookie('test_filter'); 910 deleteCookie('model_filter'); 911 deleteCookie('central_model_filter'); 912 deleteCookie('manufacture_filter'); 913 deleteCookie('model_category_filter'); 914 deleteCookie('central_model_category_filter'); 915 deleteCookie('user_filter'); 916 deleteCookie('usergroup_filter'); 917 deleteCookie('main_bill_filter'); 918 localStorage.removeItem('editarticle-form'); 919 localStorage.removeItem('editdir-form'); 920 localStorage.removeItem('editmanufacture-form'); 921 localStorage.removeItem('editmodel_category-form'); 922 localStorage.removeItem('editmodel-form'); 923 localStorage.removeItem('sign_img'); 924}); 925// END - GENERAL 926// ACCORDION 927$(document).on('click', '.my-accordion', function (e) { 928 let $this = $(this); 929 let id = $this.data('target'); 930 if ($('#' + id).hasClass('hide-me')) { 931 $('#' + id).hide().promise().done(function () { 932 $('#' + id).removeClass('hide-me').promise().done(function () { 933 $('#' + id).slideDown(500); 934 $this.addClass('shown'); 935 }); 936 }); 937 } else { 938 $('#' + id).slideUp(500).promise().done(function () { 939 $('#' + id).addClass('hide-me'); 940 $this.removeClass('shown'); 941 }); 942 } 943}) 944// END - ACCORDION 945// TOOLTIP 946$(document).on('mouseover', '.my-tooltip', function (e) { 947 $this = $(this); 948 let toolTipText = $this.attr('title'); 949 $this.data('title', toolTipText); 950 $this.attr('title', ''); 951 let offset = $(this).offset(); 952 let windowWith = $(window).width() - 16; 953 let toolTipEl = document.createElement('div'); 954 toolTipEl.className = 'my-tooltip-content ' + $this.data('color') + ($this.hasClass('top') ? ' top' : '') + ($this.hasClass('left') ? ' left' : ''); 955 toolTipEl.textContent = toolTipText; 956 $(toolTipEl).css('top', e.originalEvent.clientY); 957 if ($this.hasClass('left')) { 958 $(toolTipEl).css('right', windowWith - offset.left); 959 $(toolTipEl).css('max-width', offset.left); 960 } else { 961 $(toolTipEl).css('left', offset.left); 962 $(toolTipEl).css('max-width', (windowWith - offset.left)); 963 } 964 $('body').append(toolTipEl); 965 966}).on('mouseout', '.my-tooltip', function () { 967 $this = $(this); 968 $this.attr('title', $this.data('title')); 969 $('.my-tooltip-content').remove(); 970}); 971$(document).on('click', '.my-tooltip', function (e) { 972 e.preventDefault(); 973 e.stopImmediatePropagation(); 974}); 975$(document).on('touchstart', function (e) { 976 $('.my-tooltip').each(function (idx, el) { 977 $this = $(el); 978 $this.attr('title', $this.data('title')); 979 $('.my-tooltip-content').remove(); 980 }); 981}); 982// END - TOOLTIP 983// BREADCRUMBS 984if ($('.my-breadcrumbs').length > 0) { 985 changeBreadcrumbsView(); 986} 987function changeBreadcrumbsView() { 988 const breadcrumbs = $('.my-breadcrumbs'); 989 let width = breadcrumbs.find('.breadcrumb').map((idx, el) => $(el).outerWidth()).toArray().reduce((partialSum, a) => partialSum + a, 0); 990 if (width > breadcrumbs.width() && !$('.my-breadcrumbs').hasClass('mobil')) { 991 $('.my-breadcrumbs').addClass('mobil'); 992 } else { 993 width = breadcrumbs.find('.breadcrumb').map((idx, el) => { 994 if (idx < (breadcrumbs.find('.breadcrumb').length - 1)) { 995 return $(el).outerWidth() + $(el).find('span').outerWidth() 996 } else { 997 return $(el).outerWidth() 998 } 999 }).toArray().reduce((partialSum, a) => partialSum + a, 0); 1000 if (width < breadcrumbs.width()) { 1001 $('.my-breadcrumbs').removeClass('mobil'); 1002 } 1003 let tmpWidth = breadcrumbs.find('.breadcrumb').map((idx, el) => $(el).outerWidth()).toArray().reduce((partialSum, a) => partialSum + a, 0); 1004 let spanWidth = breadcrumbs.find('.breadcrumb:last-of-type span').outerWidth(); 1005 let maxSpanWidth = breadcrumbs.width() - (tmpWidth - spanWidth); 1006 breadcrumbs.find('.breadcrumb:last-of-type span').css('max-width', maxSpanWidth); 1007 } 1008} 1009// END - BREADCRUMBS 1010// EXPORT 1011async function hideLoadingFromApp() { 1012 return new Promise(async (resolve, reject) => { 1013 let hideLoading = $('html').attr('data-hide-loading'); 1014 if ((hideLoading !== '' && hideLoading !== undefined)) { 1015 $('html').attr('data-hide-loading', ''); 1016 $('#my-loading').fadeOut(300); 1017 resolve(true); 1018 } else { 1019 setTimeout(async () => { 1020 resolve(await hideLoadingFromApp()); 1021 }, 300); 1022 } 1023 }); 1024} 1025 1026async function mergePdfs(files) { 1027 const mergedPdf = await PDFLib.PDFDocument.create(); 1028 const imageFiles = [];
1028 // sammeln der Bildpfade 1029 1030 for (let file of files) { 1031 if (file instanceof Uint8Array) { 1032 // pdfMake PDF 1033 const pdf = await PDFLib.PDFDocument.load(file); 1034 const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); 1035 copiedPages.forEach(p => mergedPdf.addPage(p)); 1036 1037 } else if (typeof file === 'string') { 1038 const ext = file.split('.').pop().toLowerCase(); 1039 1040 if (ext === 'pdf') { 1041 // PDF vom Server laden 1042 const pdfBytes = await fetch(file).then(res => res.arrayBuffer()); 1043 const pdf = await PDFLib.PDFDocument.load(pdfBytes); 1044 const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); 1045 copiedPages.forEach(p => mergedPdf.addPage(p)); 1046 } else if (['jpg', 'jpeg', 'png'].includes(ext)) { 1047 // Bild merken, wird später in Galerie eingefügt 1048 imageFiles.push(file); 1049 } 1050 } 1051 } 1052 1053 // Bilder als Galerie einfügen 1054 if (imageFiles.length > 0) { 1055 await addImagesAsGallery(mergedPdf, imageFiles, 42.5); // 42.5pt â 15mm Rand 1056 } 1057 1058 return await mergedPdf.saveAsBase64({ dataUri: true }); 1059} 1060async function mergePdfs(pdfsToMerges) { 1061 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED_STEP_7']); 1062 const mergedPdf = await PDFLib.PDFDocument.create(); 1063 try { 1064 for (let index = 0; index < pdfsToMerges.length; index++) { 1065 let pdf = await PDFLib.PDFDocument.load(pdfsToMerges[index]); 1066 const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
1067 copiedPages.forEach(p => mergedPdf.addPage(p)); 1068 } 1069 } catch (error) { 1070 console.log(error); 1071 } 1072 return await mergedPdf.saveAsBase64({ dataUri: true }); 1073} 1074 1075async function mergePdfsAndImages(files, asBytes = false) { 1076 const mergedPdf = await PDFLib.PDFDocument.create(); 1077 const imageFiles = []; 1078 1079 for (let file of files) { 1080 try { 1081 if (file instanceof Uint8Array) { 1082 const pdf = await PDFLib.PDFDocument.load(file); 1083 const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); 1084 copiedPages.forEach(p => mergedPdf.addPage(p)); 1085 1086 } else if (typeof file === 'string') { 1087 const ext = file.split('.').pop().toLowerCase(); 1088 1089 if (ext === 'pdf') { 1090 const pdfBytes = await fetch(file).then(res => res.arrayBuffer()); 1091 const pdf = await PDFLib.PDFDocument.load(pdfBytes); 1092 const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
1093 copiedPages.forEach(p => mergedPdf.addPage(p)); 1094 1095 } else if (['jpg', 'jpeg', 'png'].includes(ext)) { 1096 imageFiles.push(file); 1097 } 1098 } else { 1099 console.warn('mergePdfs: unbekannter Dateityp', file); 1100 } 1101 } catch (error) { 1102 console.error('mergePdfs error:', error, file); 1103 } 1104 } 1105 1106 if (imageFiles.length > 0) { 1107 await addImagesAsGallery(mergedPdf, imageFiles, 42.5); 1108 } 1109 1110 if (asBytes) { 1111 return await mergedPdf.save(); 1112 } 1113 return await mergedPdf.saveAsBase64({ dataUri: true }); 1114} 1115// Bild fuer die Galerie laden. Grosse Fotos werden auf maxPx verkleinert (JPEG), damit die PDFs nicht riesig werden. 1116async function getGalleryImage(file, maxPx = 1600) { 1117 const ext = file.split('.').pop().toLowerCase(); 1118 const blob = await fetch(file).then(res => res.blob()); 1119 try { 1120 const bitmap = await createImageBitmap(blob); 1121 if (Math.max(bitmap.width, bitmap.height) > maxPx) { 1122 const scale = maxPx / Math.max(bitmap.width, bitmap.height); 1123 const canvas = document.createElement('canvas'); 1124 canvas.width = Math.round(bitmap.width * scale); 1125 canvas.height = Math.round(bitmap.height * scale); 1126 const ctx = canvas.getContext('2d'); 1127 ctx.fillStyle = '#ffffff'; 1128 ctx.fillRect(0, 0, canvas.width, canvas.height); 1129 ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height); 1130 bitmap.close(); 1131 const jpgBlob = await new Promise(resolve => canvas.toBlob(resolve, 'image/jpeg', 0.85)); 1132 if (jpgBlob) { 1133 return { bytes: await jpgBlob.arrayBuffer(), isPng: false }; 1134 } 1135 } else { 1136 bitmap.close(); 1137 } 1138 } catch (error) { 1139 console.log(error); 1140 } 1141 return { bytes: await blob.arrayBuffer(), isPng: ext === 'png' }; 1142} 1143async function addImagesAsGallery(mergedPdf, imageFiles, pageMargin = 42.5) { 1144 const pageWidth = 595.28; 1145 const pageHeight = 841.89; 1146 const availableWidth = pageWidth - pageMargin * 2; 1147 const availableHeight = pageHeight - pageMargin * 2; 1148 1149 let page = mergedPdf.addPage([pageWidth, pageHeight]); 1150 let x = pageMargin; 1151 let y = pageHeight - pageMargin; 1152 let rowHeight = 0; 1153 const spacing = 10; 1154 1155 for (const file of imageFiles) { 1156 const galleryImage = await getGalleryImage(file); 1157 const image = galleryImage.isPng ? await mergedPdf.embedPng(galleryImage.bytes) : await mergedPdf.embedJpg(galleryImage.bytes); 1158 1159 const imgWidth = image.width; 1160 const imgHeight = image.height; 1161 1162 const maxWidth = availableWidth / 2 - spacing; 1163 const scale = maxWidth / imgWidth; 1164 const drawWidth = imgWidth * scale; 1165 const drawHeight = imgHeight * scale; 1166 1167 if (x + drawWidth > availableWidth + pageMargin) { 1168 x = pageMargin; 1169 y -= rowHeight + spacing; 1170 rowHeight = 0; 1171 } 1172 1173 if (y - drawHeight < pageMargin) { 1174 page = mergedPdf.addPage([pageWidth, pageHeight]); 1175 x = pageMargin; 1176 y = pageHeight - pageMargin; 1177 rowHeight = 0; 1178 } 1179 1180 page.drawImage(image, { x, y: y - drawHeight, width: drawWidth, height: drawHeight }); 1181 1182 x += drawWidth + spacing; 1183 rowHeight = Math.max(rowHeight, drawHeight); 1184 } 1185} 1186 1187function base64ToArrayBuffer(base64) { 1188 var binary_string = window.atob(base64); 1189 var len = binary_string.length; 1190 var bytes = new Uint8Array(len); 1191 for (var i = 0; i < len; i++) { 1192 bytes[i] = binary_string.charCodeAt(i); 1193 } 1194 return bytes.buffer; 1195} 1196async function exporttest(self) { 1197 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED']); 1198 const id = self.data('id'); 1199 $.ajax({ 1200 type: 'GET', 1201 url: 'gettestdataforexport', 1202 cache: false, 1203 data: { 1204 id: id 1205 }, 1206 success: async function (result) { 1207 try { 1208 let data = JSON.parse(result); 1209 if (typeof data === 'object') { 1210 let base64 = await testToPDF(data['testData'], data['data']['logo'], true); 1211 await downloadFile(base64, data['data']['filename'], data['data']['mimetype']) 1212 } else { 1213 await hideLoading(); 1214 console.log(result); 1215 } 1216 } catch (err) { 1217 await hideLoading(); 1218 console.log(err); 1219 console.log(result); 1220 } 1221 } 1222 }); 1223} 1224// base64: Base64-Data-URL oder Blob. keepLoading: Ladeanzeige nicht ausblenden (Zwischendateien beim Export in Teilen) 1225async function downloadFile(base64, filename, mimetype, keepLoading = false) { 1226 if (base64 instanceof Blob && ($('html').data('plt-android') || $('html').data('plt-ios'))) { 1227 base64 = await toBase64(base64); 1228 } 1229 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 1230 try { 1231 var messageObj = { function: 'downloadFile', base64: base64, filename: filename, type: mimetype }; 1232 var stringifiedMessageObj = JSON.stringify(messageObj); 1233 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 1234 await hideLoadingFromApp(); 1235 } catch (error) { 1236 console.log(error); 1237 } 1238 } else { 1239 if (!keepLoading) { 1240 await hideLoading(); 1241 } 1242 $('#loading-bar').hide(); 1243 let a = document.createElement("a"); 1244 let blobUrl = null; 1245 if (base64 instanceof Blob) { 1246 blobUrl = URL.createObjectURL(base64); 1247 a.href = blobUrl; 1248 } else { 1249 a.href = base64; 1250 } 1251 a.download = filename; 1252 a.click(); 1253 if (blobUrl) { 1254 setTimeout(() => URL.revokeObjectURL(blobUrl), 60000); 1255 } 1256 } 1257} 1258$(document).on('click', '#export-test', async function () { 1259 exporttest($(this)); 1260}); 1261function getTitlePagePDF() { 1262 return new Promise(async (resolve, reject) => { 1263 const tabelListEl = $('.my-table-list'); 1264 const tableName = tabelListEl.data('table-name'); 1265 let res = await getAjaxPopUp('titlepagepopup', { tableName: tableName }); 1266 if (res) { 1267 1268 await initPDFViewer(); 1269 let popup = $('#title-page-popup'); 1270 let id = popup.attr('id'); 1271 $('#' + id + ' .bold').on('click', async function () { 1272 const base64 = $('#canvas_container').attr('data-src') 1273 await hidePopUp(popup); 1274 popup.remove(); 1275 resolve(base64); 1276 }); 1277 $('#' + id + ' .close-popup').on('click', async function () { 1278 await hidePopUp(popup); 1279 popup.remove(); 1280 reject('dismiss'); 1281 }); 1282 $('#' + id + ' .upload').on('click', async function () { 1283 await getAjaxPopUp('uploadnewtitlepage'); 1284 $('#upload-pdf-popup #my-drop-container input[type="file"]').on("change", async function () {
1285 let $this = $(this); 1286 let pdf = $this[0].files[0]; 1287 if (pdf.size < 5000000 && pdf.type === "application/pdf") { 1288 const pdfBase64 = await toBase64(pdf); 1289 $.ajax({ 1290 type: 'POST', 1291 url: 'uploadtitlepage', 1292 cache: false, 1293 data: { 1294 pdfBase64: pdfBase64, 1295 tableName: tableName 1296 }, 1297 success: async function (result) { 1298 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_UPLOADED'], 'fa-save', 'success'); 1299 let tmppopup = $('#upload-pdf-popup'); 1300 await hidePopUp(tmppopup); 1301 changeCanvasContainerSrc(pdfBase64); 1302 tmppopup.remove(); 1303 } 1304 }); 1305 } else { 1306 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_TO_BIG'], 'fa-triangle-exclamation', 'warning'); 1307 } 1308 }); 1309 $('#upload-pdf-popup .close-popup').on('click', async function () { 1310 let tmppopup = $('#upload-pdf-popup'); 1311 await hidePopUp(tmppopup); 1312 tmppopup.remove(); 1313 }); 1314 1315 $("#my-drop-container").on("dragenter", function (e) { 1316 e.preventDefault(); 1317 e.stopPropagation(); 1318 $(this).addClass('drag-over'); 1319 }); 1320 $("#my-drop-container").on("dragleave", function (e) { 1321 e.preventDefault(); 1322 e.stopPropagation(); 1323 $(this).removeClass('drag-over'); 1324 }); 1325 $('body #my-drop-container').on("drop dragdrop", async function (e) { 1326 e.stopPropagation(); 1327 e.preventDefault(); 1328 $(this).removeClass('drag-over'); 1329 let pdf = e.originalEvent.dataTransfer.files[0]; 1330 if (pdf.size < 5000000 && pdf.type === "application/pdf") { 1331 const pdfBase64 = await toBase64(pdf); 1332 $.ajax({ 1333 type: 'POST', 1334 url: 'uploadtitlepage', 1335 cache: false, 1336 data: { 1337 pdfBase64: pdfBase64, 1338 tableName: tableName 1339 }, 1340 success: async function (result) { 1341 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_UPLOADED'], 'fa-save', 'success'); 1342 let tmppopup = $('#upload-pdf-popup'); 1343 changeCanvasContainerSrc(pdfBase64); 1344 await hidePopUp(tmppopup); 1345 tmppopup.remove(); 1346 } 1347 }); 1348 } else { 1349 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_TO_BIG'], 'fa-triangle-exclamation', 'warning'); 1350 } 1351 }); 1352 }); 1353 $('#' + id + ' .generate').on('click', async function () { 1354 let data = {}; 1355 data['date_formate'] = $('#date_format').val(); 1356 data['tableName'] = $('.my-table-list').data('table-name'); 1357 data['postData'] = $('#export-popup').find('form').serializeArray(); 1358 data['ids'] = getExportIds(); 1359 1360 getAjaxPopUp('generatenewtitlepage', data); 1361 }); 1362 $('#' + id + ' .delete').on('click', async function () { 1363 $.ajax({ 1364 type: 'POST', 1365 url: 'uploadtitlepage', 1366 cache: false, 1367 data: { 1368 pdfBase64: null, 1369 delete: true, 1370 tableName: tableName 1371 }, 1372 success: async function (result) { 1373 try { 1374 let data = JSON.parse(result); 1375 if (typeof data === 'object') { 1376 if (data['delete']) { 1377 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_DELETED'], 'fa-tras
1377h', 'success'); 1378 if (data['base64']) { 1379 changeCanvasContainerSrc(data['base64']); 1380 } 1381 } 1382 } 1383 } catch (error) { 1384 console.log(result); 1385 console.log(error); 1386 } 1387 } 1388 }); 1389 }); 1390 1391 } 1392 }); 1393} 1394function changeCanvasContainerSrc(src) { 1395 $('#canvas_container').attr('data-src', src); 1396 initPDFViewer(); 1397} 1398pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; 1399let initPDFViewerRunning = false; 1400async function initPDFViewer() { 1401 return new Promise(async (resolve, reject) => { 1402 if (initPDFViewerRunning == false) { 1403 initPDFViewerRunning = true; 1404 let link = $("#canvas_container").attr('data-src'); 1405 let pdf = await pdfjsLib.getDocument(link).promise; 1406 let numPages = pdf.numPages; 1407 $('#canvas_container .inner').children().remove(); 1408 for (let currPage = 1; currPage <= numPages; currPage++) { 1409 let page = await pdf.getPage(currPage); 1410 let viewport = page.getViewport({ scale: 1 }); 1411 let canvas = document.createElement("canvas"); 1412 canvas.style.display = "block"; 1413 let context = canvas.getContext('2d'); 1414 let width = $('#canvas_container .inner').width(); 1415 let height = viewport.height / (viewport.width / width); 1416 canvas.width = width * 4; 1417 canvas.height = height * 4; 1418 viewport = page.getViewport({ scale: (width * 4 / viewport.width) }); 1419 page.render({ canvasContext: context, viewport: viewport }); 1420 $('#canvas_container .inner').append(canvas); 1421 $('#canvas_container').height($('#canvas_container .inner').height() / 4) 1422 } 1423 initPDFViewerRunning = false; 1424 } 1425 resolve(true) 1426 }); 1427} 1428 1429function toBase64(file) { 1430 return new Promise((resolve, reject) => { 1431 const reader = new FileReader(); 1432 reader.readAsDataURL(file); 1433 reader.onload = () => resolve(reader.result); 1434 reader.onerror = error => reject(error); 1435 }); 1436} 1437function toDataUrl(url) { 1438 return new Promise((resolve, reject) => { 1439 var xhr = new XMLHttpRequest(); 1440 xhr.onload = function () { 1441 var reader = new FileReader(); 1442 reader.onloadend = function () { 1443 resolve(reader.result); 1444 } 1445 reader.readAsDataURL(xhr.response); 1446 }; 1447 xhr.open('GET', url); 1448 xhr.responseType = 'blob'; 1449 xhr.send(); 1450 }); 1451} 1452// PDF-Export in Teilen: Eine Datei ("Teil") wird abgeschlossen und heruntergeladen, sobald eine dieser Grenzen erreicht ist. 1453// Dadurch bleibt der Speicherbedarf konstant, egal wie viele Eintraege exportiert werden. 1454const EXPORT_TABLE_CHUNK_ROWS = 1000; // Zeilen der Zusammenfassung pro pdfMake-Dokument (gerade Zahl wegen der Zebra-Streifen) 1455const EXPORT_TEST_BATCH = 50; // Pruefungen pro Serveranfrage 1456function getExportLimits() { 1457 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 1458 return { maxBytes: 30000000, maxPages: 1000, maxTests: 500 }; 1459 } 1460 // navigator.deviceMemory gibt es nur in Chrome/Edge (max. 8). Sonst vorsichtig sein. 1461 if (!(navigator.deviceMemory >= 8)) { 1462 return { maxBytes: 30000000, maxPages: 1000, maxTests: 500 }; 1463 } 1464 return { maxBytes: 60000000, maxPages: 2000, maxTests: 1000 }; 1465} 1466function isExportHeapHigh() { 1467 return !!performance.memory && performance.memory.usedJSHeapSize > performance.memory.jsHeapSizeLimit * 0.7; 1468} 1469let exportCancelled = false; 1470$(document).on('click', '#my-loading-cancel', function () { 1471 exportCancelled = true; 1472 $(this).prop('disabled', true).find('span').text(translate['EXPORT_DATA']['CANCELLING']); 1473}); 1474function checkExportCancelled() { 1475 if (exportCancelled) { 1476 throw new Error('EXPORT_CANCELLED'); 1477 } 1478} 1479function exportYield() { 1480 return new Promise(resolve => setTimeout(resolve, 0)); 1481} 1482async function createExportPart() { 1483 return { doc: await PDFLib.PDFDocument.create(), pages: 0, bytes: 0, tests: 0 }; 1484} 1485async function addPdfToExportPart(part, source, tests = 0) { 1486 const pdf = await PDFLib.PDFDocument.load(source, { updateMetadata: false }); 1487 const copiedPages = await part.doc.copyPages(pdf, pdf.getPageIndices());
1488 copiedPages.forEach(p => part.doc.addPage(p)); 1489 part.pages += copiedPages.length; 1490 part.bytes += (typeof source === 'string') ? Math.round(source.length * 0.75) : source.length; 1491 part.tests += tests; 1492} 1493function shouldCloseExportPart(part, limits) { 1494 return part.pages >= limits.maxPages || part.bytes >= limits.maxBytes || part.tests >= limits.maxTests || (part.bytes > 5000000 && isExportHeapHigh()); 1495} 1496async function fetchExportTestDatas(ids, dateFormat) { 1497 let lastError = null; 1498 for (let attempt = 0; attempt < 3; attempt++) { 1499 try { 1500 const result = await $.ajax({ 1501 type: 'POST', 1502 url: 'gettestdataforexport', 1503 cache: false, 1504 data: { ids: ids, date_format: dateFormat } 1505 }); 1506 const parsed = JSON.parse(result); 1507 if (parsed && Array.isArray(parsed['testDatas'])) { 1508 return parsed['testDatas']; 1509 } 1510 lastError = new Error('invalid response'); 1511 } catch (error) { 1512 lastError = error; 1513 } 1514 await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1))); 1515 } 1516 throw lastError; 1517} 1518async function exportPdfInParts(data, titlePage, with_attachments) { 1519 const limits = getExportLimits(); 1520 const testIds = data['test_ids'] || []; 1521 const hasTable = !!data['dataArray'] && data['dataArray'].length > 1; 1522 if (!hasTable && testIds.length == 0) { 1523 presentToast(translate['EXPORT_DATA']['NO_DATA_FOR_EXPORT'], 'fa-triangle-exclamation', 'warning'); 1524 await hideLoading(); 1525 return; 1526 } 1527 const header = hasTable ? data['dataArray'][0] : null; 1528 const rows = hasTable ? data['dataArray'].slice(1) : []; 1529 data['dataArray'] = null; 1530 1531 // Grobe Schaetzung, damit der Nutzer vorab weiss, was auf ihn zukommt 1532 const estimatedPages = (rows.length / 12) + (testIds.length * 2); 1533 const estimatedParts = Math.max(1, Math.ceil(Math.max(estimatedPages / limits.maxPages, testIds.length / limits.maxTests))); 1534 if (estimatedParts > 1) { 1535 await hideLoading(); 1536 let message = translate['EXPORT_DATA']['SPLIT_MESSAGE'].replace('##', testIds.length || rows.length).replace('%%', estimatedParts); 1537 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 1538 message += translate['EXPORT_DATA']['SPLIT_MESSAGE_APP']; 1539 } 1540 if (!await submitFormAfterConfirm(translate['EXPORT_DATA']['SPLIT_TITLE'], message)) { 1541 return; 1542 } 1543 } 1544 1545 exportCancelled = false; 1546 clearPdfImageCache(); 1547 $('#my-loading-cancel').prop('disabled', false).show().find('span').text(translate['DISMISS']); 1548 1549 let partNumber = 1; 1550 let downloaded = 0; 1551 let part = null; 1552 let testsStartTime = 0; 1553 const progress = function (extraLine = '') { 1554 let lines = [translate['TEST']['FILE_WILL_BE_EXPORTED']]; 1555 if (estimatedParts > 1) { 1556 lines.push(translate['EXPORT_DATA']['PART_PROGRESS'].replace('##', partNumber).replace('%%', Math.max(estimatedParts, partNumber))); 1557 } 1558 if (extraLine) { 1559 lines.push(extraLine); 1560 } 1561 return lines.join('<br />'); 1562 }; 1563 const getEta = function (done) { 1564 if (done < 3) { 1565 return ''; 1566 } 1567 const remainingSeconds = (Date.now() - testsStartTime) / done * (testIds.length - done) / 1000; 1568 return (remainingSeconds >= 60) ? translate['EXPORT_DATA']['TIME_REMAINING'].replace('##', Math.ceil(remainingSeconds / 60)) : ''; 1569 }; 1570 const flushPart = async function (isLast) { 1571 downloaded++; 1572 let filename = data['filename']; 1573 if (!(isLast && downloaded == 1)) { 1574 filename = filename.replace(/\.pdf$/i, '') + '_' + translate['EXPORT_DATA']['PART'] + '_' + downloaded + '.pdf'; 1575 } 1576 await showLoading(progress(translate['EXPORT_DATA']['SAVING_PART'])); 1577 const bytes = await part.doc.save(); 1578 part.doc = null; 1579 await downloadFile(new Blob([bytes], { type: data['mimetype'] }), filename, data['mimetype'], !isLast); 1580 if (!isLast) { 1581 await new Promise(resolve => setTimeout(resolve, 1000)); // Browser mehrere Downloads nacheinander erlauben 1582 partNumber++; 1583 part = await createExportPart(); 1584 } 1585 }; 1586 1587 try { 1588 part = await createExportPart(); 1589 if (titlePage) { 1590 await addPdfToExportPart(part, titlePage); 1591 } 1592 1593 // 1. Zusammenfassung (Tabelle) in Stuecken 1594 for (let start = 0; start < rows.length; start += EXPORT_TABLE_CHUNK_ROWS) { 1595 checkExportCancelled(); 1596 const chunkEnd = Math.min(start + EXPORT_TABLE_CHUNK_ROWS, rows.length); 1597 await showLoading(progress(translate['TEST']['FILE_WILL_BE_EXPORTED_STEP_3'].replace('##', start).replace('%%', rows.length))); 1598 const chunkBytes = await tableListToPDFMaker([header.slice()].concat(rows.slice(start, chunkEnd)), data['logo'], data['title'], data['ref_date'], data['show_ref_date'], { 1599 continuation: start > 0, 1600 quiet: true, 1601 asBytes: true, 1602 onProgress: (row) => showLoading(progress(translate['TEST']['FILE_WILL_BE_EXPORTED_STEP_5'].replace('##', start + row).replace('%%', rows.length))) 1603 }); 1604 for (let k = start; k < chunkEnd; k++) { 1605 rows[k] = null; 1606 } 1607 await addPdfToExportPart(part, chunkBytes); 1608 if ((chunkEnd < rows.length || testIds.length > 0) && shouldCloseExportPart(part, limits)) { 1609 await flushPart(false); 1610 } 1611 await exportYield(); 1612 } 1613 1614 // 2. Einzelne Pruefungen: in kleinen Paketen vom Server holen, einzeln als PDF bauen und sofort anhaengen 1615 testsStartTime = Date.now(); 1616 for (let start = 0; start < testIds.length; start += EXPORT_TEST_BATCH) { 1617 checkExportCancelled(); 1618 const testDatas = await fetchExportTestDatas(testIds.slice(start, start + EXPORT_TEST_BATCH), data['date_format']); 1619 for (let k = 0; k < testDatas.length; k++) { 1620 checkExportCancelled(); 1621 const done = start + k; 1622 await showLoading(progress(translate['TEST']['FILE_WILL_BE_EXPORTED_STEP_4'].replace('##', done).replace('%%', testIds.length) + '<br />' + getEta(done))); 1623 const testBytes = await testToPDF(testDatas[k], data['logo'], with_attachments, { asBytes: true }); 1624 testDatas[k] = null; 1625 await addPdfToExportPart(part, testBytes, 1); 1626 if ((done + 1 < testIds.length) && shouldCloseExportPart(part, limits)) { 1627 await flushPart(false); 1628 } 1629 } 1630 await exportYield(); 1631 } 1632 1633 await flushPart(true); 1634 if (downloaded > 1) { 1635 presentToast(translate['EXPORT_DATA']['FINISHED_PARTS'].replace('##', downloaded), 'fa-save', 'success'); 1636 } 1637 } catch (error) { 1638 if (error && error.message === 'EXPORT_CANCELLED') { 1639 presentToast(translate['EXPORT_DATA']['CANCELLED'], 'fa-ban', 'warning'); 1640 } else { 1641 console.log(error); 1642 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'warning'); 1643 } 1644 await hideLoading(); 1645 } finally { 1646 if (part) { 1647 part.doc = null; 1648 } 1649 $('#my-loading-cancel').hide(); 1650 clearPdfImageCache(); 1651 } 1652} 1653$(document).on('click', '#confirm-export', async function (e) { 1654 let popup = $(this).parents('.my-popup'); 1655 const tableName = getListTableName(); 1656 let ids = getExportIds(); 1657 let titlePage = ''; 1658 let with_attachments = false;
1659 if (popup.find('select[name="file_type"]').val() == 'PDF') { 1660 if (popup.find('input[name="with_title_page"]').prop('checked')) { 1661 try { 1662 titlePage = await getTitlePagePDF(); 1663 } catch (error) { 1664 return; 1665 } 1666 } 1667 if (popup.find('input[name="with_attachments"]').prop('checked')) { 1668 with_attachments = true; 1669 } 1670 } 1671 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED_STEP_1']); 1672 popup.find('.close-and-remove-popup').trigger('click'); 1673 $.ajax({ 1674 type: 'POST', 1675 url: 'export', 1676 cache: false, 1677 data: { 1678 data: JSON.stringify(popup.find('form').serializeArray()), 1679 tableName: tableName, 1680 ids: ids, 1681 from_cart: $('#cart-popup').length > 0 ? 1 : 0 1682 }, 1683 success: async function (result) { 1684 try { 1685 let data = JSON.parse(result); 1686 let base64 = ''; 1687 if (data['type'] == 'PDF') { 1688 if (tableName != 'main_bill') { 1689 await exportPdfInParts(data, titlePage, with_attachments); 1690 return; 1691 } 1692 if (data['dataArray'].length > 1) { 1693 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED']); 1694 base64 = await tableListToPDFMaker(data['dataArray'], data['logo'], data['title'], data['ref_date'], data['show_ref_date']); 1695 if (data['summary'] == '1') { 1696 data['detailsPdfs'] = data['detailsPdfs'].map(x => base64ToArrayBuffer(x)); 1697 data['detailsPdfs'].unshift(base64); 1698 base64 = await mergePdfs(data['detailsPdfs']); 1699 } else if (data['summary'] == '0') { 1700 data['detailsPdfs'] = data['detailsPdfs'].map(x => base64ToArrayBuffer(x)); 1701 base64 = await mergePdfs(data['detailsPdfs']); 1702 } 1703 } 1704 } else { 1705 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED']); 1706 base64 = data['base64']; 1707 } 1708 if (base64) { 1709 if (titlePage) { 1710 base64 = await mergePdfs([titlePage, base64]); 1711 } 1712 await downloadFile(base64, data['filename'], data['mimetype']); 1713 } else { 1714 presentToast(translate['EXPORT_DATA']['NO_DATA_FOR_EXPORT'], 'fa-triangle-exclamation', 'warning'); 1715 await hideLoading(); 1716 } 1717 1718 } catch (err) { 1719 await hideLoading(); 1720 console.log(err); 1721 console.log(result); 1722 } 1723 }, 1724 }); 1725}); 1726// END - EXPORT 1727// REFRESHER 1728var mouseY = 0; 1729var startMouseY = 0; 1730var offsetRefresh = 0; 1731$(document).on('mousedown touchstart', function (ev) { 1732 if (ev.pageY === undefined) { 1733 mouseY = ev.touches[0].pageY; 1734 } else { 1735 mouseY = ev.pageY; 1736 } 1737 startMouseY = mouseY; 1738 $(document).on('mousemove touchmove', function (e) { 1739 if (mouseY < ($(window).height() * 0.10)) { 1740 let pageY = 0; 1741 if (e.pageY === undefined) { 1742 pageY = e.touches[0].pageY; 1743 } else { 1744 pageY = e.pageY; 1745 } 1746 if (pageY > mouseY) { 1747 offsetRefresh = pageY - startMouseY; 1748 let percentage = 100 / ($(window).height() * 0.25) * offsetRefresh; 1749 if (offsetRefresh < ($(window).height() * 0.25)) { 1750 $('.refresher i').removeClass('rotate'); 1751 $('.refresher').css('top', offsetRefresh / 2.5 + 'px'); 1752 $('.refresher').css('opacity', percentage / 100); 1753 $('.refresher i').css('transform', 'rotate(' + (3.6 * percentage) + 'deg)'); 1754 $('body').css('margin-top', offsetRefresh / 3 + 'px'); 1755 } else { 1756 $('.refresher i').addClass('rotate'); 1757 } 1758 } else { 1759 $(document).unbind("mousemove"); 1760 } 1761 } 1762 }); 1763}); 1764$('html').on('mouseup touchend', function (ev) { 1765 if (offsetRefresh > ($(window).height() * 0.25)) { 1766 location.reload(); 1767 } 1768 $('.refresher').css('top', '0px'); 1769 $('.refresher').css('opacity', '0'); 1770 $('.refresher i').css('transform', 'rotate(0deg)'); 1771 $('body').css('margin-top', '0px'); 1772 $(document).unbind("mousemove"); 1773}); 1774$('html').on('mouseleave', function (ev) { 1775 if (offsetRefresh > ($(window).height() * 0.25)) { 1776 location.reload(); 1777 } 1778 $('.refresher').css('top', '0px'); 1779 $('.refresher').css('opacity', '0'); 1780 $('.refresher i').css('transform', 'rotate(0deg)'); 1781 $('body').css('margin-top', '0px'); 1782 $(document).unbind("mousemove"); 1783}); 1784 1785// FORM FUNCTIONS 1786function getFormData($form) { 1787 var unindexed_array = $form.serializeArray(); 1788 var indexed_array = {}; 1789 1790 $.map(unindexed_array, function (n, i) { 1791 if (n['name'].includes('[]')) { 1792 if (indexed_array[n['name']]) { 1793 indexed_array[n['name']].push(n['value']); 1794 } else { 1795 indexed_array[n['name']] = [n['value']]; 1796 } 1797 } else { 1798 indexed_array[n['name']] = n['value']; 1799 } 1800 }); 1801 1802 return indexed_array; 1803} 1804$(document).on('focus', 'input[readonly].remove-read-only', function () { 1805 if ($(this).attr('readonly')) { 1806 $(this).prop('readonly', false); 1807 $(this).blur(); 1808 $(this).focus(); 1809 } 1810}); 1811 1812$(document).on('input', '.my-input input[type="search"]', function () { 1813 updateClearSearch($(this)); 1814}); 1815if ($('.my-input input[type="search"]').length > 0) { 1816 $('.my-input input[type="search"]').each(function (idx, el) { 1817 updateClearSearch($(el)); 1818 }); 1819} 1820function updateClearSearch(el) { 1821 if (el.length > 0) { 1822 let value = el.val(); 1823 if (value.length > 0) { 1824 el.parents('.my-input').find('.clear-search').show(); 1825 } else { 1826 el.parents('.my-input').find('.clear-search').hide(); 1827 } 1828 } 1829} 1830 1831$(document).on('input', '.my-input input', function () { 1832 $(this).parents('.my-input').removeClass('error'); 1833}); 1834$(document).on('input', '.my-input.time-input input[type="text"]', function () { 1835 setTimeInputValues($(this).parents('.my-input')); 1836}); 1837$(document).on('input', '.my-input select', function () { 1838 $(this).parents('.my-input').removeClass('error'); 1839}); 1840$(document).on('input', '.my-input.time-input select', function () { 1841 setTimeInputValues($(this).parents('.my-input')); 1842}); 1843function setTimeInputValues(inputEl) { 1844 let val = inputEl.find('input[type="text"]').val(); 1845 val = val.replace(/[^0-9]+/g, ''); 1846 const divisor = inputEl.find('select option:selected').data('divisor'); 1847 const minuteVal = divisor * val; 1848 inputEl.find('input[type="hidden"]').val(minuteVal); 1849 inputEl.find('input[type="text"]').val(val); 1850 if (minuteVal > 2147483647) { 1851 let errorMessage = inputEl.find('.input-error').data('error1'); 1852 errorMessage = errorMessage.replace('#', (Math.floor(2147483647 / divisor) + ' ' + inputEl.find('select option:selected').text())); 1853 inputEl.find('.input-error').text(errorMessage); 1854 inputEl.addClass('error'); 1855 } 1856} 1857async function saveFormCheckBeforeUnload() { 1858 $('form.check-before-unload').data('serialize', $('form.check-before-unload').seri
1858alize()); 1859} 1860let skipBeforeUnload = false; 1861$(window).bind('pagehide beforeunload', function (e) { 1862 if (skipBeforeUnload) { 1863 skipBeforeUnload = false; 1864 return; 1865 } 1866 if ($('.my-table-list').length > 0) { 1867 if ($('.my-table-list').data('filter-article_id') !== undefined) { 1868 delete filter['article_id']; 1869 updateFilter('article_id', ""); 1870 } 1871 } 1872 1873 if ($('form.check-before-unload').length > 0) { 1874 if ($('form.check-before-unload').serialize() != $('form.check-before-unload').data('serialize')) { 1875 if ($('form.save-in-local-storage').length > 0) { 1876 if ($('form.save-in-local-storage [name="edit"]').val() != '1') { 1877 if ($('form.save-in-local-storage [name="is_ref_id"]').length <= 0) { 1878 localStorage.setItem($('form.save-in-local-storage').attr('id'), JSON.stringify(getFormData($('form.save-in-local-storage')))); 1879 } else { 1880 return true; 1881 } 1882 } 1883 } else { 1884 return true; 1885 } 1886 } 1887 } 1888 $('#loading-bar').show(); 1889 e = null; 1890}); 1891 1892$(document).on('click', '.popup-select', async function () { 1893 const inputEl = $(this); 1894 const popupSelectType = inputEl.data('popup-select'); 1895 if (popupSelectType == 'parent_dir_id') { 1896 const currentId = inputEl.find('input[type="hidden"].main-val').val(); 1897 const targetDirID = $('input[name="current_id"]').val(); 1898 openmoveelementstodirpopup({ dir_id: currentId, targetDirID: targetDirID }); 1899 $(document).off('click', '#move-elements-to-dir-popup #confirm_move').on('click', '#move-elements-to-dir-popup #confirm_move', async function (e) { 1900 let dirID = getCurrentDirFromMoveElementsPopup(); 1901 let dirName = getCurrentDirNameFromMoveElementsPopup(); 1902 inputEl.find('input[type="hidden"].main-val').val(dirID).change(); 1903 inputEl.find('input[type="text"]').val(dirName).change(); 1904 inputEl.removeClass('error'); 1905 hidePopUp($('#move-elements-to-dir-popup')); 1906 $('#move-elements-to-dir-popup').remove(); 1907 }); 1908 } else { 1909 await getPopUpSelectValue(inputEl); 1910 } 1911}); 1912$(document).on('keydown', '.my-input', function (e) { 1913 if (!$(this).hasClass('textarea') && e.target.tagName.toLowerCase() !== 'textarea') { 1914 if (e.key === "Enter") { 1915 e.preventDefault(); 1916 } 1917 } 1918}); 1919async function getPopUpSelectValue(inputEl) { 1920 return new Promise(async (resolve, reject) => { 1921 const currentId = inputEl.find('input[type="hidden"].main-val').val(); 1922 const popupSelectType = inputEl.data('popup-select'); 1923 const title = inputEl.find('label').text(); 1924 const triggerClick = inputEl.attr('id'); 1925 await getAjaxPopUp('getpopupselect', { 'type': popupSelectType, 'currentId': currentId, 'title': title }); 1926 $('#select-popup #search').focus(); 1927 setTimeout(() => { 1928 if ($('#select-popup input:checked').length > 0) { 1929 $('#select-popup .popup-body').animate({ 1930 scrollTop: $('#select-popup input:checked').parents('.element').position().top - ($('#select-popup .popup-header').outerHeight() + $('#select-popup .search-wrapper').outerHeight() + $(window).height() * 0.05) 1931 }, 200); 1932 } 1933 }, 300); 1934 1935 $('#select-popup #confirm').click(async function (e) { 1936 let id = $('#select-popup input:checked').val(); 1937 inputEl.find('input[type="hidden"].main-val').val(id).change(); 1938 if (inputEl.find('input[type="hidden"].random-id').length > 0) 1939 inputEl.find('input[type="hidden"].random-id').val($('#select-popup input:checked').parents('.element').find('.bg-img').data('random-id')).change(); 1940 else if ($('.prev-img').length > 0) { 1941 if ($('.prev-img + input[type="hidden"]').val() == '' || $('.prev-img + input[type="hidden"]').length == 0) { 1942 $('.prev-img').css('background-image', $('#select-popup input:checked').parents('.element').find('.bg-img.change-img').css('background-image')); 1943 inputEl.find('input[type="hidden"].img-value').val($('#select-popup input:checked').parents('.element').find('.bg-img.change-img').css('background-image')).change(); 1944 } 1945 } 1946 inputEl.find('input[type="text"]').val($('#select-popup input:checked').parents('.element').find('.name').text()).change(); 1947 $('#select-popup').find('.close-and-remove-popup').trigger('click'); 1948 inputEl.removeClass('error'); 1949 resolve(id); 1950 }); 1951 let justCheckedOne = $('#select-popup .element input[type="radio"]:checked').length > 0; 1952 $('#select-popup .element input[type="radio"]').change(async function (e) { 1953 if (!justCheckedOne) { 1954 $('#select-popup #confirm').trigger('click'); 1955 } 1956 }); 1957 $('#select-popup #add_new').click(async function (e) { 1958 const functionName = $(this).data('function-name') 1959 window[functionName]('?redirect=' + encodeURI(window.location.pathname.replace($('base').attr('href'), '') + '?triggerclick=' + triggerClick)); 1960 }); 1961 $('#select-popup .clear-search').click(function (e) { 1962 $(this).parents('.my-input').find('input[type="search"]').val(''); 1963 let allElements = $('#select-popup .elements .element'); 1964 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#select-popup .elements"); 1965 $('#select-popup .popup-body').animate({ 1966 scrollTop: 0 1967 }, 200); 1968 if (!isTouchDevice()) { 1969 $(this).parents('.my-input').find('input[type="search"]').focus(); 1970 } 1971 }); 1972 $('#select-popup #search').on('input', function (e) { 1973 const val = $(this).val().toLowerCase(); 1974 let allElements = $('#select-popup .elements .element'); 1975 if (val.length > 0) { 1976 allElements.each((idx, el) => { 1977 const name = $(el).find('.name').text().toLowerCase(); 1978 if (name.includes(val)) { 1979 $(el).attr('data-order', 0); 1980 } else { 1981 $(el).attr('data-order', levenshteinDistance(val, name)); 1982 } 1983 }); 1984 allElements.sort((a, b) => $(a).attr("data-order") - $(b).attr("data-order")).appendTo("#select-popup .elements"); 1985 } else { 1986 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#select-popup .elements"); 1987 } 1988 $('#select-popup .popup-body').animate({ 1989 scrollTop: 0 1990 }, 200); 1991 }) 1992 }); 1993} 1994function resetFormCheckBeforeUnload() { 1995 $('form.check-before-unload').data('serialize', $('form.check-before-unload').seri
1995alize()); 1996 if ($('form.save-in-local-storage').length > 0) { 1997 if ($('form.save-in-local-storage [name="edit"]').val() != '1') { 1998 if ($('form.save-in-local-storage [name="is_ref_id"]').length <= 0) { 1999 localStorage.removeItem($('form.save-in-local-storage').attr('id')); 2000 } 2001 } 2002 } 2003 return true; 2004} 2005 2006function submitForm(form) { 2007 $(form).find('input[type="submit"]').prop('disabled', true); 2008 form.submit(); 2009 return true; 2010} 2011 2012$('input[type="color"]').on('input', function (e) { 2013 let tmpColor = $(e.target).val(); 2014 if (/^#[0-9A-F]{6}$/i.test(tmpColor)) { 2015 const hex = tmpColor; 2016 const r = parseInt(hex.replace('#', '').substr(0, 2), 16); 2017 const g = parseInt(hex.replace('#', '').substr(2, 2), 16); 2018 const b = parseInt(hex.replace('#', '').substr(4, 2), 16); 2019 if (!(r > 230 && g > 230 && b > 230)) { 2020 changeTheme(tmpColor); 2021 $('#color-value').val(tmpColor); 2022 } 2023 } else { 2024 $(e.target).val('#3880ff'); 2025 $('#color-value').val('#3880ff'); 2026 changeTheme('#3880ff'); 2027 } 2028}); 2029$('#color-value').on('input', function () { 2030 let tmpColor = $(this).val(); 2031 if (/^#[0-9A-F]{6}$/i.test(tmpColor)) { 2032 const hex = tmpColor; 2033 const r = parseInt(hex.replace('#', '').substr(0, 2), 16); 2034 const g = parseInt(hex.replace('#', '').substr(2, 2), 16); 2035 const b = parseInt(hex.replace('#', '').substr(4, 2), 16); 2036 if (!(r > 230 && g > 230 && b > 230)) { 2037 changeTheme(tmpColor); 2038 $('input[type="color"]').val(tmpColor); 2039 } 2040 } else if (tmpColor == '') { 2041 $('input[type="color"]').val('#3880ff'); 2042 changeTheme('#3880ff'); 2043 } else { 2044 $('input[type="color"]').val('#3880ff'); 2045 changeTheme('#3880ff'); 2046 } 2047}); 2048$('#color-value').on('blur', function () { 2049 let tmpColor = $(this).val(); 2050 if (/^#[0-9A-F]{6}$/i.test(tmpColor)) { 2051 const hex = tmpColor; 2052 const r = parseInt(hex.replace('#', '').substr(0, 2), 16); 2053 const g = parseInt(hex.replace('#', '').substr(2, 2), 16); 2054 const b = parseInt(hex.replace('#', '').substr(4, 2), 16); 2055 if (!(r > 230 && g > 230 && b > 230)) { 2056 changeTheme(tmpColor); 2057 $('input[type="color"]').val(tmpColor); 2058 } 2059 } else if (tmpColor == '') { 2060 $('input[type="color"]').val('#3880ff'); 2061 $(this).val('#3880ff'); 2062 changeTheme('#3880ff'); 2063 } else { 2064 $('input[type="color"]').val('#3880ff'); 2065 $(this).val('#3880ff'); 2066 changeTheme('#3880ff'); 2067 } 2068}); 2069function changeTheme(colorString = "#3880ff") { 2070 let color = tinycolor(colorString); 2071 let colorContrast = tinycolor(color.isLight() ? '#000000' : '#ffffff'); 2072 let colorShade = tinycolor(colorString).darken(8).toString(); 2073 let colorTint = tinycolor(colorString).lighten(8).toString(); 2074 let colorLight = tinycolor(colorString).lighten(35).toString(); 2075 let colorMedium = tinycolor(colorString).lighten(15).toString(); 2076 if ((color._r < 150 && color._g < 150 && color._b < 150)) { 2077 colorLight = tinycolor(colorString).lighten(50).toString(); 2078 colorMedium = tinycolor(colorString).lighten(25).toString(); 2079 } 2080 if ((color._r < 80 && color._g < 80 && color._b < 80)) { 2081 colorLight = tinycolor(colorString).lighten(70).toString(); 2082 colorMedium = tinycolor(colorString).lighten(35).toString(); 2083 } 2084 if (isDarkMode) { 2085 colorLight = tinycolor(colorString).darken(40).toString(); 2086 colorMedium = tinycolor(colorString).darken(20).toString(); 2087 if ((color._r > 150 && color._g > 150 && color._b > 150)) { 2088 colorLight = tinycolor(colorString).darken(50).toString(); 2089 colorMedium = tinycolor(colorString).darken(25).toString(); 2090 } 2091 if ((color._r > 80 && color._g > 80 && color._b > 80)) { 2092 colorLight = tinycolor(colorString).darken(70).toString(); 2093 colorMedium = tinycolor(colorString).darken(35).toString(); 2094 } 2095 } 2096 document.documentElement.style.setProperty('--color-primary-medium', colorMedium); 2097 document.documentElement.style.setProperty('--color-primary-light', colorLight); 2098 document.documentElement.style.setProperty('--color-primary', color); 2099 document.documentElement.style.setProperty('--color-primary-contrast', colorContrast); 2100 document.documentElement.style.setProperty('--color-primary-shade', colorShade); 2101 document.documentElement.style.setProperty('--color-primary-tint', colorTint); 2102 // document.querySelector('meta[name="theme-color"]').setAttribute("content", color.hex()); 2103 // document.querySelector('meta[name="msapplication-navbutton-color"]').setAttribute("content", color.hex()); 2104 // document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]').setAttribute("content", color.hex()); 2105} 2106$(document).on('click', '.my-input .multiple-input .input-item .remove', function (e) { 2107 if ($(this).parents('.input-item').find('.value').attr('data-col-name') != undefined) { 2108 let name = $(this).parents('.input-item').find('.value').text(); 2109 let colname = $(this).parents('.input-item').find('.value').attr('data-col-name'); 2110 let newOption = document.createElement('option'); 2111 newOption.value = colname; 2112 newOption.textContent = name; 2113 $(this).parents('.my-input').find('.tmp-input select').append(newOption); 2114 let options = $(this).parents('.my-input').find('.tmp-input select option:not([value=""])'); 2115 let arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get(); 2116 arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; }); 2117 options.each(function (i, o) { 2118 o.value = arr[i].v; 2119 $(o).text(arr[i].t); 2120 }); 2121 $(this).parents('.my-input').find('.tmp-input').show(); 2122 } 2123 let tmpEl = $(this).parents('.multiple-input'); 2124 $(this).parents('.input-item').remove(); 2125 updateMultipleInputValue(tmpEl); 2126}); 2127$('.my-input #add_value').click(function () { 2128 addValueToMultipleInput($(this).parents('.my-input')); 2129}); 2130function addValueToMultipleInput(myInputEL) { 2131 let tmpInputEl = myInputEL.find('.tmp-input'); 2132 let inputEl = ''; 2133 if (tmpInputEl.prop("tagName") == 'INPUT') { 2134 inputEl = myInputEL.find('input.tmp-input'); 2135 } else { 2136 inputEl = myInputEL.find('select'); 2137 } 2138 const val = inputEl.val(); 2139 let error = false;
2140 if (inputEl.attr('type') == 'email') { 2141 re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 2142 if (!re.test(val.trim())) { 2143 error = true; 2144 } 2145 } 2146 if (!error) { 2147 let newInputItem = document.createElement('div'); 2148 newInputItem.className = 'input-item'; 2149 2150 let newInputItemValue = document.createElement('span'); 2151 newInputItemValue.className = 'value'; 2152 if (tmpInputEl.prop("tagName") == 'INPUT') { 2153 newInputItemValue.textContent = val.trim(); 2154 } else { 2155 newInputItemValue.setAttribute('data-col-name', val); 2156 newInputItemValue.textContent = inputEl.find('option[value="' + val + '"]').text(); 2157 } 2158 newInputItem.appendChild(newInputItemValue); 2159 2160 let newInputItemRemove = document.createElement('span'); 2161 newInputItemRemove.className = 'remove'; 2162 newInputItemRemove.innerHTML = '<i class="fa-solid fa-xmark"></i>'; 2163 newInputItem.appendChild(newInputItemRemove); 2164 tmpInputEl.before(newInputItem); 2165 if (tmpInputEl.prop("tagName") == 'INPUT') { 2166 inputEl.val(''); 2167 } else { 2168 inputEl.find('option[value="' + val + '"]').remove(); 2169 if (inputEl.find('option').length <= 1) { 2170 tmpInputEl.hide(); 2171 } 2172 } 2173 $(this).parents('.my-input').find('#add_value').addClass('hide-me'); 2174 updateMultipleInputValue(inputEl.parents('.multiple-input')); 2175 } else { 2176 let inputWrapperEl = inputEl.parents('.my-input'); 2177 inputWrapperEl.addClass('error'); 2178 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 2179 inputEl.focus(); 2180 } 2181} 2182$('.my-input .multiple-input input.tmp-input').on('keyup', function (e) { 2183 const val = $(this).val(); 2184 if (val.length > 0) { 2185 $(this).parents('.my-input').find('#add_value').removeClass('hide-me'); 2186 } else { 2187 $(this).parents('.my-input').find('#add_value').addClass('hide-me'); 2188 } 2189}); 2190$('.my-input .multiple-input input.tmp-input').on('keydown', function (e) { 2191 const val = $(this).val(); 2192 if (e.key === "Backspace") { 2193 if (val.length == 0) { 2194 $(this).parents('.multiple-input').find('.input-item:last-of-type').remove(); 2195 updateMultipleInputValue($(this).parents('.multiple-input')); 2196 } 2197 } else if (e.key === "Enter") { 2198 e.preventDefault(); 2199 addValueToMultipleInput($(this).parents('.my-input')); 2200 } 2201}); 2202$(document).on('change', '.my-input .multiple-input .tmp-input select', function (e) { 2203 addValueToMultipleInput($(this).parents('.my-input')); 2204}) 2205function updateMultipleInputValue(el) { 2206 let tmpInputEl = el.find('.tmp-input'); 2207 let get_only_select = tmpInputEl.data('get_only_select'); 2208 let values = []; 2209 if (tmpInputEl.prop("tagName") == 'INPUT') { 2210 el.find('.input-item').each((idx, item) => { 2211 values.push($(item).find('.value').text()); 2212 }); 2213 } else { 2214 if (get_only_select === true) { 2215 el.find('.input-item').each((idx, item) => { 2216 values.push($(item).find('.value').data('col-name')); 2217 }); 2218 } else { 2219 values = el.find('select option').map((idx, el) => ($(el).val() !== '') ? $(el).val() : null).toArray() 2220 } 2221 } 2222 el.find('input[type="hidden"]').val(values.join(",")); 2223} 2224$(document).on('click', '.my-input label+i,.my-input label+svg', function (e) { 2225 $(this).parents('.my-input').find('label').trigger('click'); 2226}); 2227 2228$('input[type="range"]').on('input', function (e) { 2229 let target = $(e.target); 2230 let value = Math.round(target.val() * 100); 2231 target.css('--value', value + '%'); 2232 target.find('+label').html(target.find('+label').data('text').replace('#', value)); 2233}); 2234 2235let currentImageEl = null; 2236$('.my-image button').click(async function (e) { 2237 let target = $(this).parents('.my-image'); 2238 target.removeClass('error'); 2239 const onlySvg = target.hasClass('only-svg'); 2240 currentImageEl = target; 2241 let result = await getImage(target, onlySvg); 2242 if (result !== null && result != 'remove') { 2243 target.find('.prev-img').css('background-image', 'url(' + result + ')'); 2244 target.find('input.img-value').val(result); 2245 target.find('input.for-delete').val('0'); 2246 } else if (result === 'remove') { 2247 target.find('.prev-img').css('background-image', 'url(' + target.find('.prev-img').attr('data-default') + ')'); 2248 target.find('input.img-value').val(''); 2249 target.find('input.for-delete').val('1'); 2250 } 2251}); 2252 2253function imageInputSetData(target, imageData) { 2254 target.find('.prev-img').css('background-image', 'url(' + imageData + ')'); 2255 target.find('input.img-value').val(imageData); 2256 target.find('input.for-delete').val('0'); 2257} 2258$('.login-form input').on('keydown', function (e) { 2259 if (e.key === "Enter") { 2260 $('.login-form button[type="submit"]').trigger('click'); 2261 } 2262}); 2263// END - FORM FUNCTIONS 2264 2265// NFC 2266let lastFocusedElement; 2267$(document).on('focus', '.field-for-focus', function (e) { 2268 lastFocusedElement = $(this); 2269}); 2270$(document).on('click', '#scan-nfc', async function (e) { 2271 let nfc_tag = await getNFC(); 2272 let target = $(this).data('target'); 2273 writeNFCOrQRCodeToEl(nfc_tag, target); 2274}); 2275function normalizeScannedCode(code) { 2276 if (code.includes('Ser. No.')) { 2277 code = code.replace(/(\r\n|\n|\r)/gm, ""); 2278 code = code.replace('Ser. No.: ', ''); 2279 code = code.substr(0, code.indexOf(' Model')); 2280 } 2281 return code; 2282} 2283function writeNFCOrQRCodeToEl(code, target) { 2284 if (code !== '') { 2285 code = normalizeScannedCode(code); 2286 if (code !== '') { 2287 if (target == 'search') { 2288 $('.my-table-list-filter-search').val(code); 2289 $('.my-auto-complete').addClass('hide-me'); 2290 updateFilter('searchStr', encodeURI($('.my-table-list-filter-search').val())); 2291 updateClearSearch($('.my-table-list-filter-search')); 2292 getTableList(false, true); 2293 } 2294 if (target == 'focus-or-nfc-id') { 2295 let el; 2296 if (lastFocusedElement) { 2297 el = lastFocusedElement; 2298 } else { 2299 if ($('[name="nfc_id"]').length > 0) { 2300 el = $('[name="nfc_id"]'); 2301 } 2302 } 2303 if (el) { 2304 let splittedCode = code.split(''); 2305 writeSplittedCodeToEl(el, splittedCode); 2306 } 2307 } 2308 if (target == 'focus-or-customer_number') { 2309 let el; 2310 if (lastFocusedElement) { 2311 el = lastFocusedElement; 2312 } else { 2313 if ($('[name="customer_number"]').length > 0) { 2314 el = $('[name="customer_number"]'); 2315 } 2316 } 2317 if (el) { 2318 let splittedCode = code.split(''); 2319 writeSplittedCodeToEl(el, splittedCode); 2320 } 2321 } 2322 if (target == 'hot-cell') { 2323 let splittedCode = code.split(''); 2324 writeSplittedCodeToHot(splittedCode); 2325 } 2326 } 2327 } 2328} 2329let writeSplittedCell = null; 2330async function writeSplittedCodeToHot(splittedCode, index = 0) { 2331 if (typeof writeSplittedCodeToTabulator === 'function' && typeof table !== 'undefined' && table !== null) { 2332 writeSplittedCodeToTabulator(splittedCode, index); 2333 return; 2334 } 2335 if (hot !== undefined) { 2336 if (lastHotCell !== undefined) { 2337 if (lastHotCell.col >= 0 && lastHotCell.row >= 0) { 2338 if (writeSplittedCell == null) 2339 writeSplittedCell = lastHotCell; 2340 if (splittedCode.length > 0) { 2341 await hot.setDataAtCell(writeSplittedCell.row, writeSplittedCell.col, splittedCode.filter((x, i) => i <= index).join('')); 2342 if (index < splittedCode.length) { 2343 setTimeout(() => { 2344 writeSplittedCodeToHot(splittedCode, index + 1) 2345 }, 40); 2346 } else { 2347 writeSplittedCell = null; 2348 } 2349 } 2350 } else { 2351 presentToast(translate['TABULATOR_JS']['NO_CELL_SELECTED'], 'fa-triangle-exclamation', 'warning') 2352 } 2353 } else { 2354 presentToast(translate['TABULATOR_JS']['NO_CELL_SELECTED'], 'fa-triangle-exclamation', 'warning') 2355 } 2356 } 2357} 2358function writeSplittedCodeToEl(el, splittedCode) { 2359 if (splittedCode.length > 0) { 2360 let currVal = el.val() + splittedCode[0]; 2361 el.focus(); 2362 el.val(currVal); 2363 splittedCode.splice(0, 1); 2364 setTimeout(() => { 2365 writeSplittedCodeToEl(el, splittedCode) 2366 }, 40); 2367 } 2368} 2369$(document).on('click', '.nfc_unsubscribe', async function (e) { 2370 return new Promise(async (resolve, reject) => { 2371 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2372 try { 2373 var messageObj = { function: 'unsubscribeNFC' }; 2374 var stringifiedMessageObj = JSON.stringify(messageObj); 2375 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 2376 } catch (error) { 2377 } 2378 } 2379 resolve(null); 2380 }) 2381}) 2382async function getNFC() { 2383 await showLoading(); 2384 return new Promise(async (resolve, reject) => { 2385 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2386 try { 2387 var messageObj = { function: 'scanNFC' }; 2388 var stringifiedMessageObj = JSON.stringify(messageObj); 2389 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 2390 if ($('html').data('plt-ios')) { 2391 hideLoading(); 2392 let res = await getNFCFromApp(); 2393 if (res === false || res == '') { 2394 await openNFCPopUp(); 2395 } 2396 resolve(res); 2397 } else { 2398 await openNFCPopUp(); 2399 hideLoading(); 2400 resolve(await getNFCFromApp()); 2401 } 2402 } catch (error) { 2403 resolve(null); 2404 } 2405 } else { 2406 hideLoading(); 2407 getAjaxPopUp('scannfc', { nfc_available: false }); 2408 } 2409 }); 2410} 2411async function openNFCPopUp() { 2412 return new Promise(async (resolve, reject) => { 2413 let nfc_available = $('html').attr('data-nfc-available'); 2414 let error = $('html').attr('data-error'); 2415 if ((nfc_available !== '' && nfc_available !== undefined) || (error !== '' && error !== undefined)) { 2416 if (nfc_available !== '' && nfc_available !== undefined) { 2417 getAjaxPopUp('scannfc', { nfc_available: (nfc_available === 'true') }); 2418 resolve(true); 2419 } else if (error !== '' && error !== undefined) { 2420 $('html').attr('data-error', ''); 2421 let errorMessage = translate[error]; 2422 if (errorMessage == undefined) { 2423 errorMessage = translate['NFC_QR']['NFC_ERROR']; 2424 } 2425 presentToast(errorMessage, 'fa-triangle-exclamation', 'warning'); 2426 resolve(true); 2427 } 2428 } else { 2429 setTimeout(async () => { 2430 resolve(openNFCPopUp()); 2431 }, 300); 2432 } 2433 }); 2434} 2435async function getNFCFromApp() { 2436 return new Promise(async (resolve, reject) => { 2437 let nfc_tag = $('html').attr('data-nfc'); 2438 let error = $('html').attr('data-error'); 2439 if ((nfc_tag !== '' && nfc_tag !== undefined) || (error !== '' && error !== undefined)) { 2440 if (nfc_tag !== '' && nfc_tag !== undefined) { 2441 $('#scannfc-popup').find('.close-and-remove-popup').trigger('click'); 2442 $('html').attr('data-nfc', ''); 2443 resolve(nfc_tag); 2444 } else if (error !== '' && error !== undefined) { 2445 $('html').attr('data-error', ''); 2446 let errorMessage = translate[error]; 2447 if (errorMessage == undefined) { 2448 errorMessage = translate['NFC_QR']['NFC_ERROR']; 2449 } 2450 presentToast(errorMessage, 'fa-triangle-exclamation', 'warning'); 2451 resolve(''); 2452 } 2453 } else { 2454 setTimeout(async () => { 2455 resolve(await getNFCFromApp()); 2456 }, 300); 2457 } 2458 }); 2459} 2460// END - NFC 2461// QR 2462$(document).on('click', '#scan-qrcode', async function (e) { 2463 let qr_code = await getQRCode(); 2464 let target = $(this).data('target'); 2465 writeNFCOrQRCodeToEl(qr_code, target); 2466}); 2467async function getQRCode() { 2468 return new Promise(async (resolve, reject) => { 2469 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2470 try { 2471 await closeWebQr();
2472 var messageObj = { function: 'scanQR' }; 2473 var stringifiedMessageObj = JSON.stringify(messageObj); 2474 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 2475 resolve(await getQRFromApp()); 2476 } catch (error) { 2477 console.error(error); 2478 } 2479 } else { 2480 resolve(await openWebQr()); 2481 } 2482 }); 2483} 2484 2485var qrCanScann = true; 2486var qrScannerActive = false; 2487 2488// QR/Barcode-Scanner-Engine: app/files/js/qr-scanner.js (zxing-wasm, Open Source). 2489// Erkennt invertierte Codes (z.B. weiÃer QR-Code auf grauem/dunklem Hintergrund) 2490// automatisch bei jedem Frame mit, kein separater "Invertieren"-Modus mehr nötig. 2491// onCode: Wenn gesetzt, bleibt die Kamera nach jedem Scan offen und onCode wird pro Code aufgerufen 2492async function openWebQr(onCode = null) { 2493 return new Promise(async (resolve, reject) => { 2494 qrCanScann = true; 2495 await showLoading(); 2496 await getAjaxPopUp('getwebqr'); 2497 2498 $('#useQRFromApp').on('click', async function (e) { 2499 await closeWebQr(false); 2500 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2501 try { 2502 var messageObj = { function: 'scanQR' }; 2503 var stringifiedMessageObj = JSON.stringify(messageObj); 2504 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 2505 resolve(await getQRFromApp()); 2506 } catch (error) { 2507 resolve(null); 2508 } 2509 } 2510 }); 2511 try { 2512 await window.QrScanner.start(document.getElementById('qr-video'), { 2513 onResult: async (decodedText) => { 2514 if (decodedText.length !== 0 && qrCanScann) { 2515 $('#qr-shaded-region').addClass('scanned'); 2516 beep(); 2517 qrCanScann = false; 2518 if (onCode) { 2519 await onCode(decodedText); 2520 $('#qr-shaded-region').removeClass('scanned'); 2521 qrCanScann = true; 2522 return; 2523 } 2524 closeWebQr(); 2525 resolve(decodedText); 2526 } 2527 }, 2528 onError: (err) => { 2529 console.error('Fehler beim Scannen:', err); 2530 } 2531 }); 2532 qrScannerActive = true; 2533 2534 $('#webqr-popup').addClass('show'); 2535 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2536 $('#useQRFromApp').removeClass('hide-me'); 2537 } 2538 hideLoading(); 2539 } catch (err) { 2540 hideLoading(); 2541 console.error(`Fehler beim Starten des Scanners: ${err}`); 2542 if (err.toString().toLowerCase().includes('permission')) { 2543 presentToast(translate['ATTACHMENT']['WEB_PICUTRE_NO_PERMISSION'], 'fa-triangle-exclamation', 'warning'); 2544 } else { 2545 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'danger'); 2546 } 2547 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 2548 try { 2549 await closeWebQr(); 2550 var messageObj = { function: 'scanQR' }; 2551 var stringifiedMessageObj = JSON.stringify(messageObj); 2552 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 2553 resolve(await getQRFromApp()); 2554 } catch (error) { 2555 console.error(error); 2556 } 2557 } else { 2558 closeWebQr(); 2559 } 2560 } 2561 }); 2562} 2563$(document).on('click', '.close-webqr', function (e) { 2564 closeWebQr(); 2565}); 2566function beep() { 2567 let snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2
2567cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXb
2567VRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU="); 2568 snd.play(); 2569} 2570async function closeWebQr(anim = true) { 2571 if (anim) 2572 await hidePopUp($('#webqr-popup')); 2573 if (qrScannerActive) { 2574 window.QrScanner.stop(); 2575 qrScannerActive = false; 2576 } 2577 $('#webqr-popup').remove(); 2578} 2579async function getQRFromApp() { 2580 return new Promise(async (resolve, reject) => { 2581 let qr_code = $('html').attr('data-qr'); 2582 let error = $('html').attr('data-error'); 2583 if ((qr_code !== '' && qr_code !== undefined) || (error !== '' && error !== undefined)) { 2584 if (qr_code !== '' && qr_code !== undefined) { 2585 $('html').attr('data-qr', ''); 2586 resolve(qr_code); 2587 } else if (error !== '' && error !== undefined) { 2588 $('html').attr('data-error', ''); 2589 console.log(error); 2590 let errorMessage = translate['NFC_QR'][error]; 2591 if (errorMessage == undefined) { 2592 resolve(await openWebQr()); 2593 } else { 2594 presentToast(errorMessage, 'fa-triangle-exclamation', 'warning'); 2595 } 2596 resolve(''); 2597 } 2598 } else { 2599 setTimeout(async () => { 2600 resolve(await getQRFromApp()); 2601 }, 300); 2602 } 2603 }); 2604} 2605// END - QR 2606 2607// ATTACHMENT 2608let pdfDoc = null; 2609let pdfViewer = null; 2610let eventBus = null; 2611let linkService = null; 2612let currentScale = 1; // wird nach pagesinit gesetzt 2613let minScale = 1; // min Zoom = volle Breite 2614let currentPage = 1; 2615 2616// Ãffnet Base64-PDF 2617async function openBase64Pdf(base64) { 2618 const base64Data = base64.split(',')[1]; 2619 const pdfBytes = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0)); 2620 2621 const loadingTask = pdfjsLib.getDocument({ data: pdfBytes }); 2622 pdfDoc = await loadingTask.promise; 2623 2624 eventBus = new pdfjsViewer.EventBus(); 2625 linkService = new pdfjsViewer.PDFLinkService({ eventBus }); 2626 2627 pdfViewer = new pdfjsViewer.PDFViewer({ 2628 container: document.getElementById('viewerContainer'), 2629 viewer: document.getElementById('pdfViewer'), 2630 eventBus: eventBus, 2631 linkService: linkService 2632 }); 2633 2634 linkService.setViewer(pdfViewer); 2635 pdfViewer.setDocument(pdfDoc); 2636 linkService.setDocument(pdfDoc, null); 2637 2638 // Vollbreite erst nach Seiteninitialisierung 2639 eventBus.on('pagesinit', function () { 2640 pdfViewer.currentPageNumber = currentPage; 2641 pdfViewer.currentScaleValue = 'page-fit'; // volle Breite 2642 currentScale = pdfViewer.currentScale; 2643 minScale = currentScale; // minScale merken 2644 $('#pageNumber').val(currentPage); 2645 }); 2646 2647 $.scrollLock(true); 2648 $('#popup-pdf').fadeIn(300); 2649} 2650 2651// Toolbar Zoom 2652$('#zoomIn').click(() => { 2653 currentScale = Math.min(currentScale + 0.2, 5); 2654 pdfViewer.currentScale = currentScale; 2655}); 2656 2657$('#zoomOut').click(() => { 2658 currentScale = Math.max(currentScale - 0.2, minScale); 2659 pdfViewer.currentScale = currentScale; 2660}); 2661if ($('#viewerContainer').length > 0) { 2662 const container = document.getElementById('viewerContainer'); 2663 // Touch-Pinch Zoom 2664 let lastDistance = null; 2665 let pinchCenterStart = null; 2666 let pinchZoomRAF = null; 2667 let startScroll = null; 2668 2669 container.addEventListener('touchstart', function (e) { 2670 if (e.touches.length === 2) { 2671 const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2; 2672 const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2; 2673 pinchCenterStart = { x: midX, y: midY }; 2674 startScroll = { left: container.scrollLeft, top: container.scrollTop }; 2675 } 2676 }); 2677 2678 container.addEventListener('touchmove', function (e) { 2679 if (e.touches.length === 2 && pinchCenterStart && startScroll) { 2680 e.preventDefault(); 2681 const dx = e.touches[0].clientX - e.touches[1].clientX; 2682 const dy = e.touches[0].clientY - e.touches[1].clientY; 2683 const distance = Math.sqrt(dx * dx + dy * dy); 2684 2685 if (lastDistance) { 2686 const delta = (distance - lastDistance) * 0.0015; 2687 const oldScale = currentScale; 2688 currentScale += delta; 2689 currentScale = Math.max(minScale, Math.min(5, currentScale)); 2690 2691 if (!pinchZoomRAF) { 2692 pinchZoomRAF = requestAnimationFrame(() => { 2693 pdfViewer.currentScale = currentScale; 2694 const rect = container.getBoundingClientRect(); 2695 const offsetX = pinchCenterStart.x - rect.left; 2696 const offsetY = pinchCenterStart.y - rect.top; 2697 container.scrollLeft = startScroll.left + (offsetX * (currentScale / oldScale - 1)); 2698 container.scrollTop = startScroll.top + (offsetY * (currentScale / oldScale - 1)); 2699 pinchZoomRAF = null; 2700 }); 2701 } 2702 } 2703 lastDistance = distance; 2704 } 2705 }); 2706 2707 container.addEventListener('touchend', function (e) { 2708 if (e.touches.length < 2) { 2709 lastDistance = null; 2710 pinchCenterStart = null; 2711 startScroll = null; 2712 if (pinchZoomRAF) cancelAnimationFrame(pinchZoomRAF); 2713 pinchZoomRAF = null; 2714 } 2715 }); 2716 2717 // Trackpad / Ctrl+Wheel Zoom 2718 let wheelZoomRAF = null; 2719 2720 container.addEventListener('wheel', function (e) { 2721 if (e.ctrlKey) { 2722 e.preventDefault(); 2723 2724 const rect = container.getBoundingClientRect(); 2725 const offsetX = e.clientX - rect.left + container.scrollLeft; 2726 const offsetY = e.clientY - rect.top + container.scrollTop; 2727 2728 const oldScale = currentScale; 2729 currentScale += e.deltaY * -0.0025; // kleiner = sanfter 2730 currentScale = Math.max(minScale, Math.min(5, currentScale)); 2731 2732 // Verzögertes Update über requestAnimationFrame 2733 if (!wheelZoomRAF) { 2734 wheelZoomRAF = requestAnimationFrame(() => { 2735 pdfViewer.currentScale = currentScale; 2736 2737 const scaleRatio = currentScale / oldScale; 2738 container.scrollLeft = offsetX * scaleRatio - (e.clientX - rect.left); 2739 container.scrollTop = offsetY * scaleRatio - (e.clientY - rect.top); 2740 2741 wheelZoomRAF = null; 2742 }); 2743 } 2744 } 2745 }); 2746} 2747// Close Button 2748$('#popup-pdf .close').click(() => { 2749 $('#popup-pdf').fadeOut(300).promise().done(function () { 2750 if (pdfViewer) { 2751 pdfViewer.cleanup(); 2752 pdfViewer = null; 2753 } 2754 }) 2755 $.scrollLock(false); 2756}); 2757$(document).on('click', '.preview-attachment-in-lightbox', async function () { 2758 2759 let href = $(this).data('href'); 2760 if (typeof href == "undefined") { 2761 let images = $(this).data('images') 2762 if (images) { 2763 images = images.split('#'); 2764 let imageDatas = [];
2765 images.forEach(function (src, index) { 2766 imageDatas.push({ src: src, thumb: src }); 2767 }); 2768 lg = $(this).get(0); 2769 const dynamicGallery = lightGallery(lg, { download: !($('html').data('plt-android') || $('html').data('plt-ios')), dynamic: true, dynamicEl: imageDatas }); 2770 } 2771 } else { 2772 await showLoading(); 2773 $.ajax({ 2774 url: href + '&for_ajax=1', 2775 success: async function (result) { 2776 try { 2777 let data = JSON.parse(result); 2778 if (data && data.base64) { 2779 await openBase64Pdf(data.base64); 2780 } 2781 } catch (err) { 2782 console.error(err); 2783 } finally { 2784 await hideLoading(); 2785 } 2786 }, 2787 error: function (err) { console.error(err); } 2788 }); 2789 } 2790}); 2791function addFilesToList(files) { 2792 let indexItem = $('#my-drop-container .upload-item').length; 2793 Array.prototype.forEach.call(files, async (file, index) => { 2794 try { 2795 let base64 = await readFileAsync(file); 2796 let re = /(?:\.([^.]+))?$/; 2797 let filename_extension = re.exec(file.name)[1]; 2798 let grid = document.createElement('div'); 2799 grid.className = 'grid-container upload-item'; 2800 let wrapperImage = document.createElement('div'); 2801 wrapperImage.className = 'wrapper-images'; 2802 let wrapperGridValues = document.createElement('div'); 2803 wrapperGridValues.className = 'wrapper-values'; 2804 let gridValues = document.createElement('div'); 2805 gridValues.className = 'grid-container'; 2806 let wrapperName = document.createElement('div'); 2807 wrapperName.className = 'col-12'; 2808 let wrapperFilename = document.createElement('div'); 2809 wrapperFilename.className = 'col-12'; 2810 let wrapperInfo = document.createElement('div'); 2811 wrapperInfo.className = 'my-attachment-infos'; 2812 2813 let wrapperInfoFileSize = document.createElement('div'); 2814 wrapperInfoFileSize.className = 'filesize'; 2815 wrapperInfoFileSize.innerHTML = '<i class="fa-solid fa-database"></i> ' + humanFileSize(file.size); 2816 wrapperInfo.appendChild(wrapperInfoFileSize); 2817 2818 let wrapperInfoFileType = document.createElement('div'); 2819 wrapperInfoFileType.className = 'filetype'; 2820 wrapperInfoFileType.innerHTML = '<i class="fa-solid fa-file-circle-question"></i> ' + file.type; 2821 wrapperInfo.appendChild(wrapperInfoFileType); 2822 2823 if (["image/jpeg", "image/gif", "image/png", "image/jpg"].includes(file.type)) { 2824 let i = new Image(); 2825 i.onload = function () { 2826 let wrapperInfoImageSize = document.createElement('div'); 2827 wrapperInfoImageSize.className = 'imagesize'; 2828 wrapperInfoImageSize.innerHTML = '<i class="fa-solid fa-up-right-and-down-left-from-center"></i> ' + i.width + " x " + i.height + ' px'; 2829 wrapperInfo.appendChild(wrapperInfoImageSize); 2830 }; 2831 i.src = base64; 2832 } 2833 2834 let thumbnail = document.createElement('div'); 2835 thumbnail.className = 'thumbnail'; 2836 let thumbnailChess = document.createElement('div'); 2837 thumbnailChess.className = 'chess'; 2838 let thumbnailBgImg = document.createElement('div'); 2839 thumbnailBgImg.className = 'bg-img'; 2840 let loadingSvg = document.createElementNS("http://www.w3.org/2000/svg", 'svg'); 2841 loadingSvg.style.height = '100%'; 2842 loadingSvg.style.width = '100%'; 2843 loadingSvg.setAttribute("viewBox", "0 0 25 25"); 2844 2845 let loadingSvgPath = document.createElementNS("http://www.w3.org/2000/svg", 'path'); 2846 loadingSvgPath.setAttribute("fill", "none"); 2847 loadingSvgPath.setAttribute("d", "M0 0 25 0 25 25 0 25 Z"); 2848 if (file.type.includes("image/")) { 2849 thumbnailBgImg.style.backgroundImage = "url('" + base64 + "')"; 2850 } else if (file.type.includes("video/")) { 2851 thumbnailBgImg.innerHTML = '<i class="fa-solid fa-video"></i>'; 2852 } else if (file.type.includes("application/pdf")) { 2853 thumbnailBgImg.innerHTML = '<i class="fa-solid fa-file-pdf"></i>'; 2854 } else if (file.type.includes("application/zip")) { 2855 thumbnailBgImg.innerHTML = '<i class="fa-solid fa-file-zipper"></i>'; 2856 } else { 2857 thumbnailBgImg.innerHTML = '<i class="fa-solid fa-file"></i>'; 2858 }
2859 thumbnailChess.appendChild(thumbnailBgImg); 2860 loadingSvg.appendChild(loadingSvgPath); 2861 thumbnailChess.appendChild(loadingSvg); 2862 thumbnail.appendChild(thumbnailChess); 2863 wrapperImage.appendChild(thumbnail); 2864 2865 let inputName = document.createElement('div'); 2866 inputName.className = 'col-12'; 2867 let inputNameMyInput = document.createElement('div'); 2868 inputNameMyInput.className = 'my-input with-icon'; 2869 let inputNameInputContainer = document.createElement('div'); 2870 inputNameInputContainer.className = 'input-container'; 2871 let inputNameInputError = document.createElement('div'); 2872 inputNameInputError.className = 'input-error'; 2873 inputNameInputError.setAttribute('data-error1', translate["ATTACHMENT"]["ERROR"]["NAME"]); 2874 let inputNameInput = document.createElement('input'); 2875 inputNameInput.type = "text"; 2876 inputNameInput.setAttribute('maxlength', "150"); 2877 inputNameInput.setAttribute('name', "name_" + indexItem); 2878 inputNameInput.setAttribute('id', "name_" + indexItem); 2879 inputNameInput.value = file.name.replace(/\.[^/.]+$/, "").replaceAll('_', ' ').replaceAll('-', ' '); 2880 let inputNameLabel = document.createElement('label'); 2881 inputNameLabel.setAttribute('for', "name_" + indexItem); 2882 inputNameLabel.innerHTML = translate["ATTACHMENT"]["NAME"]; 2883 let inputNameIcon = document.createElement('i'); 2884 inputNameIcon.className = 'fa-solid fa-signature'; 2885 2886 inputName.appendChild(inputNameMyInput); 2887 inputNameMyInput.appendChild(inputNameInputContainer); 2888 inputNameMyInput.appendChild(inputNameInputError); 2889 inputNameInputContainer.appendChild(inputNameInput); 2890 inputNameInputContainer.appendChild(inputNameLabel); 2891 inputNameInputContainer.appendChild(inputNameIcon); 2892 2893 let inputFileName = document.createElement('div'); 2894 inputFileName.className = 'col-12'; 2895 let inputFileNameMyInput = document.createElement('div'); 2896 inputFileNameMyInput.className = 'my-input with-icon'; 2897 let inputFileNameInputContainer = document.createElement('div'); 2898 inputFileNameInputContainer.className = 'input-container'; 2899 let inputFileNameInputError = document.createElement('div'); 2900 inputFileNameInputError.className = 'input-error'; 2901 inputFileNameInputError.setAttribute('data-error1', translate["ATTACHMENT"]["ERROR"]["NAME"]); 2902 let inputFileNameInput = document.createElement('input'); 2903 inputFileNameInput.type = "text"; 2904 inputFileNameInput.setAttribute('maxlength', "150"); 2905 inputFileNameInput.setAttribute('name', "filename_" + indexItem); 2906 inputFileNameInput.setAttribute('id', "filename_" + indexItem); 2907 inputFileNameInput.value = secureFileName(file.name); 2908 let inputFileNameLabel = document.createElement('label'); 2909 inputFileNameLabel.setAttribute('for', "filename_" + indexItem); 2910 inputFileNameLabel.innerHTML = translate["ATTACHMENT"]["FILENAME"]; 2911 let inputFileNameIcon = document.createElement('i'); 2912 inputFileNameIcon.className = 'fa-solid fa-file'; 2913 2914 inputFileName.appendChild(inputFileNameMyInput); 2915 inputFileNameMyInput.appendChild(inputFileNameInputContainer); 2916 inputFileNameMyInput.appendChild(inputFileNameInputError); 2917 inputFileNameInputContainer.appendChild(inputFileNameInput); 2918 inputFileNameInputContainer.appendChild(inputFileNameLabel); 2919 inputFileNameInputContainer.appendChild(inputFileNameIcon); 2920 2921 let removeEl = document.createElement('div'); 2922 removeEl.className = 'remove-item'; 2923 let removeElI = document.createElement('i'); 2924 removeElI.className = 'fa-solid fa-times'; 2925 2926 let base64Input = document.createElement('input'); 2927 base64Input.setAttribute('type', 'hidden'); 2928 base64Input.setAttribute('name', 'base64_' + indexItem); 2929 base64Input.value = base64; 2930 2931 let fileextensionInput = document.createElement('input'); 2932 fileextensionInput.setAttribute('type', 'hidden'); 2933 fileextensionInput.setAttribute('name', 'file_extension_' + indexItem); 2934 fileextensionInput.value = filename_extension; 2935 2936 removeEl.appendChild(removeElI); 2937 grid.appendChild(fileextensionInput); 2938 grid.appendChild(base64Input); 2939 grid.appendChild(wrapperImage); 2940 grid.appendChild(wrapperGridValues); 2941 grid.appendChild(removeEl); 2942 wrapperGridValues.appendChild(gridValues); 2943 gridValues.appendChild(wrapperName); 2944 wrapperName.appendChild(inputName); 2945 gridValues.appendChild(wrapperFilename); 2946 wrapperFilename.appendChild(inputFileName); 2947 gridValues.appendChild(wrapperInfo); 2948 2949 if (file.size >= publicConsts['MAX_FILE_SIZE']) { 2950 let overlayError = document.createElement('div'); 2951 overlayError.className = 'overlay-error'; 2952 let overlayErrorInner = document.createElement('div'); 2953 overlayErrorInner.className = 'overlay-error-inner'; 2954 overlayErrorInner.innerText = translate['ATTACHMENT']['ER
2954ROR']['MAX_FILE_SIZE'] + ' ' + humanFileSize(publicConsts['MAX_FILE_SIZE']); 2955 wrapperGridValues.appendChild(overlayError); 2956 overlayError.appendChild(overlayErrorInner); 2957 grid.className = 'grid-container upload-item uploaderror'; 2958 } 2959 if (!["image/jpeg", "image/gif", "image/png", "image/jpg", "application/pdf"].includes(file.type)) { 2960 let overlayError = document.createElement('div'); 2961 overlayError.className = 'overlay-error'; 2962 let overlayErrorInner = document.createElement('div'); 2963 overlayErrorInner.className = 'overlay-error-inner'; 2964 overlayErrorInner.innerText = translate['ATTACHMENT']['WRONG_FILE_TYPE']; 2965 wrapperGridValues.appendChild(overlayError); 2966 overlayError.appendChild(overlayErrorInner); 2967 grid.className = 'grid-container upload-item uploaderror'; 2968 } 2969 2970 $('#my-drop-container .attachment-file-list').append(grid); 2971 2972 if ($('#my-drop-container .upload-item').length > 0) { 2973 $('#remove_all_items').removeClass('hide-me'); 2974 } else { 2975 $('#remove_all_items').addClass('hide-me'); 2976 } 2977 } catch (err) { 2978 console.log(err); 2979 } 2980 }); 2981} 2982$(document).on('click', '#my-drop-container .upload-item .remove-item', function () { 2983 $(this).parents('.upload-item').remove(); 2984 if ($('#my-drop-container .upload-item').length > 0) { 2985 $('#remove_all_items').removeClass('hide-me'); 2986 } else { 2987 $('#remove_all_items').addClass('hide-me'); 2988 } 2989}); 2990let onUpload = false; 2991$('#upload_now').click(async function () { 2992 if (!onUpload) { 2993 onUpload = true; 2994 let error = false; 2995 let index = 0; 2996 while ($('#my-drop-container .upload-item').get(index) !== undefined) { 2997 let myItem = $($('#my-drop-container .upload-item').get(index)); 2998 if (myItem.find('input[name^="name"]').val().trim().length <= 0) { 2999 let inputEl = myItem.find('input[name^="name"]'); 3000 let inputWrapperEl = inputEl.parents('.my-input'); 3001 inputWrapperEl.addClass('error'); 3002 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 3003 if (!error) 3004 inputEl.focus(); 3005 error = true; 3006 } 3007 if (myItem.find('input[name^="filename"]').val().trim().length <= 0) { 3008 let inputEl = myItem.find('input[name^="filename"]'); 3009 let inputWrapperEl = inputEl.parents('.my-input'); 3010 inputWrapperEl.addClass('error'); 3011 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 3012 if (!error) 3013 inputEl.focus(); 3014 error = true; 3015 } 3016 index++; 3017 } 3018 if (!error) { 3019 index = 0; 3020 while ($('#my-drop-container .upload-item').get(index) !== undefined) { 3021 let myItem = $($('#my-drop-container .upload-item').get(index)); 3022 if (!myItem.hasClass('uploaded') && !myItem.hasClass('uploaderror')) { 3023 if (index == 0) { 3024 scrollToEl(myItem); 3025 } 3026 await uploadFile(myItem); 3027 } 3028 index++; 3029 } 3030 } 3031 onUpload = false; 3032 } else { 3033 scrollToEl($('#my-drop-container .upload-item:not(.uploaded)')); 3034 } 3035}); 3036$('#remove_all_items').click(function () { 3037 $('#my-drop-container .upload-item').remove(); 3038}); 3039 3040function uploadFile(item) { 3041 return new Promise((resolve, reject) => { 3042 $(window).scrollTop(item.offset().top - $('.gap-top').height() - 50); 3043 let base64 = item.find('input[name^="base64"]').val(); 3044 let name = item.find('input[name^="name"]').val(); 3045 let filename = item.find('input[name^="filename"]').val(); 3046 let type = $('#my-drop-container').data('type'); 3047 let parent_id = $('#my-drop-container').data('parent_id'); 3048 $.ajax({ 3049 xhr: function () { 3050 let xhr = new window.XMLHttpRequest(); 3051 xhr.upload.addEventListener("progress", function (evt) { 3052 if (evt.lengthComputable) { 3053 let percentComplete = 100 - (evt.loaded / evt.total) * 100; 3054 item.css('--uploadPercentage', percentComplete); 3055 } 3056 }, false); 3057 return xhr; 3058 }, 3059 type: 'POST', 3060 url: 'uploadfile', 3061 data: { 3062 base64: base64, 3063 name: name, 3064 filename: filename, 3065 parent_id: parent_id, 3066 type: type 3067 }, 3068 cache: false, 3069 success: function (result) { 3070 try { 3071 let data = JSON.parse(result); 3072 if (typeof data === 'object') { 3073 if (data.done) { 3074 item.addClass('uploaded'); 3075 } else { 3076 item.addClass('uploaderror'); 3077 let overlayError = document.createElement('div'); 3078 overlayError.className = 'overlay-error'; 3079 let overlayErrorInner = document.createElement('div'); 3080 overlayErrorInner.className = 'overlay-error-inner'; 3081 overlayErrorInner.innerHTML = data.error; 3082 overlayError.appendChild(overlayErrorInner); 3083 item.find('.wrapper-values').append(overlayError); 3084 } 3085 } else { 3086 if (result == 'NO_RIGHTS') { 3087 presentToast(translate['NO_RIGTHS']["ERROR"]["NO_RIGHTS"], 'fa-triangle-exclamation', 'warning'); 3088 } else { 3089 console.log(data); 3090 } 3091 } 3092 } catch (err) { 3093 if (result == 'NO_RIGHTS') { 3094 presentToast(translate['NO_RIGTHS']["ERROR"]["NO_RIGHTS"], 'fa-triangle-exclamation', 'warning'); 3095 } else { 3096 console.log(err, result) 3097 } 3098 } 3099 resolve(true); 3100 }, 3101 }); 3102 }); 3103} 3104$(document).on('input', '#my-drop-container input[name*="filename"], #editattachment input[name="filenmae"]', function () { 3105 $(this).val(secureFileName($(this).val(), false)); 3106}) 3107$(document).on('blur', '#my-drop-container input[name*="filename"], #editattachment input[name="filenmae"]', function () { 3108 $(this).val(secureFileName($(this).val(), true)); 3109}) 3110function secureFileName(name, withDefault = true) { 3111 name = name.replace(/\.[^/.]+$/g, ""); 3112 name = name.replaceAll('ä', 'ae'); 3113 name = name.replaceAll('.', '-'); 3114 name = name.replaceAll('Ã', 'ae'); 3115 name = name.replaceAll('ö', 'oe'); 3116 name = name.replaceAll('Ã', 'oe'); 3117 name = name.replaceAll('ü', 'ue'); 3118 name = name.replaceAll('Ã', 'ue'); 3119 name = name.replaceAll('Ã', 'ss'); 3120 name = name.replaceAll(' ', '-'); 3121 name = name.replace(/([\s])\1+/g, '-'); 3122 name = name.replace(/[^A-Za-z0-9_\- ]/g, ''); 3123 while (name.includes('--')) { 3124 name = name.replaceAll('--', '-'); 3125 } 3126 name = name.toLocaleLowerCase(); 3127 name = name.substring(0, 150); 3128 if (withDefault) 3129 name = (name.length == 0) ? 'file' : name; 3130 return name; 3131} 3132if ($("#my-drop-container").length > 0) { 3133 initDragAndDrop(); 3134} 3135async function initDragAndDrop(targetEL = null) { 3136 return new Promise((resolve, reject) => { 3137 3138 $(document).on("dragenter", "#my-drop-container", function (e) { 3139 e.preventDefault(); 3140 e.stopPropagation(); 3141 $(this).addClass('drag-over'); 3142 }); 3143 $(document).on("dragleave", "#my-drop-container", function (e) { 3144 e.preventDefault(); 3145 e.stopPropagation(); 3146 $(this).removeClass('drag-over'); 3147 }); 3148 $("body").on("drop dragdrop", "#my-drop-container", async function (e) { 3149 e.stopPropagation(); 3150 e.preventDefault(); 3151 $(this).removeClass('drag-over'); 3152 let file = e.originalEvent.dataTransfer.files[0]; 3153 if (targetEL !== null) { 3154 resolve(await changeFileImgValue(file, targetEL)); 3155 } else { 3156 addFilesToList(e.originalEvent.dataTransfer.files); 3157 } 3158 }); 3159 $(document).on("change", '#my-drop-container input[type="file"]', async function (e) {
3160 let $this = $(this); 3161 let file = $this[0].files[0]; 3162 if (targetEL !== null) { 3163 resolve(await changeFileImgValue(file, targetEL)); 3164 } else { 3165 addFilesToList($this[0].files); 3166 } 3167 }); 3168 }); 3169} 3170function readFileAsync(file) { 3171 return new Promise((resolve, reject) => { 3172 let reader = new FileReader(); 3173 reader.onload = () => { 3174 resolve(reader.result); 3175 }; 3176 reader.onerror = reject; 3177 reader.readAsDataURL(file); 3178 }); 3179} 3180function humanFileSize(bytes, si = false, dp = 2) { 3181 const thresh = si ? 1000 : 1024; 3182 if (Math.abs(bytes) < thresh) { 3183 return bytes + ' B'; 3184 } 3185 const units = si 3186 ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] 3187 : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; 3188 let u = -1; 3189 const r = 10 ** dp; 3190 do { 3191 bytes /= thresh; 3192 ++u; 3193 } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1); 3194 3195 return (bytes.toFixed(dp) + ' ' + units[u]).replace('.', ','); 3196} 3197$("html").on("drop", function (e) { 3198 e.preventDefault(); 3199 e.stopPropagation(); 3200}); 3201$("html").on("dragover", function (e) { 3202 e.preventDefault(); 3203 e.stopPropagation(); 3204}); 3205 3206$(document).on('click', '#select-popup .clear-search', function (e) { 3207 $(this).parents('.my-input').find('input[type="search"]').val(''); 3208 let allElements = $('#select-popup .elements .element'); 3209 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#select-popup .elements"); 3210 $('#select-popup .popup-body').animate({ 3211 scrollTop: 0 3212 }, 200); 3213 if (!isTouchDevice()) { 3214 $(this).parents('.my-input').find('input[type="search"]').focus(); 3215 } 3216}); 3217$(document).on('input', '#select-popup #search', function (e) { 3218 const val = $(this).val().toLowerCase(); 3219 let allElements = $('#select-popup .elements .element'); 3220 if (val.length > 0) { 3221 allElements.each((idx, el) => { 3222 const name = $(el).find('.name').text().toLowerCase(); 3223 if (name.includes(val)) { 3224 $(el).attr('data-order', 0); 3225 } else { 3226 $(el).attr('data-order', levenshteinDistance(val, name)); 3227 } 3228 }); 3229 allElements.sort((a, b) => $(a).attr("data-order") - $(b).attr("data-order")).appendTo("#select-popup .elements"); 3230 } else { 3231 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#select-popup .elements"); 3232 } 3233 $('#select-popup .popup-body').animate({ 3234 scrollTop: 0 3235 }, 200); 3236}) 3237// END-RESOURCES 3238// IMAGE 3239async function getImage(targetEL, onlySvg = false) { 3240 return new Promise((resolve, reject) => { 3241 let onlySvg = targetEL.hasClass('only-svg'); 3242 let buttons = []; 3243 if (!onlySvg) { 3244 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 3245 buttons.push({ 3246 icon: '<i class="fa-solid fa-camera"></i>', 3247 text: translate['ATTACHMENT']['TAKE_PHOTO'], 3248 style: 'default', 3249 handler: async () => { 3250 closeMyActionSheet($('#image-action-sheet')); 3251 resolve(await takeImageWithCamera(targetEL)); 3252 } 3253 }); 3254 } else { 3255 try { 3256 if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { 3257 buttons.push({ 3258 icon: '<i class="fa-solid fa-camera"></i>', 3259 text: translate['ATTACHMENT']['TAKE_PHOTO'], 3260 style: 'default', 3261 handler: async () => { 3262 closeMyActionSheet($('#image-action-sheet')); 3263 resolve(await takeImageWithCamera(targetEL)); 3264 } 3265 }); 3266 } 3267 } catch (error) { } 3268 } 3269 } else { 3270 buttons.push({ 3271 icon: '<i class="fa-solid fa-cloud"></i>', 3272 text: translate['ATTACHMENT']['SELECT_ON_SERVER'], 3273 style: 'default', 3274 handler: async () => { 3275 closeMyActionSheet($('#image-action-sheet')); 3276 resolve(await getSVGFromServer(targetEL)); 3277 } 3278 }); 3279 } 3280 3281 buttons.push({ 3282 icon: '<i class="fa-solid fa-image"></i>', 3283 text: translate['ATTACHMENT']['SELECT_ON_DEVICE'], 3284 style: 'default', 3285 handler: async () => { 3286 closeMyActionSheet($('#image-action-sheet')); 3287 resolve(await getImageFromDevice(targetEL, onlySvg)); 3288 } 3289 }); 3290 // Bild löschen 3291 buttons.push({
3292 icon: '<i class="fa-solid fa-trash"></i>', 3293 text: translate['ATTACHMENT']['DELETE_IMAGE'], 3294 style: 'default', 3295 handler: (e) => { 3296 closeMyActionSheet($('#image-action-sheet')); 3297 resolve('remove'); 3298 } 3299 }); 3300 // Abbrechen 3301 buttons.push({ 3302 icon: '<i class="fa-solid fa-ban"></i>', 3303 text: translate['DISMISS'], 3304 style: 'default', 3305 handler: () => { 3306 closeMyActionSheet($('#image-action-sheet')); 3307 resolve(null); 3308 } 3309 }); 3310 myActionSheet(translate['ATTACHMENT']['CHANGE_IMAGE'], 'image-action-sheet', buttons); 3311 }); 3312} 3313async function getSVGFromServer(targetEL) { 3314 return new Promise(async (resolve, reject) => { 3315 await getAjaxPopUp('getsvgfromserver'); 3316 $('#svg-from-server-popup #confirm-svg-icon').click(async function (e) { 3317 let icon = $('#svg-from-server-popup input[name="icon"]:checked').val(); 3318 if (icon) { 3319 let svg = await getSVG(icon); 3320 let base64 = "data:image/svg+xml;base64," + window.btoa(svg); 3321 $('#svg-from-server-popup').find('.close-and-remove-popup').trigger('click'); 3322 resolve(base64); 3323 } else { 3324 presentToast(translate['MODEL_CATEGORY']['ERROR']['IMAGE'], 'fa-triangle-exclamation', 'warning'); 3325 } 3326 }); 3327 myActionSheet(translate['ATTACHMENT']['CHANGE_IMAGE'], 'image-action-sheet', buttons); 3328 }); 3329} 3330async function takeImageWithCamera(targetEL) { 3331 return new Promise(async (resolve, reject) => { 3332 if ($('html').data('memory-full')) { 3333 getAjaxPopUp('nomemoryleft'); 3334 } else { 3335 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 3336 try { 3337 var messageObj = { function: 'takeImage' }; 3338 var stringifiedMessageObj = JSON.stringify(messageObj); 3339 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 3340 resolve(await getImageFromApp(targetEL)); 3341 } catch (error) { 3342 resolve(null); 3343 } 3344 } else { 3345 // Browser 3346 await getAjaxPopUp('getcamerapopup'); 3347 resolve(await getImageFromCamera(targetEL)); 3348 } 3349 } 3350 }); 3351} 3352async function getImageFromDevice(targetEL, onlySvg = false) { 3353 return new Promise(async (resolve, reject) => { 3354 if ($('html').data('memory-full')) { 3355 getAjaxPopUp('nomemoryleft'); 3356 } else { 3357 if (($('html').data('plt-android') || $('html').data('plt-ios')) && !onlySvg) { 3358 try { 3359 var messageObj = { function: 'takeImageFromLibrary' }; 3360 var stringifiedMessageObj = JSON.stringify(messageObj); 3361 webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj); 3362 resolve(await getImageFromApp(targetEL)); 3363 } catch (error) { 3364 resolve(null); 3365 } 3366 } else { 3367 await getAjaxPopUp('getuploadimagepopup', { onlySvg: onlySvg }); 3368 resolve(await initDragAndDropImg(targetEL, onlySvg)); 3369 } 3370 } 3371 }); 3372} 3373 3374let myVideo; 3375function getImageFromCamera(targetEL) { 3376 return new Promise((resolve, reject) => { 3377 myVideo = document.getElementById('myVideoStreamForCamera'); 3378 let myCanvas = document.getElementById('myCanvasForCamera'); 3379 let myImage = document.getElementById('myPrevImage'); 3380 let popup = $('#myVideoStreamForCamera').parents('.my-popup'); 3381 try { 3382 if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { 3383 navigator.mediaDevices.getUserMedia({ video: { width: { min: 1280 }, height: { min: 720 } }, audio: false }).then(stream => { 3384 myVideo.srcObject = stream; 3385 popup.find('#take-picture').removeClass('hide-me'); 3386 $(document).on('click', ('#' + popup.attr('id') + ' #take-picture'), function (e) { 3387 myCanvas.width = myVideo.videoWidth; 3388 myCanvas.height = myVideo.videoHeight; 3389 myCanvas.getContext("2d").drawImage(myVideo, 0, 0); 3390 popup.find('#take-picture').addClass('hide-me'); 3391 popup.find('#retake-picture').removeClass('hide-me'); 3392 popup.find('#rotate-picture').removeClass('hide-me'); 3393 popup.find('#confirm-image').removeClass('hide-me'); 3394 let image = myCanvas.toDataURL('image/png'); 3395 popup.find('.video-wrapper').addClass('hide-me'); 3396 popup.find('.cropper-wrapper').removeClass('hide-me'); 3397 myImage.src = image; 3398 myImage.onload = async function () { 3399 resolve(await initCropper(myImage, targetEL)); 3400 }; 3401 }); 3402 }).catch(err => { 3403 if (err.toString().toLowerCase().includes('permission')) { 3404 presentToast(translate['ATTACHMENT']['WEB_PICUTRE_NO_PERMISSION'], 'fa-triangle-exclamation', 'warning'); 3405 } else { 3406 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'danger'); 3407 } 3408 closePhotoPopUp(); 3409 resolve(null); 3410 }); 3411 } else { 3412 presentToast(translate['ATTACHMENT']['WEB_PICUTRE_NOT_SUPPORTED'], 'fa-ban', 'warning'); 3413 closePhotoPopUp(); 3414 resolve(null); 3415 } 3416 } catch (error) { 3417 presentToast(translate['ATTACHMENT']['WEB_PICUTRE_NOT_SUPPORTED'], 'fa-ban', 'warning'); 3418 closePhotoPopUp(); 3419 resolve(null); 3420 } 3421 }); 3422} 3423 3424$(document).on('click', '.close-camera-popup', function (e) { 3425 closePhotoPopUp(); 3426}); 3427async function closePhotoPopUp(popup = null) { 3428 if (popup == null) { 3429 popup = $('#myVideoStreamForCamera').parents('.my-popup'); 3430 } 3431 await hidePopUp(popup); 3432 popup.remove(); 3433 if (myVideo) {
3434 myVideo.srcObject.getTracks().forEach(function (track) { 3435 track.stop(); 3436 }); 3437 } 3438} 3439let cropper = null; 3440 3441async function initCropper(myImage, targetEL) { 3442 let ratio = 1; 3443 if (targetEL.data('ratio') !== '' && targetEL.data('ratio') !== undefined) { 3444 ratio = targetEL.data('ratio'); 3445 } 3446 $('.cropper-wrapper').css('--ratio', ratio); 3447 return new Promise((resolve, reject) => { 3448 setTimeout(() => { 3449 let width = myImage.naturalWidth; 3450 let height = myImage.naturalHeight; 3451 let y = width - height; 3452 let x = height - width; 3453 if (y > 0) { 3454 y = y / 2 * -1; 3455 } else { 3456 y = 0; 3457 } 3458 if (x > 0) { 3459 x = x / 2 * -1; 3460 } else { 3461 x = 0; 3462 } 3463 cropper = new Cropper(myImage, { 3464 autoCropArea: 1, 3465 viewMode: 0, 3466 aspectRatio: ratio, 3467 autoCrop: true, 3468 zoomable: false, 3469 movable: false, 3470 minContainerWidth: 100, 3471 minContainerHeight: 100, 3472 data: { 3473 x: x, 3474 y: y, 3475 width: width, 3476 height: height 3477 } 3478 }); 3479 // Handler aus früheren initCropper()-Aufrufen entfernen - sonst 3480 // sammeln sie sich pro Bild an und feuern mehrfach (teils auf 3481 // einen bereits zerstörten Cropper). 3482 $(document).off('click.cropper'); 3483 $(document).on('click.cropper', '#confirm-image', function (e) { 3484 // getCroppedCanvas() liefert null, solange das Bild noch nicht 3485 // geladen ist (ready === false) oder der Cropper zerstört wurde. 3486 if (!cropper || !cropper.ready) { 3487 return; 3488 } 3489 const canvas = cropper.getCroppedCanvas({ 3490 width: 1200 3491 }); 3492 if (!canvas) { 3493 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'danger'); 3494 return; 3495 } 3496 let popup = $(this).parents('.my-popup'); 3497 let image = canvas.toDataURL('image/png'); 3498 closePhotoPopUp(popup); 3499 resolve(image); 3500 }); 3501 $(document).on('click.cropper', '#retake-picture', async function (e) { 3502 let popup = $(this).parents('.my-popup'); 3503 let myCanvas = document.getElementById('myCanvasForCamera'); 3504 if (myCanvas) { 3505 const context = myCanvas.getContext('2d'); 3506 context.clearRect(0, 0, myCanvas.width, myCanvas.height); 3507 popup.find('#take-picture').removeClass('hide-me'); 3508 popup.find('#rotate-picture').addClass('hide-me'); 3509 popup.find('#retake-picture').addClass('hide-me'); 3510 popup.find('#confirm-image').addClass('hide-me'); 3511 popup.find('.video-wrapper').removeClass('hide-me'); 3512 popup.find('.cropper-wrapper').addClass('hide-me'); 3513 } else { 3514 closePhotoPopUp(popup); 3515 resolve(null); 3516 currentImageEl.find('button').trigger('click'); 3517 } 3518 if (cropper) { 3519 cropper.destroy(); 3520 cropper = null; 3521 } 3522 }); 3523 3524 $(document).on('click.cropper', '#rotate-picture', async function (e) { 3525 if (cropper && cropper.ready) { 3526 cropper.rotate(90); 3527 } 3528 }); 3529 $(document).on('click.cropper', '#get-other-picture', function (e) { 3530 let popup = $(this).parents('.my-popup'); 3531 popup.find('#get-other-picture').addClass('hide-me'); 3532 popup.find('#rotate-picture').addClass('hide-me'); 3533 popup.find('#confirm-image').addClass('hide-me'); 3534 popup.find('#my-drop-container').removeClass('hide-me'); 3535 popup.find('.cropper-wrapper').addClass('hide-me'); 3536 if (cropper) { 3537 cropper.destroy(); 3538 cropper = null; 3539 } 3540 }); 3541 }, 100); 3542 3543 }); 3544} 3545async function getImageFromApp(targetEL) { 3546 return new Promise(async (resolve, reject) => { 3547 let image = $('html').attr('data-image'); 3548 let error = $('html').attr('data-error'); 3549 if ((image !== '' && image !== undefined) || (error !== '' && error !== undefined)) { 3550 if (image !== '' && image !== undefined) { 3551 image = image.replace('data:image/png;base64,data:image/png;base64', 'data:image/png;base64'); 3552 await getAjaxPopUp('getcropperpopup'); 3553 $('#cropper-popup #rotate-picture').removeClass('hide-me'); 3554 $('#cropper-popup #retake-picture').removeClass('hide-me'); 3555 $('#cropper-popup #confirm-image').removeClass('hide-me'); 3556 $('#cropper-popup .cropper-wrapper').removeClass('hide-me'); 3557 $('html').attr('data-image', ''); 3558 let myImage = document.getElementById('myimage'); 3559 myImage.src = image; 3560 myImage.onload = async function () { 3561 resolve(await initCropper(myImage, targetEL)); 3562 } 3563 } else if (error !== '') { 3564 $('html').attr('data-error', ''); 3565 presentToast(translate['ATTACHMENT'][error], 'fa-triangle-exclamation', 'warning'); 3566 } 3567 } else { 3568 setTimeout(async () => { 3569 resolve(await getImageFromApp(targetEL)); 3570 }, 300); 3571 } 3572 }); 3573} 3574async function initDragAndDropImg(targetEL, onlySvg = false) { 3575 return new Promise((resolve, reject) => { 3576 3577 $(document).on("dragenter", "#my-drop-container", function (e) { 3578 e.preventDefault(); 3579 e.stopPropagation(); 3580 $(this).addClass('drag-over'); 3581 }); 3582 $(document).on("dragleave", "#my-drop-container", function (e) { 3583 e.preventDefault(); 3584 e.stopPropagation(); 3585 $(this).removeClass('drag-over'); 3586 }); 3587 $("body").on("drop dragdrop", "#my-drop-container", async function (e) { 3588 e.stopPropagation(); 3589 e.preventDefault(); 3590 $(this).removeClass('drag-over'); 3591 let file = e.originalEvent.dataTransfer.files[0]; 3592 resolve(await changeFileImgValue(file, targetEL, onlySvg)); 3593 }); 3594 $(document).on("change", '#upload-image-popup #my-drop-container input[type="file"]', async function () {
3595 let $this = $(this); 3596 let file = $this[0].files[0]; 3597 resolve(await changeFileImgValue(file, targetEL, onlySvg)); 3598 }); 3599 }); 3600} 3601async function changeFileImgValue(file, targetEL, onlySvg = false) { 3602 return new Promise((resolve, reject) => { 3603 let imagesTypes = ["image/jpeg", "image/png", "image/jpg", "image/svg+xml"]; 3604 if (onlySvg) 3605 imagesTypes = ["image/svg+xml"]; 3606 const maxFileSizeInKB = 5000; 3607 var reader = new FileReader(); 3608 reader.onload = function () { 3609 let image = reader.result; 3610 if (file.type == "image/svg+xml") { 3611 closePhotoPopUp($('#myimage').parents('.my-popup')); 3612 resolve(image); 3613 } else { 3614 let myImage = document.getElementById('myimage'); 3615 myImage.src = image; 3616 $('#upload-image-popup #get-other-picture').removeClass('hide-me'); 3617 $('#upload-image-popup #rotate-picture').removeClass('hide-me'); 3618 $('#upload-image-popup #confirm-image').removeClass('hide-me'); 3619 $('#upload-image-popup #my-drop-container').addClass('hide-me'); 3620 $('#upload-image-popup .cropper-wrapper').removeClass('hide-me'); 3621 myImage.onload = async function () { 3622 resolve(await initCropper(myImage, targetEL)); 3623 } 3624 } 3625 3626 } 3627 if (imagesTypes.includes(file.type)) { 3628 if (file.size / 1000 < maxFileSizeInKB) { 3629 reader.readAsDataURL(file); 3630 } else { 3631 presentToast(translate['ATTACHMENT']['MAX_FILE_SIZE'], 'fa-triangle-exclamation', 'warning'); 3632 } 3633 } else { 3634 if (onlySvg) { 3635 presentToast(translate['ATTACHMENT']['WRONG_FILE_TYPE_ONLY_SVG'], 'fa-triangle-exclamation', 'warning'); 3636 } else { 3637 presentToast(translate['ATTACHMENT']['WRONG_FILE_TYPE_IMG'], 'fa-triangle-exclamation', 'warning'); 3638 } 3639 } 3640 }); 3641} 3642$("html").on("drop", function (e) { 3643 e.preventDefault(); 3644 e.stopPropagation(); 3645}); 3646$("html").on("dragover", function (e) { 3647 e.preventDefault(); 3648 e.stopPropagation(); 3649}); 3650// END - IMAGE 3651 3652// ACTION SHEET 3653$(document).on("click", ".my-action-sheet", function (e) { 3654 if ($(e.target).hasClass('my-action-sheet')) { 3655 closeMyActionSheet($(this)); 3656 } 3657}) 3658function myActionSheet(title, id, buttons) { 3659 let myActionSheet = document.createElement('div'); 3660 myActionSheet.setAttribute('id', id); 3661 myActionSheet.className = 'my-action-sheet'; 3662 3663 let myActionSheetInner = document.createElement('div'); 3664 myActionSheetInner.className = 'inner'; 3665 myActionSheet.appendChild(myActionSheetInner); 3666 3667 if (title != '') { 3668 let myActionSheetTitle = document.createElement('div'); 3669 myActionSheetTitle.className = 'title'; 3670 myActionSheetTitle.textContent = title; 3671 myActionSheetInner.appendChild(myActionSheetTitle); 3672 } 3673 let myActionSheetList = document.createElement('ul'); 3674 buttons.forEach((data, index) => { 3675 let myActionSheetListItem = document.createElement('li'); 3676 myActionSheetListItem.className = data['style']; 3677 myActionSheetListItem.innerHTML = data['icon'] + '<span>' + data['text'] + '</span>'; 3678 myActionSheetListItem.addEventListener('click', data['handler']); 3679 myActionSheetList.appendChild(myActionSheetListItem); 3680 }); 3681 myActionSheetInner.appendChild(myActionSheetList); 3682 $('body').append(myActionSheet); 3683 $('#' + id).fadeIn(500).addClass('shown'); 3684 return $('#' + id); 3685} 3686 3687function closeMyActionSheet(el) { 3688 el.removeClass('shown').fadeOut(500).promise().done(function () { 3689 el.remove(); 3690 }); 3691} 3692 3693// END - ACTION SHEET 3694 3695// POPUP FUNCTIONS 3696 3697function showPopUp(popupEl, animationTime = 500) { 3698 return new Promise(function (resolve, reject) { 3699 popupEl.fadeIn(animationTime).promise().done(function () { 3700 resolve(true); 3701 }); 3702 }); 3703} 3704 3705function hidePopUp(popupEl) { 3706 return new Promise(function (resolve, reject) { 3707 popupEl.fadeOut(500).promise().done(function () { 3708 resolve(true); 3709 }); 3710 }); 3711} 3712 3713$(document).on('click', '.my-popup .close-popup', function (e) { 3714 let popUpEl = $(this).parents('.my-popup'); 3715 hidePopUp(popUpEl); 3716}); 3717 3718$(document).on('click', '.my-popup .close-and-remove-popup', async function (e) { 3719 let popUpEl = $(this).parents('.my-popup'); 3720 await hidePopUp(popUpEl); 3721 popUpEl.remove(); 3722}); 3723 3724$(document).on('click', '.my-popup .generate-titlepage-pdf', async function (e) { 3725 let popUpEl = $(this).parents('.my-popup'); 3726 await generateTitlePage(popUpEl); 3727 popUpEl.remove(); 3728}); 3729 3730function getAjaxPopUp(action, data, animationTime = 500) { 3731 return new Promise(function (resolve, reject) { 3732 $('#loading-bar').show(); 3733 $.ajax({ 3734 type: 'POST', 3735 url: action, 3736 cache: false, 3737 data: { 3738 data: JSON.stringify(data) 3739 }, 3740 success: function (result) { 3741 $('#loading-bar').hide(); 3742 if (/<[a-z][\s\S]*>/i.test(result)) { 3743 $('body').append(result).delay(10).promise().done(async function () { 3744 await showPopUp($('#' + $(result).attr('id')), animationTime); 3745 resolve(true); 3746 }); 3747 } else { 3748 handleResult(result); 3749 resolve(false) 3750 } 3751 }, 3752 }); 3753 }) 3754} 3755 3756async function infoPopup(title, message, link) { 3757 return new Promise((resolve, reject) => { 3758 $('#loading-bar').show(); 3759 $.ajax({ 3760 type: 'POST', 3761 url: 'getinfopopup', 3762 data: { 3763 title: title, 3764 message: message, 3765 link: link, 3766 }, 3767 cache: false, 3768 success: function (result) { 3769 $('#loading-bar').hide(); 3770 if (/<[a-z][\s\S]*>/i.test(result)) { 3771 $('body').append(result).delay(10).promise().done(function () { 3772 let popupEl = $('#' + $(result).attr('id')); 3773 showPopUp(popupEl); 3774 resolve(true); 3775 }); 3776 } else { 3777 if (result == 'NO_RIGHTS') { 3778 presentToast(translate['NO_RIGTHS']["ERROR"]["NO_RIGHTS"], 'fa-triangle-exclamation', 'warning'); 3779 } else { 3780 console.log(result) 3781 } 3782 resolve(false); 3783 } 3784 }, 3785 }); 3786 }); 3787 3788} 3789 3790$('.submit-form-after-confirm').click(async function (e) { 3791 e.preventDefault(); 3792 let el = $(this); 3793 if (await submitFormAfterConfirm($(el).data('title'), $(el).data('message'))) { 3794 el.unbind('click').click(); 3795 } 3796 return false;
3797}) 3798async function submitFormAfterConfirm(title, message) { 3799 return new Promise((resolve, reject) => { 3800 $('#loading-bar').show(); 3801 $.ajax({ 3802 type: 'POST', 3803 url: 'getconfirmpopup', 3804 data: { 3805 title: title, 3806 message: message, 3807 }, 3808 cache: false, 3809 success: function (result) { 3810 $('#loading-bar').hide(); 3811 if (/<[a-z][\s\S]*>/i.test(result)) { 3812 $('body').append(result).delay(10).promise().done(function () { 3813 let popupEl = $('#' + $(result).attr('id')); 3814 popupEl.find('.my-link.bold').bind('click', () => { 3815 resolve(true); 3816 popupEl.find('.close-and-remove-popup').trigger('click'); 3817 }); 3818 popupEl.find('.my-link.close-and-remove-popup').bind('click', () => { 3819 resolve(false); 3820 }); 3821 showPopUp(popupEl); 3822 3823 }); 3824 } else { 3825 handleResult(result); 3826 resolve(false); 3827 } 3828 }, 3829 }); 3830 }); 3831 3832} 3833async function getarticlenotokorinrepairpopup(noQuestions = false) { 3834 return new Promise(async (resolve, reject) => { 3835 $('#loading-bar').show(); 3836 await getAjaxPopUp('getarticlenotokorinrepairpopup', { message: noQuestions ? translate['ARTICLE']['TEST_POSTIVE_OR_NEGATIVE'] : translate['ARTICLE']['MESSAGE_SET_ARTICLE_NOT_OK'] }); 3837 $('#loading-bar').hide(); 3838 let popupEl = $('#articlenotokorinrepair-popup'); 3839 popupEl.find('.my-link.in_repair').bind('click', () => { 3840 resolve('in_repair'); 3841 popupEl.find('.close-and-remove-popup').trigger('click'); 3842 }); 3843 popupEl.find('.my-link.not_ok').bind('click', () => { 3844 resolve('not_ok'); 3845 popupEl.find('.close-and-remove-popup').trigger('click'); 3846 }); 3847 popupEl.find('.my-link.close-and-remove-popup').bind('click', () => { 3848 resolve(false); 3849 }); 3850 }); 3851 3852} 3853function convertRemToPixels(rem) { 3854 return rem * parseFloat(getComputedStyle(document.documentElement).fontSize); 3855} 3856async function getUserSignPopUp() { 3857 return new Promise((resolve, reject) => { 3858 $('#loading-bar').show(); 3859 let width = 836; 3860 let widthVP = $(window).width(); 3861 if (widthVP > 768) { 3862 if (widthVP < (836 + convertRemToPixels(6))) { 3863 width = widthVP - convertRemToPixels(6); 3864 } 3865 } else { 3866 width = widthVP - convertRemToPixels(4); 3867 } 3868 $.ajax({ 3869 type: 'POST', 3870 url: 'getusersignpopup', 3871 cache: false, 3872 data: { 3873 canvas_width: Math.round(width) 3874 }, 3875 success: function (result) { 3876 $('#loading-bar').hide(); 3877 if (/<[a-z][\s\S]*>/i.test(result)) { 3878 $('body').append(result).delay(10).promise().done(async function () { 3879 let popupEl = $('#' + $(result).attr('id')); 3880 popupEl.find('.my-link.bold').bind('click', () => { 3881 let sign = $('#sign_canvas').get(0).toDataURL(); 3882 resolve(sign); 3883 popupEl.find('.close-and-remove-popup').trigger('click'); 3884 }); 3885 popupEl.find('.my-link.close-and-remove-popup').bind('click', () => { 3886 resolve(false); 3887 }); 3888 await showPopUp(popupEl); 3889 signPaths = []; 3890 saveResizeAndRedisplaySignCanvas(); 3891 3892 }); 3893 } else { 3894 handleResult(result); 3895 resolve(false); 3896 } 3897 }, 3898 }); 3899 }); 3900} 3901 3902async function generateTitlePage(popUpEl) {
3903 let data = getFormData(popUpEl.find('form')); 3904 let base64 = await generateTitlePagePDF(data); 3905 $.ajax({ 3906 type: 'POST', 3907 url: 'uploadtitlepage', 3908 cache: false, 3909 data: { 3910 pdfBase64: base64, 3911 tableName: $('.my-table-list').data('table-name') 3912 }, 3913 success: async function (result) { 3914 presentToast(translate['EXPORT_DATA']['TITLEPAGE']['FILE_GENERATED'], 'fa-save', 'success'); 3915 await hidePopUp(popUpEl); 3916 changeCanvasContainerSrc(base64); 3917 popUpEl.remove(); 3918 } 3919 }); 3920} 3921$(document).on('input', '#generate-titlepage-form #dirText', function () { 3922 const val = $(this).val(); 3923 const newlineArr = val.split(/[\r\n]+/); 3924 let strArr = []; 3925 for (let index = 0; index < newlineArr.length; index++) { 3926 if (index < 5) { 3927 strArr.push(newlineArr[index].substr(0, 65)); 3928 } 3929 } 3930 $(this).val(strArr.join("\r\n")); 3931}); 3932 3933// END-POPUP FUNCTIONS 3934 3935// SIGN FUNCTIONS 3936 3937 3938jQuery.event.special.touchmove = { 3939 setup: function (_, ns, handle) { 3940 this.addEventListener("touchmove", handle, { passive: !ns.includes("noPreventDefault") }); 3941 } 3942}; 3943let signPaths = []; 3944 3945$(document).on('mousedown touchstart', '#sign_canvas', function (e) { 3946 let drawingSign = false; 3947 let saveXSign = 0; 3948 let saveYSign = 0; 3949 let timestamp = null; 3950 drawingSign = true; 3951 canSwipeMenu = false;
3952 const canvasPosition = $(this).get(0).getBoundingClientRect(); 3953 saveXSign = e.offsetX; 3954 saveYSign = e.offsetY; 3955 $(document).on('mousemove touchmove', '#sign_canvas', function (e) { 3956 if (!drawingSign) 3957 return; 3958 3959 const canvasPosition = $(this).get(0).getBoundingClientRect(); 3960 let ctx = $(this).get(0).getContext('2d'); 3961 let currentX = 0; 3962 let currentY = 0; 3963 if (e.offsetX && e.offsetY) { 3964 currentX = e.offsetX; 3965 currentY = e.offsetY; 3966 } else { 3967 if (e.touches) { 3968 currentX = e.touches[0].clientX - canvasPosition.x; 3969 currentY = e.touches[0].clientY - canvasPosition.y; 3970 } 3971 } 3972 3973 if (timestamp === null) { 3974 timestamp = Date.now(); 3975 } 3976 const now = Date.now(); 3977 const dt = now - timestamp; 3978 const dx = saveXSign - currentX; 3979 const dy = saveYSign - currentY; 3980 const speedX = Math.abs(Math.round(dx / dt * 100)); 3981 const speedY = Math.abs(Math.round(dy / dt * 100)); 3982 let speed = speedX; 3983 if (speedY > speedX) { 3984 speed = speedY; 3985 } 3986 const maxSpeed = 200; 3987 speed = (speed > maxSpeed) ? maxSpeed : speed; 3988 const speedFactor = 1 - (100 / maxSpeed * speed / 100); 3989 3990 ctx.lineCap = 'round'; 3991 ctx.lineJoin = 'round'; 3992 ctx.strokeStyle = '#000'; 3993 let signScaleFactor = 100 / 863 * $('#sign_canvas').get(0).width / 100; 3994 let lineWidth = (4 + (3 * speedFactor)) * signScaleFactor; 3995 ctx.lineWidth = (lineWidth >= 1) ? lineWidth : 1; 3996 3997 let path = new Path2D(); 3998 path.moveTo(saveXSign, saveYSign); 3999 path.lineTo(currentX, currentY); 4000 path.closePath(); 4001 4002 ctx.stroke(path); 4003 signPaths.push({ width: $('#sign_canvas').get(0).width, path: path, speedFactor: speedFactor }); 4004 4005 saveXSign = currentX; 4006 saveYSign = currentY; 4007 timestamp = now; 4008 }); 4009 $(document).on('mouseup touchend', '#sign_canvas', function (e) { 4010 drawingSign = false; 4011 canSwipeMenu = true; 4012 }); 4013}); 4014function saveResizeAndRedisplaySignCanvas() { 4015 let el = $('#sign_canvas').get(0); 4016 el.width = $('#sign_canvas').parent().width(); 4017 el.height = $('#sign_canvas').parent().width() * 0.5; 4018 let ctx = el.getContext('2d'); 4019 ctx.clearRect(0, 0, el.width, el.height); 4020 4021 ctx.lineJoin = 'round'; 4022 ctx.strokeStyle = '#000'; 4023 let signScaleFactorLine = 100 / 863 * el.width / 100; 4024 4025 signPaths.forEach((path) => { 4026 let lineWidth = (4 + (3 * path.speedFactor)) * signScaleFactorLine; 4027 ctx.lineWidth = (lineWidth >= 1) ? lineWidth : 1; 4028 let signScaleFactor = 100 / path.width * el.width / 100; 4029 ctx.scale(signScaleFactor, signScaleFactor); 4030 ctx.stroke(path['path']) 4031 ctx.scale((1 / signScaleFactor), (1 / signScaleFactor)); 4032 }); 4033} 4034$(document).on('click', '#user-sign-popup .clear', function (e) { 4035 let ctx = $('#sign_canvas').get(0).getContext('2d'); 4036 ctx.clearRect(0, 0, $('#sign_canvas').get(0).width, $('#sign_canvas').get(0).height); 4037 signPaths = []; 4038}); 4039 4040 4041// END-SIGN FUNCTIONS 4042 4043// TOAST FUNCTIONS 4044 4045$('.show-toast').click(function () { 4046 presentToast($(this).data('text'), $(this).data('icon'), $(this).data('color'), $(this).data('duration')); 4047}); 4048 4049if ($('.show-toast-now').length > 0) { 4050 $('.show-toast-now').each(function (idx, el) { 4051 presentToast($(el).data('text'), $(el).data('icon'), $(el).data('color'), $(el).data('duration')); 4052 }); 4053} 4054 4055$(document).on('click', '.my-toast', function () { 4056 let id = $(this).attr('id'); 4057 removeToast(id); 4058}) 4059 4060function presentToast(message = '', icon = 'cloud-done', color = 'success', duration = 10000) { 4061 let id = 'toast-' + new Date().getTime(); 4062 let html = '<div id="' + id + '" class="my-toast' + ((color !== '') ? ' ' + color : '') + '">' + ((icon !== '') ? '<i class="fa-solid ' + icon + '"></i>' : '') + ((message !== '') ? '<span>' + message + '</span>' : '') + '</div>'; 4063 $('body').append(html).delay(100).promise().done(function () { 4064 $('#' + id).addClass('show'); 4065 resetToastsPostions(); 4066 }); 4067 if (duration > 0) { 4068 setTimeout(() => { 4069 removeToast(id); 4070 }, duration); 4071 } 4072 return id; 4073} 4074 4075function resetToastsPostions() { 4076 let bottom = 16; 4077 if ($('.my-fixed-buttons.right-bottom').length > 0) { 4078 bottom += $('.my-fixed-buttons.right-bottom').outerHeight() + 16; 4079 } 4080 $('.my-toast.show').each(function (idx, el) { 4081 $(el).css('bottom', bottom); 4082 bottom += $(el).outerHeight() + 16; 4083 }); 4084} 4085 4086function removeToast(id) { 4087 let tmptoast = $('#' + id); 4088 if (tmptoast.length > 0) { 4089 let bottom = 16; 4090 if ($('.my-fixed-buttons.right-bottom').length > 0) { 4091 bottom += $('.my-fixed-buttons.right-bottom').outerHeight() + 16; 4092 } 4093 $('.my-toast.show').each(function (idx, el) { 4094 if ($(el).attr('id') !== id) { 4095 $(el).css('bottom', bottom); 4096 bottom += $(el).outerHeight() + 16; 4097 } 4098 }); 4099 $(tmptoast).removeClass('show').delay(300).promise().done(function () { 4100 $(tmptoast).remove(); 4101 }); 4102 } 4103} 4104 4105 4106// END-TOAST FUNCTIONS 4107 4108// MENU FUNCTIONS 4109 4110$(document).on('click', '.remove-agb-pop-up', function (e) { 4111 let popUpEl = $('#agb-popup'); 4112 popUpEl.remove(); 4113}); 4114 4115 4116$('.menu-top .menu-button').click(function () { 4117 $('.menu-left').toggleClass('open'); 4118}); 4119 4120$('.my-content').click(function () { 4121 $('.menu-left').removeClass('open'); 4122}); 4123 4124$('.menu-left .menu-point .main-point .arrow').click(function (e) { 4125 e.preventDefault(); 4126 if ($(this).parents('.menu-point').hasClass('open')) { 4127 $(this).parents('.menu-point').find('.sub-point').slideUp({ 4128 duration: 300 4129 }); 4130 $(this).parents('.menu-point').removeClass('open'); 4131 } else { 4132 $(this).parents('.menu-point').find('.sub-point').slideDown({ 4133 complete: function () { 4134 $(this).css({ 4135 display: "flex" 4136 }) 4137 }, 4138 start: function () { 4139 $(this).css({ 4140 display: "flex" 4141 }) 4142 }, 4143 duration: 300 4144 }); 4145 $(this).parents('.menu-point').addClass('open'); 4146 } 4147 4148}); 4149 4150$('.menu-left .account-wrapper').click(function (e) {
4151 $(this).toggleClass('sub-menu-shown').find('.sub-menu').slideToggle(300); 4152}); 4153 4154$('#addaccount').click(async function () { 4155 $('#addaccount').prop('disabled', true); 4156 await getAjaxPopUp('addaccount'); 4157 $('#addaccount').prop('disabled', false); 4158}); 4159 4160// END-MENU FUNCTIONS 4161 4162// TAB FUNCTIONS 4163 4164$('.my-tabs .tab').click(function () { 4165 const tabs = $(this).parents('.my-tabs'); 4166 const target = $($(this).data('target')); 4167 tabs.find('.tab').removeClass('active'); 4168 $(this).addClass('active'); 4169 tabs.find('.content').removeClass('active'); 4170 target.addClass('active'); 4171}); 4172 4173$(window).on('load', function () { 4174 let container = $('.my-tab-nav-wrapper'); 4175 let activeTab = container.find('.active'); 4176 if (activeTab.length) { 4177 $('.my-content').addClass('with-tabs'); 4178 $('.my-fixed-buttons').addClass('with-tabs'); 4179 container.animate( 4180 { 4181 scrollLeft: (activeTab.position().left + container.scrollLeft() - container.offset().left - 20) 4182 }, 4183 150 4184 ); 4185 } 4186 let activeMenuPoint = $('.menu-point.active'); 4187 let containerMenu = $('.menu-wrapper'); 4188 if (activeMenuPoint.length > 0) { 4189 let diff = (activeMenuPoint.offset().top + activeMenuPoint.outerHeight()) - containerMenu.outerHeight(); 4190 if (activeMenuPoint.length) { 4191 if (diff > 0) { 4192 $('.menu-wrapper').animate( 4193 { 4194 scrollTop: diff 4195 }, 4196 150 4197 ); 4198 } 4199 } 4200 } 4201}); 4202 4203// END-TAB FUNCTIONS 4204 4205// SETTING FUNCTIONS 4206 4207$('#economic_unit_id').on('change', function () { 4208 const val = $(this).val(); 4209 switch (val) { 4210 case "1": 4211 $('[data-for="PRIVATE"]').removeClass('hide-me'); 4212 $('[data-for="COMPANY"]').addClass('hide-me'); 4213 $('[data-for="COMPANY_AND_ITALY"]').addClass('hide-me'); 4214 if ($('select[name="country"]').val() == 'ITALY') { 4215 $('[data-for="PRIVATE_AND_ITALY"]').removeClass('hide-me'); 4216 } else { 4217 $('[data-for="PRIVATE_AND_ITALY"]').addClass('hide-me'); 4218 } 4219 break; 4220 default: 4221 $('[data-for="PRIVATE"]').addClass('hide-me'); 4222 $('[data-for="PRIVATE_AND_ITALY"]').addClass('hide-me'); 4223 $('[data-for="COMPANY"]').removeClass('hide-me'); 4224 if ($('select[name="country"]').val() == 'ITALY') { 4225 $('[data-for="COMPANY_AND_ITALY"]').removeClass('hide-me'); 4226 } else { 4227 $('[data-for="COMPANY_AND_ITALY"]').addClass('hide-me'); 4228 } 4229 break; 4230 } 4231}); 4232if ($('#settings-form select[name="country"]').length > 0 && $('#settings-form select[name="province"] option').length < 2) { 4233 updateProvices(); 4234} 4235$('#settings-form #country').on('change', function () { 4236 const val = $(this).val(); 4237 $('input[name="province_hidden"]').val(''); 4238 switch (val) { 4239 case "ITALY": 4240 if ($('select[name="economic_unit_id"]').val() != '1') { 4241 $('[data-for="COMPANY_AND_ITALY"]').removeClass('hide-me'); 4242 } else { 4243 $('[data-for="COMPANY_AND_ITALY"]').addClass('hide-me'); 4244 } 4245 if ($('select[name="economic_unit_id"]').val() == '1') { 4246 $('[data-for="PRIVATE_AND_ITALY"]').removeClass('hide-me'); 4247 } else { 4248 $('[data-for="PRIVATE_AND_ITALY"]').addClass('hide-me'); 4249 } 4250 break; 4251 default: 4252 $('[data-for="COMPANY_AND_ITALY"]').addClass('hide-me'); 4253 $('[data-for="PRIVATE_AND_ITALY"]').addClass('hide-me'); 4254 break; 4255 } 4256 updateProvices(); 4257}); 4258function updateProvices() {
4259 let currentProvice = $('select[name="province"]').data('current-val') 4260 let provinces = $('select[name="country"] option:selected').data('provinces'); 4261 $('select[name="province"] option').not(':first').remove(); 4262 if (provinces.length > 0) { 4263 $('.province-container.select').removeClass('hide-me'); 4264 $('.province-container.input').addClass('hide-me'); 4265 $('.province-container.select [name="province_hidden"]').attr('name', 'province'); 4266 $('.province-container.select [id="province_hidden"]').attr('id', 'province'); 4267 $('.province-container.select [for="province_hidden"]').attr('for', 'province'); 4268 $('.province-container.input [name="province"]').attr('name', 'province_hidden'); 4269 $('.province-container.input [id="province"]').attr('id', 'province_hidden'); 4270 $('.province-container.input [for="province"]').attr('for', 'province_hidden'); 4271 $('input[name="province_hidden"]').val(''); 4272 provinces.forEach(function (province) { 4273 let optionEl = document.createElement('option'); 4274 optionEl.value = province['name'] + ' - ' + province['region'] + ' (' + province['code'] + ')'; 4275 optionEl.textContent = province['name'] + ' - ' + province['region'] + ' (' + province['code'] + ')'; 4276 $('select[name="province"]').append(optionEl); 4277 }); 4278 if ($('select[name="province"] option[value="' + currentProvice + '"]').length > 0) { 4279 $('select[name="province"]').val(currentProvice); 4280 } else { 4281 $('select[name="province"]').val(''); 4282 } 4283 } else { 4284 $('.province-container.select').addClass('hide-me'); 4285 $('.province-container.input').removeClass('hide-me'); 4286 $('.province-container.input [name="province_hidden"]').attr('name', 'province'); 4287 $('.province-container.input [id="province_hidden"]').attr('id', 'province'); 4288 $('.province-container.input [for="province_hidden"]').attr('for', 'province'); 4289 $('.province-container.select [name="province"]').attr('name', 'province_hidden'); 4290 $('.province-container.select [id="province"]').attr('id', 'province_hidden'); 4291 $('.province-container.select [for="province"]').attr('for', 'province_hidden'); 4292 $('select[name="province_hidden"]').val(''); 4293 } 4294} 4295 4296$('input[name="package_id"]').change(function (e) { 4297 e.preventDefault(); 4298 if ($(this).prop('checked')) { 4299 $('input[name="package_id"]:checked').prop('checked', false); 4300 $(this).prop('checked', true); 4301 } else { 4302 if ($('form').data('old-package-id') == '') { 4303 $('input[name="package_id"]:checked').prop('checked', false); 4304 } else { 4305 $(this).prop('checked', true); 4306 } 4307 } 4308 if ($('input[name="package_id"]:checked').val() > 0) { 4309 $('.show-with-package').removeClass('hide-me'); 4310 } else { 4311 $('.show-with-package').addClass('hide-me'); 4312 } 4313 updateGb(); 4314}); 4315$('#paymethod_tabs .tab').click(function (e) { 4316 const value = $(this).data('id'); 4317 $('input[name="paymethod_id"]').val(value); 4318}); 4319$('#reenter-coupon').click(function (e) { 4320 $('.coupon-wrapper').remove(); 4321 $('.coupon-input-wrapper').removeClass('hide-me'); 4322 $(this).addClass('hide-me'); 4323 $('input[name="remove-redeemed-coupon"]').val('1'); 4324 $('input[name="coupon_code"]').val(''); 4325}); 4326$('#open-contact-form').click(function (e) { 4327 getAjaxPopUp('ownpackagepopup'); 4328 $(document).on('click', '#send-own-package-request', function (e) { 4329 error = false; 4330 let popupEl = $(this).parents('.my-popup'); 4331 let val = parseInt(popupEl.find('#number_articles').val()); 4332 let note = popupEl.find('#note').val(); 4333 if (val <= 5000 || isNaN(val)) { 4334 let inputEl = popupEl.find('#number_articles'); 4335 let inputWrapperEl = inputEl.parents('.my-input'); 4336 inputWrapperEl.addClass('error'); 4337 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 4338 if (!error) 4339 inputEl.focus(); 4340 error = true; 4341 } 4342 if (!error) { 4343 $('#loading-bar').show(); 4344 $.ajax({ 4345 type: 'POST', 4346 url: 'sendownpackagerequest', 4347 data: { 4348 number_articles: val,
4349 note: note, 4350 }, 4351 cache: false, 4352 success: function (result) { 4353 $('#loading-bar').hide(); 4354 if (result == '1') { 4355 popupEl.find('.close-and-remove-popup').trigger('click'); 4356 presentToast(translate['SETTINGS']['OWN_PACKAGES_REQUEST_SENDED'], 'fa-paper-plane', 'success') 4357 } else { 4358 handleResult(result); 4359 resolve(false); 4360 } 4361 }, 4362 }); 4363 } 4364 }); 4365}); 4366$('#delete-account').click(async function () { 4367 let res = await submitFormAfterConfirm('', translate['SETTINGS']['DELETE_ACCOUNT_QUESTION']); 4368 if (res) { 4369 let deleteAccountCode = Math.floor((Math.random() * 100000)); 4370 await getAjaxPopUp('deleteaccountpopup', { code: deleteAccountCode }); 4371 $(document).on('click', '#confirm-delete-account', function () { 4372 let popupEl = $(this).parents('.my-popup'); 4373 let code = parseInt(popupEl.find('#delete_code').val()); 4374 error = false; 4375 if (code != deleteAccountCode) { 4376 let inputEl = popupEl.find('#delete_code'); 4377 let inputWrapperEl = inputEl.parents('.my-input'); 4378 inputWrapperEl.addClass('error'); 4379 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 4380 if (!error) 4381 inputEl.focus(); 4382 error = true; 4383 } 4384 if (!error) { 4385 let deleteinput = document.createElement("input"); 4386 deleteinput.name = "delete-account"; 4387 deleteinput.type = "hidden"; 4388 deleteinput.value = "1"; 4389 $('#settings-form').append(deleteinput); 4390 resetFormCheckBeforeUnload(); 4391 $('#settings-form').submit(); 4392 } 4393 }); 4394 } 4395}); 4396$('#add-gb').click(function () { 4397 updateGb(true); 4398}); 4399$('#remove-gb').click(function () { 4400 updateGb(false); 4401}); 4402async function updateGb(add = null, setMin = true) { 4403 if ($('#settings-form #memory').length > 0) { 4404 let value = parseInt($('#memory').val()); 4405 let currentMemory = parseInt($('#memory').data('current-memory')); 4406 4407 let steps = $('#memory').data('steps'); 4408 4409 const currentMemoryInGB = currentMemory / 1024 / 1024 / 1024; 4410 const minVal = Math.ceil(currentMemoryInGB); 4411 4412 let keys = Object.keys(steps).map(Number).sort((a, b) => a - b); 4413 4414 let index = keys.findIndex(k => k >= value); 4415 if (index === -1) index = keys.length - 1; 4416 4417 if (add !== null) { 4418 if (add) { 4419 if (index < keys.length - 1) { 4420 value = keys[index + 1]; 4421 } else { 4422 presentToast(translate['SETTINGS']['MEMORY']['MAX_VALUE'], 'fa-triangle-exclamation', 'warning', 6000); 4423 return; 4424 } 4425 } else { 4426 if (index > 0) { 4427 let newVal = keys[index - 1]; 4428 if (newVal < minVal) { 4429 return; 4430 } 4431 value = newVal; 4432 } else { 4433 return; 4434 } 4435 } 4436 } 4437 4438 if (value < minVal && setMin) { 4439 value = keys.find(k => k >= minVal) || minVal; 4440 } 4441 4442 $('#memory').val(value); 4443 $('.current-memory-package .value').text(value); 4444 4445 const currentMemoryInPercentage = (currentMemoryInGB / value) * 100; 4446 $('.memory-range').css('--currentMemory', currentMemoryInPercentage + '%'); 4447 $('.memory-range').parents('.memory-wrapper').removeClass('full'); 4448 $('.memory-range').parents('.memory-wrapper').removeClass('half-full'); 4449 $('.memory-range').parents('.memory-wrapper').removeClass('empty'); 4450 if (currentMemoryInPercentage >= 90) { 4451 $('.memory-range').parents('.memory-wrapper').addClass('full'); 4452 } else if (currentMemoryInPercentage >= 50) { 4453 $('.memory-range').parents('.memory-wrapper').addClass('half-full'); 4454 } else { 4455 $('.memory-range').parents('.memory-wrapper').addClass('empty'); 4456 } 4457 4458 let price = steps[value] ?? 0; 4459 $('.price-memory span').text(toFloatInput(price)); 4460 4461 let packagePrice = parseFloat($('input[name="package_id"]:checked').data('price')); 4462 let total = price + packagePrice; 4463 $('#total .value span').text(toFloatInput(total)); 4464 } 4465} 4466// END-SETTING FUNCTIONS 4467// TABLE-LIST FUNCTIONS 4468 4469if ($('.my-table-list').length > 0) {
4470 initTableList(); 4471} 4472let infiniteLoadElementsForTableListInit = false; 4473async function initTableList() { 4474 await initTableDataAttrFilter(); 4475 if (getCurrentAction() != 'articles') { 4476 await getTableList(); 4477 loadNextItemsForTableList(); 4478 } 4479} 4480function getFilter() { 4481 let filter = {}; 4482 try { 4483 const tableName = $('.my-table-list').data('table-name'); 4484 let jsonFilter = getCookie(tableName + '_filter') 4485 if (jsonFilter) { 4486 filter = JSON.parse(jsonFilter); 4487 } 4488 } catch (error) { 4489 //löscht cookie das fehler nicht nochmal kommt 4490 const tableName = $('.my-table-list').data('table-name'); 4491 const cookieName = tableName + '_filter'; 4492 deleteCookie(cookieName); 4493 $('.my-table-list-filter-search').val(''); 4494 updateClearSearch($('.my-table-list-filter-search')); 4495 $('#articles .badges .my-badge.state').removeClass('not-active'); 4496 updateFilterCounter(); 4497 updateSortForTableList($('.my-table-list').data('init-sort').split('-')[0], $('.my-table-list').data('init-sort').split('-')[1]); 4498 removeDirIdParam(); 4499 getTableList(); 4500 console.log(error); 4501 } 4502 return filter; 4503} 4504function updateFilter(fname, fvalue) { 4505 try { 4506 let filter = {}; 4507 const tableName = $('.my-table-list').data('table-name'); 4508 const cookieName = tableName + '_filter'; 4509 let jsonFilter = getCookie(cookieName); 4510 if (jsonFilter) { 4511 filter = JSON.parse(jsonFilter); 4512 } 4513 filter[fname] = fvalue; 4514 setCookie(cookieName, JSON.stringify(filter)); 4515 updateFilterCounter(); 4516 } catch (error) { 4517 console.log(error); 4518 } 4519 4520} 4521if ($('.my-table-list').length > 0) 4522 updateFilterCounter(); 4523 4524function updateFilterCounter() { 4525 let filter = {}; 4526 const tableName = $('.my-table-list').data('table-name'); 4527 const cookieName = tableName + '_filter'; 4528 let jsonFilter = getCookie(cookieName); 4529 try { 4530 if (jsonFilter) { 4531 filter = JSON.parse(jsonFilter); 4532 } 4533 if (tableName == 'attachment') { 4534 delete filter['parent_id']; 4535 delete filter['type']; 4536 } 4537 if ($('.my-table-list').data('filter-article_id') !== undefined) { 4538 delete filter['article_id']; 4539 } 4540 if (Object.values(filter).filter(x => (x != '' && x != [] && x != null && x != undefined && x != $('.my-table-list').attr('data-init-sort'))).length > 0) { 4541 $('#clear_filter').css('display', 'inline-flex'); 4542 } else { 4543 $('#clear_filter').css('display', 'none'); 4544 } 4545 delete filter['searchStr']; 4546 delete filter['orderBy']; 4547 let count = Object.values(filter).filter(x => (x != '' && x != [] && x != null && x != undefined && x != $('.my-table-list').attr('data-init-sort'))).length; 4548 if (count == 0) 4549 count = ''; 4550 $('.my-buttons-list #filter .info').text(count); 4551 } catch (error) { 4552 console.log(error); 4553 } 4554} 4555$('#clear_filter').click(function () { 4556 const tableName = $('.my-table-list').data('table-name'); 4557 const cookieName = tableName + '_filter'; 4558 deleteCookie(cookieName); 4559 $('.my-table-list-filter-search').val(''); 4560 updateClearSearch($('.my-table-list-filter-search')); 4561 $('#articles .badges .my-badge.state').removeClass('not-active'); 4562 initTableDataAttrFilter(true); 4563 updateSortForTableList($('.my-table-list').data('init-sort').split('-')[0], $('.my-table-list').data('init-sort').split('-')[1]); 4564 updateFilterCounter(); 4565 removeDirIdParam(); 4566 getTableList(); 4567}); 4568$('#sort-table-list').on('change', function () { 4569 let direction = 'asc'; 4570 if ($('#sort-table-list-order').prop('checked')) 4571 direction = 'desc'; 4572 updateSortForTableList($(this).val(), direction); 4573}); 4574$('#sort-table-list-order').on('change', function () { 4575 let direction = 'asc'; 4576 if ($(this).prop('checked')) 4577 direction = 'desc'; 4578 updateSortForTableList($('#sort-table-list').val(), direction); 4579}); 4580function updateSortForTableList(newSortColName, direction = '') { 4581 let filter = getFilter();
4582 let currentSort = filter['orderBy']; 4583 if (currentSort == '' || currentSort == undefined) 4584 currentSort = $('.my-table-list').attr('data-init-sort'); 4585 const currentSortColName = currentSort.split('-')[0]; 4586 const currentSortDirection = currentSort.split('-')[1]; 4587 let newSortDirection = 'asc'; 4588 if (direction == '') { 4589 if (currentSortColName == newSortColName) { 4590 if (currentSortDirection == 'asc') { 4591 newSortDirection = 'desc'; 4592 } 4593 } 4594 } else { 4595 newSortDirection = direction; 4596 } 4597 $('#sort-table-list-order').prop('checked', newSortDirection == 'desc'); 4598 if ($('#sort-table-list [value="' + newSortColName + '"]').length > 0) { 4599 $('#sort-table-list').val(newSortColName); 4600 } else { 4601 $('#sort-table-list').val($('#sort-table-list option:first-of-type').val()); 4602 } 4603 $('.my-table-list').find('.sort-col').removeClass('asc').removeClass('desc'); 4604 $('.my-table-list').find('.sort-col[data-col-name="' + newSortColName + '"]').addClass(newSortDirection); 4605 updateFilter('orderBy', newSortColName + '-' + newSortDirection); 4606 getTableList(); 4607} 4608$('.my-table-list .sort-col').click(function () { 4609 updateSortForTableList($(this).data('col-name')); 4610}); 4611$('.my-buttons-list #filter').click(function (e) { 4612 let tableName = $('.my-table-list').data('table-name'); 4613 if (tableName == 'tests_from_article') 4614 tableName = 'test'; 4615 getAjaxPopUp(tableName + 'filterpopup'); 4616}); 4617function updateCols(tableListName, columns) { 4618 return new Promise((resolve, reject) => { 4619 $('.my-table-list .row .cell').removeClass('hide-me'); 4620 columns.forEach((value, idx) => { 4621 $('.my-table-list .row .cell[data-col-name="' + value + '"]').addClass('hide-me'); 4622 }); 4623 $.ajax({ 4624 type: 'POST', 4625 url: 'updatetablelistcolumssettings', 4626 cache: false, 4627 data: { 4628 tableName: tableListName, 4629 columns: columns 4630 }, 4631 success: function (result) { 4632 if (result == '1') { 4633 resolve(true); 4634 } else { 4635 handleResult(result); 4636 resolve(false); 4637 } 4638 } 4639 }); 4640 }) 4641 4642} 4643$(document).on('click', '#confirm-filter', async function () { 4644 const popupEL = $(this).parents('.my-popup'); 4645 let data = popupEL.find('form').serializeArray(); 4646 let tmpIdx = data.findIndex((el, idx) => el.name == 'cols_val'); 4647 if (tmpIdx >= 0) { 4648 let columns = []; 4649 if (popupEL.find('#cols_val').val() !== '') 4650 columns = popupEL.find('#cols_val').val().split(','); 4651 let tableListName = popupEL.find('#cols_val').data('for'); 4652 await updateCols(tableListName, columns); 4653 data.splice(tmpIdx, 1); 4654 } 4655 tmpIdx = data.findIndex((el, idx) => el.name == 'cols'); 4656 if (tmpIdx >= 0) { 4657 data.splice(tmpIdx, 1); 4658 } 4659 data.forEach((value, idx) => { 4660 if (value.name == 'from_date' || value.name == 'to_date' || value.name == 'ref_date') { 4661 if (!checkDate(value.value)) { 4662 value.value = ''; 4663 } else { 4664 let tmpdate = moment(value.value, "DD.MM.YYYY"); 4665 value.value = tmpdate.format("YYYY-MM-DD"); 4666 } 4667 } 4668 updateFilter(value.name, value.value); 4669 }); 4670 popupEL.find('.close-and-remove-popup').trigger('click'); 4671 getTableList(); 4672}); 4673$(document).on('click', '#table-list-edit-element', function (e) { 4674 let link = $(this).data('link'); 4675 let id = $('.list-item .select-col input[type="checkbox"]:checked').val().replace(/\D/g, ''); 4676 window.open(link + id, '_self'); 4677}); 4678$(document).on('click', '#table-list-duplicate', function (e) { 4679 let link = $(this).data('link'); 4680 let linkArr = link.split('/'); 4681 let name = linkArr[linkArr.length - 1].substr(0, linkArr[linkArr.length - 1].indexOf('?')) 4682 let id = $('.list-item .select-col input[type="checkbox"]:checked').val().replace(/\D/g, ''); 4683 localStorage.removeItem(name + '-form'); 4684 window.open(link + id, '_self'); 4685}); 4686function initTableDataAttrFilter(afterClear = false) { 4687 return new Promise((resolve, reject) => { 4688 const tabelListEl = $('.my-table-list'); 4689 if (tabelListEl.length > 0) {
4690 Object.keys(tabelListEl.data()).forEach(function (key, idx) { 4691 if (!afterClear || key != 'filterdir_id') { 4692 if (key.startsWith('filter')) { 4693 const splitted = key.split('filter')[1].toLowerCase(); 4694 updateFilter(splitted, tabelListEl.data(key)); 4695 } 4696 } 4697 }) 4698 } 4699 resolve(true); 4700 }); 4701} 4702function handleVisibilityChange() { 4703 if (document.visibilityState === "visible") { 4704 initTableDataAttrFilter(); 4705 } 4706} 4707document.addEventListener("visibilitychange", handleVisibilityChange, false); 4708let tableListRequest = null; 4709function getTableList(add = false, jumpInOnOneResult = false) { 4710 const tabelListEl = $('.my-table-list'); 4711 if (tabelListEl.length == 0) { 4712 return Promise.resolve(); 4713 } 4714 if (tableListRequest != null) { 4715 tableListRequest.abort(); 4716 } 4717 if (!add) { 4718 tabelListEl.find('.table-list-inner .list-item').remove(); 4719 } 4720 return new Promise((resolve, reject) => { 4721 tableListGetCalled = true; 4722 const tableName = tabelListEl.data('table-name'); 4723 let filter = getFilter(); 4724 let ids = []; 4725 if (add) { 4726 ids = tabelListEl.find('.list-item').map((idx, el) => $(el).data('id')).toArray() 4727 } 4728 $('#loading-bar').show(); 4729 tableListRequest = $.ajax({ 4730 type: 'POST', 4731 url: 'gettablelist', 4732 cache: false, 4733 data: { 4734 tableName: tableName, 4735 ids: ids, 4736 filter: filter 4737 }, 4738 success: function (result) { 4739 $('#loading-bar').hide(); 4740 if (!add) { 4741 tabelListEl.find('.table-list-inner .list-item').remove(); 4742 updateMyButtonsList(); 4743 } 4744 4745 if (/<[a-z][\s\S]*>/i.test(result)) { 4746 infiniteLoadElementsForTableListInit = false; 4747 tabelListEl.show(); 4748 $('.my-hint').addClass('hide-me'); 4749 tabelListEl.find('.table-list-inner').append(result); 4750 if ($('.head-row-clone-wrapper').hasClass('active')) { 4751 rebuildTableHeadRowClone(); 4752 } 4753 if (!add || tabelListEl.find('#count').text() > 0) { 4754 $('#table-list-item-count').text(tabelListEl.find('#count').text()); 4755 $('#table-list-item-count_state_1_to_old').text(tabelListEl.find('#count_state_1_to_old').text()); 4756 $('#table-list-item-count_state_2_overdue').text(tabelListEl.find('#count_state_2_overdue').text()); 4757 $('#table-list-item-count_state_3_upcoming').text(tabelListEl.find('#count_state_3_upcomping').text()); 4758 $('#table-list-item-count_state_4_inspected').text(tabelListEl.find('#count_state_4_inspected').text()); 4759 $('#table-list-item-count_state_6_in_stock').text(tabelListEl.find('#count_state_6_in_stock').text()); 4760 $('#table-list-item-count_state_7_not_be_checked').text(tabelListEl.find('#count_state_7_not_be_checked').text()); 4761 $('#table-list-item-count_state_8_not_found').text(tabelListEl.find('#count_state_8_not_found').text()); 4762 $('#table-list-item-count_state_5_in_repair').text(tabelListEl.find('#count_state_5_in_repair').text()); 4763 $('#table-list-item-count_state_9_discarded').text(tabelListEl.find('#count_state_9_discarded').text()); 4764 } 4765 tabelListEl.find('#count').remove(); 4766 tabelListEl.find('#count_state_1_to_old').remove(); 4767 tabelListEl.find('#count_state_2_overdue').remove(); 4768 tabelListEl.find('#count_state_3_upcomping').remove(); 4769 tabelListEl.find('#count_state_4_inspected').remove(); 4770 tabelListEl.find('#count_state_6_in_stock').remove(); 4771 tabelListEl.find('#count_state_7_not_be_checked').remove(); 4772 tabelListEl.find('#count_state_8_not_found').remove(); 4773 tabelListEl.find('#count_state_5_in_repair').remove(); 4774 tabelListEl.find('#count_state_9_discarded').remove(); 4775 4776 setTimeout(() => { 4777 tabelListEl.find('.list-item').removeClass('added'); 4778 }, 100); 4779 if (jumpInOnOneResult) { 4780 if (tabelListEl.attr('id') == 'article-table-list') { 4781 if (filter['searchStr'].length > 0 && $('#table-list-item-count').text() == 1 && tabelListEl.find('.list-item').length == 1) { 4782 if (tabelListEl.find('.list-item').attr('id').includes('article')) { 4783 window.open(tabelListEl.find('.list-item').data('openlink'), '_self'); 4784 return; 4785 } 4786 } 4787 } 4788 } 4789 } else { 4790 if (result == 'empty') { 4791 if (tabelListEl.find('.list-item').length == 0) { 4792 tabelListEl.hide(); 4793 $('#table-list-item-count').text(0); 4794 $('#table-list-item-count_state_1_to_old').text(0); 4795 $('#table-list-item-count_state_2_overdue').text(0); 4796 $('#table-list-item-count_state_3_upcomping').text(0); 4797 $('#table-list-item-count_state_4_inspected').text(0); 4798 $('#table-list-item-count_state_6_in_stock').text(0); 4799 $('#table-list-item-count_state_7_not_be_checked').text(0); 4800 $('#table-list-item-count_state_8_not_found').text(0); 4801 $('#table-list-item-count_state_5_in_repair').text(0); 4802 $('#table-list-item-count_state_9_discarded').text(0); 4803 $('.my-hint').removeClass('hide-me'); 4804 } 4805 } else { 4806 if (result != 'null') 4807 handleResult(result); 4808 } 4809 } 4810 tableListGetCalled = false;
4811 }, 4812 }); 4813 }); 4814} 4815function handleResult(result, err = null, showToast = true) { 4816 if (typeof result == 'string') { 4817 if (result == 'NO_RIGHTS' && showToast) { 4818 presentToast(translate['NO_RIGTHS']["ERROR"]["NO_RIGHTS"], 'fa-triangle-exclamation', 'warning'); 4819 } else if (result.includes('<script type="text/javascript">window.location.replace("')) { 4820 window.location.reload(); 4821 } else { 4822 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'warning'); 4823 console.log(result, err); 4824 sendErrorToServer({ 4825 type: 'js-error', 4826 message: err?.message ?? null, 4827 result: result, 4828 ua: navigator.userAgent ? navigator.userAgent : null, 4829 }); 4830 } 4831 } else { 4832 console.log(result, err); 4833 sendErrorToServer({ 4834 type: 'js-error', 4835 message: err?.message ?? null, 4836 result: result, 4837 ua: navigator.userAgent ? navigator.userAgent : null, 4838 }); 4839 } 4840} 4841// Die Aktionen der Artikelliste funktionieren auch im Prüfkorb. Dort sind alle Artikel des Korbs die Auswahl. 4842function getSelectedListCheckboxes() { 4843 if ($('#cart-popup').length > 0) { 4844 return $('#cart-popup .cart-item input[type="checkbox"]:checked'); 4845 } 4846 return $('.list-item .select-col input[type="checkbox"]:checked'); 4847} 4848function getListTableName() { 4849 if ($('#cart-popup').length > 0) { 4850 return 'article'; 4851 } 4852 return $('.my-table-list').data('table-name'); 4853} 4854function getExportIds() { 4855 if ($('#cart-popup').length > 0) { 4856 return getSelectedListCheckboxes().map((idx, el) => $(el).val()).toArray(); 4857 } 4858 if ($('.my-table-list').find('.list-item .select-col input[type="checkbox"]:checked').length < $('.my-table-list').find('.list-item .select-col input[type="checkbox"]').length) { 4859 return $('.my-table-list').find('.list-item .select-col input[type="checkbox"]:checked').map((idx, el) => $(el).val()).toArray(); 4860 } 4861 return []; 4862} 4863$(document).on('click', '#table-list-select-all', async function () { 4864 $('.my-table-list .select-col input[type="checkbox"]').prop('checked', true); 4865 updateMyButtonsList(); 4866}); 4867$(document).on('click', '#table-list-deselect-all', async function () { 4868 $('.my-table-list .list-item .select-col input[type="checkbox"]').prop('checked', false); 4869 updateMyButtonsList(); 4870}); 4871$(document).on('click', '#table-list-export', async function () { 4872 const tabelListEl = $('.my-table-list'); 4873 let ids = []; 4874 getSelectedListCheckboxes().each(function () { 4875 ids.push(this.value); 4876 }); 4877 const tableName = getListTableName(); 4878 await getAjaxPopUp('exportpopup', { tableName: tableName, ids: ids, fromCart: $('#cart-popup').length > 0 }); 4879 initForPDFSelect(); 4880}); 4881 4882// Generischer "Mehrfach bearbeiten"-Einstieg für Modelle/Hersteller/ 4883// Kategorien (Ziel-URL/Typ kommen aus data-link/data-type, siehe 4884// models.tmpl.php/manufactures.tmpl.php/model_categories.tmpl.php) - anders 4885// als bei Artikeln (gemischte Liste mit Ordnern, eigener Handler oben) ist 4886// hier jede Liste homogen, ein Filtern nach id-Präfix ist nicht nötig. 4887$(document).on('click', '#table-list-multiple-edit', function () { 4888 let ids = []; 4889 let tablelistName = $('.my-table-list').attr('id'); 4890 getSelectedListCheckboxes().each(function () { 4891 if (tablelistName == 'article-table-list') { 4892 if (this.value.startsWith('article')) { 4893 ids.push(this.value.replace(/\D/g, '')); 4894 } 4895 } else { 4896 ids.push(this.value.replace(/\D/g, '')); 4897 } 4898 }); 4899 if (ids.length == 0) { 4900 return; 4901 } 4902 let form = $('<form>', { method: 'POST', action: $(this).data('link') }); 4903 console.log({ method: 'POST', action: $(this).data('link') }); 4904 4905 ids.forEach(function (id) { 4906 form.append($('<input>', { type: 'hidden', name: 'ids[]', value: id })); 4907 }); 4908 $('body').append(form); 4909 form.submit(); 4910}); 4911$(document).on('click', '#table-list-delete', async function () { 4912 const tabelListEl = $('.my-table-list'); 4913 let ids = []; 4914 let someDirsNotDeleted = false;
4915 getSelectedListCheckboxes().each(function () { 4916 if ($('#article-table-list').length > 0 && this.value.includes('dir')) { 4917 if ($('.list-item[data-id="' + this.value + '"]').find('.state').hasClass('state_10_empty')) { 4918 ids.push(this.value); 4919 } else { 4920 someDirsNotDeleted = true; 4921 } 4922 } else { 4923 ids.push(this.value); 4924 } 4925 }); 4926 const tableName = getListTableName(); 4927 let title = translate[tableName.toLocaleUpperCase()]['DELETE_TITLE']; 4928 let message = translate[tableName.toLocaleUpperCase()]['DELETE_MESSAGE']; 4929 if (title === undefined) { 4930 title = translate[tableName.toLocaleUpperCase()]['DELETE_TITLE']; 4931 } 4932 if (message === undefined) { 4933 message = translate[tableName.toLocaleUpperCase()]['DELETE_MESSAGE']; 4934 } 4935 if (ids.some(x => (x.toString().startsWith('dir')))) { 4936 title = translate['ARTICLE']['DELETE_TITLE_DIRS_AND_ARTICLES']; 4937 message = translate['ARTICLE']['DELETE_MESSAGE_DIRS_AND_ARTICLES']; 4938 } 4939 if (await submitFormAfterConfirm(title, message)) { 4940 showLoading(translate['LOADING']); 4941 $.ajax({ 4942 type: 'POST', 4943 url: 'deletefromtablelist', 4944 cache: false, 4945 data: { 4946 tableName: tableName, 4947 ids: ids 4948 }, 4949 success: function (result) { 4950 hideLoading(); 4951 try { 4952 let data = JSON.parse(result); 4953 if (typeof data === 'object') { 4954 let deletedIds = data['deletedIds']; 4955 let deleteItemCounts = data['deleteItemCounts']; 4956 if (deletedIds.length == 0 || deletedIds.length != ids.length || someDirsNotDeleted) { 4957 let str = translate[tableName.toLocaleUpperCase()]['CAN_NOT_DELETE_EVERY_ITEM']; 4958 presentToast(str, 'fa-triangle-exclamation', 'warning'); 4959 } 4960 if (deletedIds.length > 0) { 4961 presentToast(translate['SUCCESSFULLY_DELETED'], 'fa-trash', 'success', 2000); 4962 } 4963 let articleCount = 0; 4964 deletedIds.forEach((id) => { 4965 if (tableName == 'article') { 4966 if (String(tabelListEl.find('.list-item[data-id="' + id + '"]').data('id')).startsWith('article')) { 4967 articleCount++; 4968 } 4969 } 4970 tabelListEl.find('.list-item[data-id="' + id + '"]').remove(); 4971 }); 4972 if (tableName == 'article') { 4973 deleteItemCounts = articleCount; 4974 let articleLeft = parseInt($('#open-action-sheet-add-article .info').text()); 4975 if (isNaN(articleLeft)) { 4976 articleLeft = 0; 4977 } 4978 articleLeft += articleCount; 4979 $('#open-action-sheet-add-article .info').text(articleLeft); 4980 if (articleLeft > 0) { 4981 $('#open-action-sheet-add-article').attr('data-no-articles-left', false); 4982 } 4983 } 4984 let currCount = $('#table-list-item-count').text(); 4985 currCount -= deleteItemCounts; 4986 $('#table-list-item-count').text(currCount) 4987 updateMyButtonsList(); 4988 updateArticleData(); 4989 if (tabelListEl.find('.list-item').length == 0) { 4990 tabelListEl.hide(); 4991 $('.my-hint').removeClass('hide-me'); 4992 } 4993 } else { 4994 if (result == 'IDS_EMPTY') { 4995 let str = translate['CAN_NOT_DELETE_EVERY_ITEM_' + tableName.toLocaleUpperCase()]; 4996 if (str === undefined) { 4997 str = translate[tableName.toLocaleUpperCase()]['CAN_NOT_DELETE_EVERY_ITEM']; 4998 } 4999 presentToast(str, 'fa-triangle-exclamation', 'warning'); 5000 } else { 5001 handleResult(result); 5002 } 5003 } 5004 } catch (err) { 5005 if (result == 'IDS_EMPTY') { 5006 let str = translate['CAN_NOT_DELETE_EVERY_ITEM_' + tableName.toLocaleUpperCase()]; 5007 if (str === undefined) { 5008 str = translate[tableName.toLocaleUpperCase()]['CAN_NOT_DELETE_EVERY_ITEM']; 5009 } 5010 presentToast(str, 'fa-triangle-exclamation', 'warning'); 5011 } else { 5012 handleResult(result); 5013 } 5014 } 5015 } 5016 }); 5017 } 5018}); 5019function functionDeleteFromTableList(ids) { 5020 ids.forEach(function (id) { 5021 $('.list-item[data-id="' + id + '"] .select-col input[type="checkbox"]').prop('checked', true); 5022 }); 5023 $('#table-list-delete').trigger('click'); 5024} 5025function updateArticleData() { 5026 if ($('section#article').length > 0) { 5027 $.ajax({ 5028 type: 'GET', 5029 url: 'getarticledataafterdeletetests', 5030 cache: false, 5031 data: { 5032 id: $('input[name="article_id"]').val() 5033 }, 5034 success: function (result) { 5035 try { 5036 let data = JSON.parse(result); 5037 if (data['state']) { 5038 $('.my-badge.state').attr("class").split(/\s+/).forEac
5038h((el) => { 5039 if (el.startsWith('state_')) { 5040 $('.my-badge.state').removeClass(el); 5041 } 5042 }) 5043 $('.my-badge.state').addClass(data['state'].toLowerCase()).text(getStateTranslate(data['state'])); 5044 if (data['date_next_control']) { 5045 $('input[name="date_next_control"]').val(data['date_next_control']); 5046 if (['STATE_6_IN_STOCK', 'STATE_7_NOT_BE_CHECKED', 'STATE_8_NOT_FOUND', 'STATE_5_IN_REPAIR', 'STATE_9_DISCARDED', 'STATE_10_EMPTY'].indexOf(data['state']) >= 0) { 5047 $('input[name="date_next_control"]').parents('.col-12').addClass('hide-me'); 5048 } else { 5049 $('input[name="date_next_control"]').parents('.col-12').removeClass('hide-me'); 5050 } 5051 } 5052 if (data['date_not_ok']) { 5053 $('input[name="date_not_ok"]').val(data['date_not_ok']); 5054 if (['STATE_9_DISCARDED'].indexOf(data['state']) >= 0) { 5055 $('input[name="date_not_ok"]').parents('.col-12').addClass('hide-me'); 5056 } else { 5057 $('input[name="date_not_ok"]').parents('.col-12').removeClass('hide-me'); 5058 } 5059 } 5060 } 5061 } catch (error) { 5062 handleResult(result); 5063 } 5064 } 5065 }); 5066 } 5067} 5068function loadNextItemsForTableList() { 5069 pixelsFromWindowBottomToBottom = 0 + $(document).height() - $(window).scrollTop() - $(window).height(); 5070 if (pixelsFromWindowBottomToBottom < 300) { 5071 if (!infiniteLoadElementsForTableListInit) 5072 getTableList(true); 5073 infiniteLoadElementsForTableListInit = true; 5074 } 5075} 5076function setFilterWrapperSticky() { 5077 let rem = 1; 5078 if ($(window).width() < 767) { 5079 rem = 0.5; 5080 } 5081 let filterHeight = 0; 5082 if ($('.filter-wrapper').length > 0) { 5083 if ($(window).scrollTop() > ($('.filter-wrapper-line').offset().top - $('.menu-top').outerHeight() - convertRemToPixels(rem))) { 5084 $('.filter-wrapper-line').height($('.filter-wrapper:not(.sticky)').outerHeight()); 5085 if ($('.my-breadcrumbs-wrapper').length > 0) { 5086 if ($('.my-breadcrumbs').is(':visible')) { 5087 $('.filter-wrapper-line').height($('.filter-wrapper:not(.sticky)').outerHeight() + $('.my-breadcrumbs-wrapper:not(.sticky)').outerHeight()); 5088 } else { 5089 $('.filter-wrapper').addClass('box-shadow'); 5090 } 5091 } else { 5092 $('.filter-wrapper').addClass('box-shadow'); 5093 } 5094 $('.filter-wrapper').addClass('sticky'); 5095 filterHeight = parseInt($('.filter-wrapper.sticky').css('top').match(/\d+/)[0]) + $('.filter-wrapper.sticky').outerHeight() - convertRemToPixels(0.25); 5096 } else { 5097 $('.filter-wrapper-line').height(0); 5098 $('.filter-wrapper').removeClass('sticky'); 5099 $('.filter-wrapper').removeClass('box-shadow'); 5100 filterHeight = 0; 5101 $('.my-breadcrumbs-wrapper.sticky').css('top', ''); 5102 5103 } 5104 } 5105 if ($(window).width() < 767) { 5106 rem = 0.75; 5107 } 5108 if ($('.my-breadcrumbs-wrapper').length > 0) { 5109 if ($('.my-breadcrumbs').is(':visible')) { 5110 if ($(window).scrollTop() > ($('.my-breadcrumbs-wrapper-line').offset().top - $('.menu-top').outerHeight() - convertRemToPixels(rem))) { 5111 $('.my-breadcrumbs-wrapper-line').height($('.my-breadcrumbs-wrapper:not(.sticky)').outerHeight()); 5112 $('.my-breadcrumbs-wrapper').addClass('sticky'); 5113 if (filterHeight > 0) { 5114 $('.my-breadcrumbs-wrapper.sticky').css('top', filterHeight); 5115 } 5116 } else { 5117 $('.my-breadcrumbs-wrapper-line').height(0); 5118 $('.my-breadcrumbs-wrapper').removeClass('sticky'); 5119 } 5120 } 5121 } 5122} 5123function getStickyStackedTop() { 5124 let top = $('.menu-top').length > 0 ? $('.menu-top').outerHeight() : 0; 5125 if ($('.my-breadcrumbs-wrapper').hasClass('sticky')) { 5126 top = parseFloat($('.my-breadcrumbs-wrapper').css('top')) + $('.my-breadcrumbs-wrapper').outerHeight(); 5127 } else if ($('.filter-wrapper').hasClass('sticky')) { 5128 top = parseFloat($('.filter-wrapper').css('top')) + $('.filter-wrapper').outerHeight(); 5129 } 5130 return top; 5131} 5132function getOrCreateTableHeadRowClone() { 5133 let $wrapper = $('.head-row-clone-wrapper'); 5134 if ($wrapper.length === 0) { 5135 let $origRow = $('.my-table-list .head-row');
5136 $wrapper = $('<div class="head-row-clone-wrapper"><div class="table-list-inner"></div></div>'); 5137 $('body').append($wrapper); 5138 $wrapper.on('change', '.select-col input[type="checkbox"]', function () { 5139 $origRow.find('.select-col input[type="checkbox"]').prop('checked', $(this).is(':checked')).trigger('change'); 5140 }); 5141 $wrapper.on('click', '.sort-col', function (e) { 5142 e.preventDefault(); 5143 let colName = $(this).data('col-name'); 5144 $origRow.find('.sort-col[data-col-name="' + colName + '"]').trigger('click'); 5145 }); 5146 } 5147 return $wrapper; 5148} 5149function rebuildTableHeadRowClone() { 5150 let $origRow = $('.my-table-list .head-row'); 5151 if ($origRow.length === 0) { 5152 return; 5153 } 5154 let $wrapper = getOrCreateTableHeadRowClone(); 5155 $wrapper.find('.table-list-inner').html($origRow.clone(false).prop('outerHTML')); 5156 let $cloneRow = $wrapper.find('.head-row'); 5157 let widths = []; 5158 $origRow.find('> .cell').each(function () { 5159 widths.push($(this).outerWidth()); 5160 }); 5161 $cloneRow.find('> .cell').each(function (i) { 5162 $(this).css({ width: widths[i], minWidth: widths[i], maxWidth: widths[i], boxSizing: 'border-box' }); 5163 }); 5164 syncTableHeadRowCheckbox(); 5165 updateTableHeadRowTransform(); 5166} 5167function syncTableHeadRowCheckbox() { 5168 let $origCheckbox = $('.my-table-list .head-row .select-col input[type="checkbox"]'); 5169 let $cloneCheckbox = $('.head-row-clone-wrapper .head-row .select-col input[type="checkbox"]'); 5170 if ($origCheckbox.length > 0 && $cloneCheckbox.length > 0) { 5171 $cloneCheckbox.prop('checked', $origCheckbox.is(':checked')); 5172 } 5173} 5174function updateTableHeadRowTransform() { 5175 let $tableList = $('.my-table-list'); 5176 $('.head-row-clone-wrapper').css('top', getStickyStackedTop()) 5177 .find('.table-list-inner').css('transform', 'translateX(' + (-$tableList.scrollLeft()) + 'px)'); 5178} 5179let tableHeadRowWasActive = false; 5180function setTableHeadRowSticky() { 5181 let $origRow = $('.my-table-list .head-row'); 5182 if ($origRow.length === 0 || !$origRow.is(':visible')) { 5183 $('.head-row-clone-wrapper').removeClass('active'); 5184 tableHeadRowWasActive = false; 5185 return; 5186 } 5187 let isActive = $origRow[0].getBoundingClientRect().top < getStickyStackedTop(); 5188 if (isActive) { 5189 if (!tableHeadRowWasActive) { 5190 rebuildTableHeadRowClone(); 5191 } else { 5192 updateTableHeadRowTransform(); 5193 } 5194 $('.head-row-clone-wrapper').addClass('active'); 5195 } else { 5196 $('.head-row-clone-wrapper').removeClass('active'); 5197 } 5198 tableHeadRowWasActive = isActive; 5199} 5200let tableHeadRowHorizontalRAF = null; 5201$('.my-table-list').on('scroll', function () { 5202 if (!$('.head-row-clone-wrapper').hasClass('active') || tableHeadRowHorizontalRAF) { 5203 return; 5204 } 5205 tableHeadRowHorizontalRAF = requestAnimationFrame(function () { 5206 updateTableHeadRowTransform(); 5207 tableHeadRowHorizontalRAF = null; 5208 }); 5209}); 5210$(document).on('wheel', '.head-row-clone-wrapper', function (e) { 5211 let oe = e.originalEvent; 5212 let deltaX = oe.deltaX; 5213 if (deltaX === 0 && oe.shiftKey) { 5214 deltaX = oe.deltaY; 5215 } 5216 if (deltaX !== 0 && Math.abs(deltaX) >= Math.abs(oe.deltaY)) { 5217 e.preventDefault(); 5218 $('.my-table-list').scrollLeft($('.my-table-list').scrollLeft() + deltaX); 5219 } 5220}); 5221$(window).on('resize', function () { 5222 if ($('.head-row-clone-wrapper').hasClass('active')) { 5223 rebuildTableHeadRowClone(); 5224 } 5225}); 5226if ($('.filter-wrapper').length > 0 || $('.my-breadcrumbs-wrapper').length > 0) { 5227 setFilterWrapperSticky(); 5228} 5229if ($('.my-table-list').length > 0) { 5230 setTableHeadRowSticky(); 5231} 5232let mainScrollRAF = null; 5233$(window).scroll(function (e) { 5234 if (mainScrollRAF) { 5235 return; 5236 } 5237 mainScrollRAF = requestAnimationFrame(function () { 5238 mainScrollRAF = null; 5239 if ($('.filter-wrapper').length > 0 || $('.my-breadcrumbs-wrapper').length > 0) { 5240 setFilterWrapperSticky(); 5241 } 5242 if ($('.my-table-list').length > 0) {
5243 loadNextItemsForTableList(); 5244 setTableHeadRowSticky(); 5245 } 5246 }); 5247}); 5248function markMultipleListItems(currEl) { 5249 if ($('.list-item .select-col input[type="checkbox"]:checked').length > 0) { 5250 let index = $('.list-item .select-col input[type="checkbox"]').index(currEl); 5251 let indexes = []; 5252 $('.list-item .select-col input[type="checkbox"]:checked').each(function (i, e) { 5253 indexes.push($('.list-item .select-col input[type="checkbox"]').index(e)); 5254 }); 5255 indexes.sort((a, b) => { 5256 return Math.abs(index - a) - Math.abs(index - b); 5257 }); 5258 let nearstIndex = indexes[0]; 5259 if (nearstIndex > index) { 5260 for (let i = nearstIndex; i > index; i--) { 5261 $('.row.list-item').eq(i).find('.select-col input[type="checkbox"]:not(:disabled)').prop('checked', true) 5262 } 5263 } else { 5264 for (let i = nearstIndex; i < index; i++) { 5265 $('.row.list-item').eq(i).find('.select-col input[type="checkbox"]:not(:disabled)').prop('checked', true) 5266 } 5267 } 5268 } 5269} 5270$(document).on('click', '.list-item .select-col input[type="checkbox"]', function (e) { 5271 e.preventDefault(); 5272 e.stopImmediatePropagation(); 5273}); 5274$(document).on('mouseup', '.list-item .select-col input[type="checkbox"]', function (e) { 5275 e.preventDefault(); 5276 $(this).prop('checked', !$(this).prop('checked')); 5277 updateMyButtonsList(); 5278 5279}); 5280$(document).on('mousedown', '.list-item .select-col input[type="checkbox"]', function (e) { 5281 if (e.shiftKey && $('.list-item .select-col input[type="checkbox"]:checked').length > 0) { 5282 if (e.shiftKey) { 5283 markMultipleListItems($(this)); 5284 } 5285 } 5286}); 5287 5288$(document).on('change', '.my-table-list .list-item .select-col input[type="checkbox"]', function () { 5289 updateMyButtonsList(); 5290}); 5291function updateMyButtonsList() { 5292 const thisCheckedCheckboxes = $('.my-table-list .list-item .select-col input[type="checkbox"]:checked'); 5293 const thisCheckboxes = $('.my-table-list .list-item .select-col input[type="checkbox"]'); 5294 if (thisCheckedCheckboxes.length > 0) { 5295 $('.my-buttons-list .table-list-checkbox-show').removeClass('hide-me'); 5296 $('.my-buttons-list .table-list-checkbox-hide').addClass('hide-me'); 5297 if (thisCheckedCheckboxes.length === thisCheckboxes.length) { 5298 $('#table-list-selected-count').text('(' + translate['ALL'] + ')'); 5299 } else { 5300 $('#table-list-selected-count').text('(' + thisCheckedCheckboxes.length + ')'); 5301 } 5302 } else { 5303 $('.my-table-list').removeClass('long-pressed'); 5304 $('.my-buttons-list .table-list-checkbox-show').addClass('hide-me'); 5305 $('.my-buttons-list .table-list-checkbox-hide').removeClass('hide-me'); 5306 $('#table-list-selected-count').text(''); 5307 } 5308 if (thisCheckedCheckboxes.length == 1 && $('.my-table-list .list-item .select-col input[type="checkbox"]:checked').parents('.list-item').attr('id').startsWith('dir')) { 5309 $('.my-buttons-list .my-drop-down .option.show-select-only-one-dir').removeClass('hide-me') 5310 } else { 5311 $('.my-buttons-list .my-drop-down .option.show-select-only-one-dir').addClass('hide-me') 5312 } 5313 if (thisCheckedCheckboxes.length == 1 && $('.my-table-list .list-item .select-col input[type="checkbox"]:checked').parents('.list-item').attr('id').startsWith('article')) { 5314 $('.my-buttons-list .my-drop-down .option.show-select-only-one-article').removeClass('hide-me') 5315 } else { 5316 $('.my-buttons-list .my-drop-down .option.show-select-only-one-article').addClass('hide-me') 5317 } 5318 if ($('.my-table-list .list-item .select-col input[type="checkbox"]:checked').parents('.list-item').toArray().some(x => $(x).attr('id').startsWith('article'))) { 5319 $('.my-buttons-list .my-drop-down .option.show-select-article').removeClass('hide-me') 5320 } else { 5321 $('.my-buttons-list .my-drop-down .option.show-select-article:not(.show-select-dir)').addClass('hide-me'); 5322 } 5323 if ($('.my-table-list .list-item .select-col input[type="checkbox"]:checked').parents('.list-item').toArray().some(x => $(x).attr('id').startsWith('dir'))) { 5324 $('.my-buttons-list .my-drop-down .option.show-select-dir').removeClass('hide-me') 5325 } else { 5326 $('.my-buttons-list .my-drop-down .option.show-select-dir:not(.show-select-article)').addClass('hide-me'); 5327 } 5328 if (thisCheckedCheckboxes.length == 1) { 5329 $('.my-buttons-list .my-drop-down .option.show-select-only-one').removeClass('hide-me') 5330 } else { 5331 $('.my-buttons-list .my-drop-down .option.show-select-only-one').addClass('hide-me') 5332 } 5333 if (thisCheckedCheckboxes.length != thisCheckboxes.length || thisCheckedCheckboxes.length <= 0) { 5334 $('.my-table-list .head-row .select-col input[type="checkbox"]').prop('checked', false); 5335 } 5336 syncTableHeadRowCheckbox(); 5337} 5338$('.my-table-list .head-row .select-col input[type="checkbox"]').change(function () { 5339 if ($(this).prop('checked')) 5340 $('.my-table-list .list-item .select-col input[type="checkbox"]').prop('checked', true); 5341 else 5342 $('.my-table-list .list-item .select-col input[type="checkbox"]').prop('checked', false); 5343 updateMyButtonsList(); 5344}); 5345let autoCompleteRequest = null; 5346function getAutoComplete() { 5347 $('#loading-bar').hide(); 5348 if (autoCompleteRequest != null) { 5349 autoCompleteRequest.abort(); 5350 } 5351 return new Promise(function (resolve) { 5352 const val = $('.my-table-list-filter-search').val(); 5353 if (val.length > 0) { 5354 $('#loading-bar').show(); 5355 const filter = getFilter(); 5356 const tableName = $('.my-table-list').data('table-name'); 5357 autoCompleteRequest = $.ajax({ 5358 type: 'POST', 5359 url: 'getautocomplete', 5360 cache: false, 5361 data: { 5362 tableName: tableName, 5363 filter: filter, 5364 currentSearchString: val 5365 }, 5366 success: function (result) { 5367 try { 5368 let data = JSON.parse(result); 5369 $('.my-auto-complete .results').children().remove(); 5370 data.forEach((result, idx) => { 5371 let resultEl = document.createElement('div'); 5372 resultEl.className = 'result'; 5373 resultEl.setAttribute('data-search-str', result['search_str']); 5374 5375 let resultType = document.createElement('span'); 5376 resultType.className = 'type'; 5377 resultType.textContent = translate['AUTOCOMPLETE'][result['type']]; 5378 5379 let resultValue = document.createElement('span'); 5380 resultValue.className = 'word'; 5381 resultValue.textContent = result['word'] + ((resultType.textContent !== '') ? ' - ' : ''); 5382 5383 resultEl.appendChild(resultValue); 5384 resultEl.appendChild(resultType); 5385 $('.my-auto-complete .results').append(resultEl); 5386 }); 5387 $('.my-auto-complete').removeClass('hide-me'); 5388 } catch (error) { 5389 handleResult(result, error); 5390 } 5391 $('#loading-bar').hide(); 5392 autoCompleteRequest = null; 5393 resolve(true); 5394 } 5395 }); 5396 } else { 5397 $('.my-auto-complete .results').children().remove(); 5398 $('.my-auto-complete').addClass('hide-me'); 5399 resolve(true); 5400 } 5401 }); 5402} 5403$('.my-table-list-filter-search').on('input', function (e) { 5404 getAutoComplete(); 5405}); 5406$('.my-table-list-filter-search').on('focus', function (e) { 5407 if ($(this).val().length > 0 && $('.my-auto-complete .result').length > 0) 5408 $('.my-auto-complete').removeClass('hide-me'); 5409}); 5410$('.my-table-list-filter-search').on('blur', function (e) { 5411 $('.my-auto-complete').addClass('hide-me'); 5412}); 5413function isTouchDevice() { 5414 return (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)); 5415} 5416$('.clear-search').click(function (e) { 5417 $(this).parents('.my-input').find('.my-table-list-filter-search').val(''); 5418 updateFilter('searchStr', encodeURI($('.my-table-list-filter-search').val())); 5419 updateClearSearch($('.my-table-list-filter-search')); 5420 getTableList(false); 5421 $('.my-auto-complete').addClass('hide-me'); 5422 if (!isTouchDevice()) { 5423 $(this).parents('.my-input').find('.my-table-list-filter-search').focus(); 5424 } 5425}); 5426$(document).on('mousedown', '.my-auto-complete .result', function (e) { 5427 $('.my-table-list-filter-search').val($(this).data('search-str')).blur(); 5428 $('.my-auto-complete').addClass('hide-me'); 5429 updateFilter('searchStr', encodeURI($('.my-table-list-filter-search').val())); 5430 getTableList(false, true); 5431 e.preventDefault(); 5432}); 5433$('.my-table-list-filter-search').on('keydown', function (e) { 5434 let autoCompleteEl = $('.my-auto-complete'); 5435 if (e.key === "Enter") { 5436 if (autoCompleteEl.is(':visible')) { 5437 if (autoCompleteEl.find('.result.active').length > 0) { 5438 $('.my-table-list-filter-search').val(autoCompleteEl.find('.result.active').data('search-str')); 5439 } 5440 } 5441 updateFilter('searchStr', encodeURI($('.my-table-list-filter-search').val())); 5442 getTableList(false, true); 5443 $('.my-auto-complete').addClass('hide-me'); 5444 } else if (e.key === "ArrowDown") { 5445 e.preventDefault(); 5446 getNextResult(1); 5447 } else if (e.key === "ArrowUp") { 5448 e.preventDefault(); 5449 getNextResult(-1); 5450 } else if (e.key === "Tab") { 5451 e.preventDefault(); 5452 if (autoCompleteEl.find('.result.active').length > 0) { 5453 $('.my-table-list-filter-search').val(autoCompleteEl.find('.result.active').data('search-str')); 5454 } 5455 } else if (e.key === "ArrowRight") { 5456 if (autoCompleteEl.find('.result.active').length > 0) { 5457 $('.my-table-list-filter-search').val(autoCompleteEl.find('.result.active').data('search-str')); 5458 } 5459 } else if (e.key === 'Escape') { 5460 e.preventDefault(); 5461 $('.my-auto-complete').addClass('hide-me'); 5462 } 5463}); 5464function getNextResult(factor) { 5465 let autoCompleteEl = $('.my-auto-complete'); 5466 let l = autoCompleteEl.find('.result').length; 5467 if (autoCompleteEl.find('.result.active').length > 0) { 5468 let currentIndex = autoCompleteEl.find('.result').index(autoCompleteEl.find('.result.active')); 5469 let nextIndex = currentIndex + factor; 5470 autoCompleteEl.find('.result.active').removeClass('active'); 5471 if (nextIndex >= 0 && nextIndex < l) { 5472 $(autoCompleteEl.find('.result').get(nextIndex)).addClass('active'); 5473 } else if (nextIndex < 0) { 5474 $(autoCompleteEl.find('.result').get((l - 1))).addClass('active'); 5475 } else if (nextIndex >= l) { 5476 $(autoCompleteEl.find('.result').get(0)).addClass('active'); 5477 } 5478 } else { 5479 if (factor > 0) { 5480 $(autoCompleteEl.find('.result').get(0)).addClass('active'); 5481 } else { 5482 $(autoCompleteEl.find('.result').get((l - 1))).addClass('active'); 5483 } 5484 } 5485} 5486 5487// END-TABLE-LIST FUNCTIONS 5488 5489// USER FUNCTIONS 5490$('#edituser-form input[name="admin"]').on("change", function (e) { 5491 if ($(this).prop('checked')) { 5492 $('#edituser-form [name="usergroup_id"]').parents('.my-input').addClass('hide-me'); 5493 $('#edituser-form [name="can_see_all_folders"]').parents('.my-input').addClass('hide-me'); 5494 $('#user-dir-select').addClass('hide-me'); 5495 5496 } else { 5497 $('#edituser-form [name="usergroup_id"]').parents('.my-input').removeClass('hide-me'); 5498 $('#edituser-form [name="can_see_all_folders"]').parents('.my-input').removeClass('hide-me'); 5499 if ($('#edituser-form select[name="can_see_all_folders"]').val() === '0') { 5500 $('#user-dir-select').removeClass('hide-me'); 5501 } 5502 } 5503}); 5504$('#edituser-form select[name="can_see_all_folders"], #editusergroup-form input[name="can_see_all_folders"]').on("change", function (e) { 5505 let val = 0; 5506 if ($(this).get(0).nodeName == 'INPUT') { 5507 val = $(this).prop('checked'); 5508 } else { 5509 val = $(this).val(); 5510 } 5511 if (val == 0) { 5512 $('#user-dir-select').removeClass('hide-me'); 5513 } else { 5514 $('#user-dir-select').addClass('hide-me'); 5515 } 5516}); 5517$('#edituser-form [readonly]:not(.remove-read-only)').on("click", function (e) { 5518 presentToast(translate['USER']['CAN_NOT_EDIT_HAS_OTHER_ACCOUNTS'], 'fa-triangle-exclamation', 'warning'); 5519}); 5520$('#user-dir-select input[type="checkbox"]').change(function () { 5521 let val = $(this).val().split('-')[1]; 5522 let id = $(this).data('id'); 5523 if (!$(this).prop("checked") && val == '1') { 5524 $(this).val(id + '-0'); 5525 $(this).prop("checked", true); 5526 // $(this).parents('.input-box').find('+ .sub-cat input[type="checkbox"]').each(function (idx, el) { 5527 // $(el).prop('checked', true).val($(el).data('id') + '-0'); 5528 // }) 5529 } else if ($(this).prop("checked") && val == '0') { 5530 $(this).val('1'); 5531 $(this).prop("checked", false); 5532 } else if (!$(this).prop("checked") && val == '0') { 5533 $(this).val(id + '-1'); 5534 // $(this).parents('.input-box').find('+ .sub-cat input[type="checkbox"]').each(function (idx, el) { 5535 // $(el).prop('checked', false).val($(el).data('id') + '-1'); 5536 // }) 5537 } else { 5538 $(this).parents('.list-item').find('> .input-box input[type="checkbox"]').each(function (idx, el) { 5539 $(el).prop('checked', true).val($(el).data('id') + '-1'); 5540 }) 5541 } 5542}); 5543function updateChecklistUserDirsParents() { 5544 $('#user-dir-select.my-input.checklist .list-item').each((idx, el) => { 5545 const subCatEl = $(el).find('.sub-cat'); 5546 const checkboxes = subCatEl.find('input[type="checkbox"]:not(.parent)'); 5547 const leng = checkboxes.length; 5548 if (leng > 0) { 5549 let count = 0; 5550 checkboxes.each((idx, el) => { 5551 if ($(el).prop('checked') && $(el).val('1')) 5552 count++; 5553 }); 5554 if (count == leng) { 5555 $(el).find('>.input-box input[type="checkbox"]').prop('checked', true).val('1'); 5556 } 5557 } 5558 }); 5559} 5560// END-USER FUNCTIONS 5561// USERGROUP FUNCTIONS 5562if ($('#usergroup-rights.my-input.checklist').length > 0) { 5563 updateChecklistParents(); 5564} 5565function updateChecklistParents() { 5566 $('#usergroup-rights.my-input.checklist .list-item').each((idx, el) => { 5567 const subCatEl = $(el).find('.sub-cat'); 5568 const checkboxes = subCatEl.find('input[type="checkbox"]:not(.parent)'); 5569 const leng = checkboxes.length; 5570 if (leng > 0) { 5571 let count = 0; 5572 checkboxes.each((idx, el) => { 5573 if ($(el).prop('checked')) 5574 count++; 5575 }); 5576 if (count == leng) { 5577 $(el).find('>.input-box input[type="checkbox"]').prop('checked', true); 5578 } else { 5579 $(el).find('>.input-box input[type="checkbox"]').prop('checked', false); 5580 } 5581 } 5582 }); 5583} 5584$('#usergroup-rights.my-input.checklist input[type="checkbox"]').change(function (e) { 5585 if ($(this).hasClass('parent')) { 5586 $(this).closest('.list-item').find('input[type="checkbox"]').prop('checked', $(this).prop('checked')); 5587 } 5588 updateChecklistParents(); 5589}); 5590// END-USERGROUP FUNCTIONS 5591// BILL FUNCTIONS 5592async function downloadBill(el) { 5593 let id = el.data('id'); 5594 await showLoading(translate['TEST']['FILE_WILL_BE_EXPORTED']); 5595 $.ajax({ 5596 type: 'POST', 5597 url: 'getbillbase64', 5598 cache: false, 5599 data: { 5600 id: id 5601 }, 5602 success: async function (result) { 5603 try { 5604 let data = JSON.parse(result); 5605 let base64 = data['base64']; 5606 let fileName = data['filename']; 5607 await downloadFile(base64, fileName, 'application/pdf'); 5608 } catch (err) { 5609 ha
5609ndleResult(result, err); 5610 } 5611 }, 5612 }); 5613} 5614$(document).on('click', '.my-table-list .get-bill-pdf', function (e) { 5615 console.log('Ss'); 5616 5617 if ($(e.target).prop("tagName") !== 'INPUT') 5618 downloadBill($(this)); 5619}) 5620$(document).on('change', '#export-popup #file_type', function () { 5621 initForPDFSelect(); 5622}); 5623function initForPDFSelect() { 5624 const val = $('#export-popup #file_type').val(); 5625 if (val == 'PDF') { 5626 $('#export-popup .for-pdf').removeClass('hide-me'); 5627 } else { 5628 $('#export-popup .for-pdf').addClass('hide-me'); 5629 } 5630 if (val == 'EXCEL') { 5631 $('#export-popup .for-excel').removeClass('hide-me'); 5632 } else { 5633 $('#export-popup .for-excel').addClass('hide-me'); 5634 } 5635 if (val == 'EXCEL' || val == 'CSV') { 5636 $('#export-popup #date_format').val('d.m.Y'); 5637 } 5638} 5639// END-BILL FUNCTIONS 5640// MODELCATEGORY FUNCTIONS 5641 5642$(document).on('click', '#open-action-sheet-add-model_category', async function () { 5643 openActionSheetAddModelCategory(); 5644}); 5645async function openActionSheetAddModelCategory(redirect = '') { 5646 let buttons = []; 5647 buttons.push({ 5648 icon: '<i class="fa-solid fa-cloud-arrow-down"></i>', 5649 text: translate['MODEL_CATEGORY']['IMPORT_FROM_DB'], 5650 style: 'default', 5651 handler: async () => { 5652 window.open('model_categories/central_model_categories' + redirect, '_self'); 5653 closeMyActionSheet($('#icon-action-sheet')); 5654 } 5655 }); 5656 const icon = await getSVG('resources/images/icons/add-model_category.svg'); 5657 buttons.push({ 5658 icon: icon, 5659 text: translate['MODEL_CATEGORY']['ADD_OWN'], 5660 style: 'default', 5661 handler: (e) => { 5662 window.open('model_categories/editmodel_category' + redirect, '_self'); 5663 closeMyActionSheet($('#icon-action-sheet')); 5664 } 5665 }); 5666 buttons.push({ 5667 icon: '<i class="fa-solid fa-table-list"></i>', 5668 text: translate['MODEL_CATEGORY']['ADD_MULTIPLE'], 5669 style: 'default', 5670 handler: (e) => { 5671 window.open('model_categories/editmultiple?type=model_category&new=1', '_self'); 5672 closeMyActionSheet($('#icon-action-sheet')); 5673 } 5674 }); 5675 // Abbrechen 5676 buttons.push({ 5677 icon: '<i class="fa-solid fa-ban"></i>', 5678 text: translate['DISMISS'], 5679 style: 'default', 5680 handler: () => { 5681 closeMyActionSheet($('#icon-action-sheet')); 5682 } 5683 }); 5684 myActionSheet(translate['ADD'], 'icon-action-sheet', buttons); 5685}; 5686// END-MODELCATEGORY FUNCTIONS 5687// MANUFACTURE FUNCTIONS 5688 5689$(document).on('click', '#open-action-sheet-add-manufacture', async function () { 5690 openActionSheetAddManufacture(); 5691}); 5692async function openActionSheetAddManufacture(redirect = '') { 5693 let buttons = []; 5694 buttons.push({ 5695 icon: '<i class="fa-solid fa-cloud-arrow-down"></i>', 5696 text: translate['MANUFACTURE']['IMPORT_FROM_DB'], 5697 style: 'default', 5698 handler: async () => { 5699 window.open('manufactures/central_manufactures' + redirect, '_self'); 5700 closeMyActionSheet($('#icon-action-sheet')); 5701 } 5702 }); 5703 const icon = await getSVG('resources/images/icons/add-manufacture.svg') 5704 buttons.push({ 5705 icon: icon, 5706 text: translate['MANUFACTURE']['ADD_OWN'], 5707 style: 'default', 5708 handler: (e) => { 5709 window.open('manufactures/editmanufacture' + redirect, '_self'); 5710 closeMyActionSheet($('#icon-action-sheet')); 5711 } 5712 }); 5713 buttons.push({ 5714 icon: '<i class="fa-solid fa-table-list"></i>', 5715 text: translate['MANUFACTURE']['ADD_MULTIPLE'], 5716 style: 'default', 5717 handler: (e) => { 5718 window.open('manufactures/editmultiple?type=manufacture&new=1', '_self'); 5719 closeMyActionSheet($('#icon-action-sheet')); 5720 } 5721 }); 5722 // Abbrechen 5723 buttons.push({ 5724 icon: '<i class="fa-solid fa-ban"></i>', 5725 text: translate['DISMISS'], 5726 style: 'default', 5727 handler: () => { 5728 closeMyActionSheet($('#icon-action-sheet')); 5729 } 5730 }); 5731 myActionSheet(translate['ADD'], 'icon-action-sheet', buttons); 5732} 5733// END-MANUFACTURE FUNCTIONS 5734// MODEL FUNCTIONS
5735$(document).on('click', '#disconnect-from-db', async function () { 5736 if (await submitFormAfterConfirm(translate['MODEL']['DISCONNECT_FROM_CENTRAL_DB_TITLE'], translate['MODEL']['DISCONNECT_FROM_CENTRAL_DB_MESSAGE'])) { 5737 const id = $(this).data('id'); 5738 const tableName = $(this).data('table-name'); 5739 $('#loading-bar').show(); 5740 $.ajax({ 5741 type: 'POST', 5742 url: 'disconnectfromcentraldb', 5743 cache: false, 5744 data: { 5745 id: id, 5746 tableName: tableName 5747 }, 5748 success: async function (result) { 5749 $('#loading-bar').hide(); 5750 if (result == 'success') { 5751 $('#disconnect-from-db').remove(); 5752 presentToast(translate['MODEL']['DISCONNECTED'], 'fa-check', 'success', 2000); 5753 } else { 5754 console.log(result); 5755 } 5756 } 5757 }); 5758 } 5759}); 5760$(document).on('click', '#open-action-sheet-add-model', async function () { 5761 openActionSheetAddModel(); 5762}); 5763async function openActionSheetAddModel(redirect = '') { 5764 await ensureTranslate(); 5765 let buttons = []; 5766 buttons.push({ 5767 icon: '<i class="fa-solid fa-cloud-arrow-down"></i>', 5768 text: translate['MODEL']['IMPORT_FROM_DB'], 5769 style: 'default', 5770 handler: async () => { 5771 window.open('models/central_models' + redirect, '_self'); 5772 closeMyActionSheet($('#icon-action-sheet')); 5773 } 5774 }); 5775 const icon = await getSVG('resources/images/icons/add-model.svg') 5776 buttons.push({ 5777 icon: icon, 5778 text: translate['MODEL']['ADD_OWN'], 5779 style: 'default', 5780 handler: (e) => { 5781 window.open('models/editmodel' + redirect, '_self'); 5782 closeMyActionSheet($('#icon-action-sheet')); 5783 } 5784 }); 5785 buttons.push({ 5786 icon: '<i class="fa-solid fa-table-list"></i>', 5787 text: translate['MODEL']['ADD_MULTIPLE'], 5788 style: 'default', 5789 handler: (e) => { 5790 window.open('models/editmultiple?type=model&new=1', '_self'); 5791 closeMyActionSheet($('#icon-action-sheet')); 5792 } 5793 }); 5794 // Abbrechen 5795 buttons.push({ 5796 icon: '<i class="fa-solid fa-ban"></i>', 5797 text: translate['DISMISS'], 5798 style: 'default', 5799 handler: () => { 5800 closeMyActionSheet($('#icon-action-sheet')); 5801 } 5802 }); 5803 myActionSheet(translate['ADD'], 'icon-action-sheet', buttons); 5804} 5805$('#editmodel input[name="model_category_random_id"]').bind("change", function () { 5806 let id = $(this).val(); 5807 let path = $('#model_image .prev-img').data('path-to-model-category-img'); 5808 if (id != '') { 5809 $.ajax({ 5810 url: path + id + '.svg', 5811 type: 'HEAD', 5812 success: function () { 5813 if (!$('#model_image .prev-img').css('background-image').includes('data:image')) { 5814 $('#model_image .prev-img').css('background-image', 'url(' + path + id + '.svg)'); 5815 } 5816 $('#model_image .prev-img').attr('data-default', path + id + '.svg'); 5817 } 5818 }); 5819 } 5820}); 5821$('#editarticle input[name="model_img_val"]').bind("change", function () { 5822 let bgCss = $(this).val(); 5823 if (bgCss != '') { 5824 $('.prev-img').css('background-image', bgCss); 5825 } 5826}); 5827$(document).on('click', '#checklists .checklist .toggle-questions', function () { 5828 $(this).parents('.checklist').toggleClass('open'); 5829 $(this).parents('.checklist').find('.questions').slideToggle(300); 5830}); 5831function updateQuestions(list) { 5832 list.find('.question').each(function (idx, el) { 5833 $(el).find('.number').text((idx + 1) + '.'); 5834 }) 5835} 5836function updateChecklists(list) { 5837 $('#checklists .checklist').each(function (idx, el) { 5838 $(el).find('[name*="checklist-id-"]').attr('name', ('checklist-id-' + idx)); 5839 $(el).find('[name*="checklist-name-"]').attr('name', ('checklist-name-' + idx)); 5840 $(el).find('[id*="checklist-name-"]').attr('id', ('checklist-name-' + idx)); 5841 $(el).find('[for*="checklist-name-"]').attr('for', ('checklist-name-' + idx)); 5842 $(el).find('[name*="checklist-controllinterval-"]').attr('name', ('checklist-controllinterval-' + idx)); 5843 $(el).find('[name*="checklist-controllinterval_input-"]').attr('name', ('checklist-controllinterval_input-' + idx)); 5844 $(el).find('[name*="time_unit_controllinterval_input-"]').attr('name', ('checklist-time_unit_controllinterval_input-' + idx)); 5845 $(el).find('[id*="checklist-controllinterval-"]').attr('id', ('checklist-controllinterval-' + idx)); 5846 $(el).find('[id*="checklist-controllinterval_input-"]').attr('id', ('checklist-controllinterval_input-' + idx)); 5847 $(el).find('[id*="time_unit_controllinterval_input-"]').attr('id', ('checklist-time_unit_controllinterval_input-' + idx)); 5848 $(el).find('[name*="question-"]').attr('name', ('question-' + idx + '[]')); 5849 $(el).find('[id*="question-"]').attr('id', ('question-' + idx + '[]')); 5850 $(el).find('[name*="type-"]').attr('name', ('type-' + idx + '[]')); 5851 $(el).find('[id*="type-"]').attr('id', ('type-' + idx + '[]')); 5852 }); 5853} 5854$(document).on('click', '#checklists .remove-checklist', function () {
5855 let checklistEl = $(this).parents('.checklist'); 5856 checklistEl.remove(); 5857 updateChecklists(); 5858}); 5859 5860$(document).on('click', '#checklists .questions .remove-question', function () { 5861 let questionEl = $(this).parents('.question'); 5862 let list = $(this).parents('.list'); 5863 questionEl.remove(); 5864 updateQuestions(list); 5865}); 5866 5867if ($('.questions .list').length > 0) { 5868 $('.questions .list').each(function (idx, el) { 5869 new Sortable(el, { 5870 filter: '.my-button', 5871 handle: '.move-icon', 5872 onUpdate: function (evt) { 5873 updateQuestions($(evt.item).parents('.list')); 5874 }, 5875 }); 5876 }); 5877} 5878async function addChecklist(scroll = true, withQuestions = true) { 5879 let checklist = document.createElement('div'); 5880 checklist.className = 'checklist'; 5881 5882 let checklistInfo = document.createElement('div'); 5883 checklistInfo.className = 'infos'; 5884 checklist.appendChild(checklistInfo); 5885 5886 let iconShow = document.createElement('i'); 5887 iconShow.className = 'fa-solid fa-plus icon-show toggle-questions'; 5888 checklistInfo.appendChild(iconShow); 5889 5890 let iconHide = document.createElement('i'); 5891 iconHide.className = 'fa-solid fa-minus icon-hide toggle-questions'; 5892 checklistInfo.appendChild(iconHide); 5893 5894 let inputChecklistId = document.createElement('input'); 5895 inputChecklistId.setAttribute('type', 'hidden'); 5896 inputChecklistId.setAttribute('name', 'checklist-id-'); 5897 inputChecklistId.setAttribute('value', ''); 5898 checklistInfo.appendChild(inputChecklistId); 5899 5900 let inputs = document.createElement('div'); 5901 inputs.className = 'inputs'; 5902 checklistInfo.appendChild(inputs); 5903 5904 let nameInput = document.createElement('div'); 5905 nameInput.className = 'my-input with-icon'; 5906 inputs.appendChild(nameInput); 5907 5908 let nameInputContainer = document.createElement('div'); 5909 nameInputContainer.className = 'input-container'; 5910 nameInput.appendChild(nameInputContainer); 5911 5912 let nameInputEl = document.createElement('input'); 5913 nameInputEl.setAttribute('type', 'text'); 5914 nameInputEl.setAttribute('name', 'checklist-name-'); 5915 nameInputEl.setAttribute('id', 'checklist-name-'); 5916 nameInputEl.setAttribute('placeholder', ' '); 5917 nameInputEl.setAttribute('value', ''); 5918 nameInputEl.setAttribute('maxlength', '200'); 5919 nameInputContainer.appendChild(nameInputEl); 5920 5921 let nameInputLabel = document.createElement('label'); 5922 nameInputLabel.setAttribute('for', 'checklist-name-'); 5923 nameInputLabel.innerText = translate['MODEL']['NAME']; 5924 nameInputContainer.appendChild(nameInputLabel); 5925 5926 let nameInputIcon = document.createElement('i'); 5927 nameInputIcon.className = 'fa-solid fa-hashtag'; 5928 nameInputContainer.appendChild(nameInputIcon); 5929 5930 let nameInputError = document.createElement('div'); 5931 nameInputError.className = 'input-error'; 5932 nameInputError.setAttribute('data-error1', translate['MODEL']['ERROR']['NAME']); 5933 nameInput.appendChild(nameInputError); 5934 5935 let controllIntervalInput = document.createElement('div'); 5936 controllIntervalInput.className = 'my-input time-input with-icon'; 5937 inputs.appendChild(controllIntervalInput); 5938 5939 let controllIntervalInputContainer = document.createElement('div'); 5940 controllIntervalInputContainer.className = 'input-container'; 5941 controllIntervalInput.appendChild(controllIntervalInputContainer); 5942 5943 let controllIntervalInputEl = document.createElement('input'); 5944 controllIntervalInputEl.setAttribute('type', 'hidden'); 5945 controllIntervalInputEl.setAttribute('name', 'checklist-controllinterval-'); 5946 controllIntervalInputEl.setAttribute('id', 'checklist-controllinterval-'); 5947 controllIntervalInputEl.setAttribute('placeholder', ' '); 5948 controllIntervalInputEl.setAttribute('value', ''); 5949 controllIntervalInputContainer.appendChild(controllIntervalInputEl); 5950 5951 let controllIntervalInputEl2 = document.createElement('input'); 5952 controllIntervalInputEl2.setAttribute('type', 'text'); 5953 controllIntervalInputEl2.setAttribute('name', 'checklist-controllinterval_input-'); 5954 controllIntervalInputEl2.setAttribute('id', 'checklist-controllinterval_input-'); 5955 controllIntervalInputEl2.setAttribute('placeholder', ' '); 5956 controllIntervalInputEl2.setAttribute('value', ''); 5957 controllIntervalInputContainer.appendChild(controllIntervalInputEl2); 5958
5959 let controllIntervalSelect = document.createElement('select'); 5960 controllIntervalSelect.setAttribute('name', 'time_unit_controllinterval_input-'); 5961 controllIntervalSelect.setAttribute('id', 'time_unit_controllinterval_input-'); 5962 controllIntervalInputContainer.appendChild(controllIntervalSelect); 5963 5964 let timeUnits = []; 5965 timeUnits.push({ name: 'year', title: 'TIME_UNIT_YEAR', divisor_to_min: 525960 }); 5966 timeUnits.push({ name: 'month', title: 'TIME_UNIT_MONTH', divisor_to_min: 43830 }); 5967 timeUnits.push({ name: 'week', title: 'TIME_UNIT_WEEK', divisor_to_min: 10080 }); 5968 timeUnits.push({ name: 'day', title: 'TIME_UNIT_DAY', divisor_to_min: 1440 }); 5969 //timeUnits.push({ name: 'hour', title: 'TIME_UNIT_HOUR', divisor_to_min: 60 }); 5970 //timeUnits.push({ name: 'minute', title: 'TIME_UNIT_MINUTE', divisor_to_min: 1 }); 5971 timeUnits.forEach(timeUnit => { 5972 let controllIntervalOption = document.createElement('option'); 5973 if (timeUnit.title == 'TIME_UNIT_MONTH') { 5974 controllIntervalOption.setAttribute('selected', 'selected'); 5975 } 5976 controllIntervalOption.setAttribute('value', timeUnit.name); 5977 controllIntervalOption.setAttribute('data-divisor', timeUnit.divisor_to_min); 5978 controllIntervalOption.innerText = translate['TIME_UNIT_TITLES'][timeUnit.title]; 5979 controllIntervalSelect.appendChild(controllIntervalOption); 5980 }); 5981 5982 let controllIntervalLabel = document.createElement('label'); 5983 controllIntervalLabel.setAttribute('for', 'storage_time_input-'); 5984 controllIntervalLabel.innerText = translate['MODEL']['CHECKLIST_CONTROLLINTERVAL']; 5985 controllIntervalInputContainer.appendChild(controllIntervalLabel); 5986 5987 controllIntervalInputContainer.insertAdjacentHTML('beforeend', await getSVG('resources/images/icons/checklist.svg')); 5988 5989 let controllIntervalIcon = document.createElement('i'); 5990 controllIntervalIcon.className = 'select-icon fa-solid fa-angle-down'; 5991 controllIntervalInputContainer.appendChild(controllIntervalIcon); 5992 5993 let controllIntervalError = document.createElement('div'); 5994 controllIntervalError.className = 'input-error'; 5995 controllIntervalError.setAttribute('data-error1', translate['MODEL']['ERROR']['MAX_INT_VALUE']); 5996 controllIntervalError.setAttribute('data-error2', translate['MODEL']['ERROR']['CHECKLIST_CONTROLLINTERVAL']); 5997 controllIntervalInput.appendChild(controllIntervalError); 5998 5999 let removeChecklist = document.createElement('button'); 6000 removeChecklist.setAttribute('type', 'button'); 6001 removeChecklist.className = 'remove-checklist danger my-icon-button'; 6002 checklistInfo.appendChild(removeChecklist); 6003 6004 let removeChecklistIcon = document.createElement('i'); 6005 removeChecklistIcon.className = 'fa-solid fa-trash'; 6006 removeChecklist.appendChild(removeChecklistIcon); 6007 6008 let questions = document.createElement('div'); 6009 questions.className = 'questions'; 6010 checklist.appendChild(questions); 6011 6012 let questionsList = document.createElement('div'); 6013 questionsList.className = 'list'; 6014 questions.appendChild(questionsList); 6015 6016 let addQuestion = document.createElement('button'); 6017 addQuestion.setAttribute('type', 'button'); 6018 addQuestion.setAttribute('id', 'add-question'); 6019 addQuestion.className = 'my-button'; 6020 questions.appendChild(addQuestion); 6021 6022 addQuestion.insertAdjacentHTML('beforeend', await getSVG('resources/images/icons/add-question.svg')); 6023 6024 let addQuestionSpan = document.createElement('span'); 6025 addQuestionSpan.innerText = translate['MODEL']['ADD_QUESTION']; 6026 addQuestion.appendChild(addQuestionSpan); 6027 6028 $('#checklists').append(checklist); 6029 if (withQuestions) { 6030 addNewQuestion($(checklist).find('.list'), translate['MODEL']['STANDART_QUESTION_1'] + (language == 'bz' ? '\n\n' + otherTranslate['it']['MODEL']['STANDART_QUESTION_1'] : ''), 'radio', false); 6031 addNewQuestion($(checklist).find('.list'), translate['MODEL']['STANDART_QUESTION_2'] + (language == 'bz' ? '\n\n' + otherTranslate['it']['MODEL']['STANDART_QUESTION_2'] : ''), 'radio', false); 6032 6033 new Sortable(questionsList, { 6034 filter: '.my-button', 6035 handle: '.move-icon', 6036 onUpdate: function (evt) { 6037 updateQuestions($(evt.item).parents('.list')); 6038 }, 6039 }); 6040 } 6041 updateChecklists(); 6042 $('#checklists .checklist:last-of-type .icon-show').trigger('click'); 6043 if (scroll) { 6044 scrollToEl($('#checklists .checklist:last-of-type')); 6045 } 6046 return checklist; 6047} 6048$(document).on('click', '#add-checklist', async function () { 6049 addChecklist(); 6050}); 6051
6052async function addNewQuestion(listEl, text = '', type = 'radio', scrollAfterAppend = true) { 6053 let question = document.createElement('div'); 6054 question.className = 'question'; 6055 6056 let toolbar = document.createElement('div'); 6057 toolbar.className = 'toolbar'; 6058 question.appendChild(toolbar); 6059 6060 let title = document.createElement('div'); 6061 title.className = 'title'; 6062 toolbar.appendChild(title); 6063 6064 let number = document.createElement('span'); 6065 number.className = 'number'; 6066 number.innerText = '0.'; 6067 title.appendChild(number); 6068 6069 let titleText = document.createElement('span'); 6070 titleText.innerHTML = ' ' + translate['MODEL']['QUESTION']; 6071 title.appendChild(titleText); 6072 6073 let selectTypDiv = document.createElement('div'); 6074 selectTypDiv.className = 'my-select-button checklist-type no-max-width small'; 6075 let selectTyp = document.createElement('select'); 6076 selectTyp.setAttribute('name', 'type-'); 6077 selectTyp.setAttribute('id', 'type-'); 6078 selectTypDiv.appendChild(selectTyp); 6079 6080 Object.entries(translate['MODEL']['QUESTION_TYPES']).forEach((data) => { 6081 let option = document.createElement('option'); 6082 option.setAttribute('value', data[0].toLocaleLowerCase()); 6083 option.innerText = data[1]; 6084 selectTyp.appendChild(option); 6085 if (data[0].toLocaleLowerCase() == type) 6086 selectTyp.value = data[0].toLocaleLowerCase(); 6087 }); 6088 6089 let selectIcon = document.createElement('i'); 6090 selectIcon.className = 'select-icon fa-solid fa-angle-down'; 6091 selectTypDiv.appendChild(selectIcon); 6092 6093 title.appendChild(selectTypDiv); 6094 6095 let removeQuestion = document.createElement('button'); 6096 removeQuestion.setAttribute('type', 'button'); 6097 removeQuestion.className = 'remove-question danger my-icon-button'; 6098 toolbar.appendChild(removeQuestion); 6099 6100 let removeQuestionIcon = document.createElement('i'); 6101 removeQuestionIcon.className = 'fa-solid fa-trash-can'; 6102 removeQuestion.appendChild(removeQuestionIcon); 6103 6104 let move = document.createElement('button'); 6105 move.setAttribute('type', 'button'); 6106 move.className = 'my-icon-button move-icon'; 6107 toolbar.appendChild(move); 6108 6109 let moveIcon = document.createElement('i'); 6110 moveIcon.className = 'fa-solid fa-arrows-up-down-left-right'; 6111 move.appendChild(moveIcon); 6112 6113 let textareaWrapper = document.createElement('div'); 6114 textareaWrapper.className = 'textarea-wrapper'; 6115 question.appendChild(textareaWrapper); 6116 6117 let textarea = document.createElement('textarea'); 6118 textarea.setAttribute('name', 'question-'); 6119 textarea.setAttribute('id', 'question-'); 6120 textarea.setAttribute('placeholder', '...'); 6121 textarea.value = text; 6122 textareaWrapper.appendChild(textarea); 6123 6124 listEl.append(question); 6125 updateQuestions(listEl); 6126 updateChecklists(); 6127 if (scrollAfterAppend) 6128 scrollToEl(listEl.find('.question:last-of-type')); 6129 return true; 6130} 6131 6132$(document).on('click', '#add-question', async function () { 6133 addNewQuestion($(this).parents('.questions').find('.list')); 6134}); 6135 6136 6137// END-MODEL FUNCTIONS 6138// ARTICLE FUNCTIONS 6139 6140function getParentDirs(dirID) { 6141 if ($('#article-table-list').length > 0) { 6142 $('.my-breadcrumbs').children().remove(); 6143 if (dirID) { 6144 $('.my-breadcrumbs').removeClass('hide-me'); 6145 return new Promise((resolve, reject) => { 6146 $.ajax({ 6147 type: 'POST', 6148 url: 'getparentdirs', 6149 cache: false, 6150 data: { 6151 dir_id: dirID 6152 }, 6153 success: function (result) { 6154 try { 6155 let data = JSON.parse(result); 6156 if (typeof data === 'object') { 6157 data.forEach(function (breadcrumb) { 6158 let breadcrumbEl = document.createElement('a'); 6159 breadcrumbEl.setAttribute('data-dir', breadcrumb['link']); 6160 breadcrumbEl.className = 'breadcrumb'; 6161 breadcrumbEl.innerHTML = breadcrumb['icon']; 6162 let breadcrumbElName = document.createElement('span'); 6163 breadcrumbElName.textContent = breadcrumb['name']; 6164 breadcrumbEl.appendChild(breadcrumbElName); 6165 $('.my-breadcrumbs').append(breadcrumbEl); 6166 }); 6167 if (data.length > 1) { 6168 let backActionDataDir = data[(data.length - 2)]['link']; 6169 $('.back-button').attr('data-dir', backActionDataDir).removeClass('hide-me'); 6170 } 6171 changeBreadcrumbsView(); 6172 resolve(true); 6173 } else { 6174 handleResult(result); 6175 resolve(false); 6176 } 6177 } catch (error) { 6178 handleResult(result, error); 6179 resolve(false); 6180 } 6181 } 6182 }); 6183 }) 6184 } else { 6185 $('.my-breadcrumbs').addClass('hide-me'); 6186 $('.back-button').attr('data-dir', '').addClass('hide-me'); 6187 let url_str = window.location.href; 6188 let url = new URL(url_str); 6189 let search_params = url.searchParams; 6190 if (search_params.has('dir_id')) { 6191 window.history.pushState('', document.title, removeParam("dir_id", url_str)); 6192 } 6193 } 6194 } 6195} 6196function removeDirIdParam() { 6197 getParentDirs(''); 6198} 6199$(document).on('click', '.list-item a[data-dir], .list-item[data-dir], .breadcrumb[data-dir], .back-button[data-dir]', function (e) { 6200 if ($(e.target).prop("tagName") !== 'INPUT') { 6201 $('.my-tooltip-content').remove(); 6202 let dirID = $(this).attr('data-dir'); 6203 $('.back-button').removeClass('hide-me').attr('data-dir', dirID); 6204 replaceUrlParam('dir_id', dirID); 6205 $('.my-table-list-filter-search').val(''); 6206 updateClearSearch($('.my-table-list-filter-search')); 6207 updateFilter('searchStr', ''); 6208 updateFilter('dir_id', dirID); 6209 getParentDirs(dirID);
6210 getTableList(); 6211 } 6212}); 6213function getCurrentAction() { 6214 let url = window.location.href; 6215 url = url.substring(url.lastIndexOf('/') + 1); 6216 if (url.includes('?')) { 6217 url = url.substring(0, url.indexOf('?')); 6218 } 6219 return url; 6220} 6221async function initDirIDParam() { 6222 if (getCurrentAction() == 'articles') { 6223 let url_str = window.location.href; 6224 let url = new URL(url_str); 6225 let search_params = url.searchParams; 6226 if (search_params.has('states')) { 6227 let statesParam = search_params.get('states').split(',').map(s => s.trim()).filter(s => s.length > 0); 6228 if (statesParam.length > 0) { 6229 updateFilter('states', statesParam); 6230 $('#articles .badges .my-badge.state').each(function () { 6231 $(this).toggleClass('not-active', statesParam.indexOf($(this).data('state')) === -1); 6232 }); 6233 } 6234 } 6235 if (search_params.has('dir_id')) { 6236 $('.back-button').removeClass('hide-me').attr('data-dir', search_params.get('dir_id')); 6237 getParentDirs(search_params.get('dir_id')); 6238 $('.my-table-list-filter-search').val(''); 6239 updateClearSearch($('.my-table-list-filter-search')); 6240 updateFilter('searchStr', ''); 6241 updateFilter('dir_id', search_params.get('dir_id')); 6242 replaceUrlParam('dir_id', search_params.get('dir_id')); 6243 await getTableList(); 6244 loadNextItemsForTableList 6245 } else { 6246 let filter = getFilter(); 6247 if (filter['dir_id']) { 6248 $('.back-button').removeClass('hide-me').attr('data-dir', filter['dir_id']); 6249 getParentDirs(filter['dir_id']); 6250 $('.my-table-list-filter-search').val(''); 6251 updateClearSearch($('.my-table-list-filter-search')); 6252 updateFilter('searchStr', ''); 6253 updateFilter('dir_id', filter['dir_id']); 6254 replaceUrlParam('dir_id', filter['dir_id']); 6255 await getTableList(); 6256 loadNextItemsForTableList 6257 } else { 6258 getParentDirs(''); 6259 updateFilter('dir_id', ''); 6260 await getTableList(); 6261 loadNextItemsForTableList 6262 } 6263 } 6264 } 6265} 6266$('#articles .badges .my-badge.state').click(function () {
6267 let clickedState = $(this).data('state'); 6268 let filter = getFilter(); 6269 let states = []; 6270 if (filter['states'] !== undefined) { 6271 states = filter['states']; 6272 } 6273 if (states.length == 0) { 6274 $('#articles .badges .my-badge.state').addClass('not-active'); 6275 states.push(clickedState); 6276 $(this).removeClass('not-active'); 6277 } else { 6278 if ($(this).hasClass('not-active')) { 6279 $(this).removeClass('not-active'); 6280 states.push(clickedState); 6281 } else { 6282 $(this).addClass('not-active'); 6283 const index = states.indexOf(clickedState); 6284 if (index !== -1) { 6285 states.splice(index, 1); 6286 } 6287 } 6288 if (states.length == 0 || states.length == $('#articles .badges .my-badge.state').length) { 6289 $('#articles .badges .my-badge.state').removeClass('not-active'); 6290 states = []; 6291 } 6292 } 6293 updateFilter('states', states); 6294 getTableList(); 6295}); 6296$(document).on('change', '#show_articles_from_dir', function () { 6297 if ($(this).val() == 1) { 6298 $('#order_by_dirs [value="1"]').prop('disabled', false); 6299 } else { 6300 $('#order_by_dirs').val('0'); 6301 $('#order_by_dirs [value="1"]').prop('disabled', true); 6302 } 6303}); 6304async function openmoveelementstodirpopup(data, animationTime = null) { 6305 await getAjaxPopUp('moveelementstodirpopup', data, animationTime); 6306 $('#move-elements-to-dir-popup #move_dir_tabs .my-tab-nav').on('click', function (e) { 6307 e.preventDefault(); 6308 const tab = $(this).data('tab'); 6309 $('#move-elements-to-dir-popup #move_dir_tabs .my-tab-nav').removeClass('active'); 6310 $(this).addClass('active'); 6311 $('#move-elements-to-dir-popup .tab-content').removeClass('active'); 6312 $('#move-elements-to-dir-popup .tab-content[data-tab-content="' + tab + '"]').addClass('active'); 6313 $('#move-elements-to-dir-popup .popup-body').animate({ 6314 scrollTop: 0 6315 }, 200); 6316 if (tab === 'search' && !isTouchDevice()) { 6317 $('#move-elements-to-dir-popup #search').focus(); 6318 } 6319 }); 6320 $('#move-elements-to-dir-popup #search').on('input', function (e) { 6321 const val = $(this).val().toLowerCase(); 6322 let allElements = $('#move-elements-to-dir-popup #forsearch .dir'); 6323 if (val.length > 0) { 6324 allElements.each((idx, el) => { 6325 const name = $(el).find('.name').text().toLowerCase(); 6326 if (name.includes(val)) { 6327 $(el).attr('data-order', 0); 6328 } else { 6329 $(el).attr('data-order', levenshteinDistance(val, name)); 6330 } 6331 }); 6332 allElements.sort((a, b) => $(a).attr("data-order") - $(b).attr("data-order")).appendTo("#move-elements-to-dir-popup #forsearch"); 6333 } else { 6334 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#move-elements-to-dir-popup #forsearch"); 6335 } 6336 $('#move-elements-to-dir-popup .popup-body').animate({ 6337 scrollTop: 0 6338 }, 200); 6339 }); 6340 6341 $('#move-elements-to-dir-popup .clear-search').click(function (e) { 6342 $(this).parents('.my-input').find('input[type="search"]').val(''); 6343 let allElements = $('#move-elements-to-dir-popup .elements .element'); 6344 allElements.sort((a, b) => $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase())).appendTo("#move-elements-to-dir-popup #forsearch"); 6345 $('#move-elements-to-dir-popup .popup-body').animate({ 6346 scrollTop: 0 6347 }, 200); 6348 if (!isTouchDevice()) { 6349 $(this).parents('.my-input').find('input[type="search"]').focus(); 6350 } 6351 }); 6352} 6353$(document).on('click', '#table-list-move-to-dir', function () { 6354 let filter = getFilter(); 6355 let dirID = null; 6356 if (filter['dir_id']) { 6357 dirID = filter['dir_id']; 6358 } 6359 openmoveelementstodirpopup({ dir_id: dirID }); 6360 $(document).off('click', '#move-elements-to-dir-popup #confirm_move').on('click', '#move-elements-to-dir-popup #confirm_move', function (e) { 6361 let dirID = getCurrentDirFromMoveElementsPopup(); 6362 let ids = []; 6363 getSelectedListCheckboxes().each(function () { 6364 ids.push(this.value); 6365 }); 6366 showLoading(translate['ARTICLE']['FOLDERS_WILL_BE_MOVED']); 6367 $.ajax({ 6368 type: 'POST', 6369 url: 'moveelementstodir', 6370 cache: false, 6371 data: { 6372 dir_id: dirID, 6373 ids: ids 6374 }, 6375 success: async function (result) { 6376 $('#loading-bar').hide(); 6377 try { 6378 let data = JSON.parse(result); 6379 if (typeof data === 'object') { 6380 hideLoading(); 6381 hidePopUp($('#move-elements-to-dir-popup')); 6382 $('#move-elements-to-dir-popup').remove(); 6383 if (data['success']) {
6384 getTableList(); 6385 } 6386 if (data['not_all_moved']) { 6387 presentToast(translate['ARTICLE']['NOT_ALL_ELEMENTS_CAN_BE_MOVED'], 'fa-triangle-exclamation', 'warning'); 6388 } 6389 } 6390 } catch (err) { 6391 hideLoading(); 6392 handleResult(result, err); 6393 } 6394 } 6395 }); 6396 }); 6397}); 6398$(document).on('click', '#move-elements-to-dir-popup .move-to-dir', async function (e) { 6399 e.preventDefault(); 6400 let id = $(this).data('id'); 6401 if (id === '') { 6402 id = null; 6403 } 6404 6405 moveToNextDir(id); 6406}); 6407async function moveToNextDir(dir_id) { 6408 $('#move-elements-to-dir-popup').addClass('old'); 6409 const targetDirID = $('input[name="current_id"]').val(); 6410 openmoveelementstodirpopup({ dir_id: dir_id, targetDirID: targetDirID }, 0); 6411 hidePopUp($('#move-elements-to-dir-popup.old').remove()); 6412 showPopUp($('#move-elements-to-dir-popup'), 0); 6413} 6414$(document).on('click', '#move-elements-to-dir-popup .dir', async function (e) { 6415 let id = $(this).find('.move-to-dir').data('id'); 6416 $('#move-elements-to-dir-popup .dir').removeClass('active'); 6417 $(this).addClass('active'); 6418}); 6419function getCurrentDirFromMoveElementsPopup() { 6420 let dirID = null; 6421 let activeDir = $('#move-elements-to-dir-popup .dir.active'); 6422 if (activeDir.length > 0) { 6423 dirID = $(activeDir).find('.move-to-dir').data('id'); 6424 } else { 6425 activeDir = $('#move-elements-to-dir-popup .parent_dir .move-to-dir'); 6426 if (activeDir.length > 0) { 6427 dirID = activeDir.data('currentid'); 6428 } 6429 } 6430 if (dirID == null || dirID == '') { 6431 dirID = 0; 6432 } 6433 return dirID; 6434} 6435function getCurrentDirNameFromMoveElementsPopup() { 6436 let dirName = translate['ARTICLE']['ALL_TITLE']; 6437 let activeDir = $('#move-elements-to-dir-popup .dir.active'); 6438 if (activeDir.length > 0) { 6439 dirName = $(activeDir).find('.name').text(); 6440 } else { 6441 activeDir = $('#move-elements-to-dir-popup .parent_dir .name'); 6442 if (activeDir.length > 0) { 6443 dirName = activeDir.text(); 6444 } 6445 } 6446 return dirName; 6447} 6448 6449$(document).on('click', '.add-new-dir', async function () { 6450 let dirID = getCurrentDirFromMoveElementsPopup(); 6451 await getAjaxPopUp('adddirpopup', { dir_id: dirID }); 6452}); 6453 6454$(document).on('click', '#open-action-sheet-add-article', async function (e) { 6455 if (!$(e.target).hasClass('info')) { 6456 let buttons = []; 6457 let canEditArticle = $(this).data('can-edit-article'); 6458 let canEditDir = $(this).data('can-edit-dir'); 6459 let noArticlesLeft = $('#open-action-sheet-add-article').attr('data-no-articles-left') != 'false'; 6460 if (canEditArticle) { 6461 const iconArticle = await getSVG('resources/images/icons/add-article.svg') 6462 buttons.push({ 6463 icon: iconArticle, 6464 text: translate['ARTICLE']['ADD_TITLE'], 6465 style: 'default', 6466 handler: async () => { 6467 if (noArticlesLeft) { 6468 getAjaxPopUp('noarticlesleft'); 6469 } else { 6470 let filter = getFilter(); 6471 let link = 'articles/editarticle'; 6472 if (filter['dir_id']) { 6473 link = link + '?parent_dir=' + filter['dir_id']; 6474 } 6475 window.open(link, '_self'); 6476 } 6477 closeMyActionSheet($('#icon-action-sheet')); 6478 } 6479 }); 6480 const iconAddMultipleArticle = await getSVG('resources/images/icons/add-multiple-articles.svg') 6481 buttons.push({ 6482 icon: iconAddMultipleArticle, 6483 text: translate['ARTICLE']['ADD_MULTIPLE'], 6484 style: 'default', 6485 handler: async () => { 6486 if (noArticlesLeft) { 6487 getAjaxPopUp('noarticlesleft'); 6488 } else { 6489 let link = 'articles/editmultiple?type=article&new=1'; 6490 window.open(link, '_self'); 6491 } 6492 closeMyActionSheet($('#icon-action-sheet')); 6493 } 6494 }); 6495 } 6496 if (canEditDir) { 6497 const iconDir = await getSVG('resources/images/icons/add-dir.svg') 6498 buttons.push({ 6499 icon: iconDir, 6500 text: translate['DIR']['ADD_TITLE'], 6501 style: 'default', 6502 handler: (e) => { 6503 let filter = getFilter(); 6504 let link = 'articles/editdir'; 6505 if (filter['dir_id']) { 6506 link = link + '?parent_dir=' + filter['dir_id']; 6507 } 6508 window.open(link, '_self'); 6509 closeMyActionSheet($('#icon-action-sheet')); 6510 } 6511 }); 6512 } 6513 // Abbrechen 6514 buttons.push({ 6515 icon: '<i class="fa-solid fa-ban"></i>', 6516 text: translate['DISMISS'], 6517 style: 'default', 6518 handler: () => { 6519 closeMyActionSheet($('#icon-action-sheet')); 6520 } 6521 }); 6522 myActionSheet(translate['ADD'], 'icon-action-sheet', buttons); 6523 } 6524}); 6525function addDirAsync(form) { 6526 let formData = new FormData(form); 6527 let error = false;
6528 $('.my-input').removeClass('error'); 6529 let name = formData.get("name").trim(); 6530 let parent_dir = formData.get("parent_dir").trim();; 6531 if (name.length < 1) { 6532 let inputEl = $(form).find("[name='name']"); 6533 let inputWrapperEl = inputEl.parents('.my-input'); 6534 inputWrapperEl.addClass('error'); 6535 inputWrapperEl.find('.input-error').text(inputWrapperEl.find('.input-error').data('error1')); 6536 if (!error) 6537 inputEl.focus(); 6538 error = true; 6539 } 6540 if (!error) { 6541 $('#loading-bar').show(); 6542 $.ajax({ 6543 type: 'POST', 6544 url: 'adddirasync', 6545 cache: false, 6546 data: { 6547 name: name, 6548 parent_dir: parent_dir 6549 }, 6550 success: async function (result) { 6551 trackEventGoogleAnalytics("Ordner hinzugefügt"); 6552 $('#loading-bar').hide(); 6553 try { 6554 let data = JSON.parse(result); 6555 if (typeof data === 'object') { 6556 if (data['success']) { 6557 const newDir = data['data']; 6558 moveToNextDir(newDir['id']); 6559 await hidePopUp($('#add-dir')); 6560 $('#add-dir').remove(); 6561 } 6562 } else { 6563 handleResult(result); 6564 } 6565 } catch (err) { 6566 handleResult(result, err); 6567 } 6568 6569 } 6570 }); 6571 } 6572 return false; 6573} 6574$(document).on('change', '#editarticle-form input[name="date_of_manufacture"]', function () { 6575 const val = $(this).val(); 6576 if (val) { 6577 if (checkDate(val)) { 6578 let dateMomentObject = moment(val, "DD.MM.YYYY"); 6579 let tmpDateOfManufacture = dateMomentObject.toDate(); 6580 let tmpDateOfPurchase = checkDate($('input[name="date_of_purchase"]').val()) ? moment($('input[name="date_of_purchase"]').val(), "DD.MM.YYYY").toDate() : null; 6581 let tmpDateFirstUse = checkDate($('input[name="date_first_use"]').val()) ? moment($('input[name="date_first_use"]').val(), "DD.MM.YYYY").toDate() : null; 6582 let editModus = $('input[name="edit"]').val(); 6583 if (editModus != '1') { 6584 if (tmpDateOfPurchase == null) { 6585 $('input[name="date_of_purchase"]').val(dateMomentObject.format("DD.MM.YYYY")).change(); 6586 tmpDateOfPurchase = tmpDateOfManufacture; 6587 } 6588 if (tmpDateFirstUse == null) { 6589 $('input[name="date_first_use"]').val(dateMomentObject.format("DD.MM.YYYY")).change(); 6590 tmpDateFirstUse = tmpDateOfPurchase; 6591 } 6592 if (tmpDateOfManufacture > tmpDateOfPurchase) { 6593 $('input[name="date_of_purchase"]').val(dateMomentObject.format("DD.MM.YYYY")).change(); 6594 } 6595 if (tmpDateOfManufacture > tmpDateFirstUse) { 6596 $('input[name="date_first_use"]').val(dateMomentObject.format("DD.MM.YYYY")).change(); 6597 } 6598 } 6599 } 6600 } 6601 6602}); 6603$(document).on('change', '#editarticle-form input[name="date_of_purchase"]', function () { 6604 const val = $(this).val(); 6605 if (val) { 6606 if (checkDate(val)) { 6607 let dateMomentObject = moment(val, "DD.MM.YYYY") 6608 let tmpDateOfPurchase = dateMomentObject.toDate(); 6609 let tmpDateFirstUse = checkDate($('input[name="date_first_use"]').val()) ? moment($('input[name="date_first_use"]').val(), "DD.MM.YYYY").toDate() : null; 6610 let editModus = $('input[name="edit"]').val(); 6611 if (editModus != '1') { 6612 if (tmpDateFirstUse == null) { 6613 $('input[name="date_first_use"]').val(dateMomentObject.format("DD.MM.YYYY")); 6614 tmpDateFirstUse = tmpDateOfPurchase; 6615 } 6616 if (tmpDateOfPurchase > tmpDateFirstUse) { 6617 $('input[name="date_first_use"]').val(dateMomentObject.format("DD.MM.YYYY")); 6618 } 6619 } 6620 } 6621 } 6622}); 6623$(document).on('change', '#editarticle-form input[name="not_ok"]', function () {
6624 let checked = $(this).prop('checked'); 6625 if (checked) { 6626 $('#editarticle-form .show-on-not-ok').removeClass('hide-me'); 6627 } else { 6628 $('#editarticle-form .show-on-not-ok').addClass('hide-me'); 6629 } 6630}); 6631$('#open_add_test_popup').click(function () { 6632 getAjaxPopUp('addtestpopup', { article_id: $(this).data('article_id') }) 6633}); 6634if ($('#show-add-test-popup').length > 0) { 6635 let multipleModus = $('#skip-test').length > 0; 6636 let testSite = $('#set-not-found').length > 0; 6637 getAjaxPopUp('addtestpopup', { article_id: $('#show-add-test-popup').data('article_id'), multipleModus: multipleModus, testSite: testSite }); 6638} 6639$(document).on('click', '.confirm_add_test', function () { 6640 let article_id = $('input[name="article_id"]').val(); 6641 if (article_id === undefined) 6642 article_id = $('#open_add_test_popup').data('article_id'); 6643 if (article_id === undefined) 6644 article_id = $('#show-add-test-popup').data('article_id'); 6645 6646 const values = $('#add-test-popup input[name="checklist_for_tests[]"]:checked').map((idx, el) => $(el).val()).toArray(); 6647 let link = 'articles/article/tests/edittest?article_id=' + article_id + '&checklist_ids=' + values.join(','); 6648 if ($('#show-add-test-popup').length > 0) { 6649 replaceUrlParam('checklist_ids', values.join(',')) 6650 link = location.href; 6651 } 6652 window.open(link, '_self'); 6653}); 6654$(document).on('click', '.trigger-back-button', function () { 6655 if ($('.back-button').length > 0) { 6656 if ($('.back-button').attr('href') != '') { 6657 window.open($('.back-button').attr('href'), '_self'); 6658 } 6659 } 6660}); 6661 6662// END-ARTICLE FUNCTIONS 6663 6664// TEST FUNCTIONS 6665$('.check-all-in-checklist i').click(function () { 6666 const val = $(this).data('for'); 6667 const id = $(this).parents('.check-all-in-checklist').data('id'); 6668 $('.my-checklist[data-id="' + id + '"]').find('input[value="' + val + '"]').prop('checked', true).change(); 6669}); 6670$('.my-checklist[data-id] input').change(function () { 6671 $(this).parents('.my-checklist').find('.checklist-title').removeClass('error'); 6672}) 6673$(document).on('click', '#add-postitive-multiple-tests', async function () { 6674 let ids = []; 6675 getSelectedListCheckboxes().each(function () { 6676 ids.push(this.value); 6677 }); 6678 let showSign = $(this).data('show_sign') == 1; 6679 let message = translate['ARTICLE']['INFO_POSITIVE_MULTIPLE_TESTS'].replace('##STATES##', '<span class="my-badge small active state state_2_overdue">' + getStateTranslate('STATE_2_OVERDUE') + '</span>, <span class="my-badge small active state state_3_upcoming">' + getStateTranslate('STATE_3_UPCOMING') + '</span> ' + translate['ARTICLE']['INFO_COMMENT_FOR_POSITIVE_MULTIPLE_TESTS_AND'] + ' <span class="my-badge small active state state_4_inspected">' + getStateTranslate('STATE_4_INSPECTED') + '</span>'); 6680 let confirm = await submitFormAfterConfirm(translate['ARTICLE']['ADD_POSITIVE_MULTIPLE_TEST'], message); 6681 if (confirm) { 6682 let withSign = false; 6683 let sign = ''; 6684 if (showSign) { 6685 withSign = await submitFormAfterConfirm('', translate['TEST']['MESSAGE_SIGN']); 6686 if (withSign) { 6687 sign = await getUserSignPopUp(); 6688 } 6689 } 6690 let comment = await getCommentForPositiveMultipleTest(); 6691 showLoading(translate['ARTICLE']['ADD_POSITIVE_MULTIPLE_TEST_LOADING']); 6692 6693 $.ajax({ 6694 type: 'POST', 6695 url: 'addpositivemultipletests', 6696 cache: false, 6697 data: { 6698 sign: sign, 6699 comment: comment, 6700 ids: ids 6701 }, 6702 success: async function (result) { 6703 hideLoading(); 6704 try { 6705 let data = JSON.parse(result); 6706 if (typeof data === 'object') { 6707 if (data['success'] == true) { 6708 trackEventGoogleAnalytics("Test hinzugefügt", { count: data['count'] }); 6709 window.location.replace(location.href + (location.href.includes('?') ? ('&positivemultipletestadded=1&count=' + data['count']) : ('?positivemultipletestadded=1&count=' + data['count']))); 6710 } else { 6711 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'warning'); 6712 } 6713 } else { 6714 handleResult(result, err); 6715 } 6716 } catch (err) { 6717 handleResult(result, err); 6718 } 6719 } 6720 }); 6721 } 6722}); 6723$(document).on('click', '#change-multi-date-first-use', async function () { 6724 let ids = []; 6725 getSelectedListCheckboxes().each(function () { 6726 ids.push(this.value); 6727 }); 6728 let res = await getAjaxPopUp('changemultidatefirstusepopup'); 6729 if (res) { 6730 $(document).on('click', '.confirm-change-multi-date-first-use', async function () { 6731 $('#loading-bar').show(); 6732 let date_first_use = $('#changemultidatefirstusepopup #date_first_use').val(); 6733 await hidePopUp($('#changemultidatefirstusepopup')); 6734 $.ajax({ 6735 type: 'POST', 6736 url: 'changemultidatefirstuse', 6737 cache: false, 6738 data: { 6739 ids: ids, 6740 date_first_use: date_first_use 6741 }, 6742 success: async function (result) { 6743 $('#loading-bar').hide(); 6744 try { 6745 let data = JSON.parse(result); 6746 if (typeof data === 'object') { 6747 if (data['success'] == true) { 6748 window.location.replace(location.href + (location.href.includes('?') ? ('&saved=1') : ('?saved=1'))); 6749 } else { 6750 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'warning'); 6751 } 6752 } else { 6753 handleResult(result, err); 6754 } 6755 } catch (err) { 6756 handleResult(result, err); 6757 } 6758 } 6759 }); 6760 }); 6761 } 6762}); 6763$(document).on('click', '#mark-as-not-found, #mark-as-found', async function () { 6764 let value = $(this).attr('id') == 'mark-as-not-found'; 6765 6766 let ids = []; 6767 getSelectedListCheckboxes().each(function () { 6768 ids.push(this.value); 6769 }); 6770 let message = translate['ARTICLE']['SIGN_ALL_MARKED_ARTICLES_AS_NOT_FOUND'].replace('##STATES##', 6771 '<span class="my-badge small active state state_1_to_old">' + getStateTranslate('STATE_1_TO_OLD') + '</span>, ' + 6772 '<span class="my-badge small active state state_2_overdue">' + getStateTranslate('STATE_2_OVERDUE') + '</span>, ' + 6773 '<span class="my-badge small active state state_3_upcoming">' + getStateTranslate('STATE_3_UPCOMING') + '</span>, ' + 6774 '<span class="my-badge small active state state_4_inspected">' + getStateTranslate('STATE_4_INSPECTED') + '</span>, ' + 6775 '<span class="my-badge small active state state_6_in_stock">' + getStateTranslate('STATE_6_IN_STOCK') + '</span> ' + 6776 '<span class="my-badge small active state state_5_in_repair">' + getStateTranslate('STATE_5_IN_REPAIR') + '</span> ' + 6777 translate['ARTICLE']['INFO_COMMENT_FOR_POSITIVE_MULTIPLE_TESTS_AND'] + 6778 ' <span class="my-badge small active state state_7_not_be_checked">' + getStateTranslate('STATE_7_NOT_BE_CHECKED') + '</span>'); 6779 if (!value) { 6780 message = translate['ARTICLE']['SIGN_ALL_MARKED_ARTICLES_AS_FOUND'].replace('##STATES##', 6781 '<span class="my-badge small active state state_8_not_found">' + getStateTranslate('STATE_8_NOT_FOUND') + '</span>'); 6782 }
6783 let confirm = await submitFormAfterConfirm('', message); 6784 if (confirm) { 6785 showLoading(translate['LOADING']); 6786 $.ajax({ 6787 type: 'POST', 6788 url: 'markasnotfound', 6789 cache: false, 6790 data: { 6791 value: value, 6792 ids: ids 6793 }, 6794 6795 success: async function (result) { 6796 hideLoading(); 6797 try { 6798 let data = JSON.parse(result); 6799 if (typeof data === 'object') { 6800 if (data['success'] == true) { 6801 getTableList(); 6802 if (value) { 6803 presentToast(translate['ARTICLE']['MARKED_AS_NOT_FOUND_SUCCESSFULLY'].replace('##', data['count']), 'fa-magnifying-glass', 'success'); 6804 } else { 6805 presentToast(translate['ARTICLE']['MARKED_AS_FOUND_SUCCESSFULLY'].replace('##', data['count']), 'fa-magnifying-glass', 'success'); 6806 } 6807 } else { 6808 presentToast(translate['ERROR_GENERAL'], 'fa-triangle-exclamation', 'warning'); 6809 } 6810 } else { 6811 handleResult(result); 6812 } 6813 } catch (err) { 6814 handleResult(result, err); 6815 } 6816 } 6817 }); 6818 } 6819}); 6820async function getCommentForPositiveMultipleTest() { 6821 return new Promise(async function (resolve) { 6822 let comment = ''; 6823 await getAjaxPopUp('getcommentforpositivemultipletestpopup'); 6824 $('#comment-for-positive-multiple-test-popup .confirm-comment-for-positive-multiple-test').click(function () { 6825 let comment = $('#comment-for-positive-multiple-test-popup #comment').val(); 6826 resolve(comment); 6827 }); 6828 }) 6829} 6830$(document).on('click', '#add-multiple-tests', async function (e) { 6831 $('#loading-bar').show(); 6832 const openInNewTab = e.metaKey || e.ctrlKey; 6833 let ids = []; 6834 getSelectedListCheckboxes().each(function () { 6835 ids.push(this.value); 6836 }); 6837 let showSign = $(this).data('show_sign') == 1; 6838 $.ajax({ 6839 type: 'POST', 6840 url: 'getallarticleidsformultipletest', 6841 cache: false, 6842 data: { 6843 ids: ids 6844 }, 6845 success: async function (result) { 6846 $('#loading-bar').hide(); 6847 try { 6848 let data = JSON.parse(result); 6849 if (typeof data === 'object') { 6850 if (data.ids.length > 0) { 6851 startMultipleTest(data.ids, showSign, openInNewTab); 6852 } 6853 } else { 6854 handleResult(result, err); 6855 } 6856 } catch (err) { 6857 handleResult(result, err); 6858 } 6859 } 6860 }); 6861}); 6862async function startMultipleTest(ids, showSign, openInNewTab) { 6863 let multipleTestData = []; 6864 ids.forEach(id => { 6865 multipleTestData.push({ 6866 id: id, 6867 test_added: false, 6868 test_id: 0 6869 }); 6870 }) 6871 localStorage.setItem('multiple_test_data', JSON.stringify(multipleTestData)); 6872 let withSign = false; 6873 if (showSign) { 6874 withSign = await submitFormAfterConfirm('', translate['TEST']['MESSAGE_SIGN']); 6875 } 6876 if (withSign) { 6877 let sign = await getUserSignPopUp(); 6878 if (sign) { 6879 localStorage.setItem('sign_img', sign); 6880 } else { 6881 localStorage.removeItem('sign_img'); 6882 } 6883 } else { 6884 localStorage.removeItem('sign_img'); 6885 } 6886 window.open('articles/edittest?multipletest=1&article_id=' + ids[0] + '&key=0', openInNewTab ? '_blank' : '_self'); 6887} 6888// CART FUNCTIONS 6889function getCart() { 6890 try { 6891 let cart = JSON.parse(localStorage.getItem('test_cart')); 6892 if (Array.isArray(cart)) { 6893 return cart; 6894 } 6895 } catch (err) { 6896 } 6897 return []; 6898} 6899function setCart(cart) { 6900 localStorage.setItem('test_cart', JSON.stringify(cart)); 6901 updateCartButton(); 6902} 6903function addToCart(ids) {
6904 let cart = getCart(); 6905 let added = 0; 6906 ids.forEach(id => { 6907 id = parseInt(id); 6908 if (!cart.includes(id)) { 6909 cart.push(id); 6910 added++; 6911 } 6912 }); 6913 setCart(cart); 6914 return added; 6915} 6916function removeFromCart(id) { 6917 setCart(getCart().filter(cartId => cartId != id)); 6918} 6919function updateCartButton() { 6920 let cart = getCart(); 6921 $('#cart-button').find('.cart-count').text(cart.length).toggleClass('hide-me', cart.length == 0); 6922 let article_id = $('#toggle-cart').data('article_id'); 6923 if (article_id) { 6924 let inCart = cart.includes(parseInt(article_id)); 6925 $('#toggle-cart').find('.add').toggleClass('hide-me', inCart); 6926 $('#toggle-cart').find('.remove').toggleClass('hide-me', !inCart); 6927 } 6928} 6929$(document).on('click', '#add-to-cart', function () { 6930 $('#loading-bar').show(); 6931 let ids = []; 6932 getSelectedListCheckboxes().each(function () { 6933 ids.push(this.value); 6934 }); 6935 $.ajax({ 6936 type: 'POST', 6937 url: 'getarticleidsforcart', 6938 cache: false, 6939 data: { 6940 ids: ids 6941 }, 6942 success: function (result) { 6943 $('#loading-bar').hide(); 6944 try { 6945 let data = JSON.parse(result); 6946 if (typeof data === 'object') { 6947 if (data.ids.length > 0) { 6948 let added = addToCart(data.ids); 6949 presentToast(translate['CART']['ADDED'].replace('##COUNT##', added), 'fa-basket-shopping', 'success', 3000); 6950 } else { 6951 presentToast(translate['CART']['NO_TESTABLE'], 'fa-triangle-exclamation', 'warning', 5000); 6952 } 6953 } else { 6954 handleResult(result); 6955 } 6956 } catch (err) { 6957 handleResult(result, err); 6958 } 6959 } 6960 }); 6961}); 6962$(document).on('click', '#toggle-cart', function () { 6963 let article_id = parseInt($(this).data('article_id')); 6964 if (getCart().includes(article_id)) { 6965 removeFromCart(article_id); 6966 } else { 6967 addToCart([article_id]); 6968 presentToast(translate['CART']['ADDED'].replace('##COUNT##', 1), 'fa-basket-shopping', 'success', 3000); 6969 } 6970}); 6971$(document).on('click', '#cart-button', async function () { 6972 if ($('#cart-popup').length == 0) { 6973 await getAjaxPopUp('getcart', { ids: getCart() }); 6974 syncCartWithPopup(); 6975 focusCartInput(); 6976 } 6977}); 6978function syncCartWithPopup() { 6979 // Entfernt Artikel, die es nicht mehr gibt oder die der User nicht mehr sehen darf 6980 let existingIds = $('#cart-popup .cart-item').map((idx, el) => parseInt($(el).data('id'))).toArray(); 6981 setCart(getCart().filter(id => existingIds.includes(id))); 6982 updateCartPopupCount(); 6983} 6984function updateCartPopupCount() {
6985 let count = getCart().length; 6986 $('#cart-popup .cart-empty').toggleClass('hide-me', count > 0); 6987 $('#cart-popup .cart-actions-dropdown').toggleClass('hide-me', count == 0); 6988} 6989// Eingabefeld für HID-NFC-Leser am Desktop: Der Leser tippt die ID wie eine Tastatur und schickt meist ein Enter 6990function focusCartInput() { 6991 if (!$('html').data('plt-android') && !$('html').data('plt-ios') && !('ontouchstart' in window)) { 6992 $('#cart-code-input').focus(); 6993 } 6994} 6995async function submitCartCodeInput() { 6996 let input = $('#cart-code-input'); 6997 let code = input.val().trim(); 6998 input.val(''); 6999 if (code !== '') { 7000 await addCodeToCart(normalizeScannedCode(code)); 7001 } 7002 focusCartInput(); 7003} 7004$(document).on('keydown', '#cart-code-input', function (e) { 7005 if (e.key == 'Enter') { 7006 e.preventDefault(); 7007 submitCartCodeInput(); 7008 } 7009}); 7010$(document).on('click', '#cart-popup .cart-code-submit', function () { 7011 submitCartCodeInput(); 7012}); 7013$(document).on('click', '#cart-popup', function () { 7014 focusCartInput(); 7015}); 7016$(document).on('click', '#cart-popup .cart-remove', function () { 7017 removeFromCart($(this).parents('.cart-item').data('id')); 7018 $(this).parents('.cart-item').remove(); 7019 updateCartPopupCount(); 7020}); 7021$(document).on('click', '#cart-popup .cart-clear', async function () { 7022 if (getCart().length == 0) { 7023 return; 7024 } 7025 let confirm = await submitFormAfterConfirm(translate['CART']['CLEAR'], translate['CART']['CLEAR_MESSAGE']); 7026 if (confirm) { 7027 setCart([]); 7028 $('#cart-popup').find('.close-and-remove-popup').first().trigger('click'); 7029 } 7030}); 7031// Nach Aktionen, die Artikel verändern, wird die Liste im Prüfkorb neu geladen 7032$(document).ajaxSuccess(function (event, xhr, settings) { 7033 if ($('#cart-popup').length > 0 && ['markasnotfound', 'moveelementstodir', 'deletefromtablelist'].includes(settings.url)) { 7034 refreshCartPopup(); 7035 } 7036}); 7037function refreshCartPopup() { 7038 $.ajax({ 7039 type: 'POST', 7040 url: 'getcart', 7041 cache: false, 7042 data: { 7043 data: JSON.stringify({ ids: getCart() }) 7044 }, 7045 success: function (result) { 7046 if (/<[a-z][\s\S]*>/i.test(result)) { 7047 $('#cart-popup .cart-list').html($('<div>').html(result).find('.cart-list').html()); 7048 syncCartWithPopup(); 7049 } 7050 } 7051 }); 7052} 7053$(document).on('click', '#cart-popup .cart-scan', function () { 7054 scanCodesToCart(getNFC, '.nfc_unsubscribe'); 7055}); 7056$(document).on('click', '#cart-popup .cart-scan-qr', function () { 7057 if ($('html').data('plt-android') || $('html').data('plt-ios')) { 7058 // Der native Scanner der App schlieÃt sich nach jedem Scan, deshalb wird er pro Code neu gestartet. 7059 // Pause danach, damit der native Scanner sauber schlieÃt, der Ergebnis-Toast sichtbar bleibt, 7060 // und erst danach die Kamera wieder öffnet (statt direkt zurück in den nächsten Scan zu laufen). 7061 scanCodesToCart(getQRCode, '.close-webqr', 2500); 7062 return; 7063 } 7064 // Im Browser bleibt die Kamera offen, bis der User sie schlieÃt 7065 let lastCode = ''; 7066 let lastTime = 0; 7067 openWebQr(async function (code) { 7068 // Derselbe Code bleibt meist noch ein paar Sekunden im Bild 7069 if (code === lastCode && Date.now() - lastTime < 3000) { 7070 lastTime = Date.now(); 7071 return; 7072 } 7073 lastCode = code; 7074 lastTime = Date.now(); 7075 await addCodeToCart(normalizeScannedCode(code)); 7076 }); 7077}); 7078async function scanCodesToCart(getCode, cancelSelector, pauseAfterScanMs = 0) {
7079 let code = await getCodeOrCancel(getCode, cancelSelector); 7080 while (code) { 7081 await addCodeToCart(normalizeScannedCode(code)); 7082 // Das Web-QR-Popup wird beim SchlieÃen animiert, das nächste darf erst danach geöffnet werden 7083 while ($('#webqr-popup').length > 0) { 7084 await new Promise(resolve => setTimeout(resolve, 100)); 7085 } 7086 if (pauseAfterScanMs) { 7087 await new Promise(resolve => setTimeout(resolve, pauseAfterScanMs)); 7088 } 7089 code = await getCodeOrCancel(getCode, cancelSelector); 7090 } 7091} 7092// Bricht der User das Scan-Popup ab, bleibt das Promise von getNFC() bzw. getQRCode() offen. Deshalb wird zusätzlich auf den Abbruch gewartet. 7093// e.originalEvent gibt es nur bei echten Klicks, die Scan-Funktionen schlieÃen das Popup per trigger bzw. per Funktion. 7094function getCodeOrCancel(getCode, cancelSelector) { 7095 return new Promise((resolve, reject) => { 7096 $(document).on('click.cartscan', cancelSelector, function (e) { 7097 if (e.originalEvent) { 7098 $(document).off('click.cartscan'); 7099 resolve(null); 7100 } 7101 }); 7102 getCode().then(code => { 7103 $(document).off('click.cartscan'); 7104 resolve(code); 7105 }); 7106 }); 7107} 7108function addCodeToCart(code) { 7109 return new Promise((resolve, reject) => { 7110 $.ajax({ 7111 type: 'POST', 7112 url: 'getarticleidbycode', 7113 cache: false, 7114 data: { 7115 code: code 7116 }, 7117 success: async function (result) { 7118 try { 7119 let data = JSON.parse(result); 7120 if (data['status'] == 'found') { 7121 if (getCart().includes(parseInt(data['id']))) { 7122 presentToast(translate['CART']['ALREADY_IN'].replace('##NAME##', data['name']), 'fa-basket-shopping', 'warning', 3000); 7123 } else { 7124 addToCart([data['id']]); 7125 $('#cart-popup .cart-list').append(data['html']); 7126 updateCartPopupCount(); 7127 presentToast(translate['CART']['ADDED_ARTICLE'].replace('##NAME##', data['name']), 'fa-basket-shopping', 'success', 3000); 7128 } 7129 } else { 7130 presentToast(translate['CART']['SCAN_' + data['status'].toUpperCase()], 'fa-triangle-exclamation', 'warning', 5000); 7131 } 7132 } catch (err) { 7133 handleResult(result, err); 7134 } 7135 resolve(true); 7136 } 7137 }); 7138 }); 7139} 7140// END-CART FUNCTIONS 7141$(document).on('click', '#skip-test', function (e) { 7142 let url_str = window.location.href; 7143 let url = new URL(url_str); 7144 let search_params = url.searchParams; 7145 let multipleTestDataKey = 0; 7146 search_params.forEach(function (val, key) { 7147 if (key == 'key') { 7148 multipleTestDataKey = val; 7149 } 7150 }); 7151 let IDs = localStorage.getItem('multiple_test_data'); 7152 let multipleTestData = JSON.parse(IDs); 7153 multipleTestDataKey = parseInt(multipleTestDataKey) + 1; 7154 if (multipleTestData.length > multipleTestDataKey) { 7155 if (multipleTestData[multipleTestDataKey]['test_added'] && multipleTestData[multipleTestDataKey]['test_id'] > 0) { 7156 window.open('articles/edittest?multipletest=1&id=' + multipleTestData[multipleTestDataKey]['test_id'] + '&key=' + multipleTestDataKey, '_self'); 7157 } else { 7158 window.open('articles/edittest?multipletest=1&article_id=' + multipleTestData[multipleTestDataKey].id + '&key=' + multipleTestDataKey, '_self'); 7159 } 7160 } else { 7161 let cookieData = getCookie('article_filter'); 7162 let filter = JSON.parse(cookieData); 7163 localStorage.removeItem('multiple_test_data'); 7164 localStorage.removeItem('sign_img'); 7165 if (filter['dir_id']) { 7166 window.open('articles?dir_id=' + filter['dir_id'], '_self'); 7167 } else { 7168 window.open('articles', '_self'); 7169 } 7170 } 7171}); 7172$(document).on('click', '#set-not-found', function (e) { 7173 let val = $(this).data('val'); 7174 let article_id = $(this).data('article_id'); 7175 $.ajax({ 7176 type: 'POST', 7177 url: 'setarticlenotfound', 7178 cache: false, 7179 data: { 7180 val: val, 7181 article_id: article_id 7182 }, 7183 success: async function (result) { 7184 try { 7185 let data = JSON.parse(result); 7186 if (typeof data === 'object') { 7187 if (data['success'] === true) { 7188 if (data['not_found'] === true) { 7189 $('#set-not-found[data-val="false"]').removeClass('hide-me'); 7190 $('#set-not-found[data-val="true"]').addClass('hide-me'); 7191 $('button[type="submit"]').addClass('hide-me'); 7192 } else { 7193 $('#set-not-found[data-val="true"]').removeClass('hide-me'); 7194 $('#set-not-found[data-val="false"]').addClass('hide-me'); 7195 $('button[type="submit"]').removeClass('hide-me'); 7196 } 7197 if ($('.my-badge.state').length > 0) { 7198 $('.my-badge.state').attr("class").split(/\s+/).forEac
7198h((el) => { 7199 if (el.startsWith('state_')) { 7200 $('.my-badge.state').removeClass(el); 7201 } 7202 }) 7203 $('.my-badge.state').addClass(data['state'].toLowerCase()).text(getStateTranslate(data['state'])); 7204 } 7205 presentToast(translate['ARTICLE']['STATE_CHANGED_TO_AFTER_SET_NOT_FOUND'] + getStateTranslate(data['state']), 'fa-floppy-disk', 'light', 2000); 7206 } 7207 } else { 7208 handleResult(result); 7209 } 7210 } catch (err) { 7211 handleResult(result, err); 7212 } 7213 } 7214 }); 7215}) 7216// END-TEST FUNCTIONS 7217 7218 7219// IMPORT FUNCTIONS 7220async function importItems(ids) { 7221 const tableName = $('.my-table-list').data('table-name'); 7222 if (await submitFormAfterConfirm(translate['MODEL']['IMPORT_ELEMENT_CONFIRM_TITLE'], translate['MODEL']['IMPORT_ELEMENT_CONFIRM_TEXT'])) { 7223 $('#loading-bar').show(); 7224 $.ajax({ 7225 type: 'POST', 7226 url: 'importfromtablelist', 7227 cache: false, 7228 data: { 7229 tableName: tableName, 7230 ids: ids 7231 }, 7232 success: async function (result) { 7233 switch (tableName) { 7234 case 'central_model': 7235 trackEventGoogleAnalytics("Modell importiert"); 7236 break; 7237 case 'central_manufacture': 7238 trackEventGoogleAnalytics("Hersteller importiert"); 7239 break; 7240 case 'central_model_category': 7241 trackEventGoogleAnalytics("Kategorie importiert"); 7242 break; 7243 } 7244 $('#loading-bar').hide(); 7245 try { 7246 let data = JSON.parse(result); 7247 if (typeof data === 'object') { 7248 data.forEach((element) => { 7249 $('.my-table-list').find('.list-item[data-id="' + element['central_db_id'] + '"] .thumbnail .icon').removeClass('hide-me'); 7250 }); 7251 if (data.length != ids.length) { 7252 presentToast(translate['CAN_NOT_IMPORT_EVERY_ITEM_' + tableName.toLocaleUpperCase()], 'fa-triangle-exclamation', 'warning'); 7253 } 7254 if (data.length > 0) { 7255 presentToast(translate['MODEL']['SUCCESSFULLY_IMPORTED'], 'fa-cloud-arrow-down', 'success', 2000); 7256 } 7257 $('.my-table-list .list-item .select-col input[type="checkbox"]').prop('checked', false); 7258 updateMyButtonsList(); 7259 let url_str = window.location.href; 7260 let url = new URL(url_str); 7261 let search_params = url.searchParams; 7262 if (search_params.has('redirect')) { 7263 if (data[0]) { 7264 let link = ''; 7265 switch (tableName) { 7266 case 'central_model': 7267 link = decodeURI(search_params.get('redirect')); 7268 link += '&model_id=' + data[0]['id'] + '&model_name=' + encodeURI(data[0]['name']); 7269 window.open(link, '_self'); 7270 break; 7271 case 'central_manufacture': 7272 link = decodeURI(search_params.get('redirect')); 7273 link += '&manufacture_id=' + data[0]['id'] + '&manufacture_name=' + encodeURI(data[0]['name']); 7274 window.open(link, '_self'); 7275 break; 7276 case 'central_model_category': 7277 link = decodeURI(search_params.get('redirect')); 7278 link += '&model_category_id=' + data[0]['id'] + '&model_category_name=' + encodeURI(data[0]['name']); 7279 window.open(link, '_self'); 7280 break; 7281 } 7282 } 7283 } 7284 } else { 7285 handleResult(result); 7286 } 7287 } catch (err) { 7288 handleResult(result, err); 7289 } 7290 }, 7291 }); 7292 } 7293} 7294$(document).on('click', '.my-table-list .import-item', function (e) { 7295 if ($(e.target).prop("tagName") !== 'INPUT') 7296 importItems([$(this).data('id')]); 7297}); 7298$(document).on('click', '#import-items', async function () { 7299 var ids = []; 7300 getSelectedListCheckboxes().each(function () { 7301 ids.push(this.value); 7302 }); 7303 importItems(ids); 7304}); 7305$('#article .show_short_or_long').click(function () { 7306 if ($(this).hasClass('short')) { 7307 $(this).find('.input').text($(this).find('.input').data('long')); 7308 $(this).removeClass('short').addClass('long'); 7309 } else { 7310 $(this).find('.input').text($(this).find('.input').data('short')); 7311 $(this).removeClass('long').addClass('short') 7312 } 7313}) 7314// END-IMPORT FUNCTIONS 7315window.onerror = function (message, source, lineno, colno, error) { 7316 sendErrorToServer({ 7317 type: 'js-error', 7318 message: message, 7319 source: source, 7320 lineno: lineno, 7321 colno: colno, 7322 stack: error ? error.stack : null, 7323 ua: navigator.userAgent ? navigator.userAgent : null, 7324 }); 7325}; 7326window.onunhandledrejection = function (event) { 7327 sendErrorToServer({ 7328 type: 'unhandled-promise', 7329 message: event.reason ? event.reason.message : 'Unknown', 7330 stack: event.reason ? event.reason.stack : null, 7331 ua: navigator.userAgent ? navigator.userAgent : null 7332 }); 7333}; 7334function sendErrorToServer(errorData) { 7335 $.ajax({ 7336 type: 'POST', 7337 url: 'log_js_error', 7338 cache: false, 7339 data: errorData 7340 }); 7341} 7342 7343// CALENDAR FUNCTIONS 7344if ($('#my-calendar').length > 0) { 7345 let myCalendarEl = document.getElementById('my-calendar'); 7346 let myCalendarOptions = $('#my-calendar').data('calendar');
7347 let calendarUrlParams = new URLSearchParams(window.location.search); 7348 if (!calendarUrlParams.has('view')) { 7349 let savedCalendarView = localStorage.getItem('calendarView'); 7350 if (savedCalendarView) { 7351 myCalendarOptions.initialView = savedCalendarView; 7352 } 7353 } 7354 if (!calendarUrlParams.has('day') && !calendarUrlParams.has('month') && !calendarUrlParams.has('year')) { 7355 let savedCalendarDate = localStorage.getItem('calendarDate'); 7356 if (savedCalendarDate) { 7357 myCalendarOptions.initialDate = savedCalendarDate; 7358 } 7359 } 7360 let myCalendar = new FullCalendar.Calendar(myCalendarEl, myCalendarOptions); 7361 myCalendar.render(); 7362 7363 let touchStartXCal = 0; 7364 let touchCurrentXCal = 0; 7365 let isSwipingCal = false; 7366 7367 const SWIPE_THRESHOLD = 180; 7368 7369 myCalendarEl.addEventListener('touchstart', (e) => { 7370 if (e.touches.length !== 1) return; 7371 7372 touchStartXCal = e.touches[0].clientX; 7373 touchCurrentXCal = touchStartXCal; 7374 isSwipingCal = true; 7375 }, { passive: true }); 7376 7377 myCalendarEl.addEventListener('touchmove', (e) => { 7378 if (!isSwipingCal) return; 7379 7380 touchCurrentXCal = e.touches[0].clientX; 7381 }, { passive: true }); 7382 7383 myCalendarEl.addEventListener('touchend', () => { 7384 if (!isSwipingCal) return; 7385 7386 const diffX = touchCurrentXCal - touchStartXCal; 7387 7388 if (Math.abs(diffX) > SWIPE_THRESHOLD) { 7389 if (diffX > 0) { 7390 myCalendar.prev(); 7391 } else { 7392 myCalendar.next(); 7393 } 7394 } 7395 7396 isSwipingCal = false; 7397 }); 7398 7399 myCalendar.on('datesSet', function (info) { 7400 let currdate = moment(myCalendar.getDate()); 7401 replaceUrlParam('day', currdate.format("DD")); 7402 replaceUrlParam('month', currdate.format("MM")); 7403 replaceUrlParam('year', currdate.format("YYYY")); 7404 replaceUrlParam('view', info.view.type); 7405 localStorage.setItem('calendarView', info.view.type); 7406 localStorage.setItem('calendarDate', currdate.format("YYYY-MM-DD")); 7407 }); 7408 7409 $(document).on('click', '.fc-filterButton-button', function () { 7410 getAjaxPopUp('calendarfilterpopup'); 7411 }); 7412 7413 $(document).on('click', '#confirm-filter-calendar', async function () { 7414 const popupEL = $(this).parents('.my-popup'); 7415 popupEL.find('form').submit(); 7416 }); 7417 7418 myCalendar.on('eventClick', function (info) { 7419 var eventObj = info.event; 7420 let datetime = moment(eventObj.startStr); 7421 let desc = ""; 7422 if (eventObj.extendedProps.description) 7423 desc = eventObj.extendedProps.description 7424 let message = datetime.format(eventObj.allDay ? 'DD.MM.YYYY' : 'DD.MM.YYYY HH:mm') + "<br /><br /><strong>" + eventObj.title + "</strong><br />" + desc + "<br />"; 7425 infoPopup(eventObj.extendedProps.category, message, eventObj.url); 7426 info.jsEvent.preventDefault(); 7427 }); 7428 7429 // myCalendar.on('dateClick', function (info) { 7430 // let dateStr = info.dateStr; 7431 // let dateOnly = dateStr.length <= 10; 7432 // if (dateOnly) { 7433 // dateStr = dateStr + ' 19:30'; 7434 // } 7435 // let datetime = moment(dateStr); 7436 // let allDay = info.allDay; 7437 // let buttons = []; 7438 7439 // if (buttons.length > 0) 7440 // myActionSheet(translate['CALENDAR']['ADD'], 'add-calender-action-sheet', buttons); 7441 7442 // }); 7443} 7444 7445$('#addicstocalendar').click(function () { 7446 let icsLink = $(this).data('ics_link'); 7447 infoPopup(translate['CALENDAR']['ADD_ICS_TO_CALENDER_TITLE'], translate['CALENDAR']['ADD_ICS_TO_CALENDER_MESSAGE'].replace('#ICS_LINK#', icsLink)); 7448}) 7449function copyIcsLink(el) { 7450 const text = el.textContent; 7451 navigator.clipboard.writeText(text).then(() => { 7452 el.style.backgroundColor = 'var(--color-success)'; 7453 el.style.color = 'var(--color-success-contrast)'; 7454 el.textContent = 'ð Link kopiert!'; 7455 setTimeout(() => { 7456 el.textContent = text; 7457 el.style.backgroundColor = 'var(--color-light)'; 7458 el.style.color = 'var(--color-font)'; 7459 }, 1500); 7460 }).catch(() => { 7461 alert('Kopieren fehlgeschlagen. Bitte manuell kopieren.'); 7462 }); 7463} 7464// END-CALENDAR FUNCTIONS
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.