Skip to content

Instantly share code, notes, and snippets.

@jmas
Last active April 5, 2016 21:37
Show Gist options
  • Save jmas/26eaa862909477ed6e600760b67059fc to your computer and use it in GitHub Desktop.
Save jmas/26eaa862909477ed6e600760b67059fc to your computer and use it in GitHub Desktop.
(function($) {
"use strict";
/**
* @param containerEl
* @param directoriesUrl
* @param listingUrl
* @param country
* @param itemTemplate
* @constructor
*/
function ListingLookup(containerEl, directoriesUrl, listingUrl, country, itemTemplate, fetchIntervalSec) {
// params
this.containerEl = containerEl;
this.directoriesUrl = directoriesUrl;
this.listingUrl = listingUrl || null;
this.country = country || '';
this.itemTemplate = itemTemplate || $('.js-listing-item-template').html();
this.fetchIntervalSec = this.fetchIntervalSec || 2000;
// internal variables
this.findTimeout = null;
this.isFetching = false;
this.directories = [];
this.directoriesSelected = [];
};
ListingLookup.prototype = {
/**
* Make ajax request to load directories data.
* @returns {Promise}
*/
loadDirectories: function() {
if (! this.directoriesUrl) {
throw new Error('Property directoriesUrl is null or undefined. Please set correct one.');
}
return $.post(this.directoriesUrl, {
country: this.country
});
},
/**
* Make ajax request to load listings data.
* @returns {Promise}
*/
loadListings: function() {
if (! this.listingUrl) {
throw new Error('You need to call setListingUrl() first.');
}
return $.get(this.listingUrl);
},
/**
* Load directories data.
* @returns {Promise}
*/
updateDirectories: function() {
var that = this;
return this.loadDirectories().then(function(response) {
if (response.result) {
that.directories = response.dirs;
that.directoriesSelected = that.directories.map(function(item) {
return item.identifier;
});
}
});
},
/**
* Load listings data.
* @returns {Promise}
*/
updateListings: function() {
var that = this;
return this.loadListings().then(function(response) {
if (response.result) {
that.directories = that.directories.map(function(item) {
if (typeof response.directories[item.identifier] !== 'undefined') {
return $.extend(item, response.directories[item.identifier]);
}
return item;
});
that.isFetching = response.fetching;
} else {
that.isFetching = false;
}
return true;
});
},
/**
* Update and render directories.
* @returns {ListingLookup}
*/
refreshDirectories: function() {
var that = this;
this.updateDirectories().then(function() {
that.render();
});
return this;
},
/**
* Set country and refresh directories.
* @param country
* @returns {ListingLookup}
*/
setCountry: function(country) {
this.country = country;
this.refreshDirectories();
return this;
},
/**
* @param listingUrl
* @returns {ListingLookup}
*/
setListingUrl: function(listingUrl) {
this.listingUrl = listingUrl;
return this;
},
/**
* @param directoryId
* @returns {*}
*/
getDirectory: function(directoryId) {
for (var i=0,len=this.directories.length; i<len; i++) {
if (this.directories[i].identifier === directoryId) {
return this.directories[i];
}
}
return null;
},
/**
* Start fetching listings and render result.
* @returns {ListingLookup}
*/
fetch: function() {
var that = this;
this.isFetching = true;
this.updateListings().then(function() {
that.render();
if (that.isFetching) {
that.findTimeout = setTimeout(function() {
that.fetch();
}, that.fetchIntervalSec);
}
});
return this;
},
/**
* Open popup for update listing data.
* @returns {ListingLookup}
*/
openSwapListingPopup: function(directoryId) {
return this;
},
/**
* Select all directories.
* @returns {ListingLookup}
*/
selectAllDirectories: function() {
this.directoriesSelected = this.directories.map(function(item) {
return item.identifier;
});
this.render();
return this;
},
/**
* Deselect all directories.
* @returns {ListingLookup}
*/
deselectAllDirectories: function() {
this.directoriesSelected = [];
this.render();
return this;
},
/**
* Toggle directory selection.
* @param directoryId
* @returns {ListingLookup}
*/
toggleDirectorySelection: function(directoryId) {
var selected = this.getDirectoriesSelected();
var indexOfElementToRemove = selected.indexOf(directoryId);
if (indexOfElementToRemove !== -1) {
selected.splice(selected.indexOf(directoryId), 1);
} else {
selected.push(directoryId);
}
this.directoriesSelected = selected;
this.render();
return this;
},
/**
* Get lost of selected directories.
* @returns {Array|*}
*/
getDirectoriesSelected: function() {
return this.directoriesSelected;
},
/**
* Check selection state of directory.
* @param directoryId
* @returns {boolean}
*/
isDirectirySelected: function(directoryId) {
return this.getDirectoriesSelected().indexOf(directoryId) !== -1;
},
/**
* The goal: to work with all DOM elements only in render() function,
* do not set or update current object properties.
* You CAN'T do in render() function:
* - set or change properties of current object,
* - call load-, update-, refresh- methods (load async data),
* - call set-methods of current object.
* You CAN do in render() function:
* - read or change DOM elements,
* - update properties of DOM elements,
* - attach event-listeners to DOM elements,
* - read properties of current oject,
* - call get-methods of current object.
* @returns {ListingLookup}
*/
render: function() {
var that = this;
var $container = $(this.containerEl);
// render list of directories
if ($container.prop('data-render-country') !== that.country) {
$container.empty();
var itemTemplate = that.itemTemplate;
var currentItemHtml;
that.directories.forEach(function(item) {
currentItemHtml = itemTemplate
.replace(/___DIRECTORY_NAME___/g, item.name)
.replace(/___DIRECTORY_ID___/g, item.identifier);
$container.append(currentItemHtml);
});
$container.prop('data-render-country', that.country);
}
// attach listeners to container if needed
if (! $container.prop('data-render-listener-attached')) {
$container.on('click', '.js-listing-swap-button', function() {
that.openSwapListingPopup($(this).attr('data-directory-id'));
return false;
});
$container.on('click', '.js-listing-checkbox', function() {
that.toggleDirectorySelection($(this).attr('data-directory-id'));
return true;
});
$container.prop('data-render-listener-attached', true);
}
// sync all directories with loaded data
$container.find('.js-listing-item').each(function() {
var $item = $(this);
var directoryId = $item.attr('data-directory-id');
var directory = that.getDirectory(directoryId);
var isDirectoryExists = (directory !== null);
if (isDirectoryExists) {
// elements
var $checkbox = $item.find('.js-listing-checkbox');
var $updatingMessage = $item.find('.js-listing-updating-message');
var $notFoundMessage = $item.find('.js-listing-not-found-message');
var $summary = $item.find('.js-listing-summary');
var $viewButton = $item.find('.js-listing-view-button');
var $createButton = $item.find('.js-listing-create-button');
var $swapButton = $item.find('.js-listing-swap-button');
var $profileLink = $item.find('.js-listing-profile-link');
var $profileAddress = $item.find('.js-listing-profile-address');
var $profilePhone = $item.find('.js-listing-profile-phone');
var $reviewsCount = $item.find('.js-listing-reviews-count');
//
$checkbox.prop('checked', that.isDirectirySelected(directoryId));
if (typeof directory.searched === 'undefined') {
$([
$updatingMessage,
$notFoundMessage,
$summary,
$viewButton,
$createButton,
$swapButton
]).each(function() {
$(this).addClass('hide');
});
} else {
var isSearchFinished = (directory.searched === true);
var isListingFound = (directory.url !== '');
if (isSearchFinished) {
$checkbox.prop('disabled', false);
$updatingMessage.addClass('hide');
if (isListingFound) {
$summary.removeClass('hide');
$checkbox.prop('checked', true);
var address = [];
if (directory.profile.street_address) {
address.push(directory.profile.street_address);
}
if (directory.profile.locality) {
address.push(directory.profile.locality);
}
if (directory.profile.region) {
address.push(directory.profile.region);
}
if (directory.profile.postcode) {
address.push(directory.profile.postcode);
}
$profileLink.attr('href', directory.url);
$profileLink.html(directory.profile.business_name);
$profileAddress.html(address.join(' '));
$profilePhone.html(directory.profile.contact_telephone);
$reviewsCount.html(directory.profile.num_reviews);
} else {
$notFoundMessage.removeClass('hide');
}
} else {
$updatingMessage.removeClass('hide');
}
}
} else {
$(this).remove();
}
});
return this;
}
};
// export
window.BL = window.BL || {};
window.BL.ListingLookup = ListingLookup;
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment