Last active
April 5, 2016 21:37
-
-
Save jmas/26eaa862909477ed6e600760b67059fc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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