Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-customizing-headers-and-footers-ms-office-live-small-business
Packt
30 Nov 2009
13 min read
Save for later

Customizing Headers and Footers with MS Office Live Small Business

Packt
30 Nov 2009
13 min read
Although a website is just a collection of web pages, the collection is not random. A central theme ties the web pages together with common elements such as branding, logo, layout, and formatting. On really large websites, the interweaving of these elements can be quite complex. Each of Google's websites, for example, has its distinct identity and yet you can identify it as a "Google website". It takes a small army of designers and illustrators to achieve such a "Similar But Distinct" identity. But it's fairly easy to establish a unifying theme for the web pages of a small website, such as yours. And you can do it all by yourself; a common header and footer is all that's usually necessary. Naturally, it would make immense sense if you could design a template for headers and footers once and use it on all of your web pages. A template isn't all that revolutionary a concept. You've probably built a template in your word processor for your letterhead or for a boilerplate, for example. Many widely-used applications save you the trouble of repetitive formatting by allowing you to make templates. Therefore, it shouldn't come as a great surprise to you that you can build page templates in Office Live Small Business as well. A web page template in Office Live Small Business has two components: information and design. The information component consists of the text and images that are specific to your website, such as your company name, logo, slogan, copyright notice, and so on. The design component deals with choosing the right font, colors, background pictures, and other such visual elements. Once you configure the necessary settings, you'll have a shell, so to say, which will appear around the content on your web pages. Choosing a title for your website A website's title is usually the name of the business it represents. My little company is called Acxede, for example. Therefore, it's logical that my site's title mimics my company's name. Now, there's only so much real estate available on a web page for the title. Because Acxede happens to be a short name, it can fit into most page layouts. But if your business is incorporated as Anthony Donaldson's Vacuum Cleaner Sales, Service, and Rentals Incorporated, this scheme of things breaks down. What do you do then? A good rule of thumb is to echo whatever name is on your business card. Unless your business card is the size of a postcard, you'd have shortened the name to something like Anthony Donaldson Inc. Use that as your site's title. People often want to set their domain name as their site's title. Because my company is called Acxede, it would, of course, be terrific to have acxede.com as my domain name. And I do. Unfortunately, not everyone is that lucky. More likely than not, the domain name you want is already taken. Let's say that you're Sam and you own a deli called, naturally, Sam's Deli. Everyone just calls it "Sam's". It wouldn't be unreasonable for you to want the domain name sams.com. The trouble is that Sam's Publishing has already snapped it up. Okay, so how about samsdeli.com? Nope. Another Sam owns it. So you're forced to settle for a domain name that doesn't echo the name of your business; something like samsfreshfood.com, perhaps. Nevertheless, your website's title should still say "Sam's Deli" because that's the name of your business, no matter what domain name you ultimately settle on. Now that you know more about setting a website's title than you ever wanted to, let's get around to doing the honors. Time for action – setting the site title Pull down the Design Site menu from the Page Manager toolbar and select Design site. A new window opens, displaying the Microsoft Office Live Small Business Web Design Tool web page with Site Designer as the active tab. Click on the Header button on the ribbon. The Customize Header dialog opens. Replace the text Welcome to my site in the gray box in the Site Title section with your site's title. I'm going to set it as The Office Live Guide for the site that I'm building—this article's companion site. Pull down the select options for the font face just above the title. You'll see a choice of seven fonts: Arial, Courier New, Georgia, Tahoma, Times New Roman, Trebuchet MS, and Verdana. Why only seven? After all, Microsoft Word seems to have a hundred. The reason is that in the Web's architecture, the task of displaying a given font is delegated to your browser. Not every browser can display every font. If a browser can't display a font that you've specified, it displays one that it thinks is right. Such a substitution might distort your web page. But these seven fonts are, more or less, the least common denominator; most browsers support them. Therefore, the chances of your web pages being distorted are quite slim if you choose one of these seven. So which of these seven should you choose? Follow this two step process: If one of the fonts in the list looks like the font on your letterhead or the sign above your office, choose that one. Not even close? Choose either Georgia or Verdana. Most fonts, such as Arial or Times New Roman, came to computer displays from the world of print. They were designed to look good on paper. Making a font look good on paper is relatively easy because text is printed on paper in very high resolution. On a monitor, however, pixels of resolution are at a premium. Besides, the resolution can vary from monitor to monitor. Therefore, text will look better onscreen if you use fonts that are designed specifically for monitors rather than using fonts that are grandfathered from the print world. Georgia and Verdana are designed specifically for monitors and so they're the ideal candidates for the text on your web pages. Set the font you've chosen. I've set it to Georgia. Next, pull down the adjacent select options for the font size. You'll see a choice of seven font sizes. They're conveniently numbered from 1 to 7. Size 1 is the smallest and size 7 is the largest. For some inexplicable reason, people often choose a size that's either too big or too small. I recommend size 5 for the title. That's just about right for most websites built with Office Live Small Business. One thing you've got to remember, though, is that: Thou shalt use Georgia or Verdana in size 5 for your site's title is not the eleventh commandment. I've suggested these settings because, in my experience, they are just about right for most websites built with Office Live Small Business. They make the header appear proportionate to the text on the web pages. But, they may not be right for your site if its title or slogan is either too long or too short. Come back and experiment with the font face or size of the header elements if your pages look out-of-whack after you finish building your website. Set the font size you've chosen. I've set it to 5. Although you can choose a color for the title. The choice of color depends on other layout options as well. Although you can make the title bold, italicize it, or underline it, you'd do well by avoiding the temptation. Depending on a combination of factors such as the font face, font size, and resolution of a visitor's monitor, these special effects can make the text quite difficult to read. The last thing you want to do is to inadvertently make the title of your site unreadable. Your Customize Header dialog should now look something like this: Keep the window open; you might as well set a slogan for your website while you're there. What just happened? You just took the first baby steps towards building your website! Agreed, all you did was set the site title—not exactly the kind of stuff that you'd write home about, but it's a fine start nevertheless. Your site's title and slogan, which you'll set in the following section, play an important role in helping people find your site from search engines. Choosing a slogan for your website An Office Live Small Business website's slogan is really just its tagline; so I'll use the terms interchangeably. Successful businesses use catchy taglines to reinforce their brands. What comes to mind when you hear "Just do it!"? Nike. How about "Don't Leave Home Without It"? American Express. And "Eat Fresh"? Subway, of course. See? People subconsciously associate taglines with brands or products. Come to think of it, the whole point of building your website is to reinforce your brand. Naturally, a good tagline will go a long way towards achieving your goal. While a tagline sounds like a no-brainer, not every business has one. If you don't, you're not alone. After all, you can't spend a few million dollars to come up with one the way Nike, American Express, and Subway probably did. But if you happen to have one, it's a good idea to immortalize it on your website. And if you don't, now's the time to scratch the creative side of your brain and think of one. But don't despair if you can't. You may be able to substitute a description of your business for the tagline with good effect. If you've shortened Anthony Donaldson's Vacuum Cleaner Sales, Service, and Rentals Incorporated, to Anthony Donaldson Inc., your tagline can be Vacuum Cleaner Sales, Service, and Rentals, or something to that effect. It may not be as potent as Nike's tagline, but at least it tells people what Anthony Donaldson does for a living. Time for action – setting the site slogan Replace the text Add your site slogan here! in the gray box in the Site Slogan section with your site slogan. I'm going to set it to Build your own website in a day! Pull down the select options for the font face just above the title and set it to the font you've chosen. I'm setting it to Georgia again. Next, pull down the adjacent select options for the font size and set it to 4. Why 4? I didn't pull the number 4 out of a hat. I chose it because size 4 is a size smaller than size 5, the size of my site's title. If your Site Title is set to a size other than five, choose one size smaller than the size of your site's title. As with the Site Title, don't select a color for your Site Slogan. And stay away from the B, I, and U buttons as well. Your Customize Header dialog should now look something like this: Click the OK button at the bottom of the Customize Header dialog. It closes and you arrive back at the Site Designer. Click the View button in Site Designer. You'll be using the View button, and the Save button next to it, quite often. When I want you to click the Save button, I'll simply tell you to save your work. If I want you to click the View button, I'll tell you to preview your website. Whenever I refer to these buttons, directly or indirectly, you now know where to find them. A pop-up message asks you whether you want to save your changes. Click OK. A preview of your site comes up in a new browser window. Notice that the site now displays the new title and slogan, as shown in the following screenshot: After you've admired your handiwork long enough, close the preview window and return to Site Designer. What just happened? You added a slogan to go along with your site's title. Why so much fuss about simply setting the title and slogan? In a word: findability. Findability? I didn't make that word up, by the way. Honest! Well-known web usability expert Jakob Nielsen did. A site is findable if it's easy to find; that is, it appears near the top of search engine results when a person searches for relevant terms. You can find great advice about building usable websites on Mr. Nielsen's website at http://www.useit.com Search engines attach considerable importance to the title of a web page. It tells them what the page is all about. But that's not the only thing they look at. They also try to determine whether the text on the web page has anything to do with its title. Because the slogan appears on every page with the title, a strong correlation between the two and their correlation with the text on your web pages will determine your web page's ranking in search results. To put it mildly, if your site's title and slogan stink, so will its ranking in the search results! Therefore, don't take these settings lightly. If you don't put enough thought behind them, you risk relegating your web pages to obscurity. Have a go hero – experiment with the site title and site slogan Although I handed down the edicts on setting the font face and the font size for the Site Title and the Site Slogan, by no means are my recommendations cast in stone. Although following my recommendations will save you a good deal of time and heartache, you'll do a disservice to yourself if you don't experiment on your own. Depending on how long your Site Title or Site Slogan is, you might find a better combination of these settings if you try out a few variations. Here are a few suggestions: If you've set your font to Georgia, you might want to try Verdana. How about Georgia for the Site Title and Verdana for the Site Slogan? Or vice-versa? Although I've recommended that you set the font size for your Site Slogan a size smaller than the font size for your Site Title, you might want to try a font size two sizes smaller than the size for your Site Title, especially if you've set different fonts for the title and the slogan. Verdana is a wide font. If your site title or slogan has several wide letters like W and M, Verdana may not be the right choice. You might want to try a similar but narrower font, such as Arial. Try out a few variations and settle on one that you like the best. You might want to get an opinion from a friend or a co-worker. And remember, you can come back and play with these settings any time. Pop quiz 1 Which of the following attributes make your website more "findable"? Your site's header Your site's title Your site's font setting Your site's slogan The answer to this quiz is given at the end of this article.
Read more
  • 0
  • 0
  • 1886

article-image-extending-tabs-jquery-ui-17
Packt
30 Nov 2009
4 min read
Save for later

Extending Tabs in jQuery UI 1.7

Packt
30 Nov 2009
4 min read
  The tab widget defines a series of useful options that allow you to add callback functions to perform different actions when certain events exposed by the widget are detected. The following table lists the configuration options that are able to accept executable functions on an event: Property Usage add Execute a function when a new tab is added. disable Execute a function when a tab is disabled. enable Execute a function when a tab is enabled. load Execute a function when a tab's remote data has loaded. remove Execute a function when a tab is removed. select Execute a function when a tab is selected. show Execute a function when the content section of a tab is shown.   Each component of the library has callback options (such as those in the previous table), which are tuned to look for key moments in any visitor interaction. Any function we use with these callbacks are usually executed before the change happens. Therefore, you can return false from your callback and prevent the action from occurring. In our next example, we will look at how easy it is to react to a particular tab being selected using the standard non-bind technique. Change the final <script> element in tabs7.html so that it appears as follows: <script type="text/javascript"> $(function(){ function handleSelect(event, tab) { $("<p>").text("The tab at index " + tab.index +  " was selected").addClass("status-message ui-corner-all") .appendTo($(".ui-tabs-nav","#myTabs")).fadeOut(5000); } var tabOpts = { select:handleSelect }; $("#myTabs").tabs(tabOpts); });</script> Save this file as tabs8.html. We also need a little CSS to complete this example, in the <head> of the page we just created add the following <link> element: <link rel="stylesheet" type="text/css" href="css/tabSelect.css"> Then in a new page in your text editor add the following code: .status-message { position:absolute; right:3px; top:4px; margin:0; padding:11px 8px 10px; font-size:11px; background-color:#ffffff; border:1px solid #aaaaaa;} Save this file as tabSelect.css in the css folder. We made use of the select callback in this example, although the principle is the same for any of the other custom events fired by tabs. The name of our callback function is provided as the value of the select property in our configuration object. Two arguments will be passed automatically to the function we define by the widget when it is executed. These are the original event object and a custom object containing useful properties from the tab which is in the function's execution context. To find out which of the tabs was clicked, we can look at the index property of the second object (remember these are zero-based indices). This is added, along with a little explanatory text, to a paragraph element that we create on the fly and append to the widget header. In this example, the callback function was defined outside the configuration object, and was instead referenced by the object. We can also define these callback functions inside our configuration object to make our code more efficient. For example, our function and configuration object from the previous example could have been defined like this: var tabOpts = { select: function(event, tab) { $("<p>").text("The tab at index " + tab.index + " was selected") .addClass("status-message ui-corner-all").appendTo($(".ui-tabs-nav", "#myTabs")).fadeOut(5000); }} Check tabs8inline.html in the code download for further clarification on this way of using event callbacks. Whenever a tab is selected, you should see the paragraph before it fades away. Note that the event is fired before the change occurs. Binding to events Using the event callbacks exposed by each component is the standard way of handling interactions. However, in addition to the callbacks listed in the previous table we can also hook into another set of events fired by each component at different times. We can use the standard jQuery bind() method to bind an event handler to a custom event fired by the tabs widget in the same way that we could bind to a standard DOM event, such as a click. The following table lists the tab widget's custom binding events and their triggers: Event Trigger tabsselect A tab is selected. tabsload A remote tab has loaded. tabsshow A tab is shown. tabsadd A tab has been added to the interface. tabsremove A tab has been removed from the interface. tabsdisable A tab has been disabled. tabsenable A tab has been enabled.
Read more
  • 0
  • 0
  • 2255

article-image-creating-text-logo-blender
Packt
30 Nov 2009
3 min read
Save for later

Creating a Text Logo in Blender

Packt
30 Nov 2009
3 min read
Here is the final image we will be creating: Let us begin! We are going to begin with the default settings in Blender, as you can see below. Creating the Background To create the background we are going to be adding a plane and then making a series of holes in it. This will then act as the basis for our entire background when we replicate the plane with two array modifiers and a mirror modifier. Go ahead and: Add a plane from top view by hitting spacebar > Add > Mesh > Plane Subdivide that plane by hitting W > Subdivide Multi > 3 divisions This will give us a grid that we can punch a few holes in with relative ease. Next, go ahead and select the vertices shown below: Then: Press x > Delete Faces to delete the selected faces Next select the inside edges of the upper-left hole by clicking on one of the edges with alt > RMB You may then hit e > esc to extrude and cancel the transform that extruding activates. Next you can hit cntrl + shift + s > 1 for the To Sphere command, this will modify the extruded vertices into a perfect circle. Check out the result below: From here we can duplicate this circle and the surrounding faces into place of all the other holes such that we have a mesh that will repeat without any gaps. Think of it as a tilable texture but in mesh form! As you will surely notice, on the bottom left and bottom right you will only duplicate have of the circle. After duplicating each piece and moving it into place it will be necessary to remove all the duplicate vertices: Select everything with a Press w > Remove Doubles Moving on, before we can replicate our pattern we need to move it such that the bottom, left corner is at the center point of our grid. If you used the default size for the plane then you can simply select everything and hold down cntrl while moving it to lock it to the grid. Now, for our final background we want the holes in our mesh to have some depth, to do this all we need to do is select each of the inner circles and extrude them down along the Z-axis as you can see in the image below: Now is where things begin to get really fun! We are going to now add two array modifiers to replicate our pattern. The first array will repeat the pattern along the X-axis to the right, and the second array will replicate the pattern down along the Y-axis. We will then you a use mirror modifier along the X and Y axis to duplicate the whole pattern across the axis’. First go to the Editing Buttons and click on Add Modifier > Array Increase the count to 10 Click Merge Add a second Array and change the count to 3 Click Merge Change the X Offset to 0 and the Y Offset to 1.0 This will leave you with 1/4 of our final pattern. To complete it: Add a Mirror Modifier Click Y in addition to the default X, this will mirror it both up and across the central axis. Add a Subsurf modifier to smooth out the mesh Select everything with a and then press w > Set Smooth Setting the mesh to smooth will likely cause some normal issues (black spots) in which case you need to hit cntrl + n > Recalculate Normals while everything is selected.
Read more
  • 0
  • 0
  • 3785

article-image-report-components-nav-2009-part-1
Packt
30 Nov 2009
13 min read
Save for later

Report components in NAV 2009: Part 1

Packt
30 Nov 2009
13 min read
Report components overview What we generally refer to as the report or report object is technically referred to as a Report Description. The Report Description is the information describing the layout for the planned output and processing logic to be followed when processing the data. Report Descriptions are stored in the database in the same way as other table or form/page descriptions. As with pages, we will use the term "report" whether we mean the output, the description, or the object. Reports share some attributes with pages including aspects of the designer, features of various controls, some triggers, and even some of the properties. Where those parallels exist, we should take notice of them. The consistency of any toolset, including NAV, makes it easier to learn and to use. This applies to developers as well as to the users. The overall structure of an NAV RTC Report consists of the following elements. Any particular report may utilize only a small number of the possible elements (for example, Section Triggers are not used by the RTC), but many different combinations are feasible and logical. Report Properties Report Triggers Data Items Data Item Properties Data Item Triggers Data Item Sections Section Triggers Data Field Controls Visual Studio Layout VS Controls VS Control Properties Request Page Request Page Properties Request Page Triggers Request Page Controls Request Page Control Properties Request Page Control Triggers The components of a report description A report description consists of a number of primary components, each of which in turn is made up of secondary components. The primary components Report Properties and Triggers and Data Item Properties and Triggers define the data flow and overall logic for processing the data. These are all designed in the C/SIDE Report Designer. A subordinate set of primary components, Data Field Controls and Working Storage, are defined within the DataItem Sections, which are also designed in the C/SIDE Report Designer. Data Fields are defined in this article as the fields contained in the DataItems (that is application tables). Working Storage (also referred to as Working Data) fields are defined in this article as the data elements that are created within a report (or other object) for use in that object. Working Storage data elements are not permanently stored in the database. These components constitute the data elements that will be made available to the Visual Studio Report Designer (VS RD). The VS RD cannot access any data elements that have not been defined within the Report Sections (each of which must be associated with a DataItem). The Report Layout  is designed in the VS RD using the data elements made available to the VS RD by the C/SIDE RD, defined in the DataItem Sections. The Report Layout includes the Page Header, Body, and Page Footer. In most cases, the Body of the report is based on a layout table. Note that the VS RD layout table is a data grid used for layout purposes and is not the same as a table of data stored in the NAV database. This terminology is confusing. When the NAV Help files regarding reports refer to a table, you will have to read very carefully to determine which meaning for "table" is intended. Within the Report Body, there can be none, one, or more Detail rows. There can also be Header and Footer rows. The Detail rows are the definition of the primary, repeating data display. A report layout may also include one or more Group rows, used to group and total data that is displayed in the Detail row(s). All of the report formatting is controlled in the Report Layout. The Font, field positioning, visibility options (including expand/collapse sections), dynamic sorting, and graphics are all defined as part of the Report Layout. The same is true for pagination control, headings and footers, some totaling, column-width control, and a number of other display details. Of course, if the display target changes dramatically in the future versions of NAV, for example, from a desktop workstation display to a browser supporting cellular phone, then the appearance of the Report Layout will change dramatically as well. One of the advantages of SSRS is to support such a level of flexibility. But, if you expect that degree of variability in output devices, you will have design accordingly. There is another primary functional component of a report description, the Request Page. It displays as a page when a report is invoked. The purpose of the Report Request Page is to allow users to enter information to control the report. Control information entered through a Request Page may include filters, control dates, other control parameters, and specifi cations as well as defining which available formatting or processing options to use for this instance of the report (that is for this run). The Request Page appears once at the beginning of a report at run time. Report Data Flow One of the principal advantages of the NAV report is its built-in data flow structure. At the beginning of any report, you must define the data item(s), the tables that the report will process. It is possible to create a working report that has no data items, but that situation normally calls for a codeunit to be used. There are rare exceptions to this, such as a report created for the purposes of processing only, perhaps to control branching or choice of objects to be run subsequently. In that case, you might have no data item, just a set of logic whose data flow is totally self-controlled. Normally in a report, NAV automatically creates a data flow process for each data item. This automatically created data flow provides specific triggers and processing events: Preceding the data For each record of the data Following the end of the data The underlying "black-box" report logic (the part we can't see or affect) loops through the named tables, reading and processing one record at a time. That flow is automatic, that is we don't have to program it. Therefore, any time we need a process that steps through a set of data one record at a time, it is quite likely we will use a report object. If you've ever worked with some of the legacy report writers or the RPG programming language, it is likely that you will recognize this looping behavior. That recognition may allow you to understand how to take advantage of NAV reports more quickly. The reference to a database table in a report is referred to as a Data Item. One of the capabilities of the report data flow structure is the ability to nest data items. If Data Item 2 is nested within Data Item 1 and related to Data Item 1, then for each record in Data Item 1, all of the related records in Data Item 2 will be processed. The next screenshot shows the data item definition screen. This example uses tables from our ICAN system. The design is for a report to list all the Gifts by Donor for each Donor Type. Thus Donor Type is the primary table (DataItem1). For each Donor Type, we want to list all the Donors that have given Gifts to ICAN (DataItem2). And for each Donor of each Donor Type, we want to list their Gifts which are recorded in the Gift Ledger (DataItem3). On the Data Item screen, we initially enter the table name Donor, as you see in the following screenshot. The Data Item Name, to which the C/AL code will refer, is DataItem1 in our example here. When we enter the second table, Donor, then we click on the right arrow at the bottom of the screen. That will cause the selected data item to be indented relative to the data item above (the "superior" data item). That causes the nesting of the processing of the indented data item within the processing of the superior data item. In this instance, we have renamed the Data Items just for the purpose of our example, in order to illustrate data flow within a report. The normal default behavior would be for the Name in the right column to default to the table name shown in the left column (for example, the Name for Donor would be displayed as < Donor > by default). This default Data Item Name would only need to be changed if the same table appeared twice within the Data Item list. For the second instance of Donor, for example, you could simply give it the Name Donor2. For each record in the superior data item, the indented data item will be fully processed. Which records are actually processed in the indented table will depend on the filters, and the defined relationships between the superior and indented tables. In other words, the visible indentation is only part of the necessary definition. We'll review the rest of it shortly. For our example, we enter a third table, Gift Ledger, and enter our example name of DataItem3. The following chart shows the data flow for this Data Item structure. The chart boxes are intended to show the nesting that results from the indenting of the Data Items in the preceding screenshot. The Donor Data Item is indented under the Donor Type Data Item. That means for every processed Donor Type record, all of the selected Donor records will be processed. That same logic applies to the Donor records and Gift Ledger records (that is, for each Donor record processed, all selected Gift records are processed). The blocks visually illustrate how the data item nesting controls the data flow. As you can see, the full range of processing for DataItem2 occurs for each DataItem1 record. In turn, the full range of processing for DataItem3 occurs for each DataItem2 record. In Classic Client reporting, the formatting and output for each record processed happened in sequence as the last step in processing that record. In other words, once a record was read and processed, it was rendered for output presentation before the next record was read. In the NAV 2009 Role Tailored Client, report processing occurs in two separate steps, the first tied primarily to what has been designed in the Classic RD, the second tied to what has been designed in the VS RD. The processing of data represented in the preceding image occurs in the first step, yielding a complete dataset containing all the data that is to be rendered for output. This intermediate dataset is a flattened version of the hierarchically structured dataset represented in the Classic RD. Each record in the new dataset contains all the fields from the sections (parent, child, grandchild, and so on) "de-normalized" into a completely flat data structure. This structure also includes Grouping, Filtering, Formatting, MultiLanguage, and other control information required to allow the Visual Studio Report Viewer to properly render the defined report. That flattened dataset is then handed off to the Visual Studio Microsoft Report Viewer. The Microsoft Report Viewer provides the new NAV 2009 reporting capabilities such as various types of graphics, interactive sorting and expand/collapse sections, output to PDF and Excel, and other advanced reporting features based on RDLC created by the VS RD design work. The elements of a report Earlier we reviewed a list of the elements of a Report object. Now we're going to learn about each of those elements. Our goal here is to understand how the pieces of the report puzzle fit together to form a useful, coherent whole. Following that, we will do some development work for our ICAN system to apply some of what we've reviewed. Report properties The Classic RD Report Properties are shown in the following screenshot. Some of these properties have essentially the same purpose as those in pages and other objects. Many of these Report Property settings only apply to Classic reports and are replaced by equivalent Report Properties in the Visual Studio RD. ID: The unique report object number. Name: The name by which this report is referred to within C/AL code. Caption: The name that is displayed for this report; Caption defaults to Name. CaptionML: The Caption translation for a defined alternative language. ShowPrintStatus: If this property is set to Yes and the ProcessingOnly property is set to No, then a Report Progress window, including a Cancel button, is displayed. When ProcessingOnly is set to Yes, if you want a Report Progress Window, you must create your own dialog box. UseReqForm: Determines if a Request Page should be displayed to allow the user the choice of Sort Sequence and entry of filters and other requested control information. UseSystemPrinter: Determines if the default printer for the report should be the defined system printer, or if NAV should check for a setup-defined User/Report printer definition. ProcessingOnly: This should be set to Yes when the report object is being used only to process data and no report output is to be generated. If this property is set to Yes, then that overrides any other property selections that would apply in a report-generating situation. TransactionType: This can be in one of four basic options: Browse, Snapshot, UpdateNoLocks, and Update. These control the record locking behavior to be applied in this report. The default is UpdateNoLocks. This property is generally only used by advanced developers. Description: This is for internal documentation; it is not used often. TopMargin, BottomMargin, LeftMargin, RightMargin: Does not apply to an RTC report. There are applicable VS RD properties. HorzGrid, VertGrid: Does not apply to an RTC report. VS RD layout has its own grid for control positioning. Permissions: This provides report-specific setting of permissions, which are the rights to access data, subdivided into Read, Insert, Modify, and Delete. This allows the developer to define report and processing permissions that override the user-by-user permissions security setup. The following printer-specific properties do not apply to an RTC report. Several can be overridden by user selections made at run time. Orientation: There is an applicable VS RD property PaperSize: There is an applicable VS RD property PaperSourceFirstPage, PaperSourceOtherPages: This is controlled in Page Setup for RTC reports DeviceFontName: This is controlled by the Report Viewer The Visual Studio RD Report Properties are shown in the following screenshot: Report triggers The following screenshot shows the Report triggers available in a report: Documentation(): Documentation is technically not a trigger, but a section which serves only the purpose of containing whatever documentation you care to put there. No C/AL code is in a Documentation section. You have no format restrictions, other than common sense and your defined practices. OnInitReport(): It executes once when the report is opened. OnPreReport(): It executes once after the Request Page completes. All the Data Item processing follows this trigger. OnPostReport(): If the report is completed normally, this trigger executes once at the end of all of the other report processing. All the Data Item processing precedes this trigger. OnCreateHyperlink(): It does not apply to an RTC report. OnHyperlink(): It does not apply to an RTC report. There are general explanations of Report Triggers in the online C/SIDE Reference Guide (Help); you should also review those explanations.
Read more
  • 0
  • 0
  • 3411

article-image-facelets-components-jsf-12
Packt
30 Nov 2009
12 min read
Save for later

Facelets Components in JSF 1.2

Packt
30 Nov 2009
12 min read
One of the more advanced features of the Facelets framework is the ability to define complex templates containing dynamic nested content. What is a template?The Merriam-Webster dictionary defines the word "template" as "a gauge, pattern, or mold (as a thin plate or board) used as a guide to the form of a piece being made" and as "something that establishes or serves as a pattern." In the context of user interface design for the Web, a template can be thought of as an abstraction of a set of pages in the web application.A template does not define content, but rather it defines placeholders for content, and provides the layout, orientation, flow, structure, and logical organization of the elements on the page. We can also think of templates as documents with "blanks" that will be filled in with real data and user interface controls at request time. One of the benefits of templating is the separation of content from presentation, making the maintenance of the views in our web application much easier. The <ui:insert> tag has a name attribute that is used to specify a dynamic content region that will be inserted by the template client. When Facelets renders a UI composition template, it attempts to substitute any <ui:insert> tags in the Facelets template document with corresponding <ui:define> tags from the Facelets template client document. Conceptually, the Facelets composition template transformation process can be visualized as follows: In this scenario, the browser requests a Facelets template client document in our JSF application. This document contains two <ui:define> tags that specify named content elements and references a Facelets template document using the <ui:composition> tag's template attribute. The Facelets template document contains two <ui:insert> tags that have the same names as the <ui:define> tags in the client document, and three <ui:include> tags for the header, footer, and navigation menu. This is a good example of the excellent support that Facelets provides for the Composite View design pattern. Facelets transforms the template client document by merging any content it defines using <ui:define> tags with the content insertion points specified in the Facelets template document using the <ui:insert> tag. The result of merging the Facelets template client document with the Facelets template document is rendered in the browser as a composite view. While this concept may seem a bit complicated at first, it is actually a powerful feature of the Facelets view defi nition framework that can greatly simplify user interface templating in a web application. In fact, the Facelets composition template document can itself be a template client by referencing another composition template. In this way, a complex hierarchy of templates can be used to construct a flexible, multi-layered presentation tier for a JSF application. Without the Facelets templating system, we would have to copy and paste view elements such as headers, footers, and menus from one page to the next to achieve a consistent look and feel across our web application. Facelets templating enables us to define our look and feel in one document and to reuse it across multiple pages. Therefore, if we decide to change the look and feel, we only have to update one document and the change is immediately propagated to all the views of the JSF application. Let's look at some examples of how to use the Facelets templating feature. A simple Facelets template The following is an example of a simple Facelets template. It simply renders a message within an HTML <h2> element. Facelets will replace the "unnamed" <ui:insert> tag (without the name attribute) in the template document with the content of the <ui:composition> tag from the template client document. template01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Facelets template example</title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><h2><ui:insert /></h2></body></html> A simple Facelets template client Let's look at a simple example of Facelets templating. The following page is a Facelets template client document. (Remember: you can identify a Facelets template client by looking for the existence of the template attribute on the <ui:composition> tag.) The <ui:composition> tag simply contains the text Hello World. templateClient01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">Hello World</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01.jsf. Another simple Facelets template client The following Facelets template client example demonstrates how a template can be reused across multiple pages in the JSF application: templateClient01a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">How are you today?</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01a.jsf: A more complex Facelets template The Facelets template in the previous example is quite simple and does not demonstrate some of the more advanced capabilities of Facelets templating. In particular, the template in the previous example only has a single <ui:insert> tag, with no name attribute specified. The behavior of the unnamed <ui:insert> tag is to include any content in the referencing template client page. In more complex templates, multiple <ui:insert> tags can be used to enable template client documents to defi ne several custom content elements that will be inserted throughout the template. The following Facelets template document declares three named <ui:insert> elements. Notice carefully where these tags are located. template02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title><ui:insert name="title" /></title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><ui:include src="/WEB-INF/includes/header.jsf" /><h2><ui:insert name="header" /></h2><ui:insert name="content" /><ui:include src="/WEB-INF/includes/footer.jsf" /></body></html> In the following example, the template client document defines three content elements named title, header, and content using the <ui:define> tag. Their position in the client document is not important because the template document determines where this content will be positioned. templateClient02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Hello World</ui:define><ui:define name="content">Page content goes here.</ui:define></ui:composition><ui:debug /></body></html> The following screenshot displays the result of a more complex Facelets UI composition template transformation when the browser requests the page named templateClient02.jsf. The next example demonstrates reusing a more advanced Facelets UI composition template. At this stage, we should have a good understanding of the basic concepts of Facelets templating and reuse. templateClient02a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body>Facelets Components[ 78 ]<ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Thanks for visiting!</ui:define><ui:define name="content">We hope you enjoyed our site.</ui:define></ui:composition><ui:debug /></body></html> The next screenshot displays the result of the Facelets UI composition transformation when the browser requests templateClient02a.jsf. We can follow this pattern to make a number of JSF pages reuse the template in this manner to achieve a consistent look and feel across our web application. Decorating the user interface The Facelets framework supports the definition of smaller, reusable view elements that can be combined at runtime using the Facelets UI tag library. Some of these tags, such as the <ui:composition> and <ui:component> tags, trim their surrounding content. This behavior is desirable when including content from one complete XHTML document within another complete XHTML document. There are cases, however, when we do not want Facelets to trim the content outside the Facelets tag, such as when we are decorating content on one page with additional JSF or HTML markup defi ned in another page. For example, suppose there is a section of content in our XHTML document that we want to wrap or "decorate" with an HTML <div> element defined in another Facelets page. In this scenario, we want all the content on the page to be displayed, and we are simply surrounding part of the content with additional markup defined in another Facelets template. Facelets provides the <ui:decoration> tag for this purpose. Decorating content on a Facelets page The following example demonstrates how to decorate content on a Facelets page with markup from another Facelets page using the <ui:decoration> tag. The <ui:decoration> tag has a template attribute and behaves like the <ui:composition> tag. Facelets templating typically uses the <ui:composition>. It references a Facelets template document that contains markup to be included in the current document. The main difference between the <ui:composition> tag and the <ui:decoration> tag is that Facelets trims the content outside the <ui:composition> tag but does not trim the content outside the <ui:decoration> tag. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:decorate example</title><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body>Text before will stay.<ui:decorate template="/WEB-INF/templates/box.jsf"><span class="header">Information Box</span><p>This is the first line of information.</p><p>This is the second line of information.</p><p>This is the third line of information.</p></ui:decorate>Text after will stay.<ui:debug /></body></html> Creating a Facelets decoration Let's examine the Facelets decoration template referenced by the previous example. The following source code demonstrates how to create a Facelets template to provide the decoration that will surround the content on another page. As we are using a <ui:composition> tag, only the content inside this tag will be used. In this example, we declare an HTML <div> element with the "box" CSS style class that contains a single Facelets <ui:insert> tag. When Facelets renders the above Facelets page, it encounters the <ui:decorate> tag that references the box.jsf page. The <ui:decorate> tag will be merged together with the associated decoration template and then rendered in the view. In this scenario, Facelets will insert the child content of the <ui:decorate> tag into the Facelets decoration template where the <ui:insert> tag is declared. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Box</title></head><body><ui:composition><div class="box"><ui:insert /></div></ui:composition></body></html> The result is that our content is surrounded or "decorated" by the <div> element. Any text before or after the <ui:decoration> is still rendered on the page, as shown in the next screenshot: The included decoration is rendered as is, and is not nested inside a UI component as demonstrated in the following Facelets debug page:
Read more
  • 0
  • 0
  • 4033

article-image-linux-e-mail-busting-spam-spamassassin
Packt
30 Nov 2009
13 min read
Save for later

Linux E-mail: Busting Spam with SpamAssassin

Packt
30 Nov 2009
13 min read
Spam, or unsolicited commercial e-mail (UCE) as it is sometimes called, is the scourge of the Internet. Spam has increased relentlessly over the last ten years and now accounts for over half of all Internet bandwidth. One in six consumers have acted on spam e-mails, so there is a strong business case for keeping spam out of your users' inboxes. There are a variety of different spam solutions, ranging from outsourcing your spam entirely to no action at all. However, if you have your own e-mail server, you can add spam filtering very easily. SpamAssassin is a very popular open source anti-spam tool. It won a Linux New Media Award-2006 as the "Best Linux-based Anti-spam Solution", and is considered by many to be the best free, open source, anti-spam tool, and better than many commercial products. In fact, several commercial products and services are based on SpamAssassin or previous versions of it. Why filter e-mail If you don't receive any spam, there may be no need to filter spam. However, once one spam message has been received, it is invariably followed by many more. Spammers can sometimes detect if a spam e-mail is viewed, using techniques such as Web bugs, which are tiny images in HTML e-mails that are fetched from web servers, and then know that an e-mail address is valid and vulnerable. If spam is filtered, the initial e-mail may never get seen, and consequently the spammer may not then target the e-mail address with further spam. Despite legal efforts against spam, it is actually on the increase. In Europe and the US, the recent legislation against spam (Directive 2002/58/EC and bill number S.877 respectively) has had little effect and spam is still on the increase in both regions. The main reason for this is that spam is a very good business model. It is very cheap to send spam, as little as one thousandth of a cent per e-mail, and it takes a very low hit rate before a profit is made. The spammer needs to turn just one spam in a hundred thousand or so into a sale to make a profit. As a result, there are many spammers and spam is used to promote a wide range of goods. Spamming costs are also negligible due to use of malware that uses innocent computers to send spam on their behalf. In contrast, the costs of spam to the recipient are remarkably high. Estimates have varied, from 10 cents per spam received, through 1,000 dollars per employee per year, up to a total cost of 140 billion dollars globally in 2007 alone. This cost is mainly labor—distracting people from their work by clogging their inboxes and forcing them to deal with many extra e-mails. Spam interferes with day-to-day work and can include material that is offensive to most people. Companies have a duty to protect their employees from such content. Spam filtering is a very cheap way of minimizing the costs and protecting the workforce. Spam is a moving target Spam isn't static. It changes on a day-to-day basis, as spammers add new methods to their arsenal and anti-spammers develop countermeasures. Due to this, the anti-spam tools that work best are those that are updated frequently. It's a similar predicament to antivirus software—virus definitions need to be updated regularly or new viruses won't be detected. SpamAssassin is regularly updated. In addition to new releases of the software, there is a vigorous community creating, critiquing, and testing new anti-spam rules. These rules can be downloaded automatically for up-to-date protection against spam. Let's discuss some of the measures used by SpamAssassin to fight spam: Open relays: These are e-mail servers that allow spammers to send e-mails even though they are not connected to the owner of the server in any way. To counter this, the anti-spam community has developed blocklists, also known as blacklists, which can be used by anti-spam software to detect spam. Any e-mail that has passed through a server on a blocklist is treated more suspiciously than one that has not. SpamAssassin uses a number of blocklists to test e-mails. Keyword filters: These are useful tools against spam. Spammers tend to repeat the same words and phrases again and again. Rules to detect these phrases are used extensively by SpamAssassin. These make up the bulk of the tests, and the user community rules mentioned previously is normally of this form. They allow specific words, phrases, or sequences of letters, numbers, and punctuation to be detected. Blacklists and whitelists: These are used to list known senders of spam and sources of good e-mail respectively. E-mails from an address on a blacklist are probably spam and are treated accordingly, while e-mails from addresses on a whitelist will be less likely to be treated as spam. SpamAssassin allows the user to enter blacklists and whitelists manually, and also builds up an automatic whitelist and blacklist based on the e-mails that it processes. Statistical filters: These are automated systems that give the probability that an e-mail is spam. This filtration is based on what the filter has seen previously as both spam and non-spam. They generally work by finding words that are present in one type of e-mail but not the other, and using this knowledge to determine which type a new e-mail is. SpamAssassin has a statistical filter called the Bayesian filter that can be very effective in improving detection rates. Content databases: These are mass e-mail detection systems. A lot of e-mail servers receive and submit e-mails to central servers. If the same e-mail is sent to thousands of recipients, it is probably a spam. The content databases prevent confidential e-mails from being sent to the server, by using a technique called hashing that also lowers the amount of data sent to the server. SpamAssassin can integrate with several content databases, notably Vipul's Razor (http://razor.sourceforge.net), Pyzor (http://sourceforge.net/apps/trac/pyzor/), and the Distributed Checksum Clearinghouse, that is, DCC (http://www.rhyolite.com/dcc/). URL blocklists: These are similar to open relay blocklists, but list the websites used by spammers. In nearly all spams, a web address is given. A database of these is built so that spam e-mails can be quickly detected. This is a very efficient and effective tool against spam. By default, SpamAssassin uses Spam URI Realtime BlockLists (SURBLs), without any further configuration required. Spam filtering options Spam can be filtered on the server or the client. The two approaches are explained next. In the first scenario, spam is filtered on the client. Mail is processed by the MTA. The e-mail is then placed in the appropriate user's inbox. The e-mail client reads all new e-mail from the inbox. The e-mail client then passes the e-mail to the filter. When the filter returns the results, the client can display the valid e-mail and either discard spam or file it in a separate folder. In this approach, the spam filtering is always done by the client and is always done when new e-mail is processed. Often when the user may be present, so he or she may either experience a delay before e-mail is visible or there may be a period where spam e-mail is present in the inbox before the client software can filter the spam from view. The amount of spam filtering that can be performed on the client may be limited. In particular, the network tests such as open relay blocklists or SURBLs might be too time consuming or complex to perform on the user's PC. As spam is a moving target, updating many client PCs can become a difficult administrative task. In the second scenario, the spam filtering is performed on the e-mail server. Incoming e-mail is received by the MTA. It is then passed on to the spam filter. The results are then sent back to the MTA. Depending on the results, the MTA places the e-mail in the appropriate user's inbox (4a), or in a separate folder for spam (4b). The e-mail client accesses e-mails in the user's inbox and it can also access the spam folder if required. This approach has several advantages: The spam filtering is done when the e-mail is received, which may be any time of the day. The user is less likely to be inconvenienced by delays. The server can specialize in spam filtering. It may use external services such as open relay blocklists, online content databases, and SURBLs. Configuration is centralized, which will ease setup (for example, firewalls may need to be configured to use online spam tests) and also maintenance (updating of rules or software). On the other hand, the disadvantages include: A single point of failure now exists. However, with care, a broken spam filtering service can be configured around. If the service is not available, e-mail will still be delivered but spam will not be filtered. All spam must be processed by one service. If this service is not scalable, large volumes of e-mail may affect mail delivery times, resulting in poor or intermittent filtering, or possibly even the loss of e-mail service. Introduction to SpamAssassin Spam filtering actually involves two phases—detecting the spam and then doing something with it. SpamAssassin is a spam detector and it modifies the e-mail it processes by putting in headers to mark whether it is spam. It is up to the MTA or the mail delivery agent in the e-mail system to react to the headers that SpamAssassin creates in an e-mail, to filter it out. However, it's possible that another part of the e-mail system could perform this task. The previous figure gives a schematic representation of SpamAssassin. At the heart of SpamAssassin is its Rules Engine that determines which rules are called. Rules trigger whether the various tests are used, including the Bayesian Filter, the network tests, and the auto-whitelists. SpamAssassin uses various databases to do its work, and these are shown too. The rules and scores are text files. Default rules and scores are included in the SpamAssassin distribution and, as we will see, both system administrators and users can add rules or change the scores of existing rules by adding them to files in specific locations. The Bayesian filter (which is a major part of SpamAssassin, and will be covered later) uses a database of statistical data based on previous spam and non-spam e-mails. The Auto-Blacklist/Whitelist also creates its own database. Downloading and installing SpamAssassin SpamAssassin is slightly different from most of the software that is used in this book. It is written in a language called Perl, which has its own distribution method called CPAN (Comprehensive Perl Archive Network). CPAN is a large website of Perl software (normally, Perl modules), and the term CPAN is also the name of the software used to download those modules and install them. Though SpamAssassin is provided as a package by many Linux distributions, we strongly recommend that you install it from source rather than use a package. This way, you will get the latest version of SpamAssassin rather than the one that was current when your Linux distributer created its release. Most Perl users will build Perl modules using CPAN and experience no difficulties. CPAN can automatically locate and install any dependencies (other components that are required to make the desired component work properly). From a Perl point of view, using CPAN to install Perl modules is like using the rpm or apt-get commands in Linux. The basics are very simple and, once a system is configured, it generally works every time. However, learning and configuring a new way of installing software may put off some people. A SpamAssassin release is distributed in source form, but administrators of Red Hat Package Manager (RPM) based systems can easily convert the latest SpamAssassin release into rpm format and then the regular rpm command can be used to install the package. The Debian repository is updated fairly quickly when SpamAssassin is updated and the regular apt-get commands can be used to install SpamAssassin. We strongly advise you to install via apt-get, CPAN, or using the rpmbuild command as described next, in preference to using an RPM provided by a distributor. As SpamAssassin is a Perl Module, it appears on CPAN first. In fact, it is only released when it arrives at CPAN. Users of CPAN can download the latest version of SpamAssassin literally minutes after it has been released. Support is also easier to obtain if SpamAssassin is built from source. Some distributors make unusual decisions when creating their RPM of SpamAssassin or may modify certain default values. These make obtaining support more difficult. RPMs also take time to be delivered. Distributors need time to build and test new versions of software before they release them, and most software packages are not updated as quickly as SpamAssassin. So, Linux distributions may not provide the latest software, and what is provided can be several versions out of date. Using CPAN The prerequisites for installing SpamAssassin 3.2.5 using CPAN are as follows: Perl version 5.6.1 or later: Most modern Linux distributions will include this as a part of the base package. Several Perl modules: The current version of SpamAssassin needs the Digest::SHA1, HTML::Parser, and the Net::DNS modules. CPAN will install these if you configure it to follow dependencies, but there are many additional Perl modules that are optional and should be installed to get the best spam detection. CPAN will issue warnings with the module names, which will enable you to identify and install them. C compiler: This may not be installed by default and may have to be added using the rpm command. The compiler used will normally be called gcc. Internet connection: CPAN will attempt to download the modules using HTTP or FTP, so the network should be configured to allow this. Configuring CPAN If you've used CPAN before, you can skip to the next section, Installing SpamAssassin Using CPAN. If a proxy server is required for Internet traffic, CPAN (and other Perl modules and scripts) will use the http_proxy environment variable. If the proxy requires a username and password, these need to be specified using environment variables. As CPAN is normally run as root, these commands should be entered as root: # HTTP_proxy=http://proxy.name:80# export HTTP_proxy# HTTP_proxy_user=username# export HTTP_proxy_user# HTTP_proxy_pass=password# export HTTP_proxy_pass Next, enter this command: # perl -MCPAN -e shell If the output is similar to the following, the CPAN module is already installed and configured, and you can skip to the next section, Installing SpamAssassin Using CPAN. cpan shell -- CPAN exploration and modules installation (v1.7601)ReadLine support enabled If the output prompts for manual configuration, as shown next, the CPAN module is installed but not configured. Are you ready for manual configuration? [yes] During configuration, the CPAN Perl module prompts for answers to around 30 questions. For most of the questions, selecting the default value is the best response. This initial configuration must be completed before the CPAN Perl module can be used. The questions are mainly about the location of various utilities, and the defaults can be chosen by pressing Enter. The only question for which we should change the default is the one about building prerequisite modules. If we configure CPAN to follow dependencies, it will install the required modules without prompting. Policy on building prerequisites (follow, ask or ignore)? [ask] follow Once CPAN is configured, exit the shell by typing exit and pressing Enter. We are now ready to use CPAN to install SpamAssassin.
Read more
  • 0
  • 0
  • 1942
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-apache-myfaces-trinidad-12-web-application-groundwork-part-1
Packt
30 Nov 2009
8 min read
Save for later

Apache MyFaces Trinidad 1.2 Web Application Groundwork: Part 1

Packt
30 Nov 2009
8 min read
Navigation Navigation deals with all aspects of the user to moving from one part of an application to another. This includes the following means that the application must support, to allow the user moving to a certain functionality that is available through various kinds of links: Support of movement invocation through mouse clicks on tree nodes or keyboard shortcuts on such nodes, for example, menu items such as tr:commandNavigationItem, tr:commandLink, and s:link Support of movement invocation through mouse-clicks on buttons or keyboard shortcuts on such controls, for example, tr:commandButton, s:button, and s:link Support of movement invocation through mouse-clicks on hyper links or keyboard shortcuts on such links, for example, tr:commandLink, and s:link Support of movement invocation through mouse-clicks on icon links or buttons, or keyboard shortcuts on such links or buttons, for example, tr:image, tr:icon, and so on Further support for other variations of similar means of direct manipulation, for example, select boxes or radio buttons that cause a form to change in a way that encompasses moving to another page with more or other fields The following Image shows various means of navigation that all have to be considered (tree links, button clicks, selections and so on): To keep such navigation as simple, and yet as effective as technically possible, we move away from the Struts-inspired JSF way of declaring the navigation by means of XML files, something also kept up by Seam. We take advantage of Trinidad's dialog framework. It allows navigation on the pure Java side so that Seam's pages.xml can concentrate on the general navigation aspects such as exception handling or security/authorization. Following advantages can be observed in such an approach: Navigation declarations are kept simple and manageable thanks to a small pages.xml and yet no *.page.xml files are needed. Navigation occurs only in two areas—the XHTML and the application-specific Seam component controllers. Navigation always works the same way—first the model is set up and made available to the view by the controller, then the controller navigates to the view using the dialog framework. Finally, when the view is left, it is either closed (click on X), cancelled (click on Cancel), or accepted (click on OK) which is followed by post processing such as selecting and passing a value on to another object. You can access all the required sources, tools or plugins, and the sample project setup here. Thus, for instance, the login dialog is a real programmatic Trinidad dialog as it is called the following way: @Begin(join=true)public void doLogin(javax.faces.event.ActionEvent event){FacesContext jsfCtx = FacesContext.getCurrentInstance();// Create the dialog UIViewRootViewHandler viewHandler = jsfCtx.getApplication().getViewHandler();UIViewRoot dialog = viewHandler.createView(jsfCtx, "/login.xhtml");RequestContext trCtx = RequestContext.getCurrentInstance();trCtx.launchDialog(dialog,null, event.getComponent(),false, null);} Whereby the XHTML does not use the standard Trinidad dialog command features, but passes control to above action listener: <tr:form><tr:commandLink id="loginCommandLink" text="Login"actionListener="#{controller.doLogin}"rendered="#{not identity.loggedIn}" blocking="true"/></tr:form> The only occurrences of login.xhtml in pages.xml are in the general declaration of pages.xml and in the general error handling, but no other navigation of login.xhtml needs to be declared: <pages xsi:schemaLocation="http://jboss.com/products/seam/pageshttp://jboss.com/products/seam/pages-2.0.xsd"login-view-id="/login.xhtml">...<exception class="org.jboss.seam.security.NotLoggedInException"><redirect view-id="/login.xhtml"><message>Please log in first</message></redirect></exception> Finally, the dialog is closed, which is again done in a programmatic way for Trinidad dialogs: public void closeDialog(){Identity id = (Identity)Contexts.lookupInStatefulContexts(org.jboss.seam.security.identity");id.login();RequestContext trCtx = RequestContext.getCurrentInstance();trCtx.returnFromDialog(null,null);} This time, we do not need to deal with an event and close it by the simpler JSF action reference: <div class="actionButtons"><tr:commandButton text="Login" action="#{controller.closeDialog}" /></div> To understand the dialog logic behind above processes let us take a look at the general principles of the dialog framework that Trinidad provides. Trinidad's Dialog Framework The Apache MyFaces Trinidad Dialog Framework is an inheritance that stems back from the days of Oracle's ADF and UIX frameworks. It was the main way to navigate across dialogs, moving from page to page, from popup dialog to main browser dialog window, and so on. It offers a declarative way that works by using the conventional pages declarations as known from the pure JSF side, also in combination with Seam's pages.xml. Furthermore, it allows navigation in a purely programmatic manner as can be seen in the preceding examples. Nowadays, the dialog framework provided with Trinidad still counts as an alternative to the usual approach based in declaring pages and referencing them from within the application. Moreover, its uniform approach of dealing with both kinds of navigation, popup windows, and main browser windows remains as yet another attractive characteristic. For both reasons, we want to take advantage of this technique and concentrate on the purely programmatic side. For the declarative, please refer to http://myfaces.apache.org/trinidad/devguide/dialogs.html. Programmatically creating a dialog To create a dialog only the invocation of a method called launchDialog is required. It is a method provided by Trinidad's RequestContext object: public abstract void launchDialog(UIViewRoot dialogRoot,java.util.Map dialogParameters, UIComponent source, boolean useWindow, Map windowProperties); So the developer needs to provide the following parameters: A JSF component tree (the UIViewRoot dialogRoot) Some objects to pass to the dialog, see the upcoming sub section A JSF component from which the dialog is initiated and which receives a Trinidad ReturnEvent when the dialog to be shown is finished (closed) A Boolean flag to set the display type, popup, or main window The size of the pop-up window that is only required if the display type is a pop-up window which is set by putting integer objects into this map with keys width and height for window width and height respectively In above example, we can see that: ViewHandler viewHandler = jsfCtx.getApplication().getViewHandler();UIViewRoot dialog = viewHandler.createView(jsfCtx, "/login.xhtml");RequestContext trCtx = RequestContext.getCurrentInstance();trCtx.launchDialog(dialog,null, event.getComponent(), false, null); The JSF view handler is applied to create the new component tree based on the current JSF Faces context and the specific page to be shown in the dialog, which is the usual way. Next, in the actual call of the launchDialog method, we can see the purely programmatic approach without passing any objects to the dialog to be launched. Furthermore, we can see that because it is inside an action event listener of a commandLink, the dialog activity is linked with that link component. In other words, once the dialog is finished, a ReturnEvent is raised and handled by a respective return event listener on that component. Providing the data flow from dialog to dialog There are two alternatives to pass objects to a dialog and back: Using Trinidad's page flow scope Using Seam's scopes The first way is sort of built-in to Trinidad dialogs because above dialogParameters is a map of parameters that is going to populate a newly created pageFlowScope map solely created for the upcoming dialog. This map also includes all the objects that stem from the currently available pageFlowScope. One could also think of it as a nested scope because once the dialog is finished, this map is not available anymore; therefore, any modifications to this newly nested scope will not be preserved once the dialog is closed. The second way would be consistent with the rest of the web application is if the other parts use such important Seam scopes as conversation. Generally, it is more advisable to prefer one of both and avoid a mixture. In this article we take advantage of page flow scopes as Trinidad is in the foreground. Returning from a dialog Once the dialog is cancelled, or the activity accepted and finished, the application must link to Trinidad's standard closing process which is calling the returnFromDialog method of RequestContext. For example, the closeWindow needs to apply Trinidad's RequestContext: RequestContext trCtx = RequestContext.getCurrentInstance();trCtx.returnFromDialog(null,null); This is a special case because the returnFromDialog method's signature is defined as follows: public abstract void returnFromDialog(Object returnValue, Map<Object,Object> returnParameters); Generally, while invoking the returnFromDialog method, one provides return objects as dialog results, that is, for instance the result of a selection. Therefore, it is perfectly normal to return a single object as returnValue while returnParameters may remain null. In any case, the ReturnEvent object provides two methods to access such dialog results: public Object getReturnValue(): This method yields the object that has been passed as the first parameter of the invocation of returnFromDialog public Map<Object, Object> getReturnParameters(): This method yields the map that has been passed as the second parameter of the invocation of returnFromDialog In the case of our simple closeDialog method, no parameters are passed back as Seam's login procedure does it all for us, and we do not need to pass anything back as it is saved by Seam in its identity object. In the following section, we will see the specific example which is in our web sample application.
Read more
  • 0
  • 0
  • 1901

article-image-user-interface-design-icefaces-18-part-1
Packt
30 Nov 2009
9 min read
Save for later

User Interface Design in ICEfaces 1.8: Part 1

Packt
30 Nov 2009
9 min read
Before we take a more detailed look at the ICEfaces components, we will discuss the desktop character of modern web applications in this article. Desktop technology  is about 40 years old now and there are best practices that can help us in our web application design. An important part of the user interface design is the page layout. We will have a look at the corresponding design process using a mockup tool. The Facelets example will be extended to show how to implement such a mockup design using Facelets templating. Finally, we will have a look at the production-ready templating of ICEfusion. Revival of the desktop The number of desktop-like web applications is growing faster and faster. The demand for this is not a big surprise. Using full-featured desktops meant that users had to suffer from the limited-user model of the first generation Web. This usage gap is now filled by web applications that mimic desktop behavior. However, there is a difference between the desktop and the Web. Although equipped with desktop-like presentations, web applications have to fulfill different user expectations. So, we have a revival of the desktop metaphor in the Web context but it is mixed with user habits based on the first decade of the Web. Nevertheless, the demand for a purer desktop presentation is already foreseeable. If you primarily followed the traditional web programming model in the past, namely the request-response pattern, you may first have to shift your mind to components and events. If you already have some desktop-programming experience you will discover a lot of similarities. However, you will also recognize how limited the Web 2.0 programming world is in comparison to modern desktops. The difference is understandable because desktop design has a long tradition. The first system was built at the end of the 1960s. There is a lot of experience in this domain. Best of all, we have established rules we can follow. Web design is still a challenge compared to desktop design. Although this article cannot discuss all of the important details of today's desktop design, we will have a quick look at the basics that are applicable to nearly all user interface designs. We can subsume all this with the following question: What makes a software system user-friendly? Software ergonomics Have you ever heard of the ISO standard 9241, Ergonomics of Human System Interaction (http://en.wikipedia.org/wiki/ISO_9241)? This standard describes how a system has to be designed to be human-engineered. There are a lot of aspects in it, from the hardware design for a machine that has to be used by a human to the user interface design of software applications. A poor hardware or interface design can result in not only injury, but also mental distress that leads to wastage of working time. The primary target is to prevent humans from damage. The most important part of ISO 9241 for software developers is part 110, dialog principles. It considers the design of dialogs between humans and information systems with a focus on: Suitability for the task Suitability for learning Suitability for individualization Conformity with user expectations Self-descriptiveness Controllability Error tolerance We will take a deeper look at these later. ISO 9241-110 has its roots in a German industry standard based on research work from the early 1980s. I frst had a look at all this during a study almost 20 years ago. Most interesting with part 110 is the stability of the theoretical model behind it. Independent of the technical advances of the IT industry in the last two decades, we can still apply these standards to modern web application design. Challenges The principles of ISO 9241-110 can help you to get better results, but they only serve as a rule. Even if you follow such principles slavishly, the result will not be automatically valuable. Creating a useful interface is still a challenging business. You have to accept a process of trial and error, ask for customer feedback, and accept a lot of iterations in development before usability becomes your friend. The technical limitations that derive from your framework decisions can be additionally frustrating. The problems that we have with today's AJAX technology are a good example of it, especially if you are already experienced with desktop development and its design rules. Apply Occam's razor Everything should be made as simple as possible, but not simpler. Albert Einstein's quote mentions two important aspects in creative processes that are also true for user interface design: Reduction Oversimplification Reduction Have you ever realized how difficult it is to recognize what is important or necessary, and what is superfluous when you enter a new domain? Often, things seem to be clear and pretty simple at the first sight. However, such a perception is based on experiences that were made outside of the domain. There is a lack of essential experiences in a majority of the cases. You may have to invest several years to get the whole picture and develop an accurate understanding before you come to an adequate decision. If your new domain is user interface design, these findings can help you to understand your customers better. If you keep questioning the eye-catching solutions that come to your mind and try to slip into the customer's role, you  will get better results faster. Oversimplification Oversimplification makes user interfaces more complex to use. This phenomenon arises if the target group for a user interface is defined as less experienced than it is in reality. For advanced users, a beginner's design is more time-consuming to use. In many cases, it is assumed that a bigger part of the users consists of beginners. However, reality shows us that advanced users make up the bigger part, whereas beginners and super users may have a portion of up to 10% each. Designing a user interface for beginners that can be used by all users may be an intuitive idea at first sight, but it is not. You have to consider the advanced users if you want to be successful with your design. This is indeed an essential experience to come to an adequate decision. User interface design principles Besides the aforementioned recommendations, the following are the most influential principles for an adequate interface design: Suitability for the task Self-descriptiveness Controllability Conformity with user expectations Error tolerance Suitability for individualization Suitability for learning Suitability for the task Although it seems to be a trivial requirement, the functionality of a web application seldom delivers what the user requires to fulfill his needs. Additionally, the presentation, navigation, or lingo often does not work for the user or is not well-suited for the function it represents. A good user interface design is based on the customer's lingo. You can write a glossary that describes the meaning of terms you use. A requirements management that results in a detailed use case model can help in implementing the adequate functionality. The iterative development of interactive user interface prototypes to get customer feedback allows finding a suitable presentation and navigation. Self-Descriptiveness Ergonomic applications have an interface design that allows answering the following questions at any time: What is the context I am working in at the moment? What is the next possible step? The answers to these questions become immediately important when a user is, for example, disrupted by a telephone call and continues his work after attending to it. The shorter the time to recognize the last working step, the better the design is. A rule of thumb is to have a caption for every web page that describes its context. Navigational elements, such as buttons, show descriptive text that allows recognizing the function behind it. If possible, separate a page into subsections that also have their captions for a better orientation. Controllability Applications have to offer their functionality in a way that the user can decide for himself when and how the application is fulfilling his requirements. For this, it is important that the application offers different ways to start a function. Beginners may prefer using the mouse to select an entry in a pull-down menu. Advanced users normally work with the keyboard because hotkeys let them use the application faster. It is also important that the user must be able to stop his/her work at any time; for example, for a lunch break or telephone call, without any disadvantages. It is not acceptable that the user has to start the last function again. With web application, this cannot be fulfilled in any case because of security reasons or limited server resources. Conformity with User Expectations User expectations are, maybe, the most important principle, but also the most sophisticated one. The expectations are closely connected to the cultural background of the target group. So, the interface designer has to have a similar socialization. We need to have a look at the use of words of the target language. Although target groups share the same language, certain terms can have different meanings; for example, the correct use of colors or pictures in icon bars is pretty important because we use these in contexts without extra explanation. However, there are cases when a color or an image can mean the opposite of what it was designed for. The behavior of an application can also be a problem when it differs from the standards of real-world processes. The advantage of standardization is an immediate understanding of processing steps, or the correct use of tools without education. If an application does not consider this and varies, the standard users have to rethink every step before they can fulfill their duties. This needs extra energy, is annoying, and is pretty bad for the acceptance of the application in the long run. If we look at the design itself, consistency in presentation, navigation, or form use is another important part. The user expects immutable behavior of the application in similar contexts. Contexts should be learned only once, and the learned ones are reusable in all other occurrences. Following this concept also helps to reuse the visual components during development. So, you have a single implementation for each context that is reused in different web pages.
Read more
  • 0
  • 0
  • 1978

article-image-report-components-nav-2009-part-2
Packt
30 Nov 2009
6 min read
Save for later

Report components in NAV 2009: Part 2

Packt
30 Nov 2009
6 min read
Data item Sections Earlier in our discussion on reports, we referred to the primary components of a report. The Triggers and Properties we have reviewed so far are the data processing components. Next in the report processing sequence are Sections. In Classic RD reports, Sections are the output layout and formatting components. In RTC reports, Sections have a much more limited, but still critically important, role. In the process of creating the initial report design, you may be entering data either completely manually as we've done in our example work, or you may use the Classic Report Wizard. If you use the Wizard, you will end up with Sections defined suitable for Classic Client Report processing. Those Sections may be only rough draft equivalents of what you may want your final report to look like, but they are a suitable starting place for the Classic RD layout work, if that were the tool you were going to use. If you are creating your report completely manually, that is by not using the Wizard, you may also find it appropriate to define Sections to the point that the Classic Client could print a basic, readable report. In our case, we are focusing our production report development effort on the RoleTailored Client, so we will invest minimal effort on Classic Client compatible report layouts. We might do just enough to allow test report runs for data examination purposes and logic flow debugging. However, creating basic Section layouts provides us with another benefit relative to our VS RD layout work, especially if we can create them using the Report Wizard, because all the fields to be used by VS RD must be specified in the Sections. Creating RTC reports via the Classic Report Wizard Let's look at the RTC report development flow again. The preceding image is very similar to the one we studied earlier in this articles, but this flowchart only shows the steps that are pertinent to VS RD. In Step 6 of this flow, there is an option to Create Layout Suggestion in the Visual Studio Report Designer as shown in the following screenshot: When you choose Create Layout Suggestion, the C/SIDE Report Designer will invoke a process that transforms the layout in Sections to a layout in the Visual Studio Report Designer. If a VS RD layout previously existed, the newly created layout will overwrite it. Therefore, this option will normally be used only once, in the initial stages of report design. Let's experiment by using the Report Wizard to create a simple report listing the gifts received by ICAN. We will access the Report Wizard in the Object Designer. Click on Reports | New, then fill in the Wizard screen as shown in the following image. Then click on OK and choose fields to display in the report as shown in the following screenshot. Click on Next, then choose the sorting order (that is index or key) that starts with Donor ID. Click on Next again and choose to Group the data by Donor ID. Click on Next again and choose to create totals for the Estimated Value field. One more, click on Next and choose the List Style for the report, then click on Finish. At this point, you will have generated a Classic Client report using the Report Wizard. If you View | Sections, you should see a C/SIDE report layout that looks much like the following screenshot. Let's save our newly generated report so that, if we need to, we can come back to this point as a checkpoint. Click on File | Save As and assign the report to ID 50002 with the Name of Gifts by Donor. Now click on Tools | Create Layout Suggestion. The process of transforming the Classic Report Layout to a Visual Studio Report Designer Layout will take a few seconds. When the report layout transformation process completes, you should see a screen that looks very similar to the following screenshot. The primary data layout portion of the same VS RD screen is shown in the next image. Compare this to the Classic RD data layout we just looked at a couple of steps ago. You will see some similarities and some considerable differences. Without doing anything else, let's save the VS RD layout we just created for the RoleTailored Client, then run both versions of the report to see the differences in the generated results. To save the VS RD layout, start by simply exiting the VS Report Designer. Once the VS RD screen closes, you will see the following question. Respond by clicking Yes. Then, when you exit the Classic Report Designer, you will see this question. Respond by clicking Yes. You will then be presented with the following message. Again, click on Yes. If there were an error in the RDLC created within the VS RD (such as an incorrect variable name used), an error message similar to the following would display. Since, hopefully, we didn't get such an error message, we can proceed to test both the Classic Client and the RoleTailored Client versions of our generated report. We can test the Classic Client (or C/SIDE RD) version of Report 50002 from the same Object Designer screen where we did our initial design work. Highlight the line for Report 50002 and click on the Run button. You should see the following screen: If we were running this as users, we might want to make a selection of specific Donors here on which to report. As we are just testing, simply click on Preview to see our report onscreen. The report will then appear, looking like the following: As you can see, with minimum development effort (and a minimum of technical knowledge), we have designed and created a report listing Gifts by Donor with subtotals by Donor. The report has proper page and column headings. Not only that, but the report was initiated withs a Request Form allowing application of filters. Close the Classic Client report; now let's run the RTC version. Just like we could do with Pages, we will run our Report test from the Windows Run option. Click on Run and enter the command to run Report 50002, as shown in the next screenshot. Click on OK. If the RoleTailored Client is not active, after a short pause, it will be activated. Then the Request Page will appear. Compare the look and contents of this Request Page with the one we saw previously for the Classic Client. As before, click on Preview and view the report. Of course, this time we're looking at the RTC version. This method of automatic transformation is very useful for getting an initial base for a new report or, obviously, for the complete generation process for a simple report where the requirements for layout are not too restrictive.
Read more
  • 0
  • 0
  • 2556

article-image-drag-and-drop-yui-part-1
Packt
30 Nov 2009
7 min read
Save for later

Drag-and-Drop with the YUI: Part-1

Packt
30 Nov 2009
7 min read
Dynamic Drag-and-Drop without the Hassle Like most of the other library components, when creating your own drag-and-drop elements, there are a range of different options available to you that allow you to tailor those objects to your requirements. These properties, like those of most other library components, can be set using an object literal supplied with the constructor, but in most cases even this is not required. The most challenging aspects of any drag-and-drop scenario in your web applications are going to center around the design of your specific implementation rather than in getting drag-and-drop to work in the first place. This utility is yet another example of the huge benefits the YUI can provide in reducing the amount of coding and troubleshooting that you need to concern yourself with. The Different Components of Drag-and-Drop In addition to the configurable properties used in your object literal, you also have several constructors that can be used to enable drag-and-drop. The first constructor YAHOO.util.DD allows for drag-and-drop at its most basic level. The supplied element will be transformed into an object that can be dragged around the page. The mechanics of drag-and-drop result in a burden of fairly high processing. The library has to keep track of the mouse pointer whilst it is moving, the draggable object needs to be repositioned, and different events are almost continually firing while the drag is taking place. In order to minimize the amount of information that needs to be processed, especially when the draggable object is fairly large, you can make use of a proxy element that will track across the page with the mouse pointer. When the proxy element reaches its final destination, it disappears and is replaced by the actual element. If a proxy element is required, we can use the YAHOO.util.DDProxy constructor instead of the basic constructor. As the proxy element is just an empty <div>, it's much easier to track and can even be shared between different drag objects on the page, reducing the overall processing that's required. Personally I think the default appearance of the proxy element is perfectly adequate, however you can also create your own custom elements to use as a proxy. The figure below shows the default proxy-element appearance: Design Considerations When working with DragDrop implementations, it is useful to consider the following aspects of the design: Can any part of the drag object be clicked on to initiate the drag, or should a drag handle be defined? Can the object be dropped on to any part of the page or should a specific drop target be defined? Should anything occur whilst the object is being dragged? Should anything occur when the item is dropped on a non-valid target? Should anything occur when the object is dropped on to a valid target? Events Events are an integral aspect of many DragDrop situations. Sometimes, however, being able to move something around the screen is the only behavior that's required, but generally you'll want something to happen either while the object is being dragged, or when it is dropped. The YAHOO.util.DragDrop utility provides a series of custom events which allow you to hook into and respond to events such as startDrag, endDrag, onDrag, onDragDrop, and onInvalidDrop. Valid targets also expose events of their own including onDragEnter, onDragOut, and onDragOver. We will be looking at a number of these events during the example that follows. Allowing Your Visitors to Drag-and-Drop The Drag-and-Drop utility uses tried and tested DHTML techniques, as well as some innovative new features, to allow you to easily create objects that can be dragged and then dropped. All that you need to do to make an element on your page dragable is to create a new instance of the YAHOO.util.DD class and feed in the id or element reference of the element that drag is to be enabled for. DragDrop Classes The base class of the Drag-and-Drop utility is YAHOO.util. DragDrop, but you'll use one of its extending subclasses, like YAHOO.util.DD, most of the time. This subclass inherits all of the properties and methods of the base class and even adds a few of its own, so it's more than capable of handling most of your drag-and-drop requirements. The YAHOO.util.DD class also has its own subclasses to deal with additional drag-and-drop requirements for different situations. The subclasses are YAHOO.util.DDProxy and YAHOO.widget.SliderThumb. As you can see, the Drag-and-Drop utility provides some of the basic functionality of another of the controls found in the YUI, the Slider Control (which we will look at in more detail towards the end of this article). Let's examine the DDProxy class, as that is relevant specifically to the Drag-and-Drop utility. Creating a proxy object that tracks with the cursor when a drag object is being dragged instead of allowing the actual drag object to track can prevent problems that arise with large drag objects not tracking properly or obscuring other content on the page. The proxy object is a small, empty object that represents the drag object and shows only its borders. The proxy object is created on the mouseDown event of the drag object and the actual drag object does not move to its new position until the mouseUp event is fired. Using a proxy object is both visually appealing and better overall for all but the simplest of implementations performance wise. The Constructor The constructor for an instance of the DragDrop object can also take a second or third argument when you are instantiating objects for dragging. The second argument, which is optional, specifies the group to which the element being dragged belongs. This refers to interaction groups—the object being dragged can only interact with and fire events with other elements in its interaction group. The third argument, which is also optional, can be used to supply a configuration object, the members of which hold additional optional configuration properties that can easily be accessed and set. Every object instantiated with the drag-and-drop constructor is a member of one or more interaction group(s), even if the second argument is not passed. When the argument is not supplied, the object will simply belong to the 'default' group instead. There is no limit as to how many groups an object can belong to. The API provides just two methods that relate to group access. .addToGroup() is used to add the object to more than one group, so the first group membership is defined with the constructor and subsequent groups with the .addToGroup() method. To remove an object from a group, just call the .removeFromGroup() method. Target Practice There is no doubt that drag-and-drop adds a hands-on, fun element to surfing the net that is way more engaging than simple point-and-click scenarios, and there are many serious applications of this behavior too. But dragging is only half of the action; without assigned drop targets, the usefulness of being able to drag elements on the page around at leisure is almost wasted. Drop targets have a class of their own in the Drag-and-Drop utility. Which extends the YAHOO.util.DragDrop base class to cater for the creation of drag elements that aren't actually dragable and this is the defining attribute of a drop target. The constructor is exactly the same as for the DD and Proxy classes with regard to the arguments passed, but YAHOO.util.DDTarget is used instead. The Target class has no methods or properties of its own, but it inherits all of the same methods and properties as the other two classes, including all of the events.
Read more
  • 0
  • 0
  • 4507
article-image-ways-improve-performance-your-server-modsecurity-25
Packt
30 Nov 2009
13 min read
Save for later

Ways to improve performance of your server in ModSecurity 2.5

Packt
30 Nov 2009
13 min read
A typical HTTP request To get a better picture of the possible delay incurred when using a web application firewall, it helps to understand the anatomy of a typical HTTP request, and what processing time a typical web page download will incur. This will help us compare any added ModSecurity processing time to the overall time for the entire request. When a user visits a web page, his browser first connects to the server and downloads the main resource requested by the user (for example, an .html file). It then parses the downloaded file to discover any additional files, such as images or scripts, that it must download to be able to render the page. Therefore, from the point of view of a web browser, the following sequence of events happens for each file: Connect to web server. Request required file. Wait for server to start serving file. Download file. Each of these steps adds latency, or delay, to the request. A typical download time for a web page is on the order of hundreds of milliseconds per file for a home cable/DSL user. This can be slower or faster, depending on the speed of the connection and the geographical distance between the client and server. If ModSecurity adds any delay to the page request, it will be to the server processing time, or in other words the time from when the client has connected to the server to when the last byte of content has been sent out to the client. Another aspect that needs to be kept in mind is that ModSecurity will increase the memory usage of Apache. In what is probably the most common Apache configuration, known as "prefork", Apache starts one new child process for each active connection to the server. This means that the number of Apache instances increases and decreases depending on the number of client connections to the server.As the total memory usage of Apache depends on the number of child processes running and the memory usage of each child process, we should look at the way ModSecurity affects the memory usage of Apache. A real-world performance test In this section we will run a performance test on a real web server running Apache 2.2.8 on a Fedora Linux server (kernel 2.6.25). The server has an Intel Xeon 2.33 GHz dual-core processor and 2 GB of RAM. We will start out benchmarking the server when it is running just Apache without having ModSecurity enabled. We will then run our tests with ModSecurity enabled but without any rules loaded. Finally, we will test ModSecurity with a ruleset loaded so that we can draw conclusions about how the performance is affected. The rules we will be using come supplied with ModSecurity and are called the "core ruleset". The core ruleset The ModSecurity core ruleset contains over 120 rules and is shipped with the default ModSecurity source distribution (it's contained in the rules sub-directory). This ruleset is designed to provide "out of the box" protection against some of the most common web attacks used today. Here are some of the things that the core ruleset protects against: Suspicious HTTP requests (for example, missing User-Agent or Accept headers) SQL injection Cross-Site Scripting (XSS) Remote code injection File disclosure We will examine these methods of attack, but for now, let's use the core ruleset and examine how enabling it impacts the performance of your web service. Installing the core ruleset To install the core ruleset, create a new sub-directory named modsec under your Apache conf directory (the location will vary depending on your distribution). Then copy all the .conf files from the rules sub-directory of the source distribution to the new modsec directory: mkdir /etc/httpd/conf/modseccp/home/download/modsecurity-apache/rules/modsecurity_crs_*.conf /etc/httpd/conf/modsec Finally, enter the following line in your httpd.conf file and restart Apache to make it read the new rule files: # Enable ModSecurity core rulesetInclude conf/modsecurity/*.conf Putting the core rules in a separate directory makes it easy to disable them—all you have to do is comment out the above Include line in httpd.conf, restart Apache, and the rules will be disabled. Making sure it works The core ruleset contains a file named modsecurity_crs_10_config.conf. This file contains some of the basic configuration directives needed to turn on the rule engine and configure request and response body access. Since we have already configured these directives, we do not want this file to conflict with our existing configuration, and so we need to disable this. To do this, we simply need to rename the file so that it has a different extension as Apache only loads *.conf files with the Include directive we used above: $ mv modsecurity_crs_10_config.conf modsecurity_crs_10_config.conf.disabled Once we have restarted Apache, we can test that the core ruleset is loaded by attempting to access an URL that it should block. For example, try surfing to http://yourserver/ftp.exe and you should get the error message Method Not Implemented, ensuring that the core rules are loaded. Performance testing basics So what effect does loading the core ruleset have on web application response time and how do we measure this? We could measure the response time for a single request with and without the core ruleset loaded, but this wouldn't have any statistical significance—it could happen that just as one of the requests was being processed, the server started to execute a processor-intensive scheduled task, causing a delayed response time. The best way to compare the response times is to issue a large number of requests and look at the average time it takes for the server to respond. An excellent tool—and the one we are going to use to benchmark the server in the following tests—is called httperf. Written by David Mosberger of Hewlett Packard Research Labs, httperf allows you to simulate high workloads against a web server and obtain statistical data on the performance of the server. You can obtain the program at http://www.hpl.hp.com/research/linux/httperf/ where you'll also find a useful manual page in the PDF file format and a link to the research paper published together with the first version of the tool. Using httperf We'll run httperf with the options --hog (use as many TCP ports as needed), --uri/index.html (request the static web page index.html) and we'll use --num-conn 1000 (initiate a total of 1000 connections). We will be varying the number of requests per second (specified using --rate) to see how the server responds under different workloads. This is what the typical output from httperf looks like when run with the above options: $ ./httperf --hog --server=bytelayer.com --uri /index.html --num-conn1000 --rate 50Total: connections 1000 requests 1000 replies 1000 test-duration20.386 sConnection rate: 49.1 conn/s (20.4 ms/conn, <=30 concurrentconnections)Connection time [ms]: min 404.1 avg 408.2 max 591.3 median 404.5stddev 16.9Connection time [ms]: connect 102.3Connection length [replies/conn]: 1.000Request rate: 49.1 req/s (20.4 ms/req)Request size [B]: 95.0Reply rate [replies/s]: min 46.0 avg 49.0 max 50.0 stddev 2.0 (4samples)Reply time [ms]: response 103.1 transfer 202.9Reply size [B]: header 244.0 content 19531.0 footer 0.0 (total19775.0)Reply status: 1xx=0 2xx=1000 3xx=0 4xx=0 5xx=0CPU time [s]: user 2.37 system 17.14 (user 11.6% system 84.1% total95.7%)Net I/O: 951.9 KB/s (7.8*10^6 bps)Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0 The output shows us the number of TCP connections httperf initiated per second ("Connection rate"), the rate at which it requested files from the server ("Request rate"), and the actual reply rate that the server was able to provide ("Reply rate"). We also get statistics on the reply time—the "reply time – response" is the time taken from when the first byte of the request was sent to the server to when the first byte of the reply was received—in this case around 103 milliseconds. The transfer time is the time to receive the entire response from the server. The page we will be requesting in this case, index.html, is 20 KB in size which is a pretty average size for an HTML document. httperf requests the page one time per connection and doesn't follow any links in the page to download additional embedded content or script files, so the number of such links in the page is of no relevance to our test. Getting a baseline: Testing without ModSecurity When running benchmarking tests like this one, it's always important to get a baseline result so that you know the performance of your server when the component you're measuring is not involved. In our case, we will run the tests against the server when ModSecurity is disabled. This will allow us to tell which impact, if any, running with ModSecurity enabled has on the server. Response time The following chart shows the response time, in milliseconds, of the server when it is running without ModSecurity. The number of requests per second is on the horizontal axis: As we can see, the server consistently delivers response times of around 300 milliseconds until we reach about 75 requests per second. Above this, the response time starts increasing, and at around 500 requests per second the response time is almost a second per request. This data is what we will use for comparison purposes when looking at the response time of the server after we enable ModSecurity. Memory usage Finding the memory usage on a Linux system can be quite tricky. Simply running the Linux top utility and looking at the amount of free memory doesn't quite cut it, and the reason is that Linux tries to use almost all free memory as a disk cache. So even on a system with several gigabytes of memory and no memory-hungry processes, you might see a free memory count of only 50 MB or so. Another problem is that Apache uses many child processes, and to accurately measure the memory usage of Apache we need to sum the memory usage of each child process. What we need is a way to measure the memory usage of all the Apache child processes so that we can see how much memory the web server truly uses. To solve this, here is a small shell script that I have written that runs the ps command to find all the Apache processes. It then passes the PID of each Apache process to pmap to find the memory usage, and finally uses awk to extract the memory usage (in KB) for summation. The result is that the memory usage of Apache is printed to the terminal. The actual shell command is only one long line, but I've put it into a file called apache_mem.sh to make it easier to use: #!/bin/sh# apache_mem.sh# Calculate the Apache memory usageps -ef | grep httpd | grep ^apache | awk '{ print $2 }' | xargs pmap -x | grep 'total kB' | awk '{ print $3 }' | awk '{ sum += $1 } END { print sum }' Now, let's use this script to look at the memory usage of all of the Apache processes while we are running our performance test. The following graph shows the memory usage of Apache as the number of requests per second increases: Apache starts out consuming about 300 MB of memory. Memory usage grows steadily and at about 150 requests per second it starts climbing more rapidly. At 500 requests per second, the memory usage is over 2.4 GB—more than the amount of physical RAM of the server. The fact that this is possible is because of the virtual memory architecture that Linux (and all modern operating systems) use. When there is no more physical RAM available, the kernel starts swapping memory pages out to disk, which allows it to continue operating. However, since reading and writing to a hard drive is much slower than to memory, this starts slowing down the server significantly, as evidenced by the increase in response time seen in the previous graph. CPU usage In both of the tests above, the server's CPU usage was consistently around 1 to 2%, no matter what the request rate was. You might have expected a graph of CPU usage in the previous and subsequent tests, but while I measured the CPU usage in each test, it turned out to run at this low utilization rate for all tests, so a graph would not be very useful. Suffice it to say that in these tests, CPU usage was not a factor. ModSecurity without any loaded rules Now, let's enable ModSecurity—but without loading any rules—and see what happens to the response time and memory usage. Both SecRequestBodyAccess and SecResponseBodyAccess were set to On, so if there is any performance penalty associated with buffering requests and responses, we should see this now that we are running ModSecurity without any rules. The following graph shows the response time of Apache with ModSecurity enabled: We can see that the response time graph looks very similar to the response time graph we got when ModSecurity was disabled. The response time starts increasing at around 75 requests per second, and once we pass 350 requests per second, things really start going downhill. The memory usage graph is also almost identical to the previous one: Apache uses around 1.3 MB extra per child process when ModSecurity is loaded, which equals a total increase of memory usage of 26 MB for this particular setup. Compared to the total amount of memory Apache uses when the server is idle (around 300 MB) this equals an increase of about 10%. Mod Security with the core ruleset loaded Now for the really interesting test we'll run httperf against ModSecurity with the core ruleset loaded and look at what that does to the response time and memory usage. Response time The following graph shows the server response time with the core ruleset loaded: At first, the response time is around 340 ms, which is about 35 ms slower than in previous tests. Once the request rate gets above 50, the server response time starts deteriorating. As the request rates grows, the response time gets worse and worse, reaching a full 5 seconds at 100 requests per second. I have capped the graph at 100 requests per second, as the server performance has already deteriorated enough at this point to allow us to see the trend. We see that the point at which memory usage starts increasing has gone down from 75 to 50 requests per second now that we have enabled the core ruleset. This equals a reduction in the maximum number of requests per second the server can handle of 33%.
Read more
  • 0
  • 0
  • 20675

article-image-navigating-your-site-using-codeigniter-17-part-1
Packt
30 Nov 2009
10 min read
Save for later

Navigating Your Site using CodeIgniter 1.7: Part 1

Packt
30 Nov 2009
10 min read
MVC:Model-View-Controller What's MVC all about? For sure at this time you are very curious about this. In short, MVC is an architectural pattern, a way of structuring our application. system application models views controllers As you can see there is a folder for each of the words (MVC); let's see what we can put into them: Models: The models represent our application data, be it in databases, in XML files or anywhere else. Also, interaction with databases is carried here. For example, models will allow us to fetch, modify, insert, and remove data from our database. All actions that require our application to talk to our database must be put in a model. Views: Files placed here are responsible for showing our data to the visitors to our site, or users of our application. No programming logic, no insert or update queries must be run here, though data access may occur in these files. They are here only to show the results of the other two. So we fetch the data in the model, and show it in the view. Now, what if we need to process the data, for example, putting it into an array? Then we do it in the controller; let's see how. Controllers: These act as a nexus between models and views, and programming logic occurs here. Take a look at this little diagram, in the left column we can see a "classical" way of doing things (a little outdated right now). We have a PHP file with SQL queries and HTML code in the same file and embedded into the HTML PHP logic. It may seem, at first glance, that this way it is easier and faster to program. But in this case the code gets messed faster and becomes cluttered with SQL queries, HTML, and PHP logic. Look at the right-side column—we have SQL queries in the Model, HTML and other graphic elements in the View, and PHP logic in the Controller. Doesn't that seem organized? The Controller calls and fetches data from the Model. It then loads the data and passes it to the Views, and sends the results to the user. Once we start working with this pattern we will feel how easy it is; it will keep our projects organized. If we need to come back to our project months after finishing it we will appreciate having made it in a structured fashion. No more of—Oh my God where did I put that query, where is that include file?—they will be in the model and the controller respectively. But, what happens if we want to put our queries in the controller? Well, CodeIgniter allows us to do so (though it is not recommended; if you can avoid, it is better to do so). Other frameworks force you to keep a particular structure, but with CI you can do programming in the way you want. Although it is recommended to keep to the structure, there will be times when we will need to do things the other way. With this structure we can accomplish two important things: Loose Coupling: Coupling is the degree by which the components of a system rely on each other. The less the components depend on each other, the more reusable and flexible the system becomes. Component Singularity: Singularity is the degree by which components have a narrow focus. In CI, each class and its functions are highly autonomous in order to allow maximum usefulness. But how does all this work? Now that we have seen how CI is structured, maybe you are asking yourself—how are the files in those three folders (models, views, controllers) working together? To answer this question we have another diagram, here it is: As you can see it's similar to the previous one, and a little summarized (but with a wider scope of things, this is how the MVC pattern works), but this time we can see some new elements, and if you look at it closely you will be able to distinguish the flow of data. Let's explain it, first of all there is a browser call to your site, then the index.php file in the root folder is called (because we removed it from the URL, using the .htaccess file, we don't see it). This file acts as a router and calls the controllers, as and when they are needed. The controllers, as they are called, come into action. Now, two things can happen: There is no need to fetch data from the database—in this case only the View is called, and loaded by the Controller. Then it is returned to the Browser for you or your visitors to see. There is the need to fetch some data from the database—in this case theController calls the Model, which in turn makes a query to the database. The database returns data to the Model, and the Model to the Controller. The Controller modifies the data in every necessary way. Then it loads the View, passing all necessary data to it, and the View is created and returned to the Browser again. Do not get confused with the first case; there will be times when you will need to create static pages. CI doesn't differentiate between static and dynamic pages. On those occasions simply don't create the Models. Now, return to our sample site to see how all this applies to it. Remember when we put the URL as http://127.0.0.1/codeigniter, CI's welcome screen appeared in our browser. Now try this URL http://127.0.0.1/codeigniter/welcome. You can also try using this URLhttp://127.0.0.1/codeigniter/index.php/welcome. In both cases the welcome screen appears in the browser. You maybe wondering, how CI knows, if you put http://127.0.0.1/codeigniter/, that it has to load the welcome controller. Don't worry, we will see that in a moment; for now, we will go on with our example: http://127.0.0.1/codeigniter/index.php/welcome A request coming to your web site's root is intercepted by the index.php file, which acts as a router. That is, it calls a controller—welcome controller—which then returns a view, just as in the previous diagram. But how does the controller do that? We are going to see how in the welcome controller. The welcome controller As we know the welcome controller is the default controller, configured in the routes.php file of the config directory and the code is at ./application/controllers/welcome.php. Here's what it says: <?php class Welcome extends Controller { function Welcome() { parent::Controller(); } function index() { $this->load->view('welcome_message'); } } /* End of file welcome.php */ /* Location: ./system/application/controllers/welcome.php */ From the second line you'll learn that this file is a class. Every controller inherits from an original Controller class, hence extends Controller. The next three lines make the constructor function. Within the class there are two functions or methods—Welcome() and index(). Though it is not necessary, naming controllers the same way as for tables is a good practice. For example, if I have a projects table I will create a projects controller. You can name your controllers the way you want, but naming them like the tables they represent keeps things organized. Also, getting used to this won't harm you, as other frameworks are stricter about this. Notice that CI uses the older PHP 4 convention for naming constructor functions, which is also acceptable by PHP 5—it doesn't require you to use PHP 5 and is happy with either version of the language. The constructor function is used to set up the class each time you instantiate it. We can obviate this and the controller will still work, and if we use it, it won't do any harm. Inside it we can put instructions to load other libraries or models, or definitions of class variables. So far the only thing inside the constructor is the parent::Controller(); statement. This is just a way of making sure that you inherit the functionality of the Controller class. If you want to understand the parent CI Controller class in detail, you can look at the file /www/CI_system/libraries/controller.php. One of the reassuring things about CI is that all the code is there for you to inspect, though you don't often need to. Working with views Let's go back to the incoming request for a moment. The router needs to know which controller and which function within that controller should handle the request. By default the index function is called if the function is not specified. So, when we put http://127.0.0.1/codeigniter/welcome/, the index function is called. If no error is shown, this function simply loads the view, ('welcome_message') using CI's loader function ($this->load->view). At this stage, it doesn't do anything cool with the view, such as passing dynamic information to it. That comes in later. The ('welcome_message') it wants to load, is in the views folder that you have just installed at /www/codeigniter/application/views/welcome_message.php. This particular view is only a simple HTML page, but it is saved as a PHP file because most views have PHP code in them (no point in doing all this if we're only going to serve up plain old static HTML). Here's the (slightly shortened) code for the view: <html> <head> <title>Welcome to CodeIgniter</title> <style type="text/css"> body { background-color: #fff; margin: 40px; font-family: Lucida Grande, Verdana, Sans-serif; font-size: 14px; color: #4F5155; } . . . . . more style information here . . . . </style> </head> <body> <h1>Welcome to CodeIgniter!</h1> <p>The page you are looking at is being generated dynamically by CodeIgniter. </p> <p>If you would like to edit this page you'll find it located at: </p> <code>system/application/views/welcome_message.php</code> <p>The corresponding controller for this page is found at:</p> <code>system/application/controllers/welcome.php</code> <p>If you are exploring CodeIgniter for the very first time, you should start by reading the <a href="user_guide/">User Guide</a>. </p> <p><br />Page rendered in {elapsed_time} seconds</p> </body> </html> As you can see, it consists entirely of HTML, with an embedded CSS stylesheet. In this simple example, the controller hasn't passed any variables to the view. Curious about—&ltp> &ltbr/> Page rendered in {elapsed_time} seconds </p>? Take a look at: http://codeigniter.com/user_guide/libraries/benchmark.html. You can name the views the way you want, and don't put the .php extension for them. You will have to specify the extension when loading them, for example: $this->load->view('welcome_message.html');
Read more
  • 0
  • 0
  • 2653

article-image-moodle-19-math-quizzes-part-2
Packt
30 Nov 2009
4 min read
Save for later

Moodle 1.9 Math Quizzes: Part 2

Packt
30 Nov 2009
4 min read
Adding a math quiz Once we've added a question or two to the question bank, we can add a quiz to our course. I want a simple quiz where each student is allowed one attempt with no help along the way. Let's see how to achieve this now: Return to your course's front page, choose a topic, click on the Add an activity drop-down menu, and select Quiz from the list. Give the quiz a name (this will appear on the course's front page) and, if you wish, you can specify a short introduction: Scroll down to the Attempts box. Set Attempts allowed to 1 and Adaptive mode to No: Scroll down to the bottom of the page, and click the Save and display button. A split screen page is displayed with the course question bank on the right and the (currently empty) quiz on the left: To add questions from the question bank to the quiz, simply select them and click on the Add to quiz button: The questions are now added to the quiz. You'll now see them listed on the left-hand side of the page: To preview the quiz, click on the Preview tab at the top of the page: That's it! The quiz is now configured. Recall that I set Adaptive mode to No. Adaptive mode adds a Submit button to each question, allowing students (with some suitable feedback from me) to learn from their mistakes as they work through the quiz. Try experimenting with this setting. See how your students behave with the Submit button. For example, don't let them think that they can guess a multiple choice answer until they eventually get it right. Remind them that they'll be penalized for each wrong answer. Encouraging students as they attempt the quiz You've seen that there are a lot of settings I've simply ignored as I've configured this quiz. Return to your course's front page, and click on Questions from the course administration block to open the course Question bank. Click on the edit icon next to the numerical question we configured earlier in this article. (Have you spotted that you can tell what type of question it is from the icon on the far-right? Hover the mouse pointer over the icon.): Remember how I mentioned that I'd started filling out feedback? I'm going to finish doing that now in this question by giving some General feedback: When you are happy with your feedback, remember to scroll to the bottom of the page and click on the Save changes button. Now, return to your course's front page, turn editing on, and click on the update icon next to the quiz we added in the previous section: On the quiz configuration page, scroll down to the Attempts section and set Adaptive mode to Yes: Scroll to the bottom of the page, and click on the Save changes button. Preview the quiz now, and notice that under each question there is a Submit button. Experiment with entering both correct and incorrect responses. Click on the Submit button, and see how Moodle reacts by giving the student our feedback. Remember: if you are planning to use Adaptive mode, then it's worth reminding your students that they will be penalized if they get an answer wrong! Reporting quiz results What's great about a Moodle quiz is the detailed reporting Moodle provides for us. Here is an example of the report page for my quiz once a student has attempted it. (In fact, this is a colleague of mine helping me to check that my feedback is understandable!): Such reporting not only allows us to see what our students have been up to, but I also find it an invaluable tool for determining the success of my teaching. Once someone has attempted your quiz, you can no longer modify it (add or remove questions). You will need to delete the attempts to unlock the quiz.
Read more
  • 0
  • 0
  • 1883
article-image-drag-and-drop-yui-part-2
Packt
30 Nov 2009
12 min read
Save for later

Drag-and-Drop with the YUI: Part-2

Packt
30 Nov 2009
12 min read
Scripting DragDrop There are two ways that we could go about achieving our objective. We could take the easy way and treat each draggable object as an independent module, with its own independent properties and event handlers. This would make the code simpler, but would mean that we would require a good deal more of it. If there are just one or two objects on your page which can be dragged and dropped then this way is fine. However, when you begin to have more than just a couple of objects that can be moved, the amount of code required to handle these objects efficiently increases dramatically. The second way may be a little more complex and therefore will require a greater degree of understanding. However, this way allows for sharing properties and event handlers across similar drag-and-drop objects. This reduces the overall footprint of your application and saves us an incredible amount of typing. Creating Individual Drag Objects We can look at both methods, so you can see just how much work the second way saves us. We'll start with the easy method. Add the following <script> tag directly before the closing </body> tag: <script type="text/javascript">//create the namespace object for this exampleYAHOO.namespace("yuibook.dd");//define the setDDs functionYAHOO.yuibook.dd.setDDs = function() {//detect the useragentvar ua = YAHOO.env.ua;if (ua.ie != 0) {ua.data = "ie";}//define variablesvar basketTotal = 0;var basketTot = 0;var Dom = YAHOO.util.Dom;//create the 3 DragDropProxy objectsvar dd1 = new YAHOO.util.DDProxy("prod1");dd1.isTarget = false;dd1.scroll = false;var dd2 = new YAHOO.util.DDProxy("prod2");dd2.isTarget = false;dd2.scroll = false;var dd3 = new YAHOO.util.DDProxy("prod3");dd3.isTarget = false;dd3.scroll = false;var basket = new YAHOO.util.DDTarget("basket");//define function to call when dd1 starts being draggeddd1.startDrag = function() {//set cursor position to top-left of proxydd1.setDelta(0,0);}//define function to call when dd1 stops being dragdeddd1.endDrag = function() {}//define function to call when dd1 enters basketdd1.onDragEnter = function(e, id) {//has dd1 been dragged into basket?if (id == "basket") {//add 1 to the total number of itemsbasketTotal += 1;var tot = YAHOO.util.Dom.get("basketTotal")tot.innerHTML = basketTotal;//create new p element to hold product summaryvar p = document.createElement("p");Dom.addClass(p, "prod");p.id = "prod" + basketTotal;//add icon for product 1 to basketvar ico = document.createElement("img");ico.setAttribute("src", "images/prod1_ico.jpg");ico.id = "imageico" + basketTotal;Dom.addClass(ico, "icon");//add product 1 summary to basketp.appendChild(ico);Dom.get("basketBody").appendChild(p);//create new p element for product 1 titlevar p2 = document.createElement("p");var info = Dom.get("prod1info");//is the browser IE?if (ua.data == "ie") {var infos = info.innerHTML.split("<BR>");} else {var infos = info.innerHTML.split("<br>");}//set product 1 titlevar title = document.createTextNode(infos[0]);Dom.addClass(p2, "prodTitle");p2.id = "prodTitle" + basketTotal;//add title to basketp2.appendChild(title);Dom.insertAfter(p2, Dom.get(ico));//create p element for product 1 pricevar p3 = document.createElement("p");var price = document.createTextNode(infos[1]);Dom.addClass(p3, "prodPrice");p3.id = "prodPrice" + basketTotal;//add product 1 price to basketp3.appendChild(price);Dom.insertAfter(p3, Dom.get(p2));//update total basket priceprice = Dom.get(p3).innerHTML;var rawPrice = price.slice(1,6);var cost = parseFloat(rawPrice);basketTot += cost;var newBasketTot = Dom.get("basketCost");newBasketTot.innerHTML = basketTot;}}//define function to call when dd2 starts being draggeddd2.startDrag = function() {dd2.setDelta(0,0);}//define function to call when dd2 stops being draggeddd2.endDrag = function() {}//define function to call when dd2 enters basketdd2.onDragEnter = function(e, id) {if (id == "basket") {//add 1 to the total number of itemsbasketTotal += 1;var tot = YAHOO.util.Dom.get("basketTotal")tot.innerHTML = basketTotal;//create new p element to hold product summaryvar p = document.createElement("p");Dom.addClass(p, "prod");p.id = "prod" + basketTotal;//add icon for product 2 to basketvar ico = document.createElement("img");ico.setAttribute("src", "images/prod2_ico.jpg");ico.id = "imageico" + basketTotal;Dom.addClass(ico, "icon");//add product 2 summary to basketp.appendChild(ico);Dom.get("basketBody").appendChild(p);//create new p element for product 2 titlevar p2 = document.createElement("p");var info = Dom.get("prod2info");//is the browser IE?if (ua.data == "ie") {var infos = info.innerHTML.split("<BR>");} else {var infos = info.innerHTML.split("<br>");}//set product 2 titlevar title = document.createTextNode(infos[0]);Dom.addClass(p2, "prodTitle");p2.id = "prodTitle" + basketTotal;//add title to basketp2.appendChild(title);Dom.insertAfter(p2, Dom.get(ico));//create p element for product 2 pricevar p3 = document.createElement("p");var price = document.createTextNode(infos[1]);Dom.addClass(p3, "prodPrice");p3.id = "prodPrice" + basketTotal;//add product 2 price to basketp3.appendChild(price);Dom.insertAfter(p3, Dom.get(p2));//update total basket priceprice = Dom.get(p3).innerHTML;var rawPrice = price.slice(1,6);var cost = parseFloat(rawPrice);basketTot += cost;var newBasketTot = Dom.get("basketCost");newBasketTot.innerHTML = basketTot;}}//define function to call when dd3 starts being draggeddd3.startDrag = function() {dd3.setDelta(0,0);}//define function to call when dd3 stops being draggeddd3.endDrag = function() {}//define function for when dd3 enters basketdd3.onDragEnter = function(e, id) {if (id == "basket") {//add 1 to the total number of itemsbasketTotal += 1;var tot = YAHOO.util.Dom.get("basketTotal")tot.innerHTML = basketTotal;//create new p element to hold product summaryvar p = document.createElement("p");Dom.addClass(p, "prod");p.id = "prod" + basketTotal;//add icon for product 3 to basketvar ico = document.createElement("img");ico.setAttribute("src", "images/prod3_ico.jpg");ico.id = "imageico" + basketTotal;Dom.addClass(ico, "icon");//add product 3 summary to basketp.appendChild(ico);Dom.get("basketBody").appendChild(p);//create new p element for product 3 titlevar p2 = document.createElement("p");var info = Dom.get("prod3info");//is the browser IE?if (ua.data == "ie") {var infos = info.innerHTML.split("<BR>");} else {var infos = info.innerHTML.split("<br>");}//set product 3 titlevar title = document.createTextNode(infos[0]);Dom.addClass(p2, "prodTitle");p2.id = "prodTitle" + basketTotal;//add title to basketp2.appendChild(title);Dom.insertAfter(p2, Dom.get(ico));//create p element for product 3 pricevar p3 = document.createElement("p");var price = document.createTextNode(infos[1]);Dom.addClass(p3, "prodPrice");p3.id = "prodPrice" + basketTotal;//add product 3 price to basketp3.appendChild(price);Dom.insertAfter(p3, Dom.get(p2));//update total basket priceprice = Dom.get(p3).innerHTML;var rawPrice = price.slice(1,6);var cost = parseFloat(rawPrice);basketTot += cost;var newBasketTot = Dom.get("basketCost");newBasketTot.innerHTML = basketTot;}}}//execute setDDs when DOM is readyYAHOO.util.Event.onDOMReady(YAHOO.yuibook.dd.setDDs);</script> All of the code here sits within the setDDs() function, which is called using the Event utility's onDOMReady() method. The first section of code within the setDDs() function uses the .env.ua() method of the YAHOO global object to determine the user-agent string of the browsing environment. We can use this as a quick and easy way of detecting the browser being used to view the page. The ie property exists within the ua object even if IE is not in use, but if it isn't in use, the property is set to 0. Therefore, if the ie property does not equal to 0 it means that IE is the browser currently being used. In this case, the ie property will hold an integer representing the version of IE in use. When IE is being used, we set the data property of our ua variable to the string ie. We then create a series of variables for use in the script. The last variable is created purely for convenience. We'll be making heavy use of the DOM utility during this example, so defining that first part of the DOM call as a short variable helps make things easier on us. Next we create all three of the individual DDProxy objects. Remember, in this implementation, each object has to have its own properties and event handlers defined for it. We also define the basket as a DDTarget so that we can make use of the .onDragEnter() method. Because we want each product to interact only with our shopping basket and not the other products on the page, we have to set the .isTarget property to false. As well as being able to specifically create drop targets using the YAHOO.util.DDTarget class, any drag object is by default also a drop target. Additionally, we can switch off the .scroll property, which causes the viewport to scroll indefinitely when the dragged object exceeds the window boundary. Using DragDrop Events Three event handlers are required for this example: startDrag, endDrag, and onDragEnter. The startDrag event fires as soon as the left mouse button has been held down for the required length of time on a drag object, or the pointer moves the specified number of pixels. The .setDelta() method used in the startDrag event handler allows us to control where the pointer is relative to the drag object, or in this case, the proxy element. By specifying 0,0 as arguments for this method, we are instructing the pointer to appear at the top-left corner of the proxy element. This is needed so that the element is placed back where it began instead of where the pointer was relative to the drag object when the drag began. The endDrag event fires when a mouseup event is detected on the object being dragged. The anonymous function here has a very special purpose, even though it is just an empty function.What it does is ensure that the item being dragged is returned to its original position once it has been dropped instead of remaining where it was dropped. This is important because if we didn't keep the listing pictures in their proper locations, the page would soon be littered with abandoned drag objects. The onDragEnter event fires when the moving object is dragged over a legal target. Since the shopping basket is the only valid target on the page, this will fire whenever a product object is dragged over the basket. This function is where the bulk of our code lies. Two arguments are specified for this function. The first is the event object, which is automatically passed to our handler. The second argument is the id of the element that triggered the event, which in this example will be the basket. We first use our YAHOO.util.Dom shortcut to get the <span> element displaying the number of items in the basket, then use the innerHTML property to alter this value in accordance with the basketTotal variable. We create a new paragraph element and give it a class of prod. This new element will act as a container for a short summary of the item placed in the basket. We can go ahead and create the different items that will make up this short description of the product that has been purchased. A new <img> element is created and stored in the ico variable. Its src attribute is set to the icon representing the product. We then give it a class name so that we can style it and an id attribute so that we can identify it. Once created and configured, we can append the <img> to the new <p> element, and then append the <p> element to the body of the basket. Now let's work on extracting some of the listing description to display in the basket. We create another new <p> element and give it a class of prodTitle. We then need to do more detection to determine which product was dropped, getting the full listing text of the product in the title variable once we have. Each part of the listing text is separated by a <br> element, so we can create an array of each different bit of information contained in the listing text using the .split() method. This is the part of the script where we use the information gathered from the ua property earlier on. IE for some reason capitalizes all HTML elements in the DOM. This means that IE sees <BR> tags, while other browsers see <br>, and is the reason we need the if statement to determine the browser in use. The first item in the infos array is the name of the product, so we can use this as the title for the product summary and create a new textNode based on it. This title element is then inserted into the DOM directly after the icon element using the DOM utility's .insertAfter() method, which takes the element to insert and the element it should be inserted after as arguments. For good measure, let's add the price of the product to the product summary. A final element is created to hold a new textNode comprised of the second item in the infos array, which happens to be the price of the product. The class for the new <p> element is set and it is then inserted as a sibling of the previous element that was created. At the bottom of our basket is a price indicator showing the total cost of all items in the basket; we can easily update this using the same method as we updated the basket contents total earlier on. We recycle the price variable, updating it with the HTML element from the basket. As the price is currently a text string rather than a number, we have to convert it. Before we can do this however, we need to remove the currency symbol from the front of it, which we can do with the .slice() method. Then we can use the standard JavaScript parseFloat math function to convert the remaining string into a true floating-point number. We can then update the current cost by adding the cost of the dropped product to it. Finally, we set the innerHTML property of the basketCost span element to the new total. As each drag object is completely independent, the rest of our script is made up of identical event handlers tied to the other drag objects (products 2 and 3). This is what bloats our code to three times the size it actually needs to be, and imagine how much typing would need to be done if there were 30 products on the page
Read more
  • 0
  • 0
  • 1295

article-image-business-process-orchestration-soa
Packt
30 Nov 2009
7 min read
Save for later

Business Process Orchestration for SOA

Packt
30 Nov 2009
7 min read
Process Orchestration can simply be defined as the coordination of events and activities in a process at technical levels, to help achieve objectives laid down by the business. From an SOA perspective, orchestration involves direction and management of multiple component services to create a composite application or an end-to-end process. While orchestration tends to imply a single central engine performing the coordination act, another overlapping concept of choreography applies to sharing this coordination activity across multiple autonomous systems. BPM Architecture and Role of Business Process Orchestration While we are covering orchestration  for SOA, it is worthwhile to also discuss reference architecture for BPM, to understand how all components of technology fit together for modeling, executing, monitoring, and optimizing a business process. Following an architecture-lead approach, as always, is a good way to initially guide BPM projects. It is not necessary to implement all aspects of this architecture from day one, but as we mature with our BPM implementation, its coverage can be increased to gain maximum value. From the perspective of this article, this reference architecture provides an understanding of how process execution and orchestration is a core activity in bridging the abstract business models and underlying SOA infrastructure. If you look at the following architecture for BPM, you will realize that it is divided into layers and groups. The vertical right side covers the aspects of modeling the processes, business rules, and services. The horizontal stack starts with the presentation layer, which allows multiple channels through which a company's customers, employees, and partners can interact. It could be a web portal, a hand-held device, and so on. These channels are supported by the process orchestration layer, which assists in orchestrating different aspects of a business process to provide information to respective users in a channel. In this layer, we will have a process engine that will take inputs from the presentation layer and interface with underlying technologies and services to complete an end-to-end process. This layer will be responsible for ensuring that information is gathered from all sources at the right time, to enable a smooth process flow. The requirements for process orchestration will be fed by the activities performed by the business modeling team and the development teams, working on the process models using standards such as BPMN and BPEL. The orchestration layer will then interface with what we call 'Enterprise Services', which could be business services, technical services, or utility services, available either as basic services, or a composition of multiple services required to support the process orchestration. To enable access to these enterprise-level services, we will have an integration layer or an Enterprise Service Bus, which will provide a standards-based interface to multiple systems within or outside the organization, and also human service providers. We also have a layer of data management services that will be different high-level data sources that the BPM landscape will use. An example is a service registry to manage multiple services or metadata, which will manage information about all of the available data sources in the landscape to which this process has access. On the vertical left side, we have the monitoring services, which will capture all the events generated by the process to help in analyzing the process performance against key performance indicators laid down by the business. As we move ahead in this article, we will use this reference architecture to understand how various technology components fit together. Let us now go ahead with an example to see how we can orchestrate a process using Oracle BPEL Process Manager. Executing BPEL Processes in BPEL Process Manager One of the fundamental benefits of using a BPM system for modeling a business process – in this case the Oracle suite of products – is to allow models created using BPMN at the business level to be executed, and to automate manual processes. It also allows a business to evaluate gaps in current processes and identify the remedial actions that can be implemented quickly using the execution engine. When working on the example for the 'Portfolio Account Opening' process, we created the business process model using BPMN, analyzed the process, converted the BPMN model into a process blueprint to be shared by the development teams, filled the technical gaps, and enriched and finally deployed the process to the BPEL Process Manager. Let us take the next step in understanding how our deployed process will work, and the functionality it offers to the users working on this process. Our aim is to make you aware of how process-driven SOA works for an end-to-end process. This explanation assumes that you have some working knowledge of BPEL constructs such as activities, partnerlinks and so on. XSD and WSDL are used with in the JDeveloper environment to create and deploy BPEL processes. For a detailed understanding of BPEL and its complex constructs, you may want to refer to these resources. For our case, we will use a simplistic representation of information, tasks and moving from one task to another. Let us go through a series of steps to trigger an instance of the account opening process: Initiation of the Process Instance First, let us initiate the services related to SOA Suite. You can open them by selecting Start SOA suite from the Program menu. After the SOA suite services have started, we will open the SOA Launch Console, which provides a dashboard for all tools under the SOA suite that can be accessed from this location. To open the console, you can either enter the URL, which is typically http://localhost:8888; unless you have specified something specific during your installation. You can also access the console from the Program menu and select SOA Launch Console. The following screenshot shows what the SOA Suite console looks like. And As you can see, it provides, in addition to from all the product literature and technical guides, links to the main components of the SOA suite including BPEL Control, which is highlighted in the image. Open the Oracle BPEL Process Manager administration interface by clicking the BPEL Control link to access the details of the account opening process we deployed earlier. The first screen we see is the Process Dashboard, which provides us with the information on the currently-deployed processes in the database. As we can see, we have our 'Portfolio Account Opening Process'. There are currently some instances of the processes already running, and some instances have completed recently. To test the flow of the process and its behavior, trigger a new process instance for the deployed process through this console. To do this, click on the 'Portfolio_Account_Opening_Process' link on the dashboard to access details of our deployed process, and initiate a new instance. In a production environment, this step could be automated through a customized graphical interface. We will use the BPEL Process Manager to initiate this test process. As you can see, the BPEL process Portfolio_Account_Opening_Process has been deployed from the development environment inside the BPEL Process Manager. To initiate the process instance, we have used a simple string as the input. In this case, we will just start the process by providing Open Account as the payload string, and posting the XML message to initiate the process instance. To check whether the process instance has started, we can view the visual flow for the instance by clicking the visual flow link. The following visual flow shows that we have triggered the instance of the process, and it has reached a stage where the bank has received the application.
Read more
  • 0
  • 0
  • 5335
Modal Close icon
Modal Close icon