1"use strict"; 2 3angular.module('rainApp').directive("webSiteFacets", function () { 4 5 var controller = function ($scope, $window, $timeout, $httpParamSerializer) { 6 7 $scope.facetsViewLimit = 6; 8 9 $scope.isStonesFacetsEnable = function () { 10 return window.isJewelry && !!window.knobby && window.knobby.module_stone_management && window.knobby.module_stones_facets; 11 }; 12 13 $scope.DYNAMIC_FACETS_META = { 14 __type__: { 15 sorder: 2, 16 title: 'Item Type', 17 hideIfOne: true, 18 }, 19 class_category: { 20 sorder: 1, 21 title: 'Class Categories', 22 normalizer: function (item) { 23 return $scope.classGroups[item] || item.key; 24 }, 25 filter: function (value, index, allValues) { 26 if (+value.key === -1 && allValues.length <= 2) { 27 // we don't need to show root All Classes category if there is only one class category 28 return false; 29 } 30 31 return true; 32 }, 33 no_checkbox: true 34 }, 35 custom_field: { 36 normalizer: function(item) { 37 if (item.custom_field_type === 'currency' && $scope.currencySymbol) { 38 return $scope.currencySymbol + item.key; 39 } 40 41 if (item.custom_field_type === 'dropdown') { 42 return item.value; 43 } 44 45 return item.key; 46 }, 47 }, 48 mfg_name: { 49 sorder: 3, 50 title: 'Brand', 51 capitalizeValue: false 52 }, 53 instructor: { 54 sorder: 4, 55 title: 'Instructor' 56 }, 57 skill_level: { 58 sorder: 5, 59 title: 'Skill Level', 60 sort: (function () { 61 var order = ['beginner', 'intermediate', 'advanced']; 62 return function (a, b) { 63 return order.indexOf(a.key) - order.indexOf(b.key) 64 } 65 })(), 66 }, 67 }; 68 69 $scope.viewAllDynamicFacets = {}; 70 $scope.viewAllVariationsFacets = {}; 71 72 $scope.init = function () { 73 $scope.classGroups = $window.classGroups; 74 75 $scope.showFacetsNumbers = $window.showFacetsNumbers; 76 $scope.currencySymbol = $window.currencySymbol; 77 $scope.decodedCurencySymbol = $window.currencySymbol; 78 $scope.search_keyword = $window.search_keyword; 79 $scope.category = $window.facetsCategory; 80 $scope.dynamicFacets = $window.facetsDynamicFacets; 81 $scope.dynamicFacetsNormalized = prepareDynamicFacets($window.facetsDynamicFacets); 82 83 $scope.dynamicFilters = $window.facetsDynamicFilters; 84 $scope.variationsFilters = $window.facetsVariationsFilters; 85 $scope.minFilterPrice = $window.minFilterPrice || 0; 86 $scope.maxFilterPrice = $window.maxFilterPrice || 2000000; 87 $scope.priceFilter = { 88 min: null, 89 max: null, 90 }; 91 92 if ($scope.isStonesFacetsEnable()) { 93 $scope.stoneOptionsFilter = { 94 carat: { 95 min: $window.stoneMinCaratFilter || 0.01, 96 max: $window.stoneMaxCaratFilter || 100, 97 filterMin: 0.01, 98 filterMax: 100, 99 }, 100 colors: $window.stoneColorsFilters || [], 101 types: $window.stoneTypesFilter || [], 102 clarities: $window.stoneClaritiesFilter || [], 103 cuts: $window.stoneCutsFilter || [], 104 shapes: $window.stoneShapesFilter || [], 105 }; 106 } 107 108 $scope.variationsFacets = {}; 109 angular.forEach($window.facetsVariationsFacets, function (values, key) { 110 $scope.variationsFacets[key] = []; 111 angular.forEach(values, function (value) { 112 $scope.variationsFacets[key].push(value); 113 }) 114 }); 115 116 $scope.hasClasses = $window.facetsHasClasses; 117 118 $scope.classDateFilter = $window.facetsClassDateFilter; 119 120 $scope.isJewelry = $window.isJewelry; 121 122 $scope.visibleColorGroups = {}; 123 $scope.getStoneFacets = []; 124 125 if ($scope.isStonesFacetsEnable()) { 126 $scope.getStoneFacets = [ 127 $scope.createStoneFilter('Type', window.stoneTypesFacets, 'types'), 128 $scope.createStoneFilter('Clarity', window.stoneClaritiesFacets, 'clarities'), 129 $scope.createStoneFilter('Cut', window.stoneCutsFacets, 'cuts'), 130 ]; 131 } 132 133 if ($scope.isStonesFacetsEnable()) { 134 $scope.visibleColorGroups = JSON.parse(localStorage.getItem('visible-color-groups')) || {}; 135 } 136 137 if ($scope.isExpandCollapseWebFiltersFlagEnabled()) { 138 if (localStorage.getItem('expand-collapse-state')) { 139 $scope.expandCollapseState = JSON.parse(localStorage.getItem('expand-collapse-state')); 140 } else {
141 if ($scope.collapseFiltersOnInit()) { 142 $scope.expandCollapseState = $scope.getExpandCollapseState(false); 143 } else { 144 $scope.expandCollapseState = $scope.getExpandCollapseState(true); 145 } 146 } 147 } 148 149 $timeout(initDatePicker); 150 151 $timeout(initPriceFilter) 152 }; 153 154 $scope.createStoneFilter = function(filterName, options, arrayName) { 155 return { 156 filterName: filterName, 157 filterOptions: Array.isArray(options) ? options : [], 158 isOptionChecked: function (value) { 159 return $scope.stoneOptionsFilter[arrayName].includes(value); 160 }, 161 toggleAction: function (value) { 162 $scope.toggleStoneFilterAction(arrayName, value); 163 }, 164 }; 165 } 166 167 $scope.toggleStoneFilterAction = function (filterName, value) { 168 var index = $scope.stoneOptionsFilter[filterName].indexOf(value); 169 170 if (index === -1) { 171 $scope.stoneOptionsFilter[filterName].push(value); 172 } else { 173 $scope.stoneOptionsFilter[filterName].splice(index, 1); 174 } 175 176 $scope.applyFilters(); 177 }; 178 179 // The editor frame keeps an 'editing' class on the preview document's root element while 180 // in edit mode; navigating away then would tear down the page being edited. 181 var isEditorEditMode = function () { 182 return !!($window.knobby && $window.knobby.module_web_editor_2026 && $window.__onyxPreview) 183 && $window.document.documentElement.classList.contains('editing'); 184 }; 185 186 var isWebsiteEditorEnabled = function () { 187 return !!($window.knobby && $window.knobby.module_web_editor_2026); 188 }; 189 190 var uuidRegex = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/; 191 192 // Under an admin domain the storefront is served beneath /{uuid}/, which window.storeUrl 193 // carries as a relative path whenever an editor is on the page; a root-absolute /iishop 194 // would leave the store. 195 var shopUrl = function () { 196 if (!isWebsiteEditorEnabled()) { 197 return '/iishop'; 198 } 199 200 if (/^\/.*\/$/.test($window.storeUrl || '')) { 201 return $window.storeUrl + 'iishop'; 202 } 203 204 var match = $window.location.pathname.match(uuidRegex); 205 206 return (match ? '/' + match[0] : '') + '/iishop'; 207 }; 208 209 $scope.shopUrl = shopUrl; 210 211 $scope.handleCategoryClick = function (category) { 212 if (isEditorEditMode()) { 213 return; 214 } 215 216 var location = category.url, 217 filtersString = $scope.getFiltersString(); 218 219 if (filtersString) { 220 location += '?'; 221 } 222 223 var match = window.location.href.match(uuidRegex); 224 225 if (!isWebsiteEditorEnabled() && '/iishop' === location && match) { 226 location = '/' + match[0]; 227 } 228 229 $window.location = location + filtersString; 230 }; 231 232 $scope.applyFilters = function (url) { 233 if (isEditorEditMode()) { 234 return; 235 } 236 237 $timeout(function () { 238 var location = url || $window.location.pathname; 239 240 var filtersString = $scope.getFiltersString(); 241 242 if (filtersString) { 243 location += '?'; 244 } 245 246 $window.location = location + filtersString; 247 }); 248 }; 249 250 $scope.priceDynamicRanges = [ 251 {min: 0, max: 30, increment: 2}, 252 {min: 30, max: 100, increment: 5}, 253 {min: 100, max: 500, increment: 10}, 254 {min: 500, max: 3000, increment: 20}, 255 {min: 3000, max: 5000, increment: 100}, 256 {min: 5000, max: 10000, increment: 200}, 257 {min: 10000, max: 20000, increment: 2000}, 258 {min: 20000, max: 50000, increment: 10000}, 259 {min: 50000, max: Infinity, increment: 20000}, 260 ]; 261 262 $scope.caratDynamicRanges = [ 263 {min: 0, max: 2, increment: 0.01}, 264 {min: 2, max: 3, increment: 0.05}, 265 {min: 3, max: 5, increment: 0.1}, 266 {min: 5, max: 10, increment: 0.5}, 267 {min: 10, max: Infinity, increment: 10}, 268 ]; 269 270 $scope.getFiltersString = function () { 271 var dataToSerialize = {}; 272 273 if ($scope.search_keyword) { 274 dataToSerialize.search_keyword = $scope.search_keyword; 275 } 276 277 if (!angular.equals({}, $scope.dynamicFilters)) { 278 dataToSerialize.dynamicFilters = $scope.dynamicFilters; 279 } 280 281 if (!angular.equals({}, $scope.variationsFilters)) { 282 dataToSerialize.variationsFilters = $scope.variationsFilters; 283 } 284 285 if ($scope.priceFilter.min !== null && $scope.priceFilter.min !== $scope.minFilterPrice) { 286 dataToSerialize.minPrice = $scope.priceFilter.min; 287 } 288 289 if ($scope.priceFilter.max !== null && $scope.priceFilter.max !== $scope.maxFilterPrice) { 290 dataToSerialize.maxPrice = $scope.priceFilter.max; 291 } 292
293 if ($scope.classDateFilter !== null) { 294 dataToSerialize.classDateFilter = $scope.classDateFilter; 295 } 296 297 if ($scope.isStonesFacetsEnable()) { 298 if ($scope.stoneOptionsFilter.shapes?.length) { 299 dataToSerialize.stnshps = $scope.stoneOptionsFilter.shapes.join('|'); 300 } 301 302 if ($scope.stoneOptionsFilter.colors?.length) { 303 dataToSerialize.stnclrs = $scope.stoneOptionsFilter.colors.join('|'); 304 } 305 306 if ($scope.stoneOptionsFilter.clarities?.length) { 307 dataToSerialize.stnclrt = $scope.stoneOptionsFilter.clarities.join('|'); 308 } 309 310 if ($scope.stoneOptionsFilter.types?.length) { 311 dataToSerialize.stntps = $scope.stoneOptionsFilter.types.join('|'); 312 } 313 314 if ($scope.stoneOptionsFilter.cuts?.length) { 315 dataToSerialize.stncuts = $scope.stoneOptionsFilter.cuts.join('|'); 316 } 317 318 if ($scope.stoneOptionsFilter.carat.min !== $scope.stoneOptionsFilter.carat.filterMin || $scope.stoneOptionsFilter.carat.max !== $scope.stoneOptionsFilter.carat.filterMax) { 319 dataToSerialize.stncrtmn = $scope.stoneOptionsFilter.carat.min; 320 dataToSerialize.stncrtmx = $scope.stoneOptionsFilter.carat.max; 321 } 322 } 323 324 var urlParams= $scope.getQueryParams(); 325 if (urlParams['sort']) { 326 dataToSerialize.sort = urlParams['sort']; 327 } 328 if (urlParams['order']) { 329 dataToSerialize.order = urlParams['order']; 330 } 331 332 if ($window.knobby && $window.knobby.module_web_editor_2026 && $window.__onyxPreview) { 333 dataToSerialize.embedded = 1; 334 } 335 336 return $httpParamSerializer(dataToSerialize); 337 }; 338 339 $scope.getQueryParams = function () { 340 var params = {}; 341 var queryString = $window.location.search.substring(1); 342 var pairs = queryString.split("&"); 343 for (var i = 0; i < pairs.length; i++) { 344 var pair = pairs[i].split("="); 345 var key = decodeURIComponent(pair[0]); 346 var value = decodeURIComponent(pair[1] || ""); 347 if (key) { 348 params[key] = value; 349 } 350 } 351 return params; 352 }; 353 354 $scope.handleAllCategoriesClick = function () { 355 $scope.clearAllFilters(false); 356 $timeout(function () { 357 $scope.handleCategoryClick({url: shopUrl()}) 358 }); 359 }; 360 361 $scope.clearAllFilters = function (apply) { 362 angular.forEach($scope.variationsFilters, function (filter, key) { 363 $scope.clearVariationFilter(key, false); 364 }); 365 angular.forEach($scope.dynamicFilters, function (filter, key) { 366 $scope.clearDynamicFacetFilter(key, false); 367 }); 368 $scope.clearPriceFilters(false); 369 $scope.clearClassDateFilter(false); 370 371 if ($scope.isExpandCollapseWebFiltersFlagEnabled()) { 372 $scope.clearSearchFilter(); 373 if ($scope.isStonesFacetsEnable()) { 374 $scope.clearStonesFilters(); 375 } 376 $timeout(function () { 377 $scope.handleCategoryClick({url: shopUrl()}) 378 }); 379 } 380 381 if (apply) { 382 $scope.applyFilters(); 383 } 384 }; 385 386 $scope.clearSearchFilter = function () { 387 $scope.search_keyword = ''; 388 } 389 390 $scope.clearStonesFilters = function () { 391 $scope.stoneOptionsFilter = { 392 carat: {}, 393 colors: [], 394 types: [], 395 clarities: [], 396 cuts: [], 397 shapes: [], 398 }; 399 } 400 401 $scope.clearDynamicFacetFilter = function (key, apply) { 402 $scope.dynamicFilters[key] = {}; 403
404 if (apply) { 405 $scope.applyFilters(); 406 } 407 }; 408 409 $scope.clearPriceFilters = function (apply) { 410 $scope.priceFilter.min = $scope.minFilterPrice; 411 $scope.priceFilter.max = $scope.maxFilterPrice; 412 413 if (apply) { 414 $scope.applyFilters(); 415 } 416 }; 417 418 $scope.clearVariationFilter = function (key, apply) { 419 $scope.variationsFilters[key] = {}; 420 421 if (apply) { 422 $scope.applyFilters(); 423 } 424 }; 425 426 $scope.clearClassDateFilter = function (apply) { 427 $scope.classDateFilter = null; 428 if (apply) { 429 $scope.applyFilters(); 430 } 431 }; 432 433 $scope.isDynamicFacetVisible = function (key, item) { 434 if ($scope.viewAllDynamicFacets[key]) { 435 return true; 436 } 437 438 var index = $scope.dynamicFacets[key].map(function (v) { 439 return v.key; 440 }).indexOf(item.key); 441 442 if (index < $scope.facetsViewLimit) { 443 return true; 444 } 445 446 if ($scope.dynamicFilters[key] !== undefined && $scope.dynamicFilters[key][item.key] !== undefined) { 447 return $scope.dynamicFilters[key][item.key]; 448 } 449 450 return false; 451 }; 452 453 $scope.isVariationFacetVisible = function (key, item) { 454 if ($scope.viewAllVariationsFacets[key]) { 455 return true; 456 } 457 458 var index = $scope.variationsFacets[key].map(function (v) { 459 return v.key; 460 }).indexOf(item.key); 461 462 if (index < $scope.facetsViewLimit) { 463 return true; 464 } 465 466 if ($scope.variationsFilters[key] !== undefined && $scope.variationsFilters[key][item.key] !== undefined) { 467 return $scope.variationsFilters[key][item.key]; 468 } 469 470 return false; 471 }; 472 473 $scope.allVariationsFacetsVisible = function (key) { 474 if ($scope.viewAllVariationsFacets[key]) { 475 return true; 476 } 477 478 return $scope.variationsFacets[key].every(function (item) { 479 return $scope.isVariationFacetVisible(key, item) 480 }); 481 }; 482 483 $scope.allDynamicFacetsVisible = function (key) { 484 if ($scope.viewAllDynamicFacets[key]) { 485 return true; 486 } 487 488 return $scope.dynamicFacets[key].every(function (item) { 489 return $scope.isDynamicFacetVisible(key, item) 490 }); 491 }; 492 493 $scope.$watch('dynamicFilters', function () { 494 clearEmpty($scope.dynamicFilters); 495 }, true); 496 497 $scope.$watch('variationsFilters', function () { 498 clearEmpty($scope.variationsFilters); 499 }, true); 500 501 var clearEmpty = function (object) { 502 angular.forEach(object, function (values) { 503 for (var key in values) { 504 if (values.hasOwnProperty(key) && !values[key]) { 505 delete values[key]; 506 } 507 } 508 }); 509 510 for (var key in object) { 511 if (object.hasOwnProperty(key) 512 && (!object[key] || Object.keys(object[key]).length <= 0)) { 513 delete object[key]; 514 } 515 } 516 }; 517 518 $scope.toggleColorGroup = function (event, colorGroup) { 519 event.preventDefault(); 520 521 var cgKey = $scope.generateStoneColorGroupKey(colorGroup); 522 523 $scope.visibleColorGroups[cgKey] = !$scope.visibleColorGroups[cgKey]; 524 localStorage.setItem('visible-color-groups', JSON.stringify($scope.visibleColorGroups)); 525 }; 526 527 $scope.generateStoneColorGroupKey = function (colorGroup) { 528 return colorGroup.replace(/[^a-zA-Z0-9]/g, ''); 529 }; 530 531 $scope.getStoneColorsFacets = function () { 532 return window.stoneColorsFacets || []; 533 }; 534 535 $scope.getStoneShapesFacets = function () { 536 return window.stoneShapesFacets || []; 537 }; 538 539 var prepareDynamicFacets = function (facets) { 540 var result = []; 541 542 angular.forEach(facets, function (facet, key) { 543 var meta = $scope.DYNAMIC_FACETS_META[key] || {}; 544 545 if (meta.sort) { 546 facet.sort(meta.sort); 547 } 548 549 if (meta.filter) { 550 facet = facet.filter(meta.filter); 551 } 552 553 if (facet.length > 0 && facet[0].custom_field) { 554 meta = $scope.DYNAMIC_FACETS_META['custom_field']; 555 556 if (facet[0].title) { 557 meta.title = facet[0].title; 558 } 559 } 560 561 result.push({ 562 sorder: meta.sorder || Infinity, 563 values: facet, 564 key: key, 565 title: meta.title || key, 566 capitalizeValue: meta.capitalizeValue = true, 567 meta: meta 568 }); 569 }); 570 571 if (window.knobby && window.knobby.module_facet_fields_order_web_fix) { 572 result.sort(function (a, b) { 573 var keyA = (a.key && a.key.includes('::') && a.key.split('::')[1]) ? a.key.split('::')[1] : ''; 574 var keyB = (b.key && b.key.includes('::') && b.key.split('::')[1]) ? b.key.split('::')[1] : ''; 575 576 return keyA.localeCompare(keyB); 577 }); 578 } else { 579 result.sort(function (a,b) { 580 return a.sorder - b.sorder; 581 }); 582 } 583 584 return result; 585 }; 586 587 var initPriceFilter = function () { 588 $scope.priceFilter = { 589 min: $window.facetsMinPriceFilter 590 && $window.facetsMinPriceFilter > $scope.minFilterPrice 591 && $window.facetsMinPriceFilter < $scope.maxFilterPrice 592 ? $window.facetsMinPriceFilter 593 : $scope.minFilterPrice, 594 max: $window.facetsMaxPriceFilter 595 && $window.facetsMaxPriceFilter < $scope.maxFilterPrice 596 && $window.facetsMaxPriceFilter > $scope.minFilterPrice 597 ? $window.facetsMaxPriceFilter 598 : $scope.maxFilterPrice, 599 }; 600 }; 601 602 var initDatePicker = function() { 603 var datePickerOptions = { 604 linkedCalendars: false, 605 minDate: moment(), 606 startDate: moment(), 607 endDate: moment(), 608 locale: { 609 format: 'MMM D, YYYY', 610 cancelLabel: 'Clear' 611 }, 612 drops: 'up', 613 autoApply: true, 614 autoUpdateInput: false, 615 opens: 'right', 616 ranges: { 617 'Today': [moment(), moment()], 618 'Tomorrow': [moment().add(1, 'days'), moment().add(1, 'days')],
619 'Next 7 Days': [moment(), moment().add(6, 'days')], 620 'This Month': [moment().startOf('month'), moment().endOf('month')], 621 } 622 }; 623 624 if ($scope.$element.find('#filterDateRange').length > 0) { 625 $scope.$element.find('#filterDateRange').daterangepicker(datePickerOptions); 626 627 $scope.$element.find('#filterDateRange').on('apply.daterangepicker', function(ev, picker) { 628 $(this).val(picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY')); 629 630 $scope.classDateFilter = picker.startDate.format('YYYY-MM-DD HH:mm:ss')+'|'+picker.endDate.format('YYYY-MM-DD HH:mm:ss'); 631 $scope.applyFilters(); 632 }); 633 634 if ($scope.classDateFilter !== null) { 635 var parts = $scope.classDateFilter.split('|'); 636 $scope.$element.find('#filterDateRange').val( 637 moment(parts[0]).format('MM/DD/YYYY') + ' - ' + moment(parts[1]).format('MM/DD/YYYY') 638 ); 639 } 640 } 641 }; 642 643 $scope.toggleFilters = function (event) { 644 var element = document.getElementById('fn_filter_wrapper'); 645 if (element.style.display === "block") { 646 element.style.display = "none"; 647 } else { 648 element.style.display = "block"; 649 } 650 if (event.target.innerText === event.target.dataset.show) { 651 event.target.innerText = event.target.dataset.hide; 652 } else { 653 event.target.innerText = event.target.dataset.show; 654 } 655 } 656 657 $scope.handleExpandCollapse = function (parent, key) { 658 if (!$scope.isExpandCollapseWebFiltersFlagEnabled()) { 659 return; 660 } 661 662 if ($scope.expandCollapseState[parent] !== undefined) { 663 $scope.expandCollapseState[parent][key] = !$scope.expandCollapseState[parent][key]; 664 } else { 665 $scope.expandCollapseState[parent] = {[key]: true}; 666 } 667 668 localStorage.setItem('expand-collapse-state', JSON.stringify($scope.expandCollapseState)); 669 } 670 671 $scope.isExpandCollapseWebFiltersFlagEnabled = function () { 672 return !!window.knobby && window.knobby.module_expand_collapse_web_filters; 673 }; 674 675 $scope.getButtonExpandCollapseAllTitle = function () { 676 const isCollapseAll = Object.values($scope.expandCollapseState).every(child => 677 Object.values(child).every(value => value === true) 678 ); 679 680 return isCollapseAll ? 'Collapse All' : 'Expand All'; 681 }; 682 683 $scope.handleExpandCollapseAll = function (action) { 684 if (action === 'Collapse All') { 685 $scope.expandCollapseState = $scope.getExpandCollapseState(false); 686 } else { 687 $scope.expandCollapseState = $scope.getExpandCollapseState(true); 688 } 689 690 localStorage.setItem('expand-collapse-state', JSON.stringify($scope.expandCollapseState)); 691 }; 692 693 $scope.collapseFiltersOnInit = function () { 694 return $scope.isStonesFacetsEnable() || ($scope.dynamicFacetsNormalized.length + Object.keys($scope.variationsFacets).length) > 3; 695 }; 696 697 $scope.getExpandCollapseState = function (value) { 698 return { 699 static: { 700 search: value, 701 categories: value, 702 price: value, 703 }, 704 dynamic: Object.fromEntries( 705 $scope.dynamicFacetsNormalized.map(facet => [facet.key, value]) 706 ), 707 variations: Object.fromEntries( 708 Object.keys($scope.variationsFacets).map(key => [key, value]) 709 ), 710 ...($scope.isStonesFacetsEnable() ? { 711 stones: { 712 Clarity: value, 713 Cut: value, 714 Type: value, 715 carat: value, 716 color: value, 717 shapes: value, 718 } 719 } : {}) 720 }; 721 }; 722 723 $scope.isAnyFilterSelected = function () { 724 return !!(Object.keys($scope.dynamicFilters).length || Object.keys($scope.variationsFilters).length || $scope.search_keyword || (!$scope.priceFilter.min && $scope.priceFilter.max !== 50000) || ($scope.isStonesFacetsEnable() && !$scope.isStoneOptionsFiltersEmpty()) || $scope.category.current); 725 } 726 727 $scope.isStoneOptionsFiltersEmpty = function () { 728 var stoneOptionsFilter = $scope.stoneOptionsFilter; 729 var arraysAreEmpty = ['clarities', 'colors', 'cuts', 'shapes', 'types'].every(function (key) { 730 return !stoneOptionsFilter[key].length; 731 }); 732 var caratFilterIsDefault = stoneOptionsFilter.carat?.filterMin === 0.01 && 733 stoneOptionsFilter.carat?.filterMax === 100; 734 735 return arraysAreEmpty && caratFilterIsDefault; 736 }; 737 }; 738 739 return { 740 restrict: 'E', 741 scope: {}, 742 controller: controller, 743 templateUrl: '/c/js/website-facets/webSiteFacetsTemplate.html?v=1.0.4', 744 link: function ($scope, $element) { 745 $scope.$element = $element; 746 $scope.init(); 747 } 748 }; 749}); 750 751angular.module('rainApp').filter('reverse', function() { 752 return function(items) { 753 return items.slice().reverse(); 754 }; 755}); 756
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.