This is my first attempt at a jQuery plugin and really doing anything with jQuery which isn't simple DOM manipulation or initialising another plugin!
I'm really keen to learn where I have gone wrong and improve on the code.
The code for the plugin is:
(function($) {
$.fn.unsplash = function(options, cbOnImageSelect) {
var defaults = {
apiRootURL: "https://api.unsplash.com", // root for API, should not need to be overridden
searchTerm: '', // the search term the results will be relating to
imagesToReturn: 6, // number of rows to output per page of results
page: 1, // page of search results to display, will be 1 to start
randomImagesToShow: 3, // number of images to display at the outset, 0 for none
apiClientId: '6066a5f8e2e83faef343bdca81bd128aebccec5d601e8e27501b0f6375423477', // can be overridden for a client id per account
orientation: 'landscape', // orientation of images to query for [landscape | portrait | squarish]
source: '', // where the plugin is being called from
cbOnImageSelect: $.noop
};
images = [];
totalImageCount = 0;
selectedImage = {};
var settings = $.extend({}, defaults, options);
//return to avoid breaking chaining
return this.each(function() {
//clear any content in the unsplash search
$('#unsplashSearch').empty();
//add a search form
$('#unsplashSearch').append('<div class="in_searchBox"><input type="text" name="us_searchTerm" id="us_searchTerm" value="" maxlength="50"><button type="submit" name="us_SearchBtn" id="us_SearchBtn"><span>Search</span></button></div>');
//bind the search handler event to the button in the form
$("#us_SearchBtn").bind("click", function(e) {
e.preventDefault();
//reset page back to 1 to avoid a new search starting on the wrong page.
settings.page = 1;
//set the settings search term to the new value
settings.searchTerm = $('#us_searchTerm').val();
searchAndPopulate(getSearchURL(settings.searchTerm, 1), settings.apiClientId);
});
$('#unsplashSearch').append('<ul id="imageList" class="horizontalList"></ul>');
$('#unsplashSearch').append('<div id="us_Paging" style="text-align: center;"></div>');
if (settings.randomImagesToShow > 0) {
//build up the request url based on whether the search term is null or not...
searchAndPopulate((!settings.searchTerm) ? getRandomURL(settings.randomImagesToShow) : getSearchURL(settings.searchTerm, 1), settings.apiClientId);
} else {
$('#us_Paging').hide();
}
//private functions
function callUnsplash(url) {
return $.ajax({
url: url,
dataType: 'json',
method: 'GET',
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', 'Client-ID ' + settings.apiClientId);
xhr.setRequestHeader('Accept-Version', 'v1');
},
success: function(json) {
totalImageCount = (json.hasOwnProperty('total')) ? json.total : settings.imagesToReturn;
images = (json.hasOwnProperty('results')) ? json.results : json;
},
error: function(xhr, status, error) {
alert("Sorry, something went wrong (" + error + " " + xhr.status + " " + xhr.statusText + ")");
}
});
}
function searchAndPopulate(url, key) {
var callUnsplashPromise = callUnsplash(url, key);
callUnsplashPromise.done(populateImages);
}
function populateImages() {
if (images.total == 0) {
} else {
//clear any existing images in the list
$('#imageList').empty();
$.each(images, function(index, image) {
var liContent = `<li><a href="#" class="splashImage" data-photoid="${image.id}"><div class="in_max200"><img src='${image.urls.thumb}' class='in_singlepic in_max200'></a></li>`;
$('#imageList').append(liContent);
});
//bind the callback function to the splashImage so it is called when clicked. if no callback is provided, then the default will be performed
$(".splashImage").bind("click", function(event) {
event.preventDefault();
if (typeof settings.cbOnImageSelect == 'function') {
var photoId = $(this).data('photoid');
var url = getImageURL(photoId);
var getImagePromise = callUnsplash(url);
getImagePromise.done(function(i) {
settings.cbOnImageSelect.call(this, i);
});
}
});
if (totalImageCount <= settings.imagesToReturn) {
$('#us_Paging').hide();
} else {
$('#us_Paging').empty().show();
if (totalImageCount > settings.imagesToReturn) {
var noOfPages = Math.ceil(totalImageCount / settings.imagesToReturn);
var x = pagination(settings.page, noOfPages);
for (var p = 0; p < x.length; p++) {
var linkText = ((x[p] !== '...') && (x[p] !== settings.page)) ? '<a href="##" class="us_changePage" data-page="' + x[p] + '">' + x[p] + '</a> ' : x[p] + ' ';
$('#us_Paging').append(linkText);
}
//add the click event to the buttons with the class us_changePage
$(".us_changePage").bind("click", function(event) {
event.preventDefault();
var nextPage = $(this).data('page');
settings.page = nextPage;
var nextURL = getSearchURL(settings.searchTerm, nextPage);
searchAndPopulate(nextURL, settings.apiClientId);
});
}
}
}
}
function getSearchURL(searchTerm, pageToShow) {
return settings.apiRootURL + '/search/photos?page=' + pageToShow + '&per_page=' + settings.imagesToReturn + '&orientation=' + settings.orientation + '&query=' + searchTerm;
}
function getRandomURL(numberOfImages) {
return settings.apiRootURL + '/photos/random?count=' + numberOfImages + '&orientation=' + settings.orientation;
}
function getImageURL(photo_id) {
return settings.apiRootURL + '/photos/' + photo_id;
}
function pagination(c, m) {
var current = c,
last = m,
delta = 2,
left = current - delta,
right = current + delta + 1,
range = [],
rangeWithDots = [],
l;
for (var i = 1; i <= last; i++) {
if (i == 1 || i == last || i >= left && i < right) {
range.push(i);
}
}
for (var i of range) {
if (l) {
if (i - l === 2) {
rangeWithDots.push(l + 1);
} else if (i - l !== 1) {
rangeWithDots.push('...');
}
}
rangeWithDots.push(i);
l = i;
}
return rangeWithDots;
}
});
};
})(jQuery);
A link to a demo on JSFiddle: click here
Questions I have:
Is there a better way of maintaining the returned images JSON between the Ajax request and populating the page i.e.
images = [];
Have I bound the click event handlers correctly in the plugin; i.e.
$("#us_SearchBtn").bind("click", function(e) {
Also if you have any suggestions on how to run a different callback depending on which "Choose background" link is clicked, I'd be really grateful.