Skip to content

implements the book finder using jquery + ajax#2

Open
hora wants to merge 3 commits intorefactoredfrom
jquery-and-ajax
Open

implements the book finder using jquery + ajax#2
hora wants to merge 3 commits intorefactoredfrom
jquery-and-ajax

Conversation

@hora
Copy link
Owner

@hora hora commented Jan 12, 2021

This PR (pull request) compares the refactored branch with the jquery-and-ajax branch.

This is to demonstrate the difference between @IrvHenri's implementation of the Book Finder App using the more up-to-date fetch API and a more legacy implementation using jQuery + Ajax.

All non-trivial suggested changes, and some cosmetic changes, have line notes directly on the diff. You can see the conversations about those changes below, or in the 'Files changed' tab.

</p>
</footer>
</body>
<script src="jquery-3.5.1.js"></script>
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use jQuery, I downloaded the latest version from the jQuery website. I picked the unminified, full-featured version.

Here, it's being loaded before the Book Finder script, because we need jQuery to be loaded first since we're using it inside script.js.

const booksDisplay = document.getElementById("books-display");
const $msgWaiting = $(".message-waiting");
const $searchForm = $("#search-form");
const $booksDisplay = $("#books-display");
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming the variables starting with a $ (as in $msgWaiting) is not necessary, but a common convention. This convention is used because it quickly lets a developer know that the variables reference jQuery objects, not DOM nodes directly.

This is important, because to interact with these objects we have to use jQuery functions, not vanilla JS DOM functions.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note that we're using jQuery's CSS-style selector syntax to look up elements in the DOM.

searchForm.addEventListener("submit", () => {
msgWaiting.style.display = "none";
const searchInput = document.getElementById("search-input").value;
$searchForm.on("submit", () => {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using jQuery's on function to bind an event handler for submit.

msgWaiting.style.display = "none";
const searchInput = document.getElementById("search-input").value;
$searchForm.on("submit", () => {
$msgWaiting.hide();
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jQuery's hide function more-or-less will do the same thing as setting the display property to none, only it's a bit more clever based on the initial display property of the element(s) being hidden.

const searchInput = document.getElementById("search-input").value;
$searchForm.on("submit", () => {
$msgWaiting.hide();
const searchInput = $("#search-input").val();
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we're working with jQuery obejcts, we need to use the jQuery val function to grab the value of the input.

datatype: "json"
}).done((booksData) => {
displayBooks(booksData.items);
});
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core part of this demo: the difference between the newer fetch API, and the more legacy (but still used) jQuery + Ajax approach.

When making an Ajax request, you don't need to specify the method if you're making GET requests, or the datatype because jQuery will (usually) infer it on its own. But it doesn't hurt to have a bit more clarity and resilience.

Note also that the ajax function returns a Promise, so we can use the Promise API to bind a callback for what to do once the Ajax request is successful.

function displayBooks(books) {
// clear any previous results
booksDisplay.innerHTML = "";
$booksDisplay.empty();
Copy link
Owner Author

@hora hora Jan 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This jQuery function clears out all the contents of a selected jQuery node.

let smallThumbnail = getThumbnail(volumeInfo);

let bookDiv = document.createElement("div");
let $bookDiv = $("<div>").addClass("book-styling");
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jQuery syntax for creating new DOM nodes is ... horrible. It works well enough for a quick addition, like this <div>, but for more than that, it gets unwieldly.

</div>
<a href = "${previewLink}" class ="book-link" target="_blank"> Google Books Preview </a>
`;
`);
Copy link
Owner Author

@hora hora Jan 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because jQuery's syntax for creating new nodes is gross, I just set all the HTML contents of the newly-created <div> all at once. This can have security implications, so it's not good for all situations.

If you find yourself needing to create DOM nodes, and using React (or similar) would be overkill, a template library like Handlebars could be very useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant