List of Figures

Chapter 1. What is a single-page application?

Figure 1.1. In a traditional web application, each new view (HTML page) is constructed on the server.

Figure 1.2. In an SPA, the presentation layer moves to the client-side code, and transactions never require a browser refresh.

Figure 1.3. The HTML shell is the beginning structure. It has no content yet, only an empty DIV tag.

Figure 1.4. Subsections of the shell are called regions. A region’s content is provided by a view.

Figure 1.5. In traditional site design, each HTML file is a complete HTML page.

Figure 1.6. In an SPA design, one complete HTML file contains placeholders for the HTML fragments stored in view files.

Figure 1.7. A view is the marriage of data and one or more templates.

Figure 1.8. Views are attached to the DOM dynamically, usually as a result of user navigation, beneath the initial container DIV or one of its regions.

Figure 1.9. Views in an SPA are seamlessly swapped (through DOM manipulation) for a given area of the screen, giving the user a more desktop-like feel.

Figure 1.10. CSS, HTML, and JavaScript are the building blocks for the single-page application. There’s no special language to learn and no browser plugins required.

Figure 1.11. Using regions, an SPA’s views can be placed so that it looks exactly like a traditional web page.

Figure 1.12. Keeping the presentation layers segregated based on their purpose allows designers and developers to work in parallel. It also allows developers to test, maintain, and deploy code more effectively.

Figure 1.13. Using the module pattern limits the scope of variables and functions to the module itself. This helps avoid many of the pitfalls associated with global scope in a single-page application.

Chapter 2. The role of MV* frameworks

Figure 2.1. Indiscriminately interweaving JavaScript, HTML, and CSS makes your project more difficult to manage as it grows.

Figure 2.2. The data of your application can be separated from its representation in the UI.

Figure 2.3. The MVC design pattern has been used for many years in the development of graphical user interfaces.

Figure 2.4. MVP is a variation of MVC. With this pattern, the view is the entry point, but its logic is in the presenter.

Figure 2.5. In MVVM, the ViewModel is aware of changes in both the model and the view and keeps the two in sync.

Figure 2.6. Data from models are combined (bound) with reusable templates to create views that make up the SPA’s UI.

Figure 2.7. Screen capture of the online directory. The user enters information in the form on the left. Valid entries appear in a list on the right.

Figure 2.8. The application’s data in our online directory project is just an array of employee models. Each model is an object that contains the employee information we’ll see onscreen.

Figure 2.9. Screen capture of the online directory. Here you see that two instances of the employee model have been added to the list.

Figure 2.10. The fully rendered template, created by a template engine

Figure 2.11. In this example, a SPAN tag’s contents are being updated dynamically as the user types into an INPUT field.

Chapter 3. Modular JavaScript

Figure 3.1. In a module, the outer function encapsulates its functionality. There’s no direct access to internal variables and functions. Access is regulated via functions in the object literal it returns.

Figure 3.2. Returning customers correctly greeted with a simple message and no mention of a discount

Figure 3.3. Suddenly everyone’s being told they’re in for a big discount!

Figure 3.4. Without a module to limit the scope of each function, both are added to the same global scope, causing a name conflict.

Figure 3.5. You use dot notation, without a var, to declare a submodule. What you’re really doing is adding a property called customer, which itself contains a module.

Figure 3.6. Using modules, our welcome message is once again correct!

Figure 3.7. Now that each getStatus() function lives in its own module, there are no more name conflicts.

Figure 3.8. The module pattern makes it clear how others should use your code.

Figure 3.9. The module pattern helps organize code into units of functionality rather than individual functions.

Figure 3.10. The outer function of the pattern creates a local scope for variables and functions. This gives the module a way to achieve privacy for internal code.

Figure 3.11. An object literal is returned. Its functions have access to the module’s internal variables and functions. This gives calling code regulated access to the module’s functionality.

Figure 3.12. The trailing parentheses cause the anonymous function of the module pattern to be invoked immediately, returning the object literal.

Figure 3.13. A closure keeps any variables or functions referenced in the IIFE alive, even after execution.

Figure 3.14. This assignment creates the module’s namespace.

Figure 3.15. The outer parentheses aren’t required.

Figure 3.16. RequireJS has no dependencies to download. You need only the require.js file.

Figure 3.17. The module loader correctly downloads and manages our AMD modules and dependencies. The require directive in main.js declares a dependency that instructs RequireJS to fetch the displayUtil module. The displayUtil module, in turn, has a dependency on the counter module that gets dynamically loaded by the module loader.

Chapter 4. Navigating the single page

Figure 4.1. In traditional web-page navigation, complete pages are sent back to the browser, triggering a refresh to display the new content.

Figure 4.2. In an SPA, the client-side router assumes control of navigation, allowing the SPA to display new views instead of complete pages.

Figure 4.3. An overview of the SPA navigation process and the role of the router

Figure 4.4. Router configuration entries serve as instructions for what happens when a route’s path matches a part of the browser’s URL.

Figure 4.5. The fragment identifier

Figure 4.6. For this example, you’ll create a basic website for a university department.

Figure 4.7. Clicking the Contact Us link produces a new fragment identifier in the browser’s URL.

Figure 4.8. Passing manderson via a route parameter results in the correct office hours being displayed.

Chapter 5. View composition and layout

Figure 5.1. Our sample project tracks the status of orders for a fictitious medical supply company and includes a layout that’s more complex and diverse than you’ve previously dealt with.

Figure 5.2. The template’s HTML forms an initial structure, but CSS refines its look and feel.

Figure 5.3. Regions give you a physical area in the UI where your views can be displayed. Within a region, views can be fixed or dynamically swapped.

Figure 5.4. CSS is used to define the physical attributes of the regions in your layout, as well as to define their relationship with other regions in the UI.

Figure 5.5. How regions and views are configured impacts view composition and ultimately the layout.

Figure 5.6. Regions can also be used in views, if you need to nest a view (or views) inside another view.

Figure 5.7. Example of a simple route

Figure 5.8. Example of a route with multiple views

Figure 5.9. The base layout begins with a top region and a bottom region.

Figure 5.10. You’ll finish up the base layout with a region for navigation and a region for content.

Figure 5.11. The base layout with styles applied

Figure 5.12. The layout’s header after styles have been applied

Figure 5.13. Your layout after both the header and navigation view are rendered

Figure 5.14. Your layout after the default route displays the open orders in the content region

Figure 5.15. To compose the customer information feature, you’re placing additional regions within the main view itself to include the related but separate contact and order history views.

Figure 5.16. What your three views look like when displayed in the content region

Figure 5.17. The result of the customer information route with each view highlighted

Figure 5.18. The nested shipping view with its own URL

Chapter 6. Inter-module interaction

Figure 6.1. As your project grows, your code base become less and less manageable if you put all your variables and functions in the global namespace.

Figure 6.2. The module forms a protective barrier around your code. Variables and functions declared within the module are private.

Figure 6.3. Each public function in the API (left of the colon) has a corresponding reference to a private object inside the module (right of the colon).

Figure 6.4. The assigned external variable can be used to indirectly reference the internal objects.

Figure 6.5. Modules can have multiple functions but should ideally have a single, overall purpose.

Figure 6.6. Modules can be reused in other modules, other features, or even throughout the entire application.

Figure 6.7. In the observer pattern, each observer is notified whenever something changes in the object it’s observing.

Figure 6.8. The messaging module uses pub/sub to publish messages, via an intermediary service, to any subscribers in the application.

Figure 6.9. Our sample project is an online store to sell used video games.

Figure 6.10. Upon arrival, users are greeted with a welcome message and can immediately begin to search for games.

Figure 6.11. High-level view of what happens when a user searches for a game title

Figure 6.12. The search controllers module uses the search services module to perform the searches. The search services module is its only dependency.

Figure 6.13. The search services module uses the app data module as a data source and the messaging services module to broadcast the number of search results.

Figure 6.14. Search results are displayed to the user, along with a brief user alert about the number of records found. Each search result is a link to display the item’s details.

Figure 6.15. The messaging service is a generic utility, blindly broadcasting any message it’s given. The only module listening in this case is the user alerts module.

Figure 6.16. High-level view of the product display process

Figure 6.17. The product display services module finds the correct product information by using the selected game’s ID.

Figure 6.18. Your data and the components of the pricing module are used to calculate the price discount for the game selected.

Figure 6.19. The resulting view after a matching game is found and a discount has been applied to the game’s price

Chapter 7. Communicating with the server

Figure 7.1. JavaScript objects are converted to JSON and added to the request body for the request. In response, the server sends back the updated cart as JSON via the response body.

Figure 7.2. With MV* frameworks, where your model extends those of the framework, you automatically inherit abilities from the parent, such as the ability to make server requests.

Figure 7.3. Frameworks that provide server communication, but don’t provide a model to extend, will most likely provide a data source object instead.

Figure 7.4. With callbacks, control passes from the save() function to either the success() function or the error() function after the process has completed.

Figure 7.5. A promise has three mutually exclusive states: pending, fulfilled, and rejected.

Figure 7.6. The product display page now features a button to add the item to the shopping cart.

Figure 7.7. The shopping cart view allows the user to modify the cart’s contents.

Chapter 8. Unit testing

Figure 8.1. Our sample project calculates the amount of the tip and the total amount to be paid. It also rates the tip given.

Figure 8.2. A unit test is a low-level, focused test created during development that’s quick to execute and offers the least lag in getting test results.

Figure 8.3. Focus unit tests on the lowest level of the application’s logic.

Figure 8.4. In this design, all the logic is hidden behind this one vague API.

Figure 8.5. Smaller, specialized functions are a better fit for unit testing.

Figure 8.6. With traditional unit testing, tests are written after the code has been created.

Figure 8.7. In test-driven development, tests are written before the code is created.

Figure 8.8. The test directory will have a similar structure but is usually kept separate from the application’s source.

Figure 8.9. QUnit test report after your first unit test is run

Figure 8.10. QUnit test report with a failed test

Figure 8.11. QUnit test report shows tests grouped together as a test module.

Figure 8.12. QUnit testing against a Backbone.js model

Figure 8.13. QUnit test report showing tests run for an AngularJS service

Figure 8.14. Your test directory after adding your second JavaScript testing framework

Chapter 9. Client-side task automation

Figure 9.1. Common uses for JavaScript-based task runners

Figure 9.2. Gulp.js is able to pipe together data streams for processing.

Appendix A. Employee directory example walk-through

Figure A.1. Screen capture of the online directory. The user enters information in the form on the left. Valid entries appear in a list on the right.

Figure A.2. Directory structure for the Backbone.js version of the application

Figure A.3. Directory structure for the Knockout version of the application

Figure A.4. Directory structure for the AngularJS version of the application

Appendix B. Review of the XMLHttpRequest API

Figure B.1. Your request to get the shopping cart contents is successful. You use a GET request, passing a cart ID of 123 via a URL parameter.

Figure B.2. The server responds with your shopping cart’s JSON-formatted text. You can see that the cart has no items.

Figure B.3. You use the POST method to send complex request objects in the form of JSON-formatted text to the server from your SPA.

Figure B.4. After the new item is posted to the server, you have one game in your shopping cart.

Appendix C. Chapter 7 server-side setup and summary

Figure C.1. The shopping cart has a list of items that holds a number of games ranging from 0 to n.

Figure C.2. The ErrorMessage object is used to relay errors back to the UI.

Figure C.3. Complete project workspace

Appendix D. Installing Node.js and Gulp.js

Figure D.1. Installing Gulp.js

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset