@stratusjs/idx
Version:
AngularJS idx/property Service and Components bundle to be used as an add on to StratusJS
570 lines (568 loc) • 33.9 kB
JavaScript
System.register(["./search.component.less", "./search.compact.component.less", "./search.classic.component.less", "lodash", "@stratusjs/runtime/stratus", "angular", "angular-material", "@stratusjs/core/misc", "@stratusjs/core/environment", "@stratusjs/angularjs-extras"], function (exports_1, context_1) {
"use strict";
var lodash_1, stratus_1, angular_1, misc_1, environment_1, min, packageName, moduleName, componentName, localDir, localDistStyle;
var __moduleName = context_1 && context_1.id;
return {
setters: [
function (_1) {
},
function (_2) {
},
function (_3) {
},
function (lodash_1_1) {
lodash_1 = lodash_1_1;
},
function (stratus_1_1) {
stratus_1 = stratus_1_1;
},
function (angular_1_1) {
angular_1 = angular_1_1;
},
function (_4) {
},
function (misc_1_1) {
misc_1 = misc_1_1;
},
function (environment_1_1) {
environment_1 = environment_1_1;
},
function (_5) {
}
],
execute: function () {
min = !environment_1.cookie('env') ? '.min' : '';
packageName = 'idx';
moduleName = 'property';
componentName = 'search';
localDir = `${stratus_1.Stratus.BaseUrl}${stratus_1.Stratus.DeploymentPath}@stratusjs/${packageName}/src/${moduleName}/`;
localDistStyle = `${stratus_1.Stratus.BaseUrl}${stratus_1.Stratus.DeploymentPath}@stratusjs/${packageName}/dist/${packageName}.bundle.min.css`;
stratus_1.Stratus.Components.IdxPropertySearch = {
bindings: {
elementId: '@',
initNow: '=',
tokenUrl: '@',
tokenOnLoad: '@',
listId: '@',
listLinkUrl: '@',
listLinkTarget: '@',
searchType: '@',
advancedSearchUrl: '@',
advancedSearchLinkName: '@',
template: '@',
options: '@',
optionsAgentGroups: '@',
optionsOfficeGroups: '@',
displayFilterFullHeight: '@',
variableSync: '@',
widgetName: '@'
},
controller($attrs, $element, $q, $mdConstant, $mdDialog, $mdPanel, $sce, $scope, $timeout, $window, Idx) {
$scope.uid = misc_1.safeUniqueId(packageName, moduleName, componentName);
$scope.elementId = $attrs.elementId || $scope.uid;
$scope._ = lodash_1.default;
stratus_1.Stratus.Instances[$scope.elementId] = $scope;
$scope.localDir = localDir;
$scope.initialized = false;
if ($attrs.tokenUrl) {
Idx.setTokenURL($attrs.tokenUrl);
}
stratus_1.Stratus.Internals.CssLoader(localDistStyle).then();
let defaultQuery;
let lastQuery;
let mlsVariables;
$scope.openPrice = false;
$scope.advancedFiltersStatus = false;
$scope.advancedSearchUrl = '';
$scope.advancedSearchLinkName = 'Advanced Search';
$scope.presetLocationText = '';
$scope.$mdConstant = $mdConstant;
const init = async () => {
$scope.widgetName = $attrs.widgetName || '';
$scope.listId = $attrs.listId || null;
$scope.listInitialized = false;
$scope.listLinkUrl = $attrs.listLinkUrl || $attrs.advancedSearchUrl || '/property/list';
$scope.listLinkTarget = $attrs.listLinkTarget || '_self';
$scope.searchType = $attrs.searchType || 'advanced';
$scope.advancedSearchUrl = $attrs.advancedSearchUrl || $scope.advancedSearchUrl;
$scope.advancedSearchLinkName = $attrs.advancedSearchLinkName || $scope.advancedSearchLinkName;
$scope.options = $attrs.options && misc_1.isJSON($attrs.options) ? JSON.parse($attrs.options) : {};
$scope.displayFilterFullHeight = $attrs.displayFilterFullHeight && misc_1.isJSON($attrs.displayFilterFullHeight) ?
JSON.parse($attrs.displayFilterFullHeight) : false;
$scope.filterMenu = null;
$scope.options.forRent ||= false;
$scope.options.agentGroups ??= [];
$scope.options.officeGroups =
($scope.options.officeGroups && lodash_1.isString($scope.options.officeGroups) && misc_1.isJSON($scope.options.officeGroups)
? JSON.parse($scope.options.officeGroups)
: ($attrs.optionsOfficeGroups && misc_1.isJSON($attrs.optionsOfficeGroups)
? JSON.parse($attrs.optionsOfficeGroups)
: $scope.options.officeGroups)) || [];
$scope.options.query ??= {};
$scope.options.query.where ??= {};
$scope.options.query.service ??= [];
$scope.setWhere($scope.options.query.where);
defaultQuery = JSON.parse(JSON.stringify(lodash_1.cloneDeep($scope.options.query.where)));
if ($scope.options.query.order) {
defaultQuery.Order = $scope.options.query.order;
}
$timeout(async () => {
await $scope.variableSync();
}, 1000);
$scope.options.selection ??= {};
$scope.options.selection.Bedrooms ??= [
{ name: '1+', value: 1 },
{ name: '2+', value: 2 },
{ name: '3+', value: 3 },
{ name: '4+', value: 4 },
{ name: '5+', value: 5 }
];
$scope.options.selection.Bathrooms ??= [
{ name: '1+', value: 1 },
{ name: '2+', value: 2 },
{ name: '3+', value: 3 },
{ name: '4+', value: 4 },
{ name: '5+', value: 5 }
];
$scope.options.selection.order ??= [
{ name: 'Highest Price', value: '-BestPrice' },
{ name: 'Lowest Price', value: 'BestPrice' },
{ name: 'Recently Updated', value: '-ModificationTimestamp' },
{ name: 'Recently Sold', value: '-CloseDate' },
{ name: 'Status + Price', value: ['Status', '-BestPrice'] },
{ name: 'Status + Recent', value: ['Status', '-ModificationTimestamp'] }
];
$scope.options.selection.Status ??= {};
$scope.options.selection.Status.default ??= {
Sale: ['Active', 'Contract'],
Lease: ['Active']
};
$scope.options.selection.ListingType ??= {};
$scope.options.selection.ListingType.group ??= {
Residential: true,
Commercial: false
};
$scope.options.selection.ListingType.list ??= {
Residential: ['House', 'Condo', 'Townhouse', 'MultiFamily', 'Manufactured', 'Land', 'LeaseHouse', 'LeaseCondo', 'LeaseTownhouse', 'LeaseOther'],
Commercial: ['Commercial', 'CommercialBusinessOp', 'CommercialResidential', 'CommercialLand', 'LeaseCommercial'],
Lease: ['LeaseHouse', 'LeaseCondo', 'LeaseTownhouse', 'LeaseOther', 'LeaseCommercial']
};
$scope.options.selection.ListingType.default ??= {
Sale: {
Residential: ['House', 'Condo', 'Townhouse'],
Commercial: ['Commercial', 'CommercialBusinessOp']
},
Lease: {
Residential: ['LeaseHouse', 'LeaseCondo', 'LeaseTownhouse'],
Commercial: ['LeaseCommercial']
}
};
$scope.options.selection.ListingType.All ??= [
{ name: 'House', value: 'House', group: 'Residential', lease: false },
{ name: 'Condo', value: 'Condo', group: 'Residential', lease: false },
{ name: 'Townhouse', value: 'Townhouse', group: 'Residential', lease: false },
{ name: 'Multi-Family', value: 'MultiFamily', group: 'Residential', lease: false },
{ name: 'Manufactured', value: 'Manufactured', group: 'Residential', lease: false },
{ name: 'Land', value: 'Land', group: 'Residential', lease: false },
{ name: 'Other', value: 'Other', group: 'Residential', lease: false },
{ name: 'Commercial', value: 'Commercial', group: 'Commercial', lease: false },
{ name: 'Commercial Business Op', value: 'CommercialBusinessOp', group: 'Commercial', lease: false },
{ name: 'Commercial Residential', value: 'CommercialResidential', group: 'Commercial', lease: false },
{ name: 'Commercial Land', value: 'CommercialLand', group: 'Commercial', lease: false },
{ name: 'House', value: 'LeaseHouse', group: 'Residential', lease: true },
{ name: 'Condo', value: 'LeaseCondo', group: 'Residential', lease: true },
{ name: 'Townhouse', value: 'LeaseTownhouse', group: 'Residential', lease: true },
{ name: 'Other', value: 'LeaseOther', group: 'Residential', lease: true },
{ name: 'Commercial', value: 'LeaseCommercial', group: 'Commercial', lease: true }
];
$scope.setWhereDefaults();
Idx.registerSearchInstance($scope.elementId, moduleName, $scope, $scope.listId);
if ($scope.listId) {
Idx.on($scope.listId, 'init', $scope.refreshSearchWidgetOptions);
Idx.on($scope.listId, 'searching', $scope.refreshSearchWidgetOptions);
}
if ($attrs.tokenOnLoad) {
try {
await Idx.tokenKeepAuth();
$scope.getMLSVariables(true);
}
catch (e) {
console.error('Search is unable to load in token data', e);
}
}
$scope.$applyAsync(() => {
$scope.initialized = true;
});
Idx.emit('init', $scope);
};
this.$onInit = () => {
$scope.Idx = Idx;
let initNow = true;
if (Object.prototype.hasOwnProperty.call($attrs.$attr, 'initNow')) {
initNow = misc_1.isJSON($attrs.initNow) ? JSON.parse($attrs.initNow) : false;
}
if (initNow) {
init().then();
return;
}
const stopWatchingInitNow = $scope.$watch('$ctrl.initNow', (initNowCtrl) => {
if (initNowCtrl !== true) {
return;
}
if (!$scope.initialized) {
init().then();
}
stopWatchingInitNow();
});
};
$scope.$watch('options.query.where.ListingType', () => {
if ($scope.options?.query?.where && $scope.options?.selection?.ListingType?.list) {
if (!$scope.options?.query?.where?.ListingType) {
$scope.options.query.where.ListingType = [];
}
if (!lodash_1.isArray($scope.options.query.where.ListingType)) {
$scope.options.query.where.ListingType = [$scope.options.query.where.ListingType];
}
$scope.options.selection.ListingType.group.Residential =
$scope.isIntersecting($scope.options.selection.ListingType.list.Residential, $scope.options.query.where.ListingType);
$scope.options.selection.ListingType.group.Commercial =
$scope.isIntersecting($scope.options.selection.ListingType.list.Commercial, $scope.options.query.where.ListingType);
$scope.options.forRent =
$scope.isIntersecting($scope.options.selection.ListingType.list.Lease, $scope.options.query.where.ListingType);
}
});
$scope.resetLocationQuery = () => {
$scope.options.query.where.Location = '';
$scope.options.query.where.eLocation = '';
$scope.options.query.where.UnparsedAddress = [];
$scope.options.query.where.StreetAddress = [];
$scope.options.query.where.eStreetAddress = [];
$scope.options.query.where.City = [];
$scope.options.query.where.eCity = [];
$scope.options.query.where.CountyOrParish = [];
$scope.options.query.where.eCountyOrParish = [];
$scope.options.query.where.MLSAreaMajor = [];
$scope.options.query.where.eMLSAreaMajor = [];
$scope.options.query.where.Neighborhood = [];
$scope.options.query.where.eNeighborhood = [];
$scope.options.query.where.PostalCode = [];
$scope.options.query.where.ListingId = [];
$scope.options.query.where.AgentLicense = [];
$scope.options.query.where.OfficeNumber = [];
$scope.options.officeGroups = [];
$scope.parsePresetLocationText();
};
$scope.getPresetLocations = () => {
const currentWhere = $scope.options.query.where;
return lodash_1.compact(lodash_1.union(currentWhere.UnparsedAddress, currentWhere.StreetAddress, currentWhere.eStreetAddress, currentWhere.City, currentWhere.eCity, currentWhere.CountyOrParish, currentWhere.eCountyOrParish, currentWhere.MLSAreaMajor, currentWhere.eMLSAreaMajor, currentWhere.Neighborhood, currentWhere.eNeighborhood, currentWhere.PostalCode));
};
$scope.getOtherPresetFilterCount = () => {
const currentWhere = $scope.options.query.where;
let filterCounts = lodash_1.compact(lodash_1.union(currentWhere.OfficeNumber, currentWhere.AgentLicense, currentWhere.ListingId)).length;
if (currentWhere.OpenHouseOnly) {
filterCounts++;
}
return filterCounts;
};
$scope.isPresetLocationSet = () => {
return $scope.getPresetLocations().length > 0;
};
$scope.parsePresetLocationText = () => {
const locations = $scope.getPresetLocations();
$scope.presetLocationText = locations.join(', ');
if (!lodash_1.isEmpty($scope.presetLocationText)) {
const html = `<span>${locations.join('</span><span>')}</span>`;
$scope.presetLocationHTML = $sce.trustAsHtml(html);
}
else {
$scope.presetLocationHTML = null;
}
$scope.presetLocationsCountText = null;
$scope.presetLocationsRemainingCountText = null;
if (locations.length > 0) {
$scope.presetLocationsCountText = `+${locations.length}`;
if (locations.length > 2) {
$scope.presetLocationsRemainingCountText = `+${locations.length - 2}`;
}
}
$scope.presetOtherFiltersCountText = null;
const filterCounts = $scope.getOtherPresetFilterCount();
if (filterCounts > 0) {
$scope.presetOtherFiltersCountText = `+${filterCounts} Filter${filterCounts > 1 ? 's' : ''}`;
}
};
$scope.focusElement = (selector) => {
if (!lodash_1.isEmpty(selector)) {
$timeout(() => {
const elementThis = $element[0];
const elementSelected = elementThis.querySelector(selector);
if (!elementSelected) {
console.warn('unable to find focusable element of', selector);
return;
}
elementSelected.focus();
}, 100);
}
};
$scope.variableSync = async () => {
$scope.variableSyncing = $attrs.variableSync && misc_1.isJSON($attrs.variableSync) ? JSON.parse($attrs.variableSync) : {};
const promises = [];
Object.keys($scope.variableSyncing).forEach((elementId) => {
promises.push($q(async (resolve) => {
const varElement = Idx.getInput(elementId);
if (varElement) {
const scopeVarPath = $scope.variableSyncing[elementId];
await Idx.updateScopeValuePath($scope, scopeVarPath, varElement.val());
$scope.setWhere($scope.options.query.where);
$scope.$watch(scopeVarPath, (value) => {
if (lodash_1.isString(value) ||
lodash_1.isNumber(value) ||
lodash_1.isUndefined(value) ||
value == null) {
if (lodash_1.isUndefined(value)) {
value = null;
}
varElement.val(value);
}
else {
varElement.val(JSON.stringify(value));
}
varElement[0].dispatchEvent(new Event('change'));
}, true);
}
resolve();
}));
});
await $q.all(promises);
};
$scope.canDisplayListingTypeButton = (listType) => {
return $scope.options.forRent === listType.lease && $scope.options.selection.ListingType.group[listType.group];
};
$scope.inArray = (item, array) => lodash_1.includes(array, item);
$scope.isIntersecting = (itemArray, array) => {
if (!lodash_1.isArray(array) || !lodash_1.isArray(itemArray)) {
console.warn('Array undefined, cannot search for', itemArray, 'in', array);
return false;
}
return lodash_1.intersection(itemArray, array).length > 0;
};
$scope.toggleArrayElement = (item, array) => {
array ??= [];
const arrayIndex = array.indexOf(item);
if (arrayIndex >= 0) {
array.splice(arrayIndex, 1);
}
else {
array.push(item);
}
};
$scope.showInlinePopup = (ev, menuElement) => {
if (!$scope.filterMenu) {
const position = $mdPanel.newPanelPosition()
.relativeTo(ev.srcElement)
.addPanelPosition($mdPanel.xPosition.CENTER, $mdPanel.yPosition.BELOW);
const animation = $mdPanel.newPanelAnimation();
animation.openFrom(position);
animation.closeTo(position);
animation.withAnimation($mdPanel.animation.FADE);
const config = {
animation,
attachTo: angular_1.element(document.body),
contentElement: menuElement,
position,
openFrom: ev,
clickOutsideToClose: true,
escapeToClose: true,
focusOnOpen: false,
zIndex: 2
};
$scope.filterMenu = $mdPanel.create(config);
$scope.filterMenu.reposition = function reposition() {
$timeout(() => {
$scope.filterMenu.updatePosition(position);
}, 100);
};
}
$scope.filterMenu.open();
};
$scope.getMLSVariables = (reset) => {
if (!mlsVariables || reset) {
mlsVariables = {};
Idx.getMLSVariables().forEach((service) => {
mlsVariables[service.id] = service;
});
}
return Object.values(mlsVariables);
};
$scope.setQuery = (newQuery) => {
newQuery ??= {};
newQuery.where ??= {};
$scope.options.query = lodash_1.cloneDeep(newQuery);
$scope.setWhere($scope.options.query.where);
};
$scope.setWhere = (newWhere) => {
newWhere ??= {};
$scope.options.query.where = lodash_1.extend(Idx.getDefaultWhereOptions(), newWhere);
lodash_1.map(Idx.getDefaultWhereOptions(), (value, key) => {
if (lodash_1.isArray(value) &&
Object.prototype.hasOwnProperty.call($scope.options.query.where, key) &&
!lodash_1.isArray($scope.options.query.where[key])) {
$scope.options.query.where[key] = [$scope.options.query.where[key]];
}
});
$scope.parsePresetLocationText();
};
$scope.setWhereDefaults = () => {
$scope.$applyAsync(() => {
if ($scope.options.query.where.ListingType.length < 1) {
$scope.options.query.where.ListingType = $scope.options.selection.ListingType.default.Sale.Residential;
$scope.selectDefaultListingType();
}
lastQuery = lodash_1.cloneDeep($scope.options.query);
$scope.parsePresetLocationText();
});
};
$scope.selectDefaultListingType = (listingGroup) => {
if (!listingGroup) {
listingGroup = 'Commercial';
if (!$scope.options.selection.ListingType.group.Commercial) {
listingGroup = 'Residential';
}
}
$scope.options.query.where.ListingType = $scope.options.forRent ?
$scope.options.selection.ListingType.default.Lease[listingGroup] :
$scope.options.selection.ListingType.default.Sale[listingGroup];
if ($scope.filterMenu) {
$scope.filterMenu.reposition();
}
if ($scope.options.forRent) {
$scope.options.query.where.Status = $scope.options.selection.Status.default.Lease;
}
else {
$scope.options.query.where.Status = ($scope.options.query.where.Status && $scope.options.query.where.Status.length > 0) ?
$scope.options.query.where.Status : $scope.options.selection.Status.default.Lease;
}
};
$scope.search = (force) => {
if (!$scope.initialized) {
console.warn($scope.uid, 'has not initialized and may not search yet');
return;
}
let listScope;
if ($scope.listId) {
listScope = Idx.getListInstance($scope.listId);
}
if (listScope) {
if (!$scope.throttledSearch) {
$scope.throttledSearch =
lodash_1.throttle(() => { listScope.search($scope.options.query, true); }, 600, { trailing: false });
}
$scope.throttledSearch();
}
else {
if ($scope.hasQueryChanged() || force) {
lastQuery = lodash_1.cloneDeep($scope.options.query);
Idx.setUrlOptions('Search', $scope.options.query.where);
$window.open($scope.listLinkUrl + '#!' + Idx.getUrlOptionsPath(defaultQuery), $scope.listLinkTarget);
}
}
};
$scope.displayOfficeGroupSelector = (searchTerm, editIndex, ev) => {
if (ev) {
ev.preventDefault();
}
let searchOnLoad = false;
const options = {
query: {
perPage: 100
}
};
if (!lodash_1.isEmpty(searchTerm) && lodash_1.isString(searchTerm)) {
options.query.where = {
OfficeName: searchTerm
};
searchOnLoad = true;
}
if (!lodash_1.isNumber(editIndex)) {
editIndex = $scope.options.officeGroups.length;
}
const template = '<md-dialog aria-label="Property Office Group Selector" class="transparent">' +
'<md-button style="text-align: center" data-ng-click="close()">Close and Accept</md-button>' +
'<stratus-idx-office-search' +
' data-template="search.group-selector"' +
` data-list-id="office-group-selector-${$scope.elementId}"` +
` data-options='${JSON.stringify(options)}'` +
` data-sync-instance="${$scope.elementId}"` +
` data-sync-instance-variable="options.officeGroups"` +
` data-sync-instance-variable-index="${editIndex}"` +
'></stratus-idx-office-search>' +
'<stratus-idx-office-list' +
` data-element-id="office-group-selector-${$scope.elementId}"` +
' data-template="list.empty"' +
` data-search-on-load="${searchOnLoad}"` +
` data-query='${JSON.stringify(options.query)}'` +
` data-query-service="${$scope.options.query.service}"` +
'></stratus-idx-office-list>' +
'</md-dialog>';
$mdDialog.show({
template,
parent: angular_1.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: true,
controllerAs: 'ctrl',
controller: ($scope, $mdDialog) => {
const dc = this;
dc.$onInit = () => {
dc.close = close;
};
function close() {
if ($mdDialog) {
$mdDialog.hide();
}
}
$scope.close = close;
}
})
.then(() => {
$scope.validateOfficeGroups();
}, () => {
$scope.validateOfficeGroups();
});
};
$scope.validateOfficeGroups = (search) => {
$scope.options.officeGroups = $scope.options.officeGroups.filter((selection) => {
return (!lodash_1.isEmpty(selection.name) && !lodash_1.isEmpty(selection.group));
});
const officeNumbers = [];
$scope.options.query.where.OfficeNumber = [];
$scope.options.officeGroups.forEach((selection) => {
officeNumbers.push(...selection.group);
});
$scope.options.query.where.OfficeNumber = officeNumbers;
if (search) {
$scope.search();
}
};
$scope.refreshSearchWidgetOptions = async (listScope) => {
if (!listScope &&
$scope.listId) {
listScope = Idx.getListInstance($scope.listId);
}
if (listScope) {
$scope.setQuery(listScope.query);
lastQuery = lodash_1.cloneDeep($scope.options.query);
$scope.listInitialized = true;
}
};
$scope.on = (emitterName, callback) => Idx.on($scope.elementId, emitterName, callback);
$scope.hasQueryChanged = () => !lodash_1.isEqual(lodash_1.clone(lastQuery), lodash_1.clone($scope.options.query));
$scope.remove = () => {
};
},
templateUrl: ($attrs) => `${localDir}${$attrs.template || componentName}.component${min}.html`
};
}
};
});
//# sourceMappingURL=search.component.js.map