# Developing Large Web Applications- P19

Chia sẻ: Cong Thanh | Ngày: | Loại File: PDF | Số trang:10

0
41
lượt xem
3

## Developing Large Web Applications- P19

Mô tả tài liệu

Developing Large Web Applications- P19:This book presents a number of techniques for applying established practices of good software engineering to web development—that is, development primarily using the disparate technologies of HTML, CSS, JavaScript, and server-side scripting languages. Whereas there are many books on how to use languages, how to use libraries, and how to approach software engineering, this is the first book to codify many of the techniques it presents. These techniques will make the components of your own web applications more reusable, maintainable, and reliable....

Chủ đề:

Bình luận(0)

Lưu

## Nội dung Text: Developing Large Web Applications- P19

1. "loc_path" => "...", "media" => "all" ), ... ); // When this member is set to true, stylesheet keys resolve to // the loc_path paths; otherwise, the aka_path paths are used. $this->css_is_local = false; // Build the data structure for resolving JavaScript filenames.$this->js_linked_info = array ( "sitewide.js" => array ( "aka_path" => "...", "loc_path" => "..." ), "yahoo-dom-event.js" => array ( "aka_path" => "...", "loc_path" => "..." ), ... ); // When this member is set to true, JavaScript keys resolve to // the loc_path paths; otherwise, the aka_path paths are used. $this->js_is_local = false; } // You would likely define a number of other methods here for tasks // specific to your web application and that apply to all parts of it. ... } Defining sectional page classes A sectional page class is a class derived from your sitewide page class that customizes the sitewide page class for a section of your application (e.g., NewCarsPage for a section of the site containing multiple pages related to new cars). Some methods that a sectional page class might define are get_header and get_footer to display a different header and footer for a section, or get_css_linked and get_js_linked to link additional CSS and JavaScript files for just that section. In addition, a sectional page class may want to register its own set of links for CSS and JavaScript files. It does this by implementing its own register_links method, which calls the parent’s register_links method first to let the parent add links for the entire web application, then appends its own entries for CSS and JavaScript files to the$css_linked_info and $js_linked_info members. Working with Pages | 161 2. Defining page-specific classes Page-specific classes are the most common pages that you’ll implement. These are classes like NewCarSearchResultsPage, presented earlier in Example 7-1. In page-specific classes, you typically implement the following from Page’s abstract interface: save_data, load_data, get_content, set_title, set_meta, and set_css_id. You might also imple- ment get_css and get_js to provide small amounts of CSS and JavaScript to embed on the page beyond what the modules already provide; however, the modules normally should have already specified everything they are able to encapsulate themselves. Of course, object orientation lets you override any method in a page’s specific class to do something different from the base class. Working with Modules As mentioned at the start of the chapter, a module is a self-contained component of the user interface that encompasses everything needed (e.g., the HTML, CSS, and JavaScript) to make an independently functioning and cohesive unit that can be used in a variety of contexts across various pages. Considering that a page is the canvas responsible for assembling a collection of modules so that they work together within a single context, modules must provide a page with everything that the page requires to assemble itself. This common requirement among modules suggests that we should have a base class from which to derive all modules. In this section, we’ll look at one example of a base class for modules called Module. Although it’s not hard to imagine features beyond those presented here for such a class, the example provides a good starting point by which to implement modules in many large web applications. A module specifies what it needs loaded for HTML, CSS, and JavaScript, but these pieces are actually assembled later by the page, because only the page can put everything together in the proper order. Therefore, when you create an instance of the Module class, you pass in a reference to the page on which the module will reside. The module then places references to all the pieces it needs in data structures within that page, and the page uses them later. Just as we did for Page, let’s explore the Module class by examining its public interface, abstract interface, and implementation details. Public Interface for the Module Class The public interface for Module consists of a single method named create, which has an implementation in the base class that is sufficient for most modules. This interface is nicely parallel to the interface for creating pages: 162 | Chapter 7: Large-Scale PHP 3. create() Creates a module and returns its HTML markup. In the process, create performs several important tasks. These include, in order, adding CSS links and embedded CSS for the module to the page, adding JavaScript links and embedded JavaScript for the module to the page, and getting the content for the module. The create method performs each of these tasks by calling methods from the abstract interface, discussed next. Abstract Interface for the Module Class The abstract interface for Module consists of methods that specific modules are expected to implement as needed. The Module class calls upon these methods at the appropriate moments from its create method. Because Module provides empty implementations for each of the methods, a class derived from Module is not required to implement all of the methods in the abstract interface; it implements only the methods that it requires. For example, if a module doesn’t need to link any JavaScript files, it doesn’t have to provide an implementation for get_js_linked. The simplest modules may implement just the get_content and get_css_linked methods. CSS management The methods in the abstract interface for managing CSS let you specify the CSS files to link and the CSS to embed for a module. These are aggregated by the page on which the module resides when the module is created so that the page can insert them at the appropriate point when the page is assembled: get_css_linked() Implement this method to return an array of keys registered in register_links (see register_links) for the CSS files to link for the module. If you follow the conven- tion that the get_css_common method of the page class will include a sitewide file, you don’t have to specify it here; however, specifying it will cause no harm because the page will check and make sure not to include it twice. get_css() Implement this method to return a string of CSS to embed for the module. This method is useful when you need to specify dynamically generated CSS for a module. JavaScript management The methods in the abstract interface for managing JavaScript let you specify the Java- Script files to link and the JavaScript to embed for a module. As with CSS, the links and embedded JavaScript are passed to the page to assemble later: Working with Modules | 163 4. get_js_linked() Implement this method to return an array of keys registered in register_links (see register_links) for the JavaScript files to link for the module. Modules that require JavaScript often link several JavaScript libraries to ensure that all dependencies between the libraries are addressed. get_js() Implement this method to return a string of JavaScript to embed for the module. This method is useful when you need to specify dynamically generated JavaScript for a module. Content for the module Modules define a single method for working with content. This method generates the HTML that appears in the module: get_content Implement this method to return the HTML markup for the content of the module. If needed, you can also create other modules within the get_content method for a module in the same way as you do for pages (see “Implementing Nested Mod- ules” on page 182). Implementation of the Module Class Because modules perform just a few tasks, our implementation of Module does not need any private or protected methods. Example 7-5 presents the code for the Module class. Example 7-5. Implementation of the Module class class Module { // Used to store a reference to the page on which the module resides. protected$page; /* * The following methods comprise the public interface for the class. */ public function __construct($page) { // All modules store a reference to the page on which they reside. // In PHP 5, objects are passed by reference. In PHP 4, we would // have had to specify we wanted a reference explicitly (using &).$this->page = $page; } public function create() { // Add module CSS styles to the page on which the module resides.$this->page->add_to_css_linked($this->get_css_linked());$this->page->add_to_css($this->get_css()); 164 | Chapter 7: Large-Scale PHP 5. // Add module JavaScript to the page on which the module resides.$this->page->add_to_js_linked($this->get_js_linked());$this->page->add_to_js($this->get_js()); return$this->get_content(); } /* * The following methods comprise the abstract interface for the * class. These are methods with empty implementations by default, * many of which specific module classes override for their needs. */ public function get_css_linked() { } public function get_css() { } public function get_js_linked() { } public function get_js() { } public function get_content() { } } Extending the Module Class Just as we extended the Page class for new types of pages, we can derive new types of modules from Module. Generally, you will find that most modules can be derived directly from Module. However, our object-oriented approach to developing modules provides the same opportunities for good maintainability and reusability as we saw with page classes earlier. One example of a specific type of module that provides a good oppor- tunity for reuse is the Layout base class for all layouts and containers (see “Layouts and Containers” on page 177). Layouts require the same capabilities as other modular-type entities, while adding some of their own. An Example Module: Slideshow Modules can be many things in a large web application: a list of search results, a form for entering search queries, a menu bar, a wrapper for standard advertising units, or a highly reusable user interface component like a selection list, paginator, or stylized Working with Modules | 165
6. button, to name a few. In this section, we explore a popular component in many large web applications: a slideshow, which presents a series of slides along with some navi- gation (right, left, or an arbitrarily chosen slide). One way to implement a slideshow is to define two modules that work together. One module, which we’ll call the Picture Slider module, provides a slider of thumbnail im- ages from which the visitor makes selections. The other module, which we’ll call the Picture Viewer module, provides a larger view of the image selected in the picture slider (see Figure 7-1). This slideshow isn’t fancy; it doesn’t change slides automatically at fixed time intervals, but it keeps the current slide as well as the position of the slider in sync with the movements specified by the visitor. Figure 7-1. The Picture Slider and Picture Viewer modules in a slideshow Example 7-6 presents implementations for PictureSlider and PictureViewer, the two classes that define the Picture Slider and Picture Viewer modules, respectively. Because these classes are normally used together, you might decide to place them both in a single 166 | Chapter 7: Large-Scale PHP
7. include file called slideshow.inc. You’ll notice with a closer look that even though the classes for the two modules are often used together, they are not tightly coupled; each works completely independently. One benefit of defining two separate classes is that you can arrange the slider and viewer on the page however you desire. For example, you can place the slider above or below the viewer, or you can place a small module of some other type between them. The Picture Slider and Picture Viewer modules are easy to configure. When you in- stantiate PictureSlider, for example, you simply pass it a gallery of images to display as an array of image data. Each member in the array is an associative array consisting of the URL for a thumbnail of the image (img_t), a URL for the large version of the image (img_l), the text for the caption (text), and text for the attribution (attr). When you instantiate PictureViewer, you pass it one member of the gallery for it to display. Notice that both PictureSlider and PictureViewer define the methods outlined for Module earlier that let you specify the CSS and JavaScript for a module and get its con- tent. These effectively allow the CSS and JavaScript to travel with the module wherever it is used. Furthermore, they document exactly where to find the CSS and JavaScript for the module, should you decide to refactor the code for the module in the future. Example 7-6. PictureSlider and PictureViewer classes for the slideshow
8. // needs YUI libraries for managing the DOM and doing animation. // Presumably, the module's own JavaScript resides in sitewide.js. return array ( "yahoo-dom-event.js", "animation.js", "sitewide.js" ); } public function get_js() { // The JavaScript here is dynamically generated. We're using PHP // to create some JavaScript that is parameterized by the module. // For instance, the total width depends on the number of slides, // calculated from the slides passed to the module's constructor. $strip_width =$this->picture_width * $this->slider_frames;$count = count($this->gallery);$total_width = $this->picture_width *$count; return
9. else $showing = ""; return 10. EOD;$i++; } // Add blank slides to fill frames when the number of pictures is // not evenly divisible by the frames that appear in the slider. while ($i %$this->slider_frames != 0) { \$items .=