1var myApp = angular.module('BungeeApp', ['ngRoute', 'ngSanitize', 'ui.validate', 'ngAnimate', 'cgNotify', 'blockUI', 'zxcvbn', 'datatables', 'ui.bootstrap', 2 'lr.upload', 'dndLists', 'ui.mask', 'ngTagsInput']); 3 4myApp 5 .controller('MainController', function ($scope, $http, $location, $route, $rootScope, $window, $filter, $timeout, $uibModal, notify, AppConstants, $sce) { 6 $rootScope.pageData = { 7 title: '', 8 menu: null, 9 showMobileMenu: false, 10 header: '', 11 }; 12 13 $rootScope.AppConstants = AppConstants; 14 $rootScope.billingChoices = { planOption: null, residenceCount: null, termLength: null }; 15 16 $scope.bodyclass = ''; 17 18 $rootScope.setPage = function (t, m, h) { 19 $rootScope.pageData.title = t; 20 $rootScope.pageData.header = h || t; 21 if (m) { 22 $rootScope.pageData.menu = m; 23 } 24 }; 25 26 $rootScope.hasBillingChoices = false; 27 28 $rootScope.enableTooltips = function () { 29 jQuery('[data-toggle="popover"]').each(function () { 30 if (jQuery(this).attr('title').length) { 31 jQuery(this).popover({ 32 placement: 'top', 33 html: true, 34 trigger: 'hover' 35 }); 36 } 37 }); 38 /* 39 jQuery("[data-toggle='tooltip']").each(function () { 40 if (jQuery(this).attr('title').length) { 41 jQuery(this).tooltip({ 42 trigger: 'hover', 43 html: true, 44 45 }); 46 } 47 });*/ 48 49 jQuery("[rel='tooltip']").each(function () { 50 if (jQuery(this).attr('title').length) { 51 jQuery(this).tooltip({ 52 trigger: 'hover', 53 html: true, 54 55 }); 56 } 57 }); 58 59 jQuery('.freshdeskTooltip').each(function () { 60 if (jQuery(this).attr('title') != null) { 61 if (jQuery(this).attr('title').length) { 62 jQuery(this).popover({ 63 placement: 'top', 64 html: true, 65 }); 66 } 67 } 68 }); 69 } 70 71 $rootScope.barsToCommas = function (input) { 72 return input.replace('|', ','); 73 } 74 75 $rootScope.getBillingChoices = function () { 76 $rootScope.ajaxCall('/Customer/GetBillingChoices', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 77 if (data != null) { 78 $rootScope.billingChoices = data; 79 $rootScope.hasBillingChoices = true; 80 } 81 }); 82 } 83 84 $rootScope.enableTooltipClose = function () { 85 jQuery(document).on("click", ".popover .tooltipClose", function () { 86 jQuery(this).parents(".popover").popover('hide'); 87 }); 88 89 jQuery(".popover").click(function (e) { 90 e.stopPropagation(); 91 }); 92 jQuery(".freshdeskTooltip").click(function (e) { 93 e.stopPropagation(); 94 }); 95 96 jQuery('body').unbind('click').click(function () { 97 jQuery(".popover").each(function () { 98 jQuery(this).popover('hide'); 99 }); 100 }); 101 } 102 103 $rootScope.addCommas = function (x) { 104 if (!x) { 105 return x; 106 } 107 108 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 109 } 110 111 $rootScope.replaceSpaces = function (x) { 112 if (!x) { 113 return x; 114 } 115 116 return x.toString().replace(/ /g, "-"); 117 } 118 119 $rootScope.displayCurrentDate = function () { 120 var today = new Date(); 121 var dd = String(today.getDate()).padStart(2, '0'); 122 var mm = String(today.getMonth() + 1).padStart(2, '0'); 123 var yyyy = today.getFullYear(); 124 125 return mm + '/' + dd + '/' + yyyy; 126 } 127 128 $rootScope.stateList = [ 129 { abbr: 'AL', name: 'Alabama' }, 130 { abbr: 'AK', name: 'Alaska' }, 131 { abbr: 'AZ', name: 'Arizona' }, 132 { abbr: 'AR', name: 'Arkansas' }, 133 { abbr: 'CA', name: 'California' }, 134 { abbr: 'CO', name: 'Colorado' }, 135 { abbr: 'CT', name: 'Connecticut' }, 136 { abbr: 'DE', name: 'Delaware' }, 137 { abbr: 'DC', name: 'District Of Columbia' }, 138 { abbr: 'FL', name: 'Florida' }, 139 { abbr: 'GA', name: 'Georgia' }, 140 { abbr: 'HI', name: 'Hawaii' }, 141 { abbr: 'ID', name: 'Idaho' }, 142 { abbr: 'IL', name: 'Illinois' }, 143 { abbr: 'IN', name: 'Indiana' }, 144 { abbr: 'IA', name: 'Iowa' }, 145 { abbr: 'KS', name: 'Kansas' }, 146 { abbr: 'KY', name: 'Kentucky' }, 147 { abbr: 'LA', name: 'Louisiana' }, 148 { abbr: 'ME', name: 'Maine' }, 149 { abbr: 'MD', name: 'Maryland' }, 150 { abbr: 'MA', name: 'Massachusetts' }, 151 { abbr: 'MI', name: 'Michigan' }, 152 { abbr: 'MN', name: 'Minnesota' }, 153 { abbr: 'MS', name: 'Mississippi' }, 154 { abbr: 'MO', name: 'Missouri' }, 155 { abbr: 'MT', name: 'Montana' }, 156 { abbr: 'NE', name: 'Nebraska' }, 157 { abbr: 'NV', name: 'Nevada' }, 158 { abbr: 'NH', name: 'New Hampshire' }, 159 { abbr: 'NJ', name: 'New Jersey' }, 160 { abbr: 'NM', name: 'New Mexico' }, 161 { abbr: 'NY', name: 'New York' }, 162 { abbr: 'NC', name: 'North Carolina' }, 163 { abbr: 'ND', name: 'North Dakota' }, 164 { abbr: 'OH', name: 'Ohio' }, 165 { abbr: 'OK', name: 'Oklahoma' }, 166 { abbr: 'OR', name: 'Oregon' }, 167 { abbr: 'PA', name: 'Pennsylvania' }, 168 { abbr: 'RI', name: 'Rhode Island' }, 169 { abbr: 'SC', name: 'South Carolina' }, 170 { abbr: 'SD', name: 'South Dakota' }, 171 { abbr: 'TN', name: 'Tennessee' }, 172 { abbr: 'TX', name: 'Texas' }, 173 { abbr: 'UT', name: 'Utah' }, 174 { abbr: 'VT', name: 'Vermont' }, 175 { abbr: 'VA', name: 'Virginia' }, 176 { abbr: 'WA', name: 'Washington' }, 177 { abbr: 'WV', name: 'West Virginia' }, 178 { abbr: 'WI', name: 'Wisconsin' }, 179 { abbr: 'WY', name: 'Wyoming' }, 180 ]; 181 182 $rootScope.countryCache = null; 183 $rootScope.getCountries = function () { 184 if ($rootScope.countries == null) { 185 $scope.ajaxCall('/Country/CountryList', {}, function (data) { 186 $rootScope.countryCache = data; 187 return data; 188 }); 189 } else { 190 return $rootScope.countryCache; 191 } 192 } 193 194 $rootScope.preventPaste = function ($event) { 195 $event.preventDefault(); 196 $event.stopPropagation(); 197 return false; 198 } 199 200 $rootScope.ajaxCall = function (url, inputData, success, error, doLoading) { 201 doLoading = ((typeof doLoading !== 'undefined') ? doLoading : true); 202 203 url = '/data' + url; 204 205 return $http.post(url, JSON.stringify(inputData), { headers: { 'X-Do-Loading': doLoading ? 'true' : 'false' } }).then(function (response) { 206 if (status == 403 || status == 401) { 207 $window.location.href = '/Login?ReturnUrl=' + $window.location.pathname; 208 return; 209 } 210 if (response.data != null) { 211 if (response.data.draw != null) { 212 // assume data tables call 213 if (success != null) { 214 success(response.data); 215 } 216 return response.data; 217 } else if (response.data.success) { 218 if (success != null) { 219 success(response.data.results); 220 } 221 return response.data.results; 222 } else { 223 if (doLoading) { 224 $rootScope.errorMessage(response.data.message); 225 } 226 227 if (error != null) { 228 error(response.data); 229 } 230 } 231 } else if (error != null) { 232 233 if (error == 'file') { 234 $rootScope.errorMessage("The maximum file upload limit is 5MB"); 235 } else { 236 error(response.data); 237 } 238 } 239 }, function (response) { 240 if (response.status == 403 || response.status == 401) { 241 $window.location.href = '/Login?ReturnUrl=' + $window.location.pathname; 242 return; 243 } 244 if (error != null) { 245 error(response.data); 246 } 247 }); 248 }; 249 250 251 $rootScope.ajaxApiCall = function (url, inputData, success, error, doLoading) { 252 doLoading = ((typeof doLoading !== 'undefined') ? doLoading : true); 253 254 if (!url.includes('https://')) { 255 url = '/data' + url; 256 } 257 258 console.log("API Call"); 259 return $http.post(url, JSON.stringify(inputData), { headers: { } }).then(function (response) { 260 if (status == 403 || status == 401) { 261 $window.location.href = '/Login?ReturnUrl=' + $window.location.pathname; 262 return; 263 } 264 if (response.data != null) { 265 if (response.data.message == 'Success') { 266 success(response.data); 267 } else { 268 if (doLoading) { 269 $rootScope.errorMessage(response.data.message); 270 } 271 272 if (error != null) { 273 error(response.data); 274 } 275 } 276 } else if (error != null) { 277 console.log("API Call 2"); 278 if (error == 'file') { 279 $rootScope.errorMessage("The maximum file upload limit is 5MB"); 280 } else { 281 error(response.data); 282 } 283 } 284 }, function (response) { 285 if (response.status == 403 || response.status == 401) { 286 $window.location.href = '/Login?ReturnUrl=' + $window.location.pathname; 287 return; 288 } 289 if (error != null) { 290 error(response.data); 291 } 292 }); 293 }; 294 295 $rootScope.ajaxCallNoLoading = function (url, inputData, success, error) { 296 return $rootScope.ajaxCall(url, inputData, success, error, false); 297 }; 298
299 $rootScope.questionsHasAdminOnly = function (questions) { 300 for (var i = 0; i < questions.length; i++) { 301 if (questions[i].adminOnly) { 302 return true; 303 } 304 } 305 return false; 306 } 307 308 $rootScope.errorMessage = function (msg) { 309 notify({ 310 message: msg, 311 classes: 'alert-danger', 312 duration: 10000, 313 }); 314 }; 315 316 $rootScope.successMessage = function (msg) { 317 notify({ 318 message: msg, 319 classes: 'alert-success', 320 duration: 10000, 321 }); 322 }; 323 324 $rootScope.setUrl = function (url) { 325 window.location.href = url; 326 } 327 328 $rootScope.formatDateToString = function (date) { 329 return $filter('date')(date, 'MM/dd/yyyy'); 330 } 331 332 $rootScope.formatDateTimeToString = function (date) { 333 return $filter('date')(date, 'MM/dd/yyyy h:mm:ss a'); 334 } 335 336 $rootScope.formatTag = function (tag) { 337 if (!tag || !tag.length) { 338 return ''; 339 } 340 341 return tag.replace(/[^a-zA-Z0-9\- ]+/g, '').toLowerCase(); 342 } 343 344 $rootScope.confirm = function (msg, ok, cancel, yesText, noText) { 345 $uibModal.open({ 346 templateUrl: 'modal-confirm-prompt', 347 controller: function ($scope, pInfo) { 348 $scope.pInfo = pInfo; 349 350 $scope.clickYes = function () { 351 if ($scope.pInfo.yesAction != null) { 352 $scope.pInfo.yesAction(); 353 } 354 $scope.$close(); 355 }; 356 357 $scope.clickNo = function () { 358 if ($scope.pInfo.noAction != null) { 359 $scope.pInfo.noAction(); 360 } 361 $scope.$close(); 362 }; 363 }, 364 backdrop: 'static', 365 resolve: { 366 pInfo: function () { 367 return { 368 prompt: msg, 369 yesText: yesText == null ? 'Yes' : yesText, 370 noText: noText == null ? 'No' : noText, 371 yesAction: ok, 372 noAction: cancel 373 }; 374 } 375 } 376 }); 377 }; 378 379 $scope.preLoad = true; 380 $scope.load = function () { 381 $timeout(function () { 382 $scope.preLoad = false; 383 }, 1000); 384 } 385 386 $rootScope.goback = function () { 387 history.back(); 388 } 389 390 $scope.priceformatter = new Intl.NumberFormat('en-US', { 391 style: 'currency', 392 currency: 'USD', 393 minimumFractionDigits: 2 394 }); 395 396 $rootScope.initFormDatePickerField = function () { 397 (function ($) { 398 console.log("Initializing the form date picker field"); 399 400 var start = '.formDatePickerField'; 401 $rootScope.initMobiscrollDatePicker('.formDatePickerField'); 402 })(jQuery); 403 } 404 405 $rootScope.showPassword = false; 406 $rootScope.tempShowPassword = function () { 407 $rootScope.showPassword = !$rootScope.showPassword; 408 $timeout(function () { 409 $rootScope.showPassword = false; 410 }, 30000); 411 } 412 413 $rootScope.currentCustomerSite = null; 414 415 $rootScope.initMobiscrollTimePicker = function (element) { 416 mobiscroll.setOptions({ 417 theme: 'ios', 418 themeVariant: 'light', 419 }); 420 421 $timeout(function () { 422 $(element).mobiscroll().datepicker({ 423 controls: ['time'], 424 select: 'date', 425 stepMinute: 5, 426 timeFormat: 'h:mmA', 427 touchUi: true, 428 anchor: $(element)[0], 429 display: 'bubble', 430 }); 431 }, 10); 432 } 433 434 $rootScope.initMobiscrollTimePickerRange = function (start, end) { 435 mobiscroll.setOptions({ 436 theme: 'ios', 437 themeVariant: 'light', 438 }); 439 440 $timeout(function () { 441 var defaultStartTime = $(start).val(); 442 var defaultEndTime = $(end).val(); 443 444 console.log(defaultStartTime); 445 console.log(defaultEndTime); 446 var picker = $(start).mobiscroll().datepicker({ 447 controls: ['time'], 448 select: 'range', 449 startInput: start, 450 endInput: end, 451 stepMinute: 5, 452 timeFormat: 'h:mmA', 453 touchUi: true, 454 anchor: $(start)[0], 455 display: 'bubble', 456 }).mobiscroll('getInst'); 457 458 $timeout(function () { 459 picker.setVal([defaultStartTime, defaultEndTime]); 460 }, 50); 461 }, 500); 462 } 463 464 $rootScope.initMobiscrollDatePicker = function (start) { 465 console.log("Shouldn't be a range"); 466 mobiscroll.setOptions({ 467 theme: 'ios', 468 themeVariant: 'light', 469 }); 470 471 $timeout(function () { 472 var defaultStartDate = $(start).val(); 473 474 var picker = $(start).mobiscroll().datepicker({ 475 controls: ['calendar'], 476 touchUi: true, 477 anchor: $(start)[0], 478 display: 'bubble', 479 select: 'date', 480 }).mobiscroll('getInst'); 481 482 $timeout(function () { 483 picker.setVal([defaultStartDate]); 484 }, 50); 485 }, 100); 486 } 487 $rootScope.initMobiscrollDateTimePicker = function (start) { 488 mobiscroll.setOptions({ 489 theme: 'ios', 490 themeVariant: 'light', 491 }); 492 493 $timeout(function () { 494 var defaultStartDate = $(start).val(); 495 496 var picker = $(start).mobiscroll().datepicker({ 497 controls: ['calendar', 'time'], 498 touchUi: true, 499 anchor: $(start)[0], 500 display: 'bubble', 501 select: 'date', 502 }).mobiscroll('getInst'); 503 504 $timeout(function () { 505 picker.setVal([defaultStartDate]); 506 }, 50); 507 }, 100); 508 } 509 510 $rootScope.initMobiscrollDatePickerRange = function (start, end) { 511 mobiscroll.setOptions({ 512 theme: 'ios', 513 themeVariant: 'light', 514 }); 515 516 $timeout(function () { 517 var defaultStartDate = $(start).val(); 518 var defaultEndDate = $(end).val(); 519 520 var picker = $(start).mobiscroll().datepicker({ 521 anchor: $(start)[0], 522 display: 'bubble', 523 controls: ['calendar'], 524 select: 'range', 525 startInput: start, 526 endInput: end, 527 touchUi: true, 528 }).mobiscroll('getInst'); 529 530 $timeout(function () { 531 picker.setVal([defaultStartDate, defaultEndDate]); 532 }, 50); 533 }, 500); 534 } 535 536 $rootScope.initMobiscrollDatePickerRangeOneInput = function (start) { 537 mobiscroll.setOptions({ 538 theme: 'ios', 539 themeVariant: 'light', 540 }); 541 542 $timeout(function () { 543 var defaultStartDate = $(start).val(); 544 545 var picker = $(start).mobiscroll().datepicker({ 546 anchor: $(start)[0], 547 display: 'bubble', 548 controls: ['calendar'], 549 select: 'range', 550 touchUi: true, 551 }).mobiscroll('getInst'); 552 553 $timeout(function () { 554 picker.setVal([defaultStartDate]); 555 }, 50); 556 }, 500); 557 } 558 559 $rootScope.removeSite = function () { 560 sessionStorage.removeItem("bungee-sitecookie-site"); 561 } 562 $rootScope.setSite = function (site) { 563 sessionStorage.setItem("bungee-sitecookie-site", site); 564 } 565 566 $rootScope.checkUrl = function(string) { 567 let givenURL; 568 try { 569 givenURL = new URL(string); 570 } catch (error) { 571 console.log("error is", error); 572 return false; 573 } 574 return true; 575 } 576 577 578 $rootScope.isAdmin = false; 579 $rootScope.isCommitteeLeader = false; 580 581 $rootScope.checkCommitteeLeader = function () { 582 if (!$rootScope.currentCustomerSite) { 583 return; 584 } 585 586 if ($rootScope.isAdmin) { 587 $rootScope.isCommitteeLeader = true; 588 } 589 590 $scope.ajaxCall('/Committee/CheckIsCommitteeLeader', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 591 $rootScope.isCommitteeLeader = data; 592 593 }, function () { 594 595 }, false); 596 } 597 598 $rootScope.getSite = function () { 599 var site = sessionStorage.getItem("bungee-sitecookie-site"); 600 angular.forEach(AppConstants.CurrentUser.sites, function (lsite) { 601 if (lsite.customerSlug == site) { 602 $rootScope.isAdmin = lsite.isAdmin; 603 $rootScope.currentCustomerSite = lsite; 604 } 605 }); 606 607 return site; 608 } 609 610 $rootScope.replies = null; 611 $rootScope.getPanelStepData = function () { 612 return new Promise(resolve => setTimeout(resolve, 500)).then(() => $rootScope.getPanelStepDataAfterWait()); 613 } 614 615 $rootScope.getPanelStepDataAfterWait = function () { 616 617 var s = $rootScope.currentCustomerSite.customerId; 618 $rootScope.ajaxCall('/SupportStep/GetCustomerCurrentStep', { customerId: s }, function (data) { 619 $rootScope.replies = data.replies; 620 }); 621 } 622 623 $rootScope.getTrialEndDate = function () { 624 var c = $rootScope.currentCustomerSite.customerId; 625 $rootScope.ajaxCall('/SupportStep/GetTrialEndDate', { customerId: c }, function (data) { 626 $rootScope.trialEndDate = data; 627 }); 628 } 629 630 $rootScope.checkPlan = function () { 631 if (!$rootScope.currentCustomerSite) { 632 return false; 633 } 634 635 if (!$rootScope.currentCustomerSite.hasTrialOrPlan) { 636 return false; 637 } 638 639 if ($rootScope.currentCustomerSite.hasTrialOrPlan == true) { 640 return true; 641 } 642 } 643 644 $rootScope.checkSitePermission = function (permission) { 645 if (!$rootScope.currentCustomerSite) { 646 //console.log("No current customer site"); 647 return false; 648 } 649 650 if (!$rootScope.currentCustomerSite.features) { 651 //console.log("No current customer site features"); 652 return false; 653 } 654 655 if ($rootScope.currentCustomerSite.features.includes(permission)) { 656 return true; 657 } 658 } 659 660 $rootScope.checkSubAdminPermission = function (permission) { 661 if (!$rootScope.currentCustomerSite) { 662 return false; 663 } 664 665 if ($rootScope.isAdmin) { 666 return true; 667 } 668 669 if (!$rootScope.currentCustomerSite.features) { 670 return false; 671 } 672 673 if (!$rootScope.currentCustomerSite.subAdminFeatures) { 674 return false; 675 } 676 if ($rootScope.currentCustomerSite.subAdminFeatures.includes(permission)) { 677 return true; 678 } 679 } 680 681 $rootScope.setCurrentCustomerSite = function (site) { 682 $rootScope.currentCustomerSite = site; 683 } 684 685 $scope.triggerUpgradeAccountModal = function () { 686 $uibModal.open({ 687 templateUrl: 'upgrade-account-modal', 688 controller: function ($scope, $timeout) { 689 $scope.upgradeAccount = function () { 690 $scope.gotoPath($scope.getSite() + "/organization"); 691 } 692 }, 693 backdrop: 'static', 694 resolve: { 695 696 } 697 }).result.then(function () { 698 699 }, function () { 700 701 }); 702 }; 703 704 $rootScope.triggerSubAdminAccessModal = function (type, id) { 705 $uibModal.open({ 706 templateUrl: 'sub-admin-access-modal', 707 size: 'lg', 708 controller: function ($scope, $timeout, type, id, customerId) { 709 $scope.matrixData = null; 710 711 $scope.label = ""; 712 $scope.typeLabel = ""; 713 714 switch (type) { 715 case 1: 716 $scope.label = "form"; 717 $scope.typeLabel = "Custom Forms"; 718 break; 719 case 2: 720 $scope.label = "amenity"; 721 $scope.typeLabel = "Amenities"; 722 break; 723 case 3: 724 $scope.label = "event"; 725 $scope.typeLabel = "Events"; 726 break; 727 case 4: 728 $scope.label = "calendar"; 729 $scope.typeLabel = "Calendars"; 730 break; 731 case 5: 732 $scope.label = "folder"; 733 $scope.typeLabel = "Document Repository"; 734 break; 735 case 6: 736 $scope.label = "form"; 737 $scope.typeLabel = "Surveys"; 738 break; 739 case 7: 740 $scope.label = "form"; 741 $scope.typeLabel = "Ticketing System"; 742 break; 743 case 8: 744 $scope.label = "form"; 745 $scope.typeLabel = "Violations"; 746 break; 747 case 9: 748 $scope.label = "committees"; 749 $scope.typeLabel = "Committees"; 750 break; 751 case 10: 752 $scope.label = "boardroom"; 753 $scope.typeLabel = "Boardroom"; 754 break; 755 } 756 757 $scope.ajaxCall('/SubAdmin/GetAssignedSubAdminUsers', { customerId: customerId, itemId: id, itemType: type }, function (data) { 758 $scope.matrixData = data; 759 });
760 761 $scope.submitAttempt = false; 762 $scope.noneSelected = false; 763 $scope.save = function (form) { 764 $scope.submitAttempt = true; 765 766 if (form.$invalid) { 767 return; 768 } 769 770 $scope.ajaxCall('/SubAdmin/SaveAssignedSubAdminUsers', { customerId: customerId, itemId: id, itemType: type, data: $scope.matrixData }, function (data) { 771 $scope.$close(); 772 }); 773 } 774 }, 775 backdrop: 'static', 776 resolve: { 777 type: function () { 778 return type; 779 }, 780 id: function () { 781 return id; 782 }, 783 customerId: function () { 784 return $rootScope.currentCustomerSite.customerId; 785 } 786 } 787 }).result.then(function () { 788 789 }, function () { 790 791 }); 792 }; 793 794 $rootScope.getSiteBySlug = function (site) { 795 796 angular.forEach(AppConstants.CurrentUser.sites, function (lsite) { 797 if (lsite.customerSlug == site) { 798 $rootScope.isAdmin = lsite.isAdmin; 799 $rootScope.currentCustomerSite = lsite; 800 } 801 }); 802 803 return site; 804 } 805 806 $rootScope.currentSites = AppConstants.CurrentUser.sites; 807 808 $rootScope.hasPublicSite = false; 809 $rootScope.checkPublicSite = function (slug) { 810 $scope.ajaxCall('/Customer/CheckPublicSite', { customerSlug: slug }, function (data) { 811 if (data == false) { 812 $rootScope.hasPublicSite = false; 813 } else { 814 $rootScope.hasPublicSite = true; 815 816 } 817 818 }, function () { 819 820 }, false); 821 } 822 823 $rootScope.hasProptia = false; 824 $rootScope.checkProptia = function () { 825 $scope.ajaxCall('/Customer/CheckProptiaEnabled', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 826 if (data == false) { 827 $rootScope.hasProptia = false; 828 } else { 829 $rootScope.hasProptia = true; 830 } 831 }, function () { 832 833 }, false); 834 } 835 836 $rootScope.hasHelpSteps = false; 837 $rootScope.checkHelpSteps = function () { 838 $scope.ajaxCall('/Customer/CheckHelpStepsEnabled', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 839 if (data == false) { 840 $rootScope.hasHelpSteps = false; 841 } else { 842 $rootScope.hasHelpSteps = true; 843 } 844 }, function () { 845 846 }, false); 847 } 848 849 $rootScope.siteSuspended = false; 850 $rootScope.checkSiteSuspended = function () { 851 $scope.ajaxCall('/Customer/CheckSiteSuspended', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 852 if (data == false) { 853 $rootScope.siteSuspended = false; 854 } else { 855 $rootScope.siteSuspended = true; 856 } 857 }, function () { 858 859 }, false); 860 } 861 862 863 $rootScope.preventDefault = function ($event) { 864 $event.preventDefault(); 865 } 866 867 868 $rootScope.hasTutorialWizard = false; 869 $rootScope.checkTutorialWizard = function () { 870 if ($rootScope.currentCustomerSite) { 871 $scope.ajaxCall('/Customer/GetSetupWizard', { customerId: $rootScope.currentCustomerSite.customerId }, function (data) { 872 $scope.steps = 0; 873 $scope.setupwizard = data; 874 if ($scope.setupwizard.step1 == true) { 875 $scope.steps++; 876 } 877 if ($scope.setupwizard.step2 == true) { 878 $scope.steps++; 879 } 880 if ($scope.setupwizard.step3 == true) { 881 $scope.steps++; 882 } 883 if ($scope.setupwizard.step4 == true) { 884 $scope.steps++; 885 } 886 if ($scope.setupwizard.step5 == true) { 887 $scope.steps++; 888 } 889 if ($scope.setupwizard.step6 == true) { 890 $scope.steps++; 891 } 892 893 if ($scope.steps == 6) { 894 $rootScope.hasTutorialWizard = true; 895 } else { 896 $rootScope.hasTutorialWizard = false; 897 } 898 }, function () { 899 900 }, false); 901 } 902 } 903 904 $rootScope.transferToInternalSite = function (domain, customerId) { 905 $scope.ajaxCall('/AuthTransfer/RequestInternalMagicToken', { customerId: customerId }, function (data) { 906 window.location = domain + "/TransferInternal/" + data; 907 }); 908 } 909 910 $rootScope.transferToMemberPortal = function (domain, customerId) { 911 $scope.ajaxCall('/AuthTransfer/RequestInternalMagicToken', { customerId: $scope.currentCustomerSite.customerId }, function (data) { 912 window.location = "https://hoastartmobileportal.azurewebsites.net/home?magicToken=" + data; 913 }); 914 } 915 916 $rootScope.transferToMemberPortalRedirect = function (customerId) { 917 $scope.ajaxCall('/AuthTransfer/RequestInternalMagicToken', { customerId: customerId }, function (data) { 918 window.location = "https://hoastartmobileportal.azurewebsites.net/home?magicToken=" + data; 919 }); 920 } 921 922 $rootScope.transferToMemberDashboardPortal = function (domain, customerId) { 923 $scope.ajaxCall('/AuthTransfer/RequestInternalMagicToken', { customerId: $scope.currentCustomerSite.customerId }, function (data) { 924 window.location = "https://hoastartmobileportal.azurewebsites.net/dashboard?magicToken=" + data; 925 }); 926 } 927 928 $rootScope.transferToProptia = function () { 929 if (AppConstants.CurrentUser.proptiaUserId == null || true) { 930 931 $scope.ajaxCall('/User/GetCurrent', { userId: AppConstants.CurrentUser.userId }, function (data) { 932 $scope.currentUser = data; 933 934 if ($scope.currentUser.proptiaUserId != null) { 935 console.log("Transferring to Proptia"); 936 var userSyncData = { 937 PassKey: 'UGcxdU5QSjUzNXFQMjNqSWdyN25UdU1hZllyQm8ybGxERll1MHNmeWhabnpsei9GTGpvOFI0a0FTL0JMcHdYQmZTYjFsWTRnaXNlNUYvV', 938 SourceIdentifier: $scope.currentUser.userId, 939 TargetIdentifier: $scope.currentUser.proptiaUserId, 940 }; 941 $scope.ajaxApiCall('https://portal.proptia.com/api/auth/signonauth', userSyncData, function (data) { 942 window.location = data.url; 943 }, function () { 944 945 }, false); 946 } else { 947 console.log("User not synced with Proptia, redirect to proptia marketing site"); 948 window.location = "https://portal.proptia.com/"; 949 } 950 }); 951 952 } 953 } 954 955 $scope.adjustHeight = function () { 956 if (jQuery('#admin-footer').length) { 957 $timeout(function () { 958 jQuery(document).ready(function () { 959 var footerHeight = jQuery('#admin-footer').height(); 960 if (jQuery(window).height() > (jQuery('.page-container').height() + footerHeight + 90)) { 961 jQuery('#admin-footer').addClass('customStickyFooter').removeClass('noStickyFooter'); 962 jQuery('#admin-footer').addClass('customStickyFooter').removeClass('noStickyFooter'); 963 } else { 964 jQuery('#admin-footer').removeClass('customStickyFooter').addClass("noStickyFooter"); 965 966 } 967 $timeout($scope.adjustHeight(), 200); 968 });
969 }, 10); 970 } 971 } 972 973 $scope.adjustHeight(); 974 975 if (AppConstants.CurrentUser.isAdmin) { 976 $rootScope.loadAdminDashboard = true; 977 } else { 978 $rootScope.loadAdminDashboard = false; 979 } 980 981 $rootScope.timeouts = []; 982 983 984 $rootScope.checkSiteAccess = async function (slug, checkAdmin) { 985 $rootScope.siteSuspended = false; 986 987 window.onbeforeunload = function (e) { 988 989 } 990 991 if ($rootScope.timeouts.length) { 992 angular.forEach($rootScope.timeouts, function (timeout) { 993 $timeout.cancel(timeout); 994 }); 995 996 $rootScope.timeouts = []; 997 } 998 var id = window.setTimeout(function () { }, 0); 999 1000 while (id--) { 1001 window.clearTimeout(id); // will do nothing if no timeout with id is present 1002 } 1003 1004 if (!AppConstants.CurrentUser.sites || !AppConstants.CurrentUser.sites.length) { 1005 var mypromise = await new Promise(resolve => { 1006 $scope.ajaxCall('/User/GetCurrentUserSites', { }, function (data) { 1007 AppConstants.CurrentUser.sites = data; 1008 $rootScope.currentSites = data; 1009 resolve("\t\t Got the data"); 1010 }); 1011 }); 1012 } 1013 1014 if (jQuery('.modal-backdrop').length) { 1015 jQuery('.modal-backdrop').remove(); 1016 } 1017 1018 if (jQuery('.modal.fade').length) { 1019 jQuery('.modal.fade').remove(); 1020 } 1021 1022 jQuery('body').removeClass('modal-open'); 1023 1024 var adminfound = false; 1025 1026 var customDomainObject = false; 1027 1028 angular.forEach(AppConstants.CurrentUser.sites, function (loopsite) { 1029 if (loopsite.isAdmin) { 1030 adminfound = true; 1031 } 1032 1033 if (loopsite.useDomain == true && loopsite.isAdmin) { 1034 if (window.location.href.includes(loopsite.customDomain)) { 1035 customDomainObject = loopsite; 1036 $rootScope.setSite(loopsite.customerSlug); 1037 1038 if (loopsite.customerSlug != slug) { 1039 window.location.href = '/admin-dashboard/#!/' + loopsite.customerSlug + '/dashboard'; 1040 return; 1041 } 1042 } 1043 } 1044 }); 1045 1046 if (!adminfound && checkAdmin) { 1047 if (AppConstants.CurrentUser.sites.length && AppConstants.CurrentUser.sites.length > 0) { 1048 var tempsite = AppConstants.CurrentUser.sites[0]; 1049 if (tempsite.customDomain) { 1050 window.location.href = tempsite.customDomain; 1051 } else { 1052 window.location.href = '/' + tempsite.customerSlug; 1053 } 1054 } 1055 } else { 1056 if (!$rootScope.currentCustomerSite || slug != $rootScope.currentCustomerSite.customerSlug) { 1057 $rootScope.getSiteBySlug(slug); 1058 if (!$rootScope.currentCustomerSite || slug != $rootScope.currentCustomerSite.customerSlug) { 1059 $rootScope.removeSite(); 1060 window.location.href = '/'; 1061 return; 1062 } 1063 } 1064 1065 if (!$rootScope.currentCustomerSite) { 1066 $rootScope.removeSite(); 1067 window.location.href = '/'; 1068 return; 1069 } 1070 1071 if (!$rootScope.isAdmin && checkAdmin) { 1072 $rootScope.removeSite(); 1073 window.location.href = '/'; 1074 return; 1075 } 1076 1077 if (!$rootScope.isAdmin && !checkAdmin && (!$rootScope.currentCustomerSite.subAdminFeatures || !$rootScope.currentCustomerSite.subAdminFeatures.length)) { 1078 angular.forEach(AppConstants.CurrentUser.sites, function (loopsite) { 1079 if (loopsite.customerSlug == slug) { 1080 if (loopsite.useDomain == true) { 1081 if (window.location.href.includes(loopsite.customDomain)) { 1082 customDomainObject = loopsite; 1083 $rootScope.setSite(loopsite.customerSlug); 1084 1085 if (loopsite.customerSlug != slug) { 1086 window.location.href = loopsite.customDomain; 1087 return; 1088 } 1089 } else { 1090 window.location.href = loopsite.customDomain; 1091 return; 1092 } 1093 } else { 1094 window.location.href = '/' + loopsite.customerSlug; 1095 return; 1096 } 1097 } 1098 }); 1099 return; 1100 } 1101 1102 $rootScope.loadAdminDashboard = true; 1103 1104 $scope.adjustHeight(); 1105 1106 $rootScope.checkPublicSite(slug); 1107 $rootScope.checkProptia(); 1108 $rootScope.checkHelpSteps(); 1109 $rootScope.checkSiteSuspended(); 1110 $rootScope.getTrialEndDate(); 1111 $rootScope.getBillingChoices(); 1112 $rootScope.setSite(slug); 1113 } 1114 } 1115 1116 $rootScope.checkPublicSites = async function () { 1117 if (AppConstants != null) { 1118 if (AppConstants.CurrentUser != null) { 1119 if (AppConstants.CurrentUser.userId != null) { 1120 if (!AppConstants.CurrentUser.sites || !AppConstants.CurrentUser.sites.length) { 1121 var mypromise = await new Promise(resolve => { 1122 $scope.ajaxCall('/User/GetCurrentUserSites', {}, function (data) { 1123 AppConstants.CurrentUser.sites = data; 1124 $rootScope.currentSites = data; 1125 resolve("\t\t Got the data"); 1126 1127 }, function (data) { 1128 console.log("Failed to retrieve data"); 1129 });
1130 1131 }); 1132 } 1133 } 1134 } 1135 } 1136 } 1137 1138 $rootScope.formatDecimalInput = function (number) { 1139 var pow = Math.pow(10 || 10, 2); 1140 number = Math.floor(number * pow) / pow; 1141 1142 if (number < 0) { 1143 number = 0; 1144 } 1145 return number; 1146 } 1147 1148 $rootScope.formatPaymentInput = function (input) { 1149 var data = parseFloat(input); 1150 1151 if (!data && data != 0) { 1152 return ""; 1153 } 1154 1155 return data.toFixed(2); 1156 } 1157 1158 $rootScope.zeroNaN = function (amount) { 1159 if (isNaN(amount)) { 1160 return 0; 1161 } 1162 return amount; 1163 } 1164 1165 $rootScope.formatMoney = function (amount) { 1166 if (isNaN(amount)) { 1167 amount = 0; 1168 } 1169 1170 amount = parseFloat(amount); 1171 return amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ","); 1172 } 1173 1174 $rootScope.formatMoneyWithDollars = function (amount) { 1175 let USDollar = new Intl.NumberFormat('en-US', { 1176 style: 'currency', 1177 currency: 'USD', 1178 }); 1179 1180 1181 if (isNaN(amount)) { 1182 amount = 0; 1183 } 1184 1185 amount = parseFloat(amount); 1186 1187 return USDollar.format(amount); 1188 1189 //return amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ","); 1190 } 1191 1192 $rootScope.calculateConvenienceFee = function (value, percentage, dollarAmount, lateFee) { 1193 if (isNaN(percentage) || percentage == null) { 1194 percentage = 0; 1195 } 1196 1197 if (isNaN(dollarAmount) || dollarAmount == null) { 1198 dollarAmount = 0; 1199 } 1200 1201 if (isNaN(lateFee) || lateFee == null) { 1202 lateFee = 0; 1203 } 1204 1205 if (isNaN(value) || value == null) { 1206 value = 0; 1207 } 1208 1209 var charge = (parseFloat(value) + lateFee); 1210 return ((charge + parseFloat(dollarAmount)) / (1 - (parseFloat(percentage) / 100)) - charge); 1211 } 1212 1213 $rootScope.isGlobalDirty = false; 1214 $rootScope.setGlobalDirty = function (isDirty) { 1215 $rootScope.isGlobalDirty = isDirty; 1216 } 1217 1218 $rootScope.checkDirtyGoToPath = function (url, m) { 1219 console.log("Checking global dirty"); 1220 console.log($rootScope.isGlobalDirty); 1221 if ($rootScope.isGlobalDirty) { 1222 if (!confirm('You have unsaved changes. Are you sure you want to leave this page?')) { 1223 event.preventDefault(); 1224 return; 1225 } else { 1226 $rootScope.gotoPath(url, m); 1227 } 1228 } else { 1229 $rootScope.gotoPath(url, m); 1230 } 1231 1232 } 1233 1234 $rootScope.gotoPath = function (url, m) { 1235 1236 jQuery('.alert-success').each(function () { 1237 jQuery(this).remove(); 1238 }); 1239 1240 $location.path(url); 1241 if (m) { 1242 $rootScope.pageData.menu = m; 1243 } 1244 $rootScope.pageData.showMobileMenu = false; 1245 }; 1246 1247 $rootScope.trustedHtml = function (plainText) { 1248 return $sce.trustAsHtml(plainText); 1249 //return plainText; 1250 } 1251 1252 $rootScope.compareObjects = function (object1, object2) { 1253 1254 const keys1 = Object.keys(object1); 1255 const keys2 = Object.keys(object2); 1256 1257 for (const key of keys1) { 1258 if (key != "$$hashKey") { 1259 const val1 = object1[key]; 1260 const val2 = object2[key]; 1261 const areObjects = $rootScope.isObject(val1) && $rootScope.isObject(val2); 1262 if ( 1263 areObjects && !$rootScope.compareObjects(val1, val2) || 1264 !areObjects && val1 !== val2 1265 ) { 1266 return false; 1267 } 1268 } 1269 } 1270 for (const key of keys2) { 1271 if (key != "$$hashKey") { 1272 const val1 = object1[key]; 1273 const val2 = object2[key]; 1274 const areObjects = $rootScope.isObject(val1) && $rootScope.isObject(val2); 1275 if ( 1276 areObjects && !$rootScope.compareObjects(val1, val2) || 1277 !areObjects && val1 !== val2 1278 ) { 1279 return false; 1280 } 1281 } 1282 } 1283 1284 return true; 1285 } 1286 1287 $rootScope.loadScript = function (url, type, charset) { 1288 if (type === undefined) type = 'text/javascript'; 1289 if (url) { 1290 var script = document.querySelector("script[src*='" + url + "']"); 1291 if (!script) { 1292 var heads = document.getElementsByTagName("head"); 1293 if (heads && heads.length) { 1294 var head = heads[0]; 1295 if (head) { 1296 script = document.createElement('script'); 1297 script.setAttribute('src', url); 1298 script.setAttribute('type', type);
1299 if (charset) script.setAttribute('charset', charset); 1300 head.appendChild(script); 1301 } 1302 } 1303 } 1304 return script; 1305 } 1306 }; 1307 1308 1309 $rootScope.isObject = function(object) { 1310 return object != null && typeof object === 'object'; 1311 } 1312 1313 $rootScope.isGoodDate = function (dt) { 1314 if (dt == null || dt == '') { 1315 return true; // blank is fine 1316 } 1317 /* 1318 if ((dt.length != 8) && (dt.length != 10)) { 1319 return false; 1320 } 1321 1322 var month = parseInt(dt.substring(0, 2)); 1323 var day = parseInt(dt.substring((dt.length == 8) ? 2 : 3, (dt.length == 8) ? 4 : 5)); 1324 var year = parseInt(dt.substring((dt.length == 8) ? 4 : 6, (dt.length == 8) ? 8 : 10)); 1325 */ 1326 1327 var re = RegExp(/^(\d?\d)\/(\d?\d)\/((\d\d)?\d\d)$/g); 1328 var found = re.exec(dt); 1329 if (found == null) { 1330 return false; 1331 } 1332 1333 var month = parseInt(found[1]); 1334 var day = parseInt(found[2]); 1335 var year = parseInt(found[3]); 1336 if (year < 100) { 1337 year += 2000; 1338 } 1339 1340 if (month < 1 || month > 12) { // check month range 1341 return false; 1342 } 1343 1344 if (day < 1 || day > 31) { 1345 return false; 1346 } 1347
1348 if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) { 1349 return false; 1350 } 1351 1352 if (month == 2) { // check for february 29th 1353 var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); 1354 if (day > 29 || (day == 29 && !isleap)) { 1355 return false; 1356 } 1357 } 1358 1359 return true; // date is valid 1360 }; 1361 1362 $rootScope.clearSingleFormField = function (targetElementClass) { 1363 $(targetElementClass).val("").trigger('change'); 1364 } 1365 }) 1366 1367 .config(function (blockUIConfig) { 1368 blockUIConfig.template = '<div class=\"block-ui-overlay\"></div><div class=\"block-ui-message-container\" aria-live=\"assertive\" aria-atomic=\"true\"><i class="fa fa-spin fa-spinner fa-3x"></i></div>'; 1369 //blockUIConfig.template = '<div class=\"block-ui-overlay\"></div><div class=\"block-ui-message-container\" aria-live=\"assertive\" aria-atomic=\"true\"></div>'; 1370 blockUIConfig.delay = 100; 1371 blockUIConfig.requestFilter = function (config) { 1372 return (config.method == 'POST') && ((config.headers['X-Do-Loading'] || 'false') == 'true'); 1373 }; 1374 }) 1375 1376 .directive('icheck', function ($timeout, $parse) { 1377 return { 1378 require: 'ngModel', 1379 scope: {}, 1380 link: function (scope, element, $attrs, ngModel) { 1381 return $timeout(function () { 1382 var value; 1383 value = $attrs['value']; 1384 1385 if ($attrs['disabled']) 1386 $(element).iCheck($attrs['disabled'] ? 'disable' : 'enable'); 1387 1388 scope.$watch(function () { return ngModel.$modelValue; }, function (newValue) { 1389 if (newValue != undefined) { 1390 $(element).iCheck('update'); 1391 } 1392 }); 1393 1394 scope.$watch($attrs['ngDisabled'], function (newValue) { 1395 if (newValue != undefined) { 1396 $(element).iCheck(newValue ? 'disable' : 'enable'); 1397 $(element).iCheck('update'); 1398 } 1399 }); 1400 1401 return $(element).iCheck({ 1402 checkboxClass: $attrs['checkboxClass'] ? $attrs['checkboxClass'] : 'icheckbox_square-blue', 1403 radioClass: $attrs['radioClass'] ? $attrs['radioClass'] : 'iradio_square-blue', 1404 increaseArea: '20%' // optional 1405 }).on('ifChanged', function (event) { 1406 if ($(element).attr('type') === 'checkbox') { 1407 ngModel.$setViewValue(event.target.checked); 1408 } 1409 }).on('ifClicked', function (event) { 1410 if ($(element).attr('type') === 'radio') { 1411 //set up for radio buttons to be de-selectable 1412 if (ngModel.$viewValue != value) { 1413 $(element).iCheck('check'); 1414 ngModel.$setViewValue(value); 1415 } 1416 else { 1417 $(element).iCheck('uncheck'); 1418 ngModel.$setViewValue(undefined); 1419 } 1420 ngModel.$render(); 1421 } 1422 }); 1423 }); 1424 } 1425 }; 1426 }) 1427 1428 .filter('localDateTime', function ($filter) { 1429 return function (input) { 1430 if (input == null) { 1431 return null; 1432 } 1433 return $filter('date')(new Date(parseInt(input)), 'short'); 1434 }; 1435 }) 1436 1437 .filter('localDate', function ($filter) { 1438 return function (input) { 1439 if (input == null) { 1440 return null; 1441 } 1442 return $filter('date')(new Date(parseInt(input)), 'M/d/yyyy'); 1443 }; 1444 }) 1445 1446 .filter('localLongDate', function ($filter) { 1447 return function (input) { 1448 return $filter('date')(new Date(parseInt(input)), 'longDate'); 1449 }; 1450 }) 1451 1452 .filter('localShortDate', function ($filter) { 1453 return function (input) { 1454 return $filter('date')(new Date(parseInt(input)), 'shortDate'); 1455 }; 1456 }) 1457 1458 .filter('localPrettyDate', function ($filter) { 1459 return function (input) { 1460 return $filter('date')(new Date(parseInt(input)), 'MMM d, yyyy'); 1461 }; 1462 }) 1463 1464 .filter('maskedDate', function ($filter) { 1465 return function (dt) { 1466 if (dt == null || dt == '') { 1467 return dt; 1468 } 1469 1470 if (dt.length == 10) { 1471 return dt; 1472 } 1473 1474 if (dt.length != 8) { 1475 return ''; 1476 } 1477 1478 return dt.substring(0, 2) + '/' + dt.substring(2, 4) + '/' + dt.substring(4, 8); 1479 }; 1480 }) 1481 1482 .filter('range', function () { 1483 return function (input, min, max) { 1484 min = parseInt(min); //Make string input int 1485 max = parseInt(max); 1486 for (var i = min; i <= max; i++) 1487 input.push(i); 1488 return input; 1489 }; 1490 }) 1491 1492 .filter('moment', function () { 1493 return function (input, momentFn /*, param1, param2, ...param n */) { 1494 var args = Array.prototype.slice.call(arguments, 2), 1495 momentObj = moment(input); 1496 return momentObj[momentFn].apply(momentObj, args); 1497 }; 1498 }) 1499 1500 .directive('dirtyTracking', ['$window', function ($window) { 1501 return { 1502 restrict: 'E', 1503 scope: { 1504 forms: '=', 1505 formProps: '=', 1506 checkDirty: '=check' 1507 }, 1508 link: function ($scope, $element, $attrs) { 1509 function isDirty() { 1510 if (!$scope.checkDirty) { 1511 return false; 1512 } 1513 var dirty = false; 1514 for (var jdx = 0; jdx < $scope.formProps.length; jdx++) { 1515 var formVars = $scope.formProps[jdx].split('.'); 1516 var formObj = $scope.forms[formVars[0]]; 1517 for (var idx = 1; idx < formVars.length; idx++) { 1518 formObj = formObj[formVars[idx]]; 1519 }
1520 if (formObj) { 1521 if (formObj.$$element.is(':visible')) { 1522 dirty |= (formObj.$pristine === false); 1523 } 1524 } 1525 } 1526 return dirty; 1527 } 1528 1529 function areYouSurePrompt() { 1530 if (isDirty()) { 1531 return 'You have unsaved changes. Are you sure you want to leave this page?'; 1532 } 1533 } 1534 1535 //$window.addEventListener('beforeunload', areYouSurePrompt); 1536 $window.onbeforeunload = areYouSurePrompt; 1537 1538 $element.bind("$destroy", function () { 1539 $window.onbeforeunload = null; 1540 }); 1541 1542 $scope.$on('$locationChangeStart', function (event) { 1543 var prompt = areYouSurePrompt(); 1544 if (!event.defaultPrevented && prompt && !confirm(prompt)) { 1545 event.preventDefault(); 1546 } 1547 }); 1548 1549 $scope.$on('modal.closing', function (event) { 1550 var prompt = areYouSurePrompt(); 1551 if (!event.defaultPrevented && prompt && !confirm(prompt)) { 1552 event.preventDefault(); 1553 } 1554 }); 1555 } 1556 }; 1557 }]) 1558 1559 .directive('timePicker', function () { 1560 return { 1561 restrict: 'E', 1562 replace: true, 1563 template: '<select ng-options="x.id as x.text for x in times"><option value="" disabled>Select...</option></select>', 1564 scope: { 1565 jump: '=' 1566 }, 1567 link: function ($scope, $element, $attrs) { 1568 $scope.times = []; 1569 for (var x = 0; x < 24 * (60 / $scope.jump); x++) { 1570 var hours = Math.floor((x * $scope.jump) / 60); 1571 var minutes = (x * $scope.jump) % 60; 1572 var ampm = (hours >= 12 ? 'pm' : 'am'); 1573 hours = hours % 12; 1574 hours = hours ? hours : 12; // the hour '0' should be '12' 1575 1576 $scope.times.push({ id: (x * $scope.jump), text: hours + ':' + (minutes < 10 ? '0' + minutes : minutes) + ' ' + ampm }); 1577 } 1578 } 1579 }; 1580 }) 1581 1582 .directive('lazyLoad', function () { 1583 return { 1584 restrict: 'A', 1585 scope: { 1586 loadMore: '&', 1587 }, 1588 link: function ($scope, $element, $attrs) { 1589 const observer = new IntersectionObserver(loadImg) 1590 const e = angular.element($element)[0]; 1591 observer.observe(e) 1592 1593 function loadImg(changes) {
1594 changes.forEach(function (change) { 1595 if (change.intersectionRatio > 0) { 1596 $scope.loadMore(); 1597 } 1598 }) 1599 } 1600 } 1601 }; 1602 }) 1603 1604 .directive('brokenParagraphs', function () { 1605 return { 1606 restrict: 'E', 1607 scope: true, 1608 template: '<p ng-repeat="line in paragraphs track by $index" ng-bind-html="line | linky : \'_blank\'" style="margin-bottom: 0px;"></p>', 1609 link: function (scope, element, attributes) { 1610 scope.$watch(attributes.text, function (text) { 1611 scope.paragraphs = []; 1612 if (text) { 1613 //remove weird newlines 1614 text.replace(/\r\n|\r/g, '\n'); 1615 1616 // split lines and paragraphs 1617 scope.paragraphs = text.split('\n'); 1618 } 1619 }); 1620 } 1621 }; 1622 }) 1623 1624 .directive('backImg', function () { 1625 return function (scope, element, attrs) { 1626 var url = attrs.backImg; 1627 element.css({ 1628 'background-image': 'url(' + url + ')', 1629 'background-size': 'cover' 1630 }); 1631 }; 1632 });
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.