Developing Large Web Applications- P20 potx

10 125 0
Developing Large Web Applications- P20 potx

Đang tải... (xem toàn văn)

Thông tin tài liệu

{ // The content for this module consists of a single image, along // with text for the caption and the attribution. $attr = ""; if (!empty($this->picture["attr"])) { $attr = <<<EOD <cite> courtesy of {$this->picture["attr"]} </cite> EOD; } if (empty($this->picture["img_l"])) $img = ""; else { $img = <<<EOD <img src="{$this->picture["img_l"]}" alt="{$this->picture["text"]}" width="600" /> EOD; } return <<<EOD <div id="picvwr" class="{$this->type}"> <div class="vwrimg"> $img </div> $attr <div class="vwrcap"> {$this->picture["text"]} </div> </div> EOD; } } ?> Example 7-7 presents the JavaScript that implements behaviors for the Picture Slider module. In a manner consistent with what we discussed for large-scale JavaScript in Chapter 5, the module has a JavaScript object that neatly encapsulates the functionality that the component requires, and the object is named PictureSlider to reflect the module’s name. In Example 7-6, the get_js_linked method of PictureSlider specifies that this object is defined in the file identified by the key sitewide.js. The JavaScript for the module needs two YUI libraries (which you can download from http://developer .yahoo.com/yui) to support it. Therefore, get_js_linked specifies keys for these files before sitewide.js. Working with Modules | 171 Example 7-7. PictureSlider JavaScript object for the slideshow PictureSlider = function() { // Set up references to the elements needed for the slider and viewer. this.slider = document.getElementById("picsld"); if (this.slider) { this.tab = this.slider.getElementsByTagName("table"); this.tab = (this.tab && this.tab.length > 0) ? this.tab[0] : null; } if (this.slider) { this.lb = YAHOO.util.Dom.getElementsByClassName ( "btnl", "img", this.slider ); this.lb = (this.lb && this.lb.length > 0) ? this.lb[0] : null; this.rb = YAHOO.util.Dom.getElementsByClassName ( "btnr", "img", this.slider ); this.rb = (this.rb && this.rb.length > 0) ? this.rb[0] : null; } this.viewer = document.getElementById("picvwr"); // You pass values for the following parameters to the module's // constructor in PHP. The module's get_js method in PHP dynamically // generates the JavaScript to set these members from those values. this.stripWidth = 0; this.totalCount = 0; this.totalWidth = 0; // This lock is needed to ensure that one left or right move of the // slider runs to completion; otherwise, misalignment could happen. this.lock = false; }; PictureSlider.prototype = new Object(); PictureSlider.prototype.slideL = function() { // Moving to the left adjusts the slider in a positive direction. this.adjust(+(this.stripWidth)); }; 172 | Chapter 7: Large-Scale PHP PictureSlider.prototype.slideR = function() { // Moving to the right adjusts the slider in a negative direction. this.adjust(-(this.stripWidth)); }; PictureSlider.prototype.adjust = function(amt) { // If already locked, do nothing; otherwise, get the lock and go. if (this.lock) return; else this.lock = true; var anim; var ease = YAHOO.util.Easing.easeOut; var pos = parseInt(YAHOO.util.Dom.getStyle(this.tab, "left")); // Prevent moving past either end of the slider during an adjustment. if (amt > 0) { if (pos + amt > 0) amt = 0; } if (amt < 0) { if (pos + amt <= -(this.totalWidth)) amt = 0; } // The following creates a closure that ensures access to members // of the PictureSlider instance from inside the update method. var obj = this; function handleComplete() { obj.update(); obj.lock = false; } // Do the sliding animation if there is any amount to move; otherwise, // just call update directly to ensure the arrow buttons are updated. if (amt != 0) { anim = new YAHOO.util.Anim(this.tab, {left: {by: amt}}, 0.5, ease); anim.onComplete.subscribe(handleComplete); anim.animate(); } else { this.update(); this.lock = false; } }; Working with Modules | 173 PictureSlider.prototype.update = function() { var pos; pos = parseInt(YAHOO.util.Dom.getStyle(this.tab, "left")); // Switch images to indicate which buttons are enabled or disabled. if (pos >= 0) this.lb.src = " /slide_arrow_off_l.gif"; else this.lb.src = " /slide_arrow_l.gif"; if (pos <= -this.totalWidth + this.stripWidth) this.rb.src = " /slide_arrow_off_r.gif"; else this.rb.src = " /slide_arrow_r.gif"; }; PictureSlider.prototype.select = function(targ, n, img, text, attr) { var sld; var el; // Switch the selection by changing the frame with the selected class. el = YAHOO.util.Dom.getElementsByClassName ( "selected", "div", this.slider ); if (el && el.length > 0) YAHOO.util.Dom.removeClass(el[0], "selected"); if (targ) YAHOO.util.Dom.addClass(targ, "selected"); // Reload the picture viewer with the current selection in the slider. this.reload(img, text, attr); // Update the text indicating the position of the selected picture. el = YAHOO.util.Dom.getElementsByClassName ( "sldpos", "div", this.slider ); if (el && el.length > 0) { el[0].innerHTML = "Showing picture <strong>" + n + "</strong> of " + this.totalCount; } }; 174 | Chapter 7: Large-Scale PHP PictureSlider.prototype.reload = function(img, text, attr) { // Handle the case of no viewer associated with the picture slider. if (!this.viewer) return; var el; // Get the image viewer and change the image currently being shown. el = YAHOO.util.Dom.getElementsByClassName ( "vwrimg", "div", this.viewer ); if (el && el.length > 0) { el = el[0].getElementsByTagName("img"); if (el && el.length > 0) { el[0].src = img; el[0].alt = text; } } // Change the attribution in the picture viewer for the selection. el = this.viewer.getElementsByTagName("cite"); if (el && el.length > 0) el[0].childNodes[0].nodeValue = "courtesy of" + attr; // Change the caption in the picture viewer based on the selection. el = YAHOO.util.Dom.getElementsByClassName ( "vwrcap", "div", this.viewer ); if (el && el.length > 0) el[0].childNodes[0].nodeValue = text; }; PictureSlider.prototype.loaded = function() { // Fire this from your initialization method for the picture slider. var el; el = YAHOO.util.Dom.getElementsByClassName ( "sldtab", "div", this.slider Working with Modules | 175 ); YAHOO.util.Dom.setStyle ( el[0], "visibility", "visible" ); }; As you can see, a slideshow contains enough interrelated pieces that defining it using nicely encapsulated modules is critical to making it highly reusable, maintainable, and ultimately reliable in the long life cycle of a large web application. Example 7-8 dem- onstrates how easy this module is to use despite all the interconnected pieces of its implementation. Just as we saw for the simple modules at the start of the chapter, you need only instantiate the modules with the necessary arguments to configure them, call their create methods, and place them within the proper section of the layout for the page. Furthermore, you need only include a single include file, slideshow.inc, to use the slideshow. The necessary HTML, CSS, and JavaScript for its modules travel with the slideshow wherever you use it. Example 7-8. Creating the modules for a slideshow <?php require_once(" /common/sitepage.inc"); require_once(" /common/slideshow.inc"); class NewCarDetailsPage extends SitePage { public function get_content() { // Create the picture slider and picture viewer for the slideshow. // The backend data will have been loaded earlier during a call to // load_data. $mod = new PictureSlider ( $this, $this->load_data["new_car_info"]["gallery"] ); $slider = $mod->create(); $mod = new PictureViewer ( $this, $this->load_data["new_car_info"]["gallery"][0] ); 176 | Chapter 7: Large-Scale PHP $viewer = $mod->create(); // Place the HTML markup for each module within the page layout. $mod = new DetailsLayout ( $this, array( ), array($slider, $viewer), array( ), array( ), array( ), array( ) ); // Return the content, which the create method for the page uses. return $mod->create(); } } ?> Layouts and Containers In Chapter 4, we discussed layouts as highly reusable, generic templates that define the overarching structure of pages. You saw that containers are even finer groupings of modules typically placed within layouts. Together, layouts and containers play a vital role in fostering reusability, maintainability, and reliability in large web applications by defining a number of standard sections in which to place modules on a page. A section is simply a region in which we can insert one or more modules. As we explore implementations for layouts and containers, you’ll see that layouts and containers are just specialized types of modules. That is, they require many of the same things that other modules do. The main distinction is that aside from the additional structural elements that a layout or container defines, the content for a layout or con- tainer is actually just the content of other modules. Because the operations you need to perform to generate the individual sections of a layout or container are generally the same for most layouts and containers, it’s useful to define a base class, Layout, for this purpose. Example 7-9 presents the Layout class, which is derived from Module. This class defines get_section, which places a set of modules within a div and assigns the div a specified class so that styles for positioning and formatting the section can be applied. Layouts and Containers | 177 Example 7-9. Implementation of the Layout class class Layout extends Module { public function __construct($page) { parent::__construct($page); } public function get_section($class, $modules) { if (count($modules) == 0) return ""; foreach ($modules as $content) $section .= empty($content) ? "" : $content; if (empty($section)) return ""; return <<<EOD <div class="$class"> $section <! $class > </div> EOD; } } Example 7-10 presents a layout class intended for laying out any page related to search results, be they search results for new cars, used cars, reviews, or articles in our web application. This layout has sections for a header at the top, three content sections in the middle, and two footers across the bottom (this is the same layout from Fig- ure 4-3 in Chapter 4). Because any HTML for modules that you pass through the lay- out’s interface for each section simply gets inserted into the proper locations in the overall structure of the layout, it is highly reusable for any page whose design observes this same structure; you simply insert different modules. As a result, layouts and con- tainers provide a good opportunity for engineers and designers to work together to establish standard guidelines under which pages can be designed and built. Classes for containers are defined in much the same way as for layouts, but they typically organize smaller groups of modules for use within sections of a layout. Example 7-10. Implementing a layout class class ResultsLayout extends Layout { protected $layreshdr; protected $layrespri; protected $layressec; protected $layrester; protected $layresftr1; protected $layresftr2; 178 | Chapter 7: Large-Scale PHP public function __construct ( $page, $layreshdr, $layrespri, $layressec, $layrester, $layresftr1, $layresftr2 ) { parent::__construct($page); $this->layreshdr = $layreshdr; $this->layrespri = $layrespri; $this->layressec = $layressec; $this->layrester = $layrester; $this->layresftr1 = $layresftr1; $this->layresftr2 = $layresftr2; } public function get_css_linked() { return array("sidewide.css"); } public function get_content() { $layreshdr = $this->get_section("layreshdr", $this->layreshdr); $layrespri = $this->get_section("layrespri", $this->layrespri); $layressec = $this->get_section("layressec", $this->layressec); $layrester = $this->get_section("layrester", $this->layrester); $layresftr1 = $this->get_section("layresftr1", $this->layresftr1); $layresftr2 = $this->get_section("layresftr2", $this->layresftr2); // The content for the layout is just the content of the modules // passed into the layout and inserted into the layout sections. return <<<EOD <div id="layres"> $layreshdr <div class="layresmaj"> $layrespri $layressec $layrester < layresmaj > </div> $layresftr1 $layresftr2 <! layres > </div> EOD; } } Layouts and Containers | 179 Special Considerations The more you work with any large web application, the more you’ll turn up special considerations that you didn’t originally think about. Fortunately, it’s relatively easy to adapt the techniques with large-scale PHP introduced in this chapter for many dif- ferent situations. Indeed, this is one of the most important tests of a good architecture: can it adapt to new situations without undue contortions? This section presents some examples of special situations in large web applications with solutions using the tech- niques from this chapter. Handling Module Variations In large web applications, modules frequently need to function or appear in a different manner on different pages. For example, suppose you would like a module to support default, compact, and mid-size presentations, as illustrated in Chapter 4. Exam- ple 7-11 demonstrates a solution wherein the class of the module’s containing div be- comes parameterized. To do this, you specify a data member for the module named $class and define setter methods that change its value. The module picks up the proper CSS when the class attribute of its containing div is set to the value stored in the $class data member. For more extensive variations requiring more significant changes to the HTML markup or JavaScript for a module, you can manage those variations in a similar manner using data members to control how the HTML markup or JavaScript is generated. It helps to have a nicely encapsulated class for the module and a well-defined interface for selecting the variations. Example 7-11. Handling variations of the Popular New Cars module class PopularNewCars extends Module { protected $class; public function __construct($page, ) { parent::__construct($page); $this->class = "default"; // Set up the module using other arguments from the constructor. } public function set_mode_default() { $this->class = "default"; } 180 | Chapter 7: Large-Scale PHP . some examples of special situations in large web applications with solutions using the tech- niques from this chapter. Handling Module Variations In large web applications, modules frequently need. with any large web application, the more you’ll turn up special considerations that you didn’t originally think about. Fortunately, it’s relatively easy to adapt the techniques with large- scale. making it highly reusable, maintainable, and ultimately reliable in the long life cycle of a large web application. Example 7-8 dem- onstrates how easy this module is to use despite all the interconnected

Ngày đăng: 03/07/2014, 07:20

Mục lục

  • Organization of This Book

  • Conventions Used in This Book

  • We’d Like to Hear From You

  • Ten Tenets for Large Web Applications

  • Chapter 2. Object Orientation

    • The Fundamentals of OOP

    • Modeling a Web Page

      • Defining Page Types

      • Object-Oriented PHP

        • Classes and Interfaces

          • Declaring a class

          • Inheritance in PHP

            • Extending classes

            • Object-Oriented JavaScript

              • Objects

                • Creating an object

                • Inheritance in JavaScript

                  • Prototype-based inheritance

                  • Chapter 3. Large-Scale HTML

                    • Modular HTML

                      • A Bad Example: Using a Table and Presentation Markup

                      • A Better Example: Using CSS

                      • The Best Example: Semantically Meaningful HTML

                      • Benefits of Good HTML

                      • HTML Tags

                        • Bad HTML Tags

                        • IDs, Classes, and Names

                        • XHTML Guidelines

                          • Proper nesting of tags

                          • End tags and empty tags

                          • JavaScript, CSS, and special characters

                          • Chapter 4. Large-Scale CSS

                            • Modular CSS

                              • Including CSS

                                • Linking

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan