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
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon

How-To Tutorials - Web Design

132 Articles
article-image-organizing-your-balsamiq-files
Packt
09 Oct 2012
3 min read
Save for later

Organizing your Balsamiq files

Packt
09 Oct 2012
3 min read
There are two important things to note about organizing your files in Balsamiq: Keep all of your .bmml files together. The assets folder houses everything else, that is, artwork, logos, PDFs, PSDs, symbols, and so on, as shown in the following screenshot: Naming your files Naming your files in Balsamiq is very important. This is because Balsamiq does not automatically remember the order in which you organized your files after you closed them. Balsamiq will reopen them in the order in which they are sitting in a folder. There are, however, two ways you can gain greater control. Alphabetically You could alphabetize your files, although this could pose a problem as you add and delete files, requiring you to carefully name the new files so that they open in the same order as before. While it is a fine solution, the time it takes to ensure proper alphabetization does not seem worth the effort. Numbering The second, and more productive way, to name your files is to not name them at all, but instead to number them. For example, after naming a new .bmml file, add a number to the end of it in sequential order, for example, filename_1, filename_2, filename_3, and so on. Subpages, in turn, become filename_1a, filename_1b, filename_1c, and so on. Keep in mind, however, that if you add, delete, or modify numbered files, you may still have to modify the remaining page numbers accordingly. Nevertheless, I suspect you will find it to be easier than alphabetizing. Another way to number your files can be found on Balsamiq's website. The link to the exact page is a bit long. Go to http://www.balsamiq.com/ and do a search for Managing Projects in Mockups for Desktop. In the article, they recommend an alternate method of numbering your files by 10s, for example, filename_10, filename_20, filename_30, and so on. The idea being that as you add or remove pages, you can do so incrementally, rather than having to do a complete renumbering each time. In other words, you could add numbers between 11 and 19 and still be fine. Keep in mind that if you choose to use single digits, be sure to add a zero before the filename for consistency and to ensure proper file folder organization, for example, filename_05, filename_06, filename_07, and so on. How you name or number your files is completely up to you. These tips are simply recommendations to consider. The bottom line is to find a system for naming your files that works for you and to stick with it. You will be glad you did.
Read more
  • 0
  • 0
  • 1208

article-image-planning-your-site-adobe-muse
Packt
27 Sep 2012
11 min read
Save for later

Planning Your Site in Adobe Muse

Packt
27 Sep 2012
11 min read
Page layouts The layout of your website can be a deciding factor on whether your visitors will stay on your website or leave with an impatient click. You could think of the layout as a map. If it's easy for the visitors to "read" the map, they are more likely to stick around and find the content you're providing. Let's take a look at some of the typical layouts we see on the Web today. Bread and butter layouts When we're designing a layout for a web page, there are a number of sections that we need to include. These sections can be broken into the following: Consistent content: This does not change throughout the site. Examples of this type of content are logos, navigation bars, and footers. Changing content: This is the part of the page that changes throughout the site, usually the main content. In some situations, the content of the sidebar may also change. A web designer's job is to create a layout that keeps the visitor focused on the content while keeping it nice and easy to navigate around the site. Some examples of conventional or bread and butter site layouts are shown in the following figure: You have a very short amount of time to capture a visitor's attention. So by choosing one of these basic layouts, you're using a tried and tested setup, which many web users will feel at home with. Don't worry that these layouts look "boxy". You can use images, colors, and typefaces, which complement the purpose of your site to completely disguise the fact that every web page is essentially made up of boxes. The bread and butter layouts featured previously are well-tested guides; however, there is absolutely no obligation for you to use one of these. What appears on a typical web page? So we've seen some basic layouts. Now we'll look at some of the elements that appear on (nearly) every web page. Logo The logo is the part of a company's overall branding and identity, and appears at the top of each page on the site along with the company name and tagline, just as it would on printed forms of marketing, such as business cards, brochures, and letterheads. This identity block increases brand recognition and ensures users know that the pages they're viewing are part of a single site. Frequently, the logo is also a link back to the home page of the site. Navigation bar The navigation for your site should be easy to use and easy to find. Just like the logo, it should appear near the top of the page. You may decide to use a horizontal menu across the top of the page, a vertical menu in a sidebar, or a combination of the two. Either way, your main navigation should be visible "above the fold", that is, any area of a web page that can be viewed without visitors having to scroll. Content Content is the King. This is what your visitors have come for. If the visitors can't find what they're looking for, they will move on very quickly. The main content is an important focal point in your design; don't waste time fling it with unnecessary "stuff". Footer Sitting at the bottom of the page, the footer usually holds copyright information, contact links information, and legalities of the site. Some designers have become very imaginative with footers and use this area to hold additional links, tweets, and "about me" information. The footer clearly separates the main content from the end of the page and indicates to users that they're at the bottom of the page. In the following screenshot, you can see a page from the Apple website, which is highly regarded for its aesthetic design. Each section is clearly delineated. If you keep in mind the idea of your site's layout as a map, then you can determine where you want to lead your visitors on the site. Wireframes Wireframing is an important part of the design process for both simple and complex projects. If you're creating a website for a client, a wireframe is a great tool for communicating your ideas visually at an early stage rather than just having a verbal description. If you're creating a website for yourself, the wireframe helps to clarify what is required on each page of your website. It can be considered an overlap between the planning process and the design process. Creating a simple wireframe ensures that your page designs take into account all of the elements you'll add to your pages and where they will be positioned. Wireframes are cost-effective because the time spent in the initial stages potentially saves you from losing much more time revising the design at a later stage. Wireframes can be created in several ways, including pen and paper and computer-based tools. When it comes to computer-based applications for wireframing, there are many options available. Some designers use Photoshop, Illustrator, or even InDesign to put together their wireframes. Specific wireframing software packages that are popular with web designers include Balsamiq and OmniGraffe. Wireframes and Mockups and Prototypes. Oh my! You may hear web designers refer to wireframes, mockups, and prototypes. Although these terms are sometimes used interchangeably, it's important to understand that they are three different things. A wireframe is a basic illustration showing the structure and components of a web page. A mockup is an image file focusing on the design elements in the site. It contains the graphics and other page elements that make up the web page but may contain dummy text and images. A prototype is an almost-complete or semi-functional web page, constructed with HTML and CSS. Prototypes give the client (or yourself) the ability to click around and check out how the final site will work. What to include in a wireframe? Think about which design elements will appear on each page of your website. As mentioned already, most websites will have elements such as logos, navigation, search bars, and footers in consistent positions throughout the site. Next, think about any extra elements that may be specific to individual pages. These include graphics and dynamic widgets. Once you know what's required, you can start to create your wireframe based on these elements. Some designers like to create their wireframes with the "big picture" in mind. Once the basic layout is in place, they get feedback from the client and revise the wireframe if necessary. Others like to create a very detailed wireframe for each page on the site, including every single design element on the list before showing it to the client. Wireframes let us try out several different ideas before settling on our favorite design, which can then be brought forward to the mockup stage. Obviously our focus in this book is on using Muse, but I would urge you not to rule out using paper sketches. It's a great way to quickly get ideas out of your head and into a tangible, visible layout. Web.without.words (www.webwithoutwords.com) is an interesting website dedicated to showing popular and well-known sites as wireframes. The text and images on each site are blocked out and it's a nice way to look at web pages and see how they can be broken down into simple boxes without getting caught up in the content. Wireframes with Muse So what are the advantages of using Muse to create our wireframes? Well, Muse not only lets you create wireframes, but it also allows you to quickly create prototypes using those wireframes. This means you can show clients the functionality of the website with the basic layout. The prototype produced by Muse can be reviewed on any web browser giving the client a good idea of how the site will appear. This kind of early testing can help alleviate time-consuming problems further down the line of the design process. We're going to prepare a site and wireframe now for a fictitious website about windsurfing. First, we'll create a new site, and then add pages in the Plan view. Site structure with Plan view. Let's start by creating a new site. Open Muse. Choose File | New Site. In the New Site dialog box, set Page Width to 960 and Min Height to 800 pixels. Set Margins to 0 all around and Padding Top and Bottom to 10 pixels each. Set the number of Columns to 16. The columns appear as guidelines on the page and we use them to help us align the design elements on our layout. Note that Gutter is set to 20 by default, leave this as it is. The Column Width is calculated by Muse and you should see a value of 41 appear automatically in that field. Remember that all of these values can be changed later if necessary. Click on OK. The Plan view opens and you'll see a thumbnail representing the Home page at the top left, and a thumbnail representing the A-Master page on the bottom pane. Save your site right away by selecting File | Save Site. Give it a descriptive name you'll recognize, such as Windsurf.muse. To create new pages, click on the plus (+) sign to the right of or below the existing pages, and then click on the page's name field to type its name. Click on the plus sign to the right of the Home page and name the new page Gear. Click on the plus sign below the Gear page to add a subpage and name that page Sails. Click on the plus sign to the right of the Sails page and name the new page Boards. Sails and Boards are now on the same level and are subpages of the Gear page. Click on the plus sign to the right of the Gear page and name the new page Learning. Click on the plus sign to the right of Learning and add one more page called Contact. Your Plan view should now look like the following screenshot: Working with thumbnails in the Plan view It's easy to add, delete, reposition, or duplicate pages when working in the Plan view. Right-click (Win) or Ctrl + click (Mac) on a thumbnail to see a contextual menu. This menu provides every option for managing your pages. In the previous screenshot, you can see the menu that appears when you right-click/Ctrl + click.   New Child Page: This option creates a new blank page at a lower level as the current thumbnail. New Sibling Page: This option creates a new blank page at the same level as the current thumbnail. Duplicate Page: This option makes an exact copy of the current page. This is most useful when you have added content and applied some formatting. Delete Page: This option gets rid of the page. Rename Page: This option allows us to change the name of the page. Go to Page: This option opens up the current page in the Design view. Page Properties: This option opens the Page Properties dialog box allowing you to set properties for the current page only. Reset Page Properties: This option reverts to the original settings for the page. Export Page: This option allows you to export your page as HTML and CSS. Menu Options: This option allows you to choose how the page will be included (or not included) in the automatically-created menu. Masters: This option lets you choose which Master design will be applied to the page. The context menu is not the only way to get to these options, for example the most common tasks in the Plan view can be completed as follows: You can rename a page by double-clicking on the page name You can delete a page by hovering your mouse over the thumbnail and then clicking on the x icon that appears in the top-right corner To reposition a page in your site map hierarchy, you can drag-and-drop a thumbnail on the same level or on a sublevel. Spend a couple of minutes adding, deleting, and repositioning pages so that you get a feel of creating the site structure. You'll find the Plan view to be intuitive to use and extremely fast for creating site maps. You can choose Edit | Undo to undo any of the steps you've taken. Muse tracks all the page names, and later in the design process it allows us to create menus quickly using menu widgets. All links created in the Plan view are maintained and are updated automatically if we make a change to the site structure. You can come back to the Plan view at any point during your web design process.
Read more
  • 0
  • 0
  • 2760

article-image-wordpress-customizing-content-display
Packt
14 Dec 2011
8 min read
Save for later

WordPress: Customizing Content Display

Packt
14 Dec 2011
8 min read
(For more resources on WordPress, see here.) At its most basic, a simple implementation of the loop could work like this: <?php if (have_posts()) : while (have_posts()) : the_post(); ?><?php the_title(); ?><?php the_content(); ?><?php endwhile; else: ?><p>Sorry, no posts matched your criteria.'</p><?php endif; ?> In the real world, however, the WordPress loop is rarely that simple. This is one of those concepts best explained by referring to a real world example, so open up the index.php file of your system's TwentyEleven theme. Look for the following lines of code: <?php if ( have_posts() ) : ?><?php twentyeleven_content_nav( 'nav-above' ); ?><?php /* Start the Loop */ ?><?php while ( have_posts() ) : the_post(); ?><?php get_template_part( 'content', get_post_format()); ?><?php endwhile; ?><?php twentyeleven_content_nav( 'nav-below' ); ?><?php else : ?><article id="post-0" class="post no-results not-found"><header class="entry-header"><h1 class="entry-title"><?php _e( 'Nothing Found','twentyeleven' ); ?></h1></header><!-- .entry-header --><div class="entry-content">3<p><?php _e( 'Apologies, but no results were foundfor the requested archive. Perhaps searching will helpfind a related post.', 'twentyeleven' ); ?></p><?php get_search_form(); ?></div><!-- .entry-content --></article><!-- #post-0 --><?php endif; ?> Most of the extra stuff seen in the loop from TwentyEleven is there to add in additional page elements, including content navigation; there's also some code to control what happens if there are no posts to display. The nature of the WordPress loops means that theme authors can add in what they want to display and thereby customize and control the output of their site. As you would expect, the WordPress Codex includes an extensive discussion of the WordPress loop. Visit http://codex.wordpress.org/The_Loop. Accessing posts within the WordPress loop In this recipe, we look at how to create a custom template that includes your own implementation of the WordPress loop. Getting ready All you need to execute this recipe is your favorite code editor and access to the WordPress files on your server. You will also need a theme template file, which we will use to hold our modified WordPress loop. How to do it Let's assume you have created a custom template. Inside of that template you will want to include the WordPress loop. Follow these steps to add the loop, along with a little customization: Access the active theme files on your WordPress installation. Find a template file and open it for editing. If you're not sure which one to use, try the index.php file. Add to the file the following line of code, which will start the loop: <?php if ( have_posts() ) : while ( have_posts() ) : the_post();?> Next, let's display the post title, wrapped in an h2 tag: <h2><?php the_title() ?></h2> Let's also add a link to all posts by this author. Add this code immediately below the previous line: <?php the_author_posts_link() ?> For the post content, let's wrap it in a div for easy styling: <div class="thecontent"><?php the_content(); ?></div> Next, let's terminate the loop and add some code to display a message if there were no posts to display: <?php endwhile; else: ?><p>Oops! There are no posts to display.</p> Finally, let's put a complete stop to the loop by ending the if statement that began the code in step number 3, above: <?php endif; ?> Save the file. That's all there is to it. Your code should look like this: ?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?><h2><?php the_title() ?></h2><?php the_author_posts_link() ?><div class="thecontent"><?php the_content(); ?></div><?php endwhile; else: ?><p>Oops! There are no posts to display.</p><?php endif; ?> How it works... This basic piece of code first checks if there are posts in your site. If the answer is yes, the loop will repeat until every post title and their contents are displayed on the page. The post title is displayed using the_title(). The author's name and link are added with the_ author_posts_link() function. The content is displayed with the_content() function and styled by the div named thecontent. Finally, if there are no posts to display, the code will display the message Oops! There are no posts to display. There's more... In the preceding code you saw the use of two template tags: the_author_posts_link and the_content. These are just two examples of the many template tags available in WordPress. The tags make your life easier by reducing an entire function to just a short phrase. You can find a full list of the template tags at: http://codex.wordpress.org/ Template_Tags. The template tags can be broken down into a number of categories: General tags: The tags in this category cover general page elements common to most templates Author tags: Tags related to author information Bookmark tags: The tag to list bookmarks Category tags: Category, tag, and item description-related Comment tags: Tags covering the comment elements Link tags: Tags for links and permalinks Post tags: Tags for posts, excerpts, titles, and attachments Post Thumbnail tags: Tags that relate to the post thumbnails Navigation Menu tags: Tags for the nav menu and menu tree Retrieving posts from a specific category There are times when you might wish to display only those posts that belong to a specific category, for example, perhaps you want to show only the featured posts. With a small modification to the WordPress loop, it's easy to grab only those posts you want to display. In this recipe we introduce query_posts(),which can be used to control which posts are displayed by the loop. Getting ready To execute this recipe, you will need a code editor and access to the WordPress files on your server. You will also need a theme template file, which we will use to hold our modified WordPress loop. To keep this recipe short and to the point, we use the loop we created in the preceding recipe. How to do it... Let's create a situation where the loop shows only those posts assigned to the Featured category. To do this, you will need to work through two different processes. First, you need to find the category ID number of the Featured category. To do this, follow these steps: Log in to the Dashboard of your WordPress site. Click on the Posts menu. Click on the Categories option. Click on the category named Featured. Look at the address bar of your browser and you will notice that part of the string looks something like this:&tag_ID=9. On the site where we are working, the Featured category has the ID of 9. Category IDs vary from site to site. The ID used in this recipe may not be the same as the ID for your site! Next, we need to add a query to our loop that will extract only those posts that belong to the Featured category, that is, to those posts that belong to the category with the ID of 9. Follow these steps: Open the file that contains the loop. We'll use the same file we created in the preceding recipe. Find the loop: <?php if ( have_posts() ) : while ( have_posts() ) :the_post(); ?><h2><?php the_title() ?></h2><?php the_author_posts_link() ?><div class="thecontent"><?php the_content(); ?></div><?php endwhile; else: ?><p>Oops! There are no posts to display.</p><?php endif; ?> Add the following line of code immediately above the loop: <?php query_posts($query_string.'&cat=9'); ?> Save the file. That's all there is to it. If you visit your site, you will now see that the page displays only the posts that belong to the category with the ID of 9. How it works... The query_posts() function modifies the default loop. When used with the cat parameter, it allows you to specify one or more categories that you want to use as filters for the posts. For example: query_posts(&query_string.'&cat=5');: Get posts from the category with ID 5 only query_posts(&query_string.'&cat=5,6,9');: Get posts from the category with IDs 5, 6, and 9 query_posts(&query_string.'&cat=-3');: Get posts from all categories, except those from the category with ID 3 For more information, visit the WordPRess Codex page on query posts: http://codex.wordpress.org/Function_Reference/query_posts
Read more
  • 0
  • 0
  • 1127
Banner background image

article-image-building-html5-pages-scratch
Packt
19 Oct 2011
13 min read
Save for later

Building HTML5 Pages from Scratch

Packt
19 Oct 2011
13 min read
  (For more resources on HTML5, see here.) In the course of building pages using just HTML5 layout elements, in this article, we will explore all four advantages of relying on HTML5 as listed above. Dreamweaver CS5 and HTML5 Before diving in to create HTML5 pages from scratch, let's survey how we are going to get our money's worth out of Dreamweaver in the process. All recent versions of Dreamweaver (CS3, CS4, and CS5) with the HTML5 Pack installed can assist our work in creating HTML5 pages from scratch in three ways. First, with the HTML5 Pack installed, code hints that automatically prompts us in completing HTML5 coding are updated in Code view for HTML5 elements. Those code hints will help us avoid mistakes in spelling elements or constructing the (minimalist) coding syntax that we will need to place HTML5 elements. Second, we will avail ourselves of Split view, so that we will see our layout congealing in Design view as we sketch out what code we need to create in Split view. Third, we will take advantage of what is arguably the single most valuable panel in Dreamweaver—the CSS Styles panel. We will be defining CSS Style rules to associate with each of the HTML5 layout elements we use. Without styles, HTML5 layout elements are nothing, so the interplay between the HTML5 elements we create and formatting we do with the CSS Styles panel will drive our page design process. Moreover, here it is important to review, or at least reinforce two foundational techniques in building any professional-quality website in Dreamweaver: Do nothing without first defining a Dreamweaver site. Secondly, and not quite so essential but still pretty foundational, we always work with external style sheets. This allows the styles we define to be applied globally, across an entire website, and makes updating sites possible. As we begin to coordinate styling in the CSS Styles panel and constructing pages with HTML5 elements, I will be reminding you and when necessary walking you through the steps required to make sure all styles are saved to an external style sheet. With this as a preview, and cautionary reminder, let's dive in to creating pages with HTML5 layout elements. Building an HTML5 page from the top As opposed to laying out pages with tables (grids of rows and columns), or non-standardized Div tags (layout blocks you name and define yourself), we will use HTML5's new, standardized layout elements. The most basic of these are self-explanatory <header>, <nav>, <article> and <section>, <aside>, and <footer> tags. In addition, as alluded to in the introduction to this article, we will use additional elements to help make content more accessible to search engines. For example, within articles, we will use new HTML5 elements that make it easy for people looking for online content (or those making such online content accessible through various forms of search engines) to find things such as the publication date of content, or the date of an upcoming event. HTML5 structural elements In order to alert browsers that we are presenting HTML5 content, we need to indicate at the top of our HTML5 code that this is an HTML5 page. As for those browsers that respond, "huh, what's that?", we will address that challenge shortly. However, first use the following steps to create a new HTML5 page from scratch: With your Dreamweaver site defined, choose File | New. In the New Document dialog, choose Blank Page from the category list on the left of the dialog. Choose HTML in the Page Type column. Choose None in the Layout column. In the Layout CSS popup if you already have a CSS file you use with HTML layouts, you can choose Link to Existing File, and select your existing HTML5-related CSS file as the styles file for your page. From the DocType popup choose HTML5 as shown in the following screenshot: (Move the mouse over the image to enlarge.) Click on Create to generate the blank page. A blank page appears in Design view of the Document window. In Split view, we can see some basic code has been generated: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Untitled Document</title> </head> <body> </body> </html> Let's briefly walk through this to situate ourselves. The <!DOCTYPE HTML> and <html> tags are sort of evolutionary holdovers from previous versions of HTML, and not actually required for HTML5 browsers. This code though, might be useful when taking into account non-HTML5 browsers, as we will examine shortly. The <head> and </head> tags d emarcate head content that is not displayed on the page, but serves as instructions to browsers. In this case, the content inside identifies that the current, most widely applicable character set, UTF-8, is implemented. This character set allows the display of characters from a wide range of languages. All the content we create for the page will be placed within the <body> and </body> tags. For this reason, our first step in creating our CSS styles for this page, will be to define a couple of basic attributes for the </body> tag. Finally, save this page as an HTML file. Choose File | Save. In the Save As dialog, make sure the folder selected in the Where popup is your Dreamweaver site folder (or a subfolder within that). Give the file a name, like html5_test, and click on Save. While we are at it, enter a descriptive title in the Title box of the Document toolbar. Resave periodically. Creating a CSS file H and-in-hand with our HTML5 fi le, we will create and use a CSS fi le to organize and manage all the styling in the page. Therefore, let's create that CSS fi le now, and as we do, add a line that will make our HTML5 page compatible with all current browsers, and most older ones. To do that, follow these steps: Choose File | New, and in the New Document dialog, choose the Blank Page category on the left, and CSS from the Page Type category. Click on Create to generate, and open a new CSS file. The file opens in Code view. We will be editing it in the CSS Styles panel, so except as a learning experience we won't need to view this page again. However, we do need to save it. Choose File | Save, and give the file a name like html5_layout.css. Make sure the site folder is selected in the Where pop up, and click on Save as shown in the following screenshot: In the tab bar at the top of the document window, toggle back to the HTML file you created, as shown in the following screenshot: View the CSS STYLES panel if it is not visible (choose Window | CSS Styles), and click on the Attach Style Sheet icon as shown in the following screenshot: The Attach External Style Sheet dialog appears. Use the Browse button to navigate to the CSS fi le you just created, and click on OK to attach the style sheet. The CSS fi le appears in the CSS Files panel (use the All tab in the CSS Styles panel as the norm, unless you are doing particular styles detective work that requires the Current tab). You will also see the link to the CSS file in Code view if you look. Next, we will add a single attribute that enables most browsers to interpret the HTML5 elements, even if they are not HTML5 compliant. To do that, follow these steps: Click on the New CSS Rule icon at the bottom of the CSS Styles panel, it is just to the right of the Attach Style Sheet icon identified in the preceding screenshot. The New CSS Rule dialog opens. In the New CSS Rule dialog, choose Compound from the first popup. We are creating a rule that will apply to more than one HTML5 layout element. These are HTML5 tags that we want to prevent from collapsing when viewed in non-HTML5 browsers. In the Choose or Enter a Name for Your Selector field, enter header. We actually want to apply the rule we are working on to additional HTML5 elements, but we will add those shortly. In the Rule Definition section of the dialog, make sure your attached CSS fi le is selected (it will be by default). Click on OK. In the CSS Rule Definition for header dialog, select the Block category, and choose block from the display popup as shown in the following screenshot, then click on OK. The Header style appears in the CSS Styles panel when you expand the CSS Styles file linked to the page. You can see that the display property for the header style has a block attribute associated with it in the CSS styles panel. We want to expand the list of HTML5 elements to which this display:block attribute is assigned. The long, slow way to do that is to duplicate steps we have traversed so far for each additional element. To do that the quick, easy way, click once in the header row, in the top half of the CSS Styles panel, and edit the list of elements to include address, article, footer, nav, section. Use commas (",") to separate the additional elements as you type them in. These are HTML5 tags that we want to prevent from collapsing when viewed in non-HTML5 browsers. The CSS Styles panel should now look like the following screenshot: With the preceding set of steps, we have told most non-HTML5 browsers to keep our basic HTML5 building-block elements on their own distinct horizontal row, so they don't smush into each other. Our basic model and scenario here is creating pages that are intended only for HTML5 browsers (like iPhones or iPads). Using HTML5 to make content accessible Having set up our HTML5 document with basic web page coding, we are now ready to create and format the HTML5 layout elements that will define how the page looks. But wait… as the TV pitchmen say… there's more! Before diving into the page design dimension of HTML layout elements, it will be helpful to quickly survey another reason to use HTML layout elements to organize content: accessibility. As alluded to in the introduction to this article, there are advantages beyond design considerations for relying on HTML5 layout elements to organize page content. These advantages revolve around the way HTML5 layout elements package content for metadata compilers (such as search engines). This emerging connection can make content organized into HTML5 layout elements more searchable, easier to organize and access. Moreover, this will be even more the case in the future as search engines and other web content organizing tools integrate HTML5 layout elements. We will take a rather simple, but interesting example of how this works right now. If you have ever copied and pasted the content between apps on an iPhone (for example, the address of a web page into an app that helps you find public transportation options or content from an article or posting that you read online in an e-mail), then you maybe familiar with the routine where you hold your finger down on the screen and are prompted with a Copy prompt. The next step is to use the somewhat awkward process of using one's fingers to define the content to copy to the clipboard, as shown in the following screenshot:   On the other hand, when content is organized into articles (or sections), a touch on the iPhone screen instantly selects an article or article section for copying, as shown in the following screenshot:   Now, in terms of added value to a website, the convenience associated with iPhone users easily selecting articles or article sections probably isn't going to turn the world upside down, although visitors are likely to note positively the convenience they experience selecting articles from your page to share. However, the fact that the iPhone browser recognizes sections (and articles, and other HTML5 layout elements) also gives a sense of the potential for the associations between content and HTML5 layout elements to make content more accessible. We can expect, for example, that in the not-so-far-off-future, people will be able to tune their search engine queries for "articles" about this or that topic. HTML5 layout and search engines: By relying on HTML5 layout elements to organize page content, you are building (in advance) support for search tools and other ways that HTML5 will facilitate finding content. HTML5 layout strategy Having surveyed the emerging value of organizing content into HTML5 layout elements, we turn to the more dramatically impactful aspect of using HTML5 layout elements: design. However, keep in mind; design and content are linked in HTML5. Unlike previous generations of web page markup language, HTML5 organizes content both to facilitate displaying that content, and to facilitate accessing that content. A basic HTML5 page layout is illustrated in the following screenshot, with self-explanatory placeholder text: The visible borders in the preceding screenshot, by the way, are a product of Dreamweaver CS5's CSS Layout Outlines (if they are not functioning, choose View | Visual Aids | CSS Layout Outlines). Again, before diving into an exploration of the specific elements in HTML5 layouts, and how they are implemented, keep in mind they both define design components of the page, and organize content. Using code hints Dreamweaver, with the HTML5 Pack, is HTML5-friendly, but not exactly HTML5-compatible. By this, I mean that it is necessary to resort to Code view to apply HTML5 elements. However, within that, you get help. As noted earlier, Dreamweaver CS5 helps create the coding for HTML5 code hints. As you begin typing HTML5 elements in Code view, beginning with "<", Dreamweaver prompts you with a set of tags that begin with the letter you type. So, for example, typing <he produces the following code hints, from which you can click on <<>header and press Enter (Windows) or Return (Mac) to place the code. You can use control spacebar on Mac or PC to bring up the full code hinting list. To close (define the end of) an HTML5 layout element, simply type </. When you do that, Dreamweaver auto-enters the close coding for the open element, as shown in the following screenshot:   As we walk through the coding involved in defining different HTML5 layout elements in the remainder of this article, you can enter the necessary code in Split view, utilizing code hints, and seeing the results in the Design half of Split view.  
Read more
  • 0
  • 0
  • 2194

article-image-python-3-designing-tasklist-application
Packt
08 Jun 2011
7 min read
Save for later

Python 3: Designing a Tasklist Application

Packt
08 Jun 2011
7 min read
  Python 3 Web Development Beginner's Guide Use Python to create, theme, and deploy unique web applications         Read more about this book       (For more resources on Python, see here.) Designing a tasklist application   Designing an application should start with a clear idea of what is expected. Not only to determine what is technically required, but almost as important, to define clear boundaries so that we don't lose time on things that are just nice to have. Nice to have features are something to be added if there is time left in the project. Thehighlightedcodesetstherotationofthecircletofalse.Withoutthis,therevolute jointwouldbejustaweld jointintheend. So let's draw up a shortlist of the relevant features of our tasklist application. Some of these may seem obvious, but as we will see, these have a direct impact on some implementation choices that we have to make, such as: The application will be used by multiple users Task lists should be stored indefinitely A task list may contain an unlimited number of tasks but the user interface is designed for optimal performance for up to 25 tasks or so Tasks may be added, deleted, and marked as done Although this list isn't exhaustive, it has some important implications. The fact that the tasklist application will be used by more than one user means that we have to identify and authorize people who want to use it. In other words, we will need some sort of logon screen and a way to check people against some sort of password database. Because we do not want to burden the user with identifying himself/herself each and every time a task list is refreshed or altered, we need some way of implementing the concept of a session. Web applications use the stateless HTTP protocol. This means, from the server's point of view, every request is a single, unrelated event, and no information is retained at the server. This obviously presents us with a problem if we want to perform a set of related actions. The solution is to ask the web browser to send a small piece of information along with every request it makes to the application after the application has identified the user. This might be accomplished in a number of ways. The server may add an extra parameter to all links inside any web page it generates, commonly referred to as a session id, or use the even more general concept of a cookie. Once the server asks the web browser to store a cookie, this cookie is sent with every following request to the same website. The advantage of cookies is that common web application frameworks (like CherryPy) are already equipped to deal with them and implementing sessions with cookies is much simpler than designing the application to alter all hyperlinks it generates to include a proper session ID. The disadvantage might be that people may block their browser from storing cookies because some websites use them to track their clicking behavior. We let the simplicity of implementation prevail and opt for cookies. If users want to block cookies this is not much of a problem as most browsers also have the option to selectively allow cookies from designated websites. The following image illustrates the way CherryPy manages sessions with the help of cookies: It starts when the client (the web browser) sends a request to CherryPy. Upon receiving the request, the first check is to see if the web browser has sent along a cookie with a session ID. If it didn't, a new session idea is generated. Also, if there was a cookie with a session ID, if this ID is no longer valid (because it has expired, for example, or is a remnant from a very old interaction and doesn't exist in the current cache of session IDs) CherryPy also generates a new session ID. At this point, no persistent information is stored if this is a new session, but if it's an existing session there might be persistent data available. If there is, CherryPy creates a Session object and initializes it with the available persistent data. If not, it creates an empty Session object. This object is available as a global variable cherrypy.session. The next step for CherryPy is to pass control to the function that will handle the request. This handler has access to the Session object and may change it, for example, by storing additional information for later reuse. (Note that the Session object acts like a dictionary so you can simply associate values with keys with cherrypy.session['key']=value. The only restriction to the keys and values is that they must be serializable if the persistent storage is on disk). Then before returning the results generated by the handler, CherryPy checks if the Session object has changed. If (and only if) it has, are the contents of the Session object saved to a more permanent storage. Finally, the response is returned accompanied by a cookie with the session ID. Time for action – creating a logon screen Our first task is to create a small application that does little more than present the user with a logon screen. It will be the starting point of our tasklist application and many others as well. The code for this example is available from the Packt website. If you have not downloaded it yet, this might be a good time to do so. Enter the following pieces of code and save it in a file called logonapp.py import cherrypy import logon class Root(object): logon = logon.Logon(path="/logon", authenticated="/", not_authenticated="/goaway") @cherrypy.expose def index(self): username=logon.checkauth('/logon') return ''' <html><body> <p>Hello user <b>%s</b></p> </body></html>'''%username @cherrypy.expose def goaway(self): return ''' <html> <body><h1>Not authenticated, please go away.</h1> </body></html>''' @cherrypy.expose def somepage(self): username=logon.checkauth('/logon',returntopage=True) return '''<html> <body><h1>This is some page.</h1> </body> </html>''' if __name__ == "__main__": import os.path current_dir = os.path.dirname(os.path.abspath(__file__)) cherrypy.quickstart(Root(),config={ '/': {'tools.sessions.on': True } } ) If you now run logonapp.py, a very simple application is available on port 8080. It presents the user with a logon screen when the top level page http://localhost:8080/ is accessed. An example is shown in the following illustration: If a correct username/password combination is entered, a welcome message is shown. If an unknown username or wrong password is entered, the user is redirected to http://localhost:8080/goaway. The somepage() method (highlighted) returns a page with (presumably) some useful content. If the user is not yet authenticated, the logon screen is shown and upon entering the correct credentials, the user is directed back to http://localhost:8080/somepage. The complete tree of web pages within the logon sample application and the possible paths the user may pick through is shown next: Logon + session ID vs. HTTP basic authentication You may wonder why we choose not to reuse CherryPy's bundled auth_basic tool that offers basic authentication (for more information on this tool, see http://www.cherrypy.org/wiki/BuiltinTools#tools.auth_ basic). If all we wanted was to check whether a user is allowed access to a single page, this would be a good choice. The basic authentication is sufficient to authenticate a user, but has no concept of a session. This means we lack a way to store data that needs to be accessible when we process subsequent requests by the same user. The sessions tool we use here does provide this additional functionality.
Read more
  • 0
  • 0
  • 2791

article-image-python-3-building-wiki-application
Packt
19 May 2011
17 min read
Save for later

Python 3: Building a Wiki Application

Packt
19 May 2011
17 min read
Python 3 Web Development Beginner's Guide Nowadays, a wiki is a well-known tool to enable people to maintain a body of knowledge in a cooperative way. Wikipedia (http://wikipedia.org) might be the most famous example of a wiki today, but countless numbers of forums use some sort of wiki and many tools and libraries exist to implement a wiki application. In this article, we will develop a wiki of our own, and in doing so, we will focus on two important concepts in building web applications. The first one is the design of the data layer. The second one is input validation. A wiki is normally a very public application that might not even employ a basic authentication scheme to identify users. This makes contributing to a wiki very simple, yet also makes a wiki vulnerable in the sense that anyone can put anything on a wiki page. It's therefore a good idea to verify the content of any submitted change. You may, for example, strip out any HTML markup or disallow external links. Enhancing user interactions in a meaningful way is often closely related with input validation. Client-side input validation helps prevent the user from entering unwanted input and is therefore a valuable addition to any application but is not a substitute for server-side input validation as we cannot trust the outside world not to try and access our server in unintended ways. The data layer A wiki consists of quite a number of distinct entities we can indentify. We will implement these entities and the relations that exist between them by reusing the Entity/Relation framework developed earlier. Time for action – designing the wiki data model As with any application, when we start developing our wiki application we must first take a few steps to create a data model that can act as a starting point for the development: Identify each entity that plays a role in the application. This might depend on the requirements. For example, because we want the user to be able to change the title of a topic and we want to archive revisions of the content, we define separate Topic and Page entities. Identify direct relations between entities. Our decision to define separate Topic and Page entities imply a relation between them, but there are more relations that can be identified, for example, between Topic and Tag. Do not specify indirect relations: All topics marked with the same tag are in a sense related, but in general, it is not necessary to record these indirect relations as they can easily be inferred from the recorded relation between topics and tags. The image shows the different entities and relations we can identify in our wiki application. In the diagram, we have illustrated the fact that a Topic may have more than one Page while a Page refers to a single User in a rather informal way by representing Page as a stack of rectangles and User as a single rectangle. In this manner, we can grasp the most relevant aspects of the relations at a glance. When we want to show more relations or relations with different characteristics, it might be a good idea to use more formal methods and tools. A good starting point is the Wikipedia entry on UML: http://en.wikipedia.org/wiki/Unified_Modelling_Language. What just happened? With the entities and relations in our data model identified, we can have a look at their specific qualities. The basic entity in a wiki is a Topic. A topic, in this context, is basically a title that describes what this topic is about. A topic has any number of associated Pages. Each instance of a Page represents a revision; the most recent revision is the current version of a topic. Each time a topic is edited, a new revision is stored in the database. This way, we can simply revert to an earlier version if we made a mistake or compare the contents of two revisions. To simplify identifying revisions, each revision has a modification date. We also maintain a relation between the Page and the User that modified that Page. In the wiki application that we will develop, it is also possible to associate any number of tags with a topic. A Tag entity consists simply of a tag attribute. The important part is the relation that exists between the Topic entity and the Tag entity. Like a Tag, a Word entity consists of a single attribute. Again, the important bit is the relation, this time, between a Topic and any number of Words. We will maintain this relation to reflect the words used in the current versions (that is, the last revision of a Page) of a Topic. This will allow for fairly responsive full text search facilities. The final entity we encounter is the Image entity. We will use this to store images alongside the pages with text. We do not define any relation between topics and images. Images might be referred to in the text of the topic, but besides this textual reference, we do not maintain a formal relation. If we would like to maintain such a relation, we would be forced to scan for image references each time a new revision of a page was stored, and probably we would need to signal something if a reference attempt was made to a non-existing image. In this case, we choose to ignore this: references to images that do not exist in the database will simply show nothing: Chapter6/wikidb.py from entity import Entity from relation import Relation class User(Entity): pass class Topic(Entity): pass class Page(Entity): pass class Tag(Entity): pass class Word(Entity): pass class Image(Entity): pass class UserPage(Relation): pass class TopicPage(Relation): pass class TopicTag(Relation): pass class ImagePage(Relation): pass class TopicWord(Relation): pass def threadinit(db): User.threadinit(db) Topic.threadinit(db) Page.threadinit(db) Tag.threadinit(db) Word.threadinit(db) Image.threadinit(db) UserPage.threadinit(db) TopicPage.threadinit(db) TopicTag.threadinit(db) ImagePage.threadinit(db) TopicWord.threadinit(db) def inittable(): User.inittable(userid="unique not null") Topic.inittable(title="unique not null") Page.inittable(content="", modified="not null default CURRENT_TIMESTAMP") Tag.inittable(tag="unique not null") Word.inittable(word="unique not null") Image.inittable(type="",data="blob",title="", modified="not null default CURRENT_TIMESTAMP", description="") UserPage.inittable(User,Page) TopicPage.inittable(Topic,Page) TopicTag.inittable(Topic,Tag) TopicWord.inittable(Topic,Word) Because we can reuse the entity and relation modules we developed earlier, the actual implementation of the database layer is straightforward (full code is available as wikidb.py). After importing both modules, we first define a subclass of Entity for each entity we identified in our data model. All these classes are used as is, so they have only a pass statement as their body. Likewise, we define a subclass of Relation for each relation we need to implement in our wiki application. All these Entity and Relation subclasses still need the initialization code to be called once each time the application starts and that is where the convenience function initdb() comes in. It bundles the initialization code for each entity and relation (highlighted). Many entities we define here are simple but a few warrant a closer inspection. The Page entity contains a modified column that has a non null constraint. It also has a default: CURRENT_TIMESTAMP (highlighted). This default is SQLite specific (other database engines will have other ways of specifying such a default) and will initialize the modified column to the current date and time if we create a new Page record without explicitly setting a value. The Image entity also has a definition that is a little bit different: its data column is explicitly defined to have a blob affinity. This will enable us to store binary data without any problem in this table, something we need to store and retrieve the binary data contained in an image. Of course, SQLite will happily store anything we pass it in this column, but if we pass it an array of bytes (not a string that is), that array is stored as is. The delivery layer With the foundation, that is, the data layer in place, we build on it when we develop the delivery layer. Between the delivery layer and the database layer, there is an additional layer that encapsulates the domain-specific knowledge (that is, it knows how to verify that the title of a new Topic entity conforms to the requirements we set for it before it stores it in the database): Each different layer in our application is implemented in its own file or files. It is easy to get confused, so before we delve further into these files, have a look at the following table. It lists the different files that together make up the wiki application and refers to the names of the layers. We'll focus on the main CherryPy application first to get a feel for the behavior of the application. Time for action – implementing the opening screen The opening screen of the wiki application shows a list of all defined topics on the right and several ways to locate topics on the left. Note that it still looks quite rough because, at this point, we haven't applied any style sheets: Let us first take a few steps to identify the underlying structure. This structure is what we would like to represent in the HTML markup: Identify related pieces of information that are grouped together. These form the backbone of a structured web page. In this case, the search features on the left form a group of elements distinct from the list of topics on the right. Identify distinct pieces of functionality within these larger groups. For example, the elements (input field and search button) that together make up the word search are such a piece of functionality, as are the tag search and the tag cloud. Try to identify any hidden functionality, that is, necessary pieces of information that will have to be part of the HTML markup, but are not directly visible on a page. In our case, we have links to the jQuery and JQuery UI JavaScript libraries and links to CSS style sheets. Identifying these distinct pieces will not only help to put together HTML markup that reflects the structure of a page, but also help to identify necessary functionality in the delivery layer because each of these functional pieces is concerned with specific information processed and produced by the server. What just happened? Let us look in somewhat more detail at the structure of the opening page that we identified. Most notable are three search input fields to locate topics based on words occurring in their bodies, based on their actual title or based on tags associated with a topic. These search fields feature auto complete functionality that allows for comma-separated lists. In the same column, there is also room for a tag cloud, an alphabetical list of tags with font sizes dependent on the number of topics marked with that tag. The structural components The HTML markup for this opening page is shown next. It is available as the file basepage.html and the contents of this file are served by several methods in the Wiki class implementing the delivery layer, each with a suitable content segment. Also, some of the content will be filled in by AJAX calls, as we will see in a moment: Chapter6/basepage.html <html> <head> <title>Wiki</title> <script src= "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"> </script> <script src= "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.3/jquery-ui.min.js" type="text/javascript"> </script> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/ jqueryui/1.8.3/themes/smoothness/jquery-ui.css" type="text/css" media="all" /> <link rel="stylesheet" href="/wiki.css" type="text/css" media="all" /> </head> <body> <div id="navigation"> <div class="navitem"> <a href="./">Wiki Home</a> </div> <div class="navitem"> <span class="label">Search topic</span> <form id="topicsearch"> <input type="text" > <button type="submit" >Search</button> </form> </div> <div class="navitem"> <span class="label">Search word</span> <form id="wordsearch"> <input type="text" > <button type="submit" >Search</button> </form> </div> <div class="navitem"> <span class="label">Search tag</span> <form id="tagsearch"> <input type="text" > <button type="submit" >Search</button> </form> </div> <div class="navitem"> <p id="tagcloud">Tag cloud</p> </div> </div> <div id="content">%s</div> <script src="/wikiweb.js" type="text/javascript"></script> </body> </html> The <head> element contains both links to CSS style sheets and <script> elements that refer to the jQuery libraries. This time, we choose again to retrieve these libraries from a public content delivery network. The highlighted lines show the top-level <div> elements that define the structure of the page. In this case, we have identified a navigation part and a content part and this is reflected in the HTML markup. Enclosed in the navigation part are the search functions, each in their own <div> element. The content part contains just an interpolation placeholder %s for now, that will be filled in by the method that serves this markup. Just before the end of the body of the markup is a final <script> element that refers to a JavaScript file that will perform actions specific to our application and we will examine those later. The application methods The markup from the previous section is served by methods of the Wiki class, an instance of which class can be mounted as a CherryPy application. The index() method, for example, is where we produce the markup for the opening screen (the complete file is available as wikiweb.py and contains several other methods that we will examine in the following sections): Chapter6/wikiweb.py @cherrypy.expose def index(self): item = '<li><a href="show?topic=%s">%s</a></li>' topiclist = "n".join( [item%(t,t)for t in wiki.gettopiclist()]) content = '<div id="wikihome"><ul>%s</ul></div>'%( topiclist,) return basepage % content First, we define the markup for every topic we will display in the main area of the opening page (highlighted). The markup consists of a list item that contains an anchor element that refers to a URL relative to the page showing the opening screen. Using relative URLs allows us to mount the class that implements this part of the application anywhere in the tree that serves the CherryPy application. The show() method that will serve this URL takes a topic parameter whose value is interpolated in the next line for each topic that is present in the database. The result is joined to a single string that is interpolated into yet another string that encapsulates all the list items we just generated in an unordered list (a <ul> element in the markup) and this is finally returned as the interpolated content of the basepage variable. In the definition of the index() method, we see a pattern that will be repeated often in the wiki application: methods in the delivery layer, like index(), concern themselves with constructing and serving markup to the client and delegate the actual retrieval of information to a module that knows all about the wiki itself. Here the list of topics is produced by the wiki.gettopiclist() function, while index() converts this information to markup. Separation of these activities helps to keep the code readable and therefore maintainable. Time for action – implementing a wiki topic screen When we request a URL of the form show?topic=value, this will result in calling the show() method. If value equals an existing topic, the following (as yet unstyled) screen is the result: Just as for the opening screen, we take steps to: Identify the main areas on screen Identify specific functionality Identify any hidden functionality The page structure is very similar to the opening screen, with the same navigational items, but instead of a list of topics, we see the content of the requested topic together with some additional information like the tags associated with this subject and a button that may be clicked to edit the contents of this topic. After all, collaboratively editing content is what a Wiki is all about. We deliberately made the choice not to refresh the contents of just a part of the opening screen with an AJAX call, but opted instead for a simple link that replaces the whole page. This way, there will be an unambiguous URL in the address bar of the browser that will point at the topic. This allows for easy bookmarking. An AJAX call would have left the URL of the opening screen that is visible in the address bar of the browser unaltered and although there are ways to alleviate this problem, we settle for this simple solution here. What just happened? As the main structure we identified is almost identical to the one for the opening page, the show() method will reuse the markup in basepage.html. Chapter6/wikiweb.py @cherrypy.expose def show(self,topic): topic = topic.capitalize() currentcontent,tags = wiki.gettopic(topic) currentcontent = "".join(wiki.render(currentcontent)) tags = ['<li><a href="searchtags?tags=%s">%s</a></li>'%( t,t) for t in tags] content = ''' <div> <h1>%s</h1><a href="edit?topic=%s">Edit</a> </div> <div id="wikitopic">%s</div> <div id="wikitags"><ul>%s</ul></div> <div id="revisions">revisions</div> ''' % ( topic, topic, currentcontent,"n".join(tags)) return basepage % content The show() method delegates most of the work to the wiki.gettopic() method (highlighted) that we will examine in the next section and concentrates on creating the markup it will deliver to the client. wiki.gettopic() will return a tuple that consists of both the current content of the topic and a list of tags. Those tags are converted to <li> elements with anchors that point to the searchtags URL. This list of tags provides a simple way for the reader to find related topics with a single click. The searchtags URL takes a tags argument so a single <li> element constructed this way may look like this: <li><a href="searchtags?tags=Python">Python</a></li>. The content and the clickable list of tags are embedded in the markup of the basepage together with an anchor that points to the edit URL. Later, we will style this anchor to look like a button and when the user clicks it, it will present a page where the content may be edited.  
Read more
  • 0
  • 0
  • 7931
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 $19.99/month. Cancel anytime
article-image-faqs-wordpress-3
Packt
15 Feb 2011
10 min read
Save for later

FAQs on WordPress 3

Packt
15 Feb 2011
10 min read
  WordPress 3 Complete Create your own complete website or blog from scratch with WordPress Learn everything you need for creating your own feature-rich website or blog from scratch Clear and practical explanations of all aspects of WordPress In-depth coverage of installation, themes, plugins, and syndication Explore WordPress as a fully functional content management system Clear, easy-to-follow, concise; rich with examples and screenshots         Read more about this book       (For more resources on WordPress, see here.) Q: What is WordPress? A: WordPress is an open source blog engine. Open source means that nobody owns it, everybody works on it, and anyone can contribute to it. Blog engine means a software application that can run a blog. It's a piece of software that lives on the web server and makes it easy for you to add and edit posts, themes, comments, and all of your other content. More expansively, WordPress can be called a publishing platform because it is by no means restricted to blogging.   Q: Why choose WordPress? A: WordPress is not the only publishing platform out there, but it has an awful lot to recommend it. A long time in refining Active in development Large community of contributors Amazingly extendable Compliant with W3C standards Multilanguage capable     Q: What are the system requirements for WordPress? A: The minimum system requirement for WordPress is a web server with the following software installed: PHP Version 4.3 or greater MySQL Version 4.1.2 or greater Although Apache and Nginx are highly recommended by the WordPress developers, any server running PHP and MySQL will do.     Q: What are the new features since 2.7? A: If you're new to WordPress, this list may not mean a whole lot to you, but if you're familiar with WordPress and have been using it for a long time, you'll find this list quite enlightening. The following are the new features: Adding support for "include" and "exclude" to [gallery] Changes Remove link on widgets to Delete because it doesn't just remove it, it deletes the settings for that widget instance Syntax highlighting and function lookup built into plugin and theme editors Improved revision comparison user interface Lots of new template files for custom taxonomies and custom post types, among others Browsing the theme directory and installing themes from the admin Allowing the dashboard widgets to be arranged in up to four columns Choosing username and password during installation rather than using "admin"     Q: How do I upgrade the existing Wordpress version with the latest one? A:If you're upgrading from a very early version of WordPress to a very recent version, you should do it in steps. That is, if you find yourself in a situation where you have to upgrade across a large span of version numbers, for example from 2.2 to 3.0.3, I highly recommend doing it in stages. Do the complete upgrade from 2.2 to 2.3.3, then from 2.3.3 to 2.5, then from 2.5 to 2.7, and finally from 2.7 to 3.0.3. When doing this, you can usually do the full content and database backup just once, but verify in between versions that the gradual upgrades are going well before you move onto the next one. You can download the previous stable versions of WordPress from this page: http://wordpress.org/download/release-archive/. Of course, another option would be to simply do a new installation of the latest version of WordPress and then move your previous content into it, and I encourage you to consider this course of action. However, sometimes contents are harder to move than it is to do the upgrades; this will be up to you to decide your specific server situation and your comfort level with the choices.   Q: What is the WordPress Codex? A: The WordPress Codex is the central repository of all the information the official WordPress team has published to help people work with WordPress. The Codex has some basic tutorials for getting started with WordPress, such as a detailed step-by-step discussion of installation, lists of every template tag and hook, and a lot more.     Q: Is WordPress available for download? A: WordPress is available in easily downloadable formats from its website, http://wordpress.org/download/. WordPress is a free, open source application, and is released under GNU General Public License (GPL). Take a look at the following screenshot in which the download links are available on the right side: The .zip file is shown as a big blue button because that'll be the most useful format for the most people. If you are using Windows, Mac, or Linux operating systems, your computer will be able to unzip that downloaded file automatically. (The .tar.gz file is provided because some Unix users prefer it.)     Q: What is the WordPress Admin Panel? A: WordPress installs a powerful and flexible administration area where you can manage all of your website content, and do much more. You can always get to the WP Admin by going to this URL: http://yoursite.com/wp-admin/. Your first time here, you'll be re-directed to the login page. In the future, WordPress will check to see if you're already logged in and, if so, you'll skip the login page. Following is the login page:     Q: How do I create a post on the blog that I created? A: To create a post, just click on New Post on the top menu. You'll be taken to the following page: Every post should have, at minimum, a title and some content. So go ahead and write in some text for those two things. When you are happy with it, click on the Publish button.     Q: What do I do if I have lost my password? A: If you have lost your password and can't get into your WP Admin panel, you can easily retrieve your password by clicking on the Lost your password? link on the login page. A newly generated password will be e-mailed to you at the e-mail address you gave during the WordPress installation. This is why you need to be sure that you enter a valid e-mail address. Otherwise, you will not be able to retrieve your password.   Q: What do you mean by Categories and Tags? A: Categories and tags are two types of information that you can add to a blog post. We use them to organize the information in your blog by topic and content (rather than just by, say, date), and to help visitors find what they are looking for on your blog.   Q: Which editor is used for writing and editing posts? A: WordPress comes with a Visual editor, otherwise known as a WYSIWYG editor. This is the default editor for typing and editing your posts. If you're comfortable with HTML, you may prefer to write and edit your posts using the HTML editor—particularly useful if you want to add special content or styling. To switch from the rich text editor to the HTML editor, click on the HTML tab next to the Visual tab at the top of the content box: You'll see your post in all its raw HTML glory, and you'll get a new set of buttons that lets you quickly bold and italicize text, as well as add link code, image code, and so on. You can make changes and swap back and forth between the tabs to see the result.     Q: What are Timestamps and how are they useful? A: WordPress will also let you alter the timestamp of your post. This is useful if you are writing a post today that you wish you'd published yesterday, or if you're writing a post in advance and don't want it to show up until the right day. By default, the timestamp will be set to the moment you publish your post. To change it, just find the Publish box, and click on the Edit link (next to the calendar icon and Publish immediately), and fields will show up with the current date and time for you to change: Change the details, click on the OK button, and then click on Publish to publish your post (or save a draft).     Q: Is there any way in which I can protect my content? A: WordPress gives you the option to hide posts. You can hide a post from everyone but yourself by marking it Private, or you can hide it from everyone but the people with whom you share a password by marking it as Password protected. To implement this, look at the Publish box at the upper right of the Edit Post page. If you click on the Edit link next to Visibility: Public, a few options will appear: If you click on the Password protected radio button, you'll get a box where you can type a password. Visitors to your blog will see the post title along with a note that they have to type in a password to read the post. If you click on the Private radio button, the post will not show up on the blog at all to any viewers, unless you are the viewer and you are logged in. If you leave the post Public and check the Stick this post to the front page checkbox, this post will be the first post on the front page, regardless of its publication date. Be sure to click on the OK button if you make any changes.     Q: What is a Widget? A: A widget is a small box of content, dynamic or not, that shows up somewhere on a widget-enabled site. Often, that location is in the sidebar of a blog, but that's not a rule. A widget area can be anywhere a theme developer wants it to be. Common widgets contain: A monthly archive of blog posts Recent comments posted on the blog A clickable list of categories A tag cloud A search box, and so on     Q: How do I add an Image gallery to my post? A: You can add an image gallery to any page or post in your website using WordPress's built-in Image Gallery functionality. There are just three simple steps: Choose a post or page for your image gallery. Upload the images you want in that gallery. Add a plugin, such as lightbox plugin, that will streamline your gallery, and save it. A lightbox effect is when the existing page content fades a little and a new item appears on top of the existing page. We can easily add the same effect to your galleries by adding a plugin. There are a number of lightbox plugins available, but the one I like these days uses jQuery Colorbox. Find this plugin, either through the WP Admin or in the Plugins Repository (http://wordpress.org/extend/plugins/jquery-colorbox/), and install it.   Summary In this article we covered some of the most frequently asked questions on WordPress 3. Further resources on this subject: WordPress 2.8 Themes Cookbook [Book] Getting Started with WordPress 3 [Article] How to Create an Image Gallery in WordPress 3 [Article] Performing Setup Tasks in the WordPress Admin Panel [Article]
Read more
  • 0
  • 0
  • 1198

article-image-performing-setup-tasks-wordpress-admin-panel
Packt
02 Feb 2011
3 min read
Save for later

Performing Setup Tasks in the WordPress Admin Panel

Packt
02 Feb 2011
3 min read
  WordPress 3 Complete Create your own complete website or blog from scratch with WordPress Learn everything you need for creating your own feature-rich website or blog from scratch Clear and practical explanations of all aspects of WordPress In-depth coverage of installation, themes, plugins, and syndication Explore WordPress as a fully functional content management system Clear, easy-to-follow, concise; rich with examples and screenshots         Read more about this book       (For more resources on Wordpress, see here.) The reader can benefit from the previous article on Getting Started with WordPress 3. After you've successfully installed WordPress, it's time for our first look at the WP Admin. There are some immediate basic changes that I recommend doing right away to make sure your installation is set up properly. You can always get to the WP Admin by going to this URL: http://yoursite.com/wp-admin/. Your first time here, you'll be re-directed to the login page. In the future, WordPress will check to see if you're already logged in and, if so, you'll skip the login page. Following is the login page: To log in, just enter the username and password you chose during the installation. Then click on Log In. Note for the future that on this page there is a link you can use to retrieve your lost password. Whenever you log in, you'll be taken directly to the Dashboard of the WP Admin. Following is a screenshot of the WP Admin that you will see immediately after you log into the blog you just installed: You'll see a lot of information and options here. We will focus on the items that we need to touch upon right after a successful installation. First, let's take a brief look at the top of the WP Admin and the Dashboard. The very top bar, which I'll refer to as the top bar, is mostly a medium grey and contains: A link to the front page of your WordPress website A rollover drop-down menu with handy links to New Post, Drafts, New Page, Upload, and Comments Your username linked to your profile A link to log out You'll also notice the Screen Options tab, which appears on many screens within the WP Admin. If you click on it, it will slide down a checklist of items on the page to show or hide. It will be different on each page. I encourage you to play around with that by checking and unchecking items, as you find you need them or don't need them. On the left, of course, is the main menu: You can click on any word in the main menu to be taken to the main page for that section, or you can click on the rollover arrow to slide down the subpages for that section. For example, if you click on the arrow next to Settings, you'll see the subpages for the Settings section: The top menu and the main menu exist on every page within the WP Admin. The main section on the right contains information for the current page you're on. In this case, we're on the Dashboard. It contains boxes that have a variety of information about your blog, and about WordPress in general. Before WordPress 3, the first thing you'd have to do would be to change the password to something easier to remember. However, now that you can choose your password during installation, this is no longer necessary. Let's jump right to general site settings.  
Read more
  • 0
  • 0
  • 2276

article-image-how-create-image-gallery-wordpress-3
Packt
31 Jan 2011
5 min read
Save for later

How to Create an Image Gallery in WordPress 3

Packt
31 Jan 2011
5 min read
  WordPress 3 Complete Create your own complete website or blog from scratch with WordPress Learn everything you need for creating your own feature-rich website or blog from scratch Clear and practical explanations of all aspects of WordPress In-depth coverage of installation, themes, plugins, and syndication Explore WordPress as a fully functional content management system Clear, easy-to-follow, concise; rich with examples and screenshots         Read more about this book       (For more resources on Wordpress, see here.) Let's get started. Choosing a post or page For my food blog, I'm going to create a new page named My Food Photos for my image gallery. You can always do this on an existing page or post. Following is my new page: Note where I have left my cursor. I made sure to leave it in a spot on the page where I want my gallery to appear, that is, underneath my introductory text (After creating this page, I will also navigate to Appearance | Menus to add it as a subpage under About.). Uploading images Now click on the Upload/Insert image icon and upload some photos (you can choose multiple photos at once). For each photo you upload, enter the title (and a caption if you'd like). When you're done, click on the Save All Changes button. You'll be taken to the Gallery tab, which will show all of the photos you've uploaded to be attached to this page: If you want to upload more photos at this point, just click on the From Computer tab at the top, and upload another photo. When you've uploaded all the photos you want (you can add more later), you may want to change the order of the photos. Just enter the numbers 1 through 6 (or however many photos you have) in the Order column: Make sure you click Save All Changes. On most computers, you can, instead of entering numbers, simply drag-and-drop images. WordPress will then generate the order numbers for you automatically. Then, you can review the Gallery Settings. There are a number of ways to use the gallery, but there is a single approach that I've found works for most people. You can experiment on your own with other settings and plugins, of course! I suggest you set Link thumbnails to to be Image File instead of Attachment Page. You can leave the other settings as they are for now. Once all of your settings are done, click on the Insert gallery button. This overlay box will disappear, and you'll see your post again. The page will have the gallery icon placeholder in the spot where you left the cursor, as seen in the following screenshot: If you're in the HTML view, you'll see the gallery shortcode in that spot: Note that because I'm uploading these photos while adding/editing this particular page, all of these photos will be "attached" to this page. That's how I know they'll be in the gallery on this page. Other photos that I've uploaded to other posts or pages will not be included in this gallery. Learning moreThe [gallery] shortcode is quite powerful! For example, you can actually give it a list of Media ID numbers—any Media item in your Media Library—to include, or you can tell it to just exclude certain items that are attached to this post or page. You can also control how the Thumbnail version of each image shows whether the medium or large. There is more! Take a look at the codex to get all of the parameters: http://codex.wordpress.org/Gallery_Shortcode Now, publish or save your page. When you view the page, there's a gallery of your images as follows: If you click on one of the images, you'll be linked to the larger version of the image. Now, this is not ideal for navigating through a gallery of images. Let's add a plugin that will streamline your gallery. Using a lightbox plugin A lightbox effect is when the existing page content fades a little and a new item appears on top of the existing page. You've seen this effect already in the WP Admin when you clicked on Add/Insert image. We can easily add the same effect to your galleries by adding a plugin. There are a number of lightbox plugins available, but the one I like these days uses jQuery Colorbox. Find this plugin, either through the WP Admin or in the Plugins Repository (http://wordpress.org/extend/plugins/jquery-colorbox/), and install it. Once you've activated the plugin, navigate to Settings | jQuery Colorbox: Use the Theme pull-down to choose the theme you want (the preview image will update to give you an idea of what it will look like); I've chosen Theme #4. Then you can choose to either Automate jQuery Colorbox for all images or Automate jQuery Colorbox for images in WordPress galleries. You can choose whether to automate for all images; I certainly suggest you automate for images in galleries. You can experiment with the other settings on this page (if you routinely upload very large images, you'll want to use the areas that let you set the maximum size of the colorbox and resize images automatically). You'll want to disable the warning (the very last check box on the page). Then, click on Save Changes. Now, when I go to my image gallery page and click on the first image, the colorbox is activated, and I can click Next and Back to navigate through the images: Summary In this article we saw how to add and manage built-in image galleries to display photos and other images. Further resources on this subject: WordPress 3 Complete [Book] WordPress 2.9 E-Commerce [Book] Getting Started with WordPress 3 [Article] How to Write a Widget in WordPress 3 [Article] Understanding jQuery and WordPress Together [Article] Tips and Tricks for Working with jQuery and WordPress [Article]
Read more
  • 0
  • 0
  • 1906

article-image-why-ajax-is-a-different-type-of-software
Packt
27 Jan 2011
14 min read
Save for later

Why Ajax is a different type of software

Packt
27 Jan 2011
14 min read
Ajax is not a piece of software in the way we think about JavaScript or CSS being a piece of software. It's actually a lot more like an overlaid function. But what does that mean, exactly? Why Ajax is a bit like human speech Human speech is an overlaid function. What is meant by this is reflected in the answer to a question: "What part of the human body has the basic job of speech?" The tongue, for one answer, is used in speech, but it also tastes food and helps us swallow. The lungs and diaphragm, for another answer, perform the essential task of breathing. The brain cannot be overlooked, but it also does a great many other jobs. All of these parts of the body do something more essential than speech and, for that matter, all of these can be found among animals that cannot talk. Speech is something that is overlaid over organs that are there in the first place because of something other than speech. Something similar to this is true for Ajax, which is not a technology in itself, but something overlaid on top of other technologies. Ajax, some people say, stands for Asynchronous JavaScript and XML, but that was a retroactive expansion. JavaScript was introduced almost a decade before people began seriously talking about Ajax. Not only is it technically possible to use Ajax without JavaScript (one can substitute VBScript at the expense of browser compatibility), but there are quite a few substantial reasons to use JavaScript Object Notation (JSON) in lieu of heavy-on-the-wire eXtensible Markup Language (XML). Performing the overlaid function of Ajax with JSON replacing XML is just as eligible to be considered full-fledged Ajax as a solution incorporating XML. Ajax helps the client talk to the server Ajax is a way of using client-side technologies to talk with a server and perform partial page updates. Updates may be to all or part of the page, or simply to data handled behind the scenes. It is an alternative to the older paradigm of having a whole page replaced by a new page loaded when someone clicks on a link or submits a form. Partial page updates, in Ajax, are associated with Web 2.0, while whole page updates are associated with Web 1.0; it is important to note that "Web 2.0" and "Ajax" are not interchangeable. Web 2.0 includes more decentralized control and contributions besides Ajax, and for some objectives it may make perfect sense to develop an e-commerce site that uses Ajax but does not open the door to the same kind of community contributions as Web 2.0. Some of the key features common in Web 2.0 include: Partial page updates with JavaScript communicating with a server and rendering to a page An emphasis on user-centered design Enabling community participation to update the website Enabling information sharing as core to what this communication allows The concept of "partial page updates" may not sound very big, but part of its significance may be seen in an unintended effect. The original expectation of partial page updates was that it would enable web applications that were more responsive. The expectation was that if submitting a form would only change a small area of a page, using Ajax to just load the change would be faster than reloading the entire page for every minor change. That much was true, but once programmers began exploring, what they used Ajax for was not simply minor page updates, but making client-side applications that took on challenges more like those one would expect a desktop program to do, and the more interesting Ajax applications usually became slower. Again, this was not because you could not fetch part of the page and update it faster, but because programmers were trying to do things on the client side that simply were not possible under the older way of doing things, and were pushing the envelope on the concept of a web application and what web applications can do. Which technologies does Ajax overlay? Now let us look at some of the technologies where Ajax may be said to be overlaid. JavaScript JavaScript deserves pride of place, and while it is possible to use VBScript for Internet Explorer as much more than a proof of concept, for now if you are doing Ajax, it will almost certainly be Ajax running JavaScript as its engine. Your application will have JavaScript working with XMLHttpRequest, JavaScript working with HTML, XHTML, or HTML5; JavaScript working with the DOM, JavaScript working with CSS, JavaScript working with XML or JSON, and perhaps JavaScript working with other things. While addressing a group of Django developers or Pythonistas, it would seem appropriate to open with, "I share your enthusiasm." On the other hand, while addressing a group of JavaScript programmers, in a few ways it is more appropriate to say, "I feel your pain." JavaScript is a language that has been discovered as a gem, but its warts were enough for it to be largely unappreciated for a long time. "Ajax is the gateway drug to JavaScript," as it has been said—however, JavaScript needs a gateway drug before people get hooked on it. JavaScript is an excellent language and a terrible language rolled into one. Before discussing some of the strengths of JavaScript—and the language does have some truly deep strengths—I would like to say "I feel your pain" and discuss two quite distinct types of pain in the JavaScript language. The first source of pain is some of the language decisions in JavaScript: The Wikipedia article says it was designed to resemble Java but be easier for non-programmers, a decision reminiscent of SQL and COBOL. The Java programmer who finds the C-family idiom of for(i = 0; i < 100; ++i) available will be astonished to find that the functions are clobbering each other's assignments to i until they are explicitly declared local to the function by declaring the variables with var. There is more pain where that came from. The following two functions will not perform the naively expected mathematical calculation correctly; the assignments to i and the result will clobber each other: function outer() { result = 0; for(i = 0; i < 100; ++i) { result += inner(i); } return result } function inner(limit) { result = 0; for(i = 0; i < limit; ++i) { result += i; } return result; } The second source of pain is quite different. It is a pain of inconsistent implementation: the pain of, "Write once, debug everywhere." Strictly speaking, this is not JavaScript's fault; browsers are inconsistent. And it need not be a pain in the server-side use of JavaScript or other non-browser uses. However, it comes along for the ride for people who wish to use JavaScript to do Ajax. Cross-browser testing is a foundational practice in web development of any stripe; a good web page with semantic markup and good CSS styling that is developed on Firefox will usually look sane on Internet Explorer (or vice versa), even if not quite pixel-perfect. But program directly for the JavaScript implementation on one version of a browser, and you stand rather sharp odds of your application not working at all on another browser. The most important object by far for Ajax is the XMLHttpRequest and not only is it not the case that you may have to do different things to get an XMLHttpRequest in different browsers or sometimes different (common) versions of the same browser, and, even when you have code that will get an XMLHttpRequest object, the objects you have can be incompatible so that code that works on one will show strange bugs for another. Just because you have done the work of getting an XMLHttpRequest object in all of the major browsers, it doesn't mean you're home free. Before discussing some of the strengths of the JavaScript language itself, it would be worth pointing out that a good library significantly reduces the second source of pain. Almost any sane library will provide a single, consistent way to get XMLHttpRequest functionality, and consistent behavior for the access it provides. In other words, one of the services provided by a good JavaScript library is a much more uniform behavior, so that you are programming for only one model, or as close as it can manage, and not, for instance, pasting conditional boilerplate code to do simple things that are handled differently by different browser versions, often rendering surprisingly different interpretations of JavaScript. Many of the things we will see done well as we explore jQuery are also done well in other libraries. We previously said that JavaScript is an excellent language and a terrible language rolled into one; what is to be said in favor of JavaScript? The list of faults is hardly all that is wrong with JavaScript, and saying that libraries can dull the pain is not itself a great compliment. But in fact, something much stronger can be said for JavaScript: If you can figure out why Python is a good language, you can figure out why JavaScript is a good language. I remember, when I was chasing pointer errors in what became 60,000 lines of C, teasing a fellow student for using Perl instead of a real language. It was clear in my mind that there were interpreted scripting languages, such as the bash scripting that I used for minor convenience scripts, and then there were real languages, which were compiled to machine code. I was sure that a real language was identified with being compiled, among other things, and that power in a language was the sort of thing C traded in. (I wonder why he didn't ask me if he wasn't a real programmer because he didn't spend half his time chasing pointer errors.) Within the past year or so I've been asked if "Python is a real programming language or is just used for scripting," and something similar to the attitude shift I needed to appreciate Perl and Python is needed to properly appreciate JavaScript. The name "JavaScript" is unfortunate; like calling Python "Assembler Kit", it's a way to ask people not to see its real strengths. (Someone looking for tools for working on an assembler would be rather disgusted to buy an "Assembler Kit" and find Python inside. People looking for Java's strengths in JavaScript will almost certainly be disappointed.) JavaScript code may look like Java in an editor, but the resemblance is a façade; besides Mocha, which had been renamed LiveScript, being renamed to JavaScript just when Netscape was announcing Java support in web browsers, it is has been described as being descended from NewtonScript, Self, Smalltalk, and Lisp, as well as being influenced by Scheme, Perl, Python, C, and Java. What's under the Java façade is pretty interesting. And, in the sense of the simplifying "façade" design pattern, JavaScript was marketed in a way almost guaranteed not to communicate its strengths to programmers. It was marketed as something that nontechnical people could add snippets of, in order to achieve minor, and usually annoying, effects on their web pages. It may not have been a toy language, but it sure was dressed up like one. Python may not have functions clobbering each other's variables (at least not unless they are explicitly declared global), but Python and JavaScript are both multiparadigm languages that support object-oriented programming, and their versions of "object-oriented" have a lot in common, particularly as compared to (for instance) Java. In Java, an object's class defines its methods and the type of its fields, and this much is set in stone. In Python, an object's class defines what an object starts off as, but methods and fields can be attached and detached at will. In JavaScript, classes as such do not exist (unless simulated by a library such as Prototype), but an object can inherit from another object, making a prototype and by implication a prototype chain, and like Python it is dynamic in that fields can be attached and detached at will. In Java, the instanceof keyword is important, as are class casts, associated with strong, static typing. Python doesn't have casts, and its isinstance() function is seen by some as a mistake. The concern is that Python, like JavaScript, is a duck-typing language: "If it looks like a duck, and it quacks like a duck, it's a duck!" In a duck-typing language, if you write a program that polls weather data, and there's a ForecastFromScreenscraper object that is several years old and screenscrapes an HTML page, you should be able to write a ForecastFromRSS object that gets the same information much more cleanly from an RSS feed. You should be able to use it as a drop-in replacement as long as you have the interface right. That is different from Java; at least if it were a ForecastFromScreenscraper object, code would break immediately if you handed it a ForecastFromRSS object. Now, in fairness to Java, the "best practices" Java way to do it would probably separate out an IForecast interface, which would be implemented by both ForecastFromScreenscraper and later ForecastFromRSS, and Java has ways of allowing drop-in replacements if they have been explicitly foreseen and planned for. However, in duck-typed languages, the reality goes beyond the fact that if the people in charge designed things carefully and used an interface for a particular role played by an object, you can make a drop-in replacement. In a duck-typed language, you can make a drop-in replacement for things that the original developers never imagined you would want to replace. JavaScript's reputation is changing. More and more people are recognizing that there's more to the language than design flaws. More and more people are looking past the fact that JavaScript is packaged like Java, like packaging a hammer to give the impression that it is basically like a wrench. More and more people are looking past the silly "toy language" Halloween costume that JavaScript was stuffed into as a kid. One of the ways good programmers grow is by learning new languages, and JavaScript is not just the gateway to mainstream Ajax; it is an interesting language in itself. With that much stated, we will be making a carefully chosen, selective use of JavaScript, and not make a language lover's exploration of the JavaScript language, overall. Much of our work will be with the jQuery library; if you have just programmed a little "bare JavaScript", discovering jQuery is a bit like discovering Python, in terms of a tool that cuts like a hot knife through butter. It takes learning, but it yields power and interesting results soon as well as having some room to grow. What is XMLHttpRequest in relation to Ajax? The XMLHttpRequest object is the reason why the kind of games that can be implemented with Ajax technologies do not stop at clones of Tetris and other games that do not know or care if they are attached to a network. They include massive multiplayer online role-playing games where the network is the computer. Without having something like XMLHttpRequest, "Ajax chess" would probably mean a game of chess against a chess engine running in your browser's JavaScript engine; with XMLHttpRequest, "Ajax chess" is more likely man-to-man chess against another human player connected via the network. The XMLHttpRequest object is the object that lets Gmail, Google Maps, Bing Maps, Facebook, and many less famous Ajax applications deliver on Sun's promise: the network is the computer. There are differences and some incompatibilities between different versions of XMLHttpRequest, and efforts are underway to advance "level-2-compliant" XMLHttpRequest implementations, featuring everything that is expected of an XMLHttpRequest object today and providing further functionality in addition, somewhat in the spirit of level 2 or level 3 CSS compliance. We will not be looking at level 2 efforts, but we will look at the baseline of what is expected as standard in most XMLHttpRequest objects. The basic way that an XMLHttpRequest object is used is that the object is created or reused (the preferred practice usually being to reuse rather than create and discard a large number), a callback event handler is specified, the connection is opened, the data is sent, and then when the network operation completes, the callback handler retrieves the response from XMLHttpRequest and takes an appropriate action. A bare-bones XMLHttpRequest object can be expected to have the following methods and properties.
Read more
  • 0
  • 0
  • 2348
article-image-how-write-widget-wordpress-3
Packt
24 Jan 2011
7 min read
Save for later

How to Write a Widget in WordPress 3

Packt
24 Jan 2011
7 min read
  WordPress 3 Complete Create your own complete website or blog from scratch with WordPress Learn everything you need for creating your own feature-rich website or blog from scratch Clear and practical explanations of all aspects of WordPress In-depth coverage of installation, themes, plugins, and syndication Explore WordPress as a fully functional content management system Clear, easy-to-follow, concise; rich with examples and screenshots Recent posts from a Category Widget In this section, we will see how to write a widget that displays recent posts from a particular category in the sidebar. The user will be able to choose how many recent posts to show and whether or not to show an RSS feed link. It will look like the following screenshot: Let's get started! Naming the widget Widgets, like plugins, need to have a unique name. Again, I suggest you search the Web for the name you want to use in order to be sure of its uniqueness. Because of the widget class, you don't need to worry so much about uniqueness in your function and variable names, since the widget class unique-ifies them for you. I've given this widget the filename ahs_postfromcat_widget.php. As for the introduction, this comment code is the same as what you use for the plugin. For this widget, the introductory comment is this: /* Plugin Name: April's List Posts Cat Widget Plugin URI: http://springthistle.com/wordpress/plugin_postfromcat Description: Allows you to add a widget with some number of most recent posts from a particular category Author: April Hodge Silver Version: 1.0 Author URI: http://springthistle.com */ Widget structure When building a widget using the widget class, your widget needs to have the following structure: class UNIQUE_WIDGET_NAME extends WP_Widget { function UNIQUE_WIDGET_NAME() { $widget_ops = array(); $control_ops = array(); $this->WP_Widget(); } function form ($instance) { // prints the form on the widgets page } function update ($new_instance, $old_instance) { // used when the user saves their widget options } function widget ($args,$instance) { // used when the sidebar calls in the widget } } // initiate the widget // register the widget Of course, we need an actual unique widget name. I'm going to use Posts_From_Category. Now, let's flesh out this code one section at a time. Widget initiation function Let's start with the widget initiation function. Blank, it looks like this: function Posts_From_Category() { $widget_ops = array(); $control_ops = array(); $this->WP_Widget(); } In this function, which has the same name as the class itself and is therefore the constructor, we initialize various things that the WP_Widget class is expecting. The first two variables, to which you can give any name you want, are just a handy way to set the two array variables expected by the third line of code. Let's take a look at these three lines of code: The $widget_ops variable is where you can set the class name, which is given to the widget div itself, and the description, which is shown in the WP Admin on the widgets page. The $control_ops variable is where you can set options for the control box in the WP Admin on the widget page, like the width and height of the widget and the ID prefix used for the names and IDs of the items inside. When you call the parent class' constructor, WP_Widget(), you'll tell it the widget's unique ID, the widget's display title, and pass along the two arrays you created. For this widget, my code now looks like this: function Posts_From_Category() { $widget_ops = array( 'classname' => 'postsfromcat', 'description' => 'Allows you to display a list of recent posts within a particular category.'); $control_ops = array( 'width' => 250, 'height' => 250, 'id_base' => 'postsfromcat-widget'); $this->WP_Widget('postsfromcat-widget', 'Posts from a Category', $widget_ops, $control_ops ); } Widget form function This function has to be named form(). You may not rename it if you want the widget class to know what it's purpose is. You also need to have an argument in there, which I'm calling $instance, that the class also expects. This is where current widget settings are stored. This function needs to have all of the functionalities to create the form that users will see when adding the widget to a sidebar. Let's look at some abbreviated code and then explore what it's doing: <?php function form ($instance) { $defaults = array('numberposts' => '5','catid'=>'1','title'=>'','rss'=>''); $instance = wp_parse_args( (array) $instance, $defaults ); ?> <p> <label for="<?php echo $this->get_field_id('title'); ?>">Title:</label> <input type="text" name="<?php echo $this->get_field_name('title') ?>" id="<?php echo $this->get_field_id('title') ?> " value="<?php echo $instance['title'] ?>" size="20"> </p> <p> <label for="<?php echo $this->get_field_id('catid'); ?>">Category ID:</label> <?php wp_dropdown_categories('hide_empty=0&hierarchical=1&id='.$this->get_field_id('catid').'&name='.$this->get_field_name('catid').'&selected='.$instance['catid']); ?> </p> <p> <label for='<?php echo $this->get_field_id('numberposts'); ?>">Number of posts:</label> <select id="<?php echo $this->get_field_id('numberposts'); ?>" name="<?php echo $this->get_field_name('numberposts'); ?>"> <?php for ($i=1;$i<=20;$i++) { echo '<option value="'.$i.'"'; if ($i==$instance['numberposts']) echo ' selected="selected"'; echo '>'.$i.'</option>'; } ?> </select> </p> <p> <input type="checkbox" id="<?php echo $this->get_field_id('rss'); ?>" name="<?php echo $this->get_field_name('rss'); ?>" <?php if ($instance['rss']) echo 'checked="checked"' ?> /> <label for="<?php echo $this->get_field_id('rss'); ?>">Show RSS feed link?</label> </p> <?php } ?> First, I set some defaults, which in this case is just for the number of posts, which I think it would be nice to set to 5. You can set other defaults in this array as well. Then you use a WordPress function named wp_parse_args(), which creates an $instance array that your form will use. What's in it depends on what defaults you've set and what settings the user has already saved. Then you create form fields. Note that for each form field, I make use of the built-in functions that will create unique names and IDs and input existing values. $this->get-field_id creates a unique ID based on the widget instance (remember, you can create more than one instance of this widget). $this->get_field_name() creates a unique name based on the widget instance. The $instance array is where you will find the current values for the widget, whether they are defaults or user-saved data. All the other code in there is just regular PHP and HTML. Note that if you give the user the ability to set a title, name that field "title", WordPress will show it on the widget form when it's minimized. The widget form this will create will look like this:  
Read more
  • 0
  • 0
  • 2525

article-image-tinkering-around-django-javascript-integration
Packt
18 Jan 2011
9 min read
Save for later

Tinkering Around in Django JavaScript Integration

Packt
18 Jan 2011
9 min read
Minor tweaks and bugfixes Good tinkering can be a process that begins with tweaks and bugfixes, and snowballs from there. Let's begin with some of the smaller tweaks and bugfixes before tinkering further. Setting a default name of "(Insert name here)" Most of the fields on an Entity default to blank, which is in general appropriate. However, this means that there is a zero-width link for any search result which has not had a name set. If a user fills out the Entity's name before navigating away from that page, everything is fine, but it is a very suspicious assumption that all users will magically use our software in whatever fashion would be most convenient for our implementation. So, instead, we set a default name of "(Insert name here)" in the definition of an Entity, in models.py: name = models.TextField(blank = True, default = u'(Insert name here)') Eliminating Borg behavior One variant on the classic Singleton pattern in Gang of Four is the Borg pattern, where arbitrarily many instances of a Borg class may exist, but they share the same dictionary, so that if you set an attribute on one of them, you set the attribute on all of them. At present we have a bug, which is that our views pull all available instances. We need to specify something different. We update the end of ajax_profile(), including a slot for time zones to be used later in this article, to: return render_to_response(u'profile_internal.html', { u'entities': directory.models.Entity.objects.filter( is_invisible = False).order_by(u'name'), u'entity': entity, u'first_stati': directory.models.Status.objects.filter( entity = id).order_by( u'-datetime')[:directory.settings.INITIAL_STATI], u'gps': gps, u'gps_url': gps_url, u'id': int(id), u'emails': directory.models.Email.objects.filter( entity = entity, is_invisible = False), u'phones': directory.models.Phone.objects.filter( entity = entity, is_invisible = False), u'second_stati': directory.models.Status.objects.filter( entity = id).order_by( u'-datetime')[directory.settings.INITIAL_STATI:], u'tags': directory.models.Tag.objects.filter(entity = entity, is_invisible = False).order_by(u'text'), u'time_zones': directory.models.TIME_ZONE_CHOICES, u'urls': directory.models.URL.objects.filter(entity = entity, is_invisible = False), }) Likewise, we update homepage(): profile = template.render(Context( { u'entities': directory.models.Entity.objects.filter( is_invisible = False), u'entity': entity, u'first_stati': directory.models.Status.objects.filter( entity = id).order_by( u'-datetime')[:directory.settings.INITIAL_STATI], u'gps': gps, u'gps_url': gps_url, u'id': int(id), u'emails': directory.models.Email.objects.filter( entity = entity, is_invisible = False), u'phones': directory.models.Phone.objects.filter( entity = entity, is_invisible = False), u'query': urllib.quote(query), u'second_stati':directory.models.Status.objects.filter( entity = id).order_by( u'-datetime')[directory.settings.INITIAL_STATI:], u'time_zones': directory.models.TIME_ZONE_CHOICES, u'tags': directory.models.Tag.objects.filter( entity = entity, is_invisible = False).order_by(u'text'), u'urls': directory.models.URL.objects.filter( entity = entity, is_invisible = False), })) Confusing jQuery's load() with html() If we have failed to load a profile in the main search.html template, we had a call to load(""). What we needed was: else { $("#profile").html(""); } $("#profile").load("") loads a copy of the current page into the div named profile. We can improve on this slightly to "blank" contents that include the default header: else { $("#profile").html("<h2>People, etc.</h2>"); } Preventing display of deleted instances In our system, enabling undo means that there can be instances (Entities, Emails, URLs, and so on) which have been deleted but are still available for undo. We have implemented deletion by setting an is_invisible flag to True, and we also need to check before displaying to avoid puzzling behavior like a user deleting an Entity, being told Your change has been saved, and then seeing the Entity's profile displayed exactly as before. We accomplish this by a specifying, for a Queryset .filter(is_invisible = False) where we might earlier have specified .all(), or adding is_invisible = False to the conditions of a pre-existing filter; for instance: def ajax_download_model(request, model): if directory.settings.SHOULD_DOWNLOAD_DIRECTORY: json_serializer = serializers.get_serializer(u'json')() response = HttpResponse(mimetype = u'application/json') if model == u'Entity': json_serializer.serialize(getattr(directory.models, model).objects.filter( is_invisible = False).order_by(u'name'), ensure_ascii = False, stream = response) else: json_serializer.serialize(getattr(directory.models, model).objects.filter(is_invisible = False), ensure_ascii = False, stream = response) return response else: return HttpResponse(u'This feature has been turned off.') In the main view for the profile, we add a check in the beginning so that a (basically) blank result page is shown: def ajax_profile(request, id): entity = directory.models.Entity.objects.filter(id = int(id))[0] if entity.is_invisible: return HttpResponse(u'<h2>People, etc.</h2>') One nicety we provide is usually loading a profile on mouseover for its area of the search result page. This means that users can more quickly and easily scan through drilldown pages in search of the right match; however, there is a performance gotcha for simply specifying an onmouseover handler. If you specify an onmouseover for a containing div, you may get a separate event call for every time the user hovers over an element contained in the div, easily getting 3+ calls if a user moves the mouse over to the link. That could be annoying to people on a VPN connection if it means that they are getting the network hits for numerous needless profile loads. To cut back on this, we define an initially null variable for the last profile moused over: Then we call the following function in the containing div element's onmouseover: PHOTO_DIRECTORY.last_mouseover_profile = null; Then we call the following function in the containing div element's onmouseover: PHOTO_DIRECTORY.mouseover_profile = function(profile) { if (profile != PHOTO_DIRECTORY.last_mouseover_profile) { PHOTO_DIRECTORY.load_profile(profile); PHOTO_DIRECTORY.last_mouseover_profile = profile; PHOTO_DIRECTORY.register_editables(); } } The relevant code from search_internal.html is as follows: <div class="search_result" onmouseover="PHOTO_DIRECTORY.mouseover_profile( {{ result.id }});" onclick="PHOTO_DIRECTORY.click_profile({{ result.id }});"> We usually, but not always, enable this mouseover functionality; not always, because it works out to annoying behavior if a person is trying to edit, does a drag select, mouses over the profile area, and reloads a fresh, non-edited profile. Here we edit the Jeditable plugin's source code and add a few lines; we also perform a second check for if the user is logged in, and offer a login form if so: /* if element is empty add something clickable (if requested) */if (!$.trim($(this).html())) { $(this).html(settings.placeholder);}$(this).bind(settings.event, function(e) { $("div").removeAttr("onmouseover"); if (!PHOTO_DIRECTORY.check_login()) { PHOTO_DIRECTORY.offer_login(); } /* abort if disabled for this element */ if (true === $(this).data('disabled.editable')) { return; } For Jeditable-enabled elements, we can override the placeholder for an empty element at method call, but the default placeholder is cleared when editing begins; overridden placeholders aren't. We override the placeholder with something that gives us a little more control and styling freedom: // publicly accessible defaults $.fn.editable.defaults = { name : 'value', id : 'id', type : 'text', width : 'auto', height : 'auto', event : 'click.editable', onblur : 'cancel', loadtype : 'GET', loadtext : 'Loading...', placeholder:'<span class="placeholder"> Click to add.</span>', loaddata : {}, submitdata : {}, ajaxoptions: {} }; All of this is added to the file jquery.jeditable.js. We now have, as well as an @ajax_login_required decorator, an @ajax_permission_required decorator. We test for this variable in the default postprocessor specified in $.ajaxSetup() for the complete handler. Because Jeditable will place the returned data inline, we also refresh the profile. This occurs after the code to check for an undoable edit and offer an undo option to the user. complete: function(XMLHttpRequest, textStatus) { var data = XMLHttpRequest.responseText; var regular_expression = new RegExp("<!-" + "-# (d+) #-" + "->"); if (data.match(regular_expression)) { var match = regular_expression.exec(data); PHOTO_DIRECTORY.undo_notification( "Your changes have been saved. " + "<a href='JavaScript:PHOTO_DIRECTORY.undo(" + match[1] + ")'>Undo</a>"); } else if (data == '{"not_permitted": true}' || data == "{'not_permitted': true}") { PHOTO_DIRECTORY.send_notification( "We are sorry, but we cannot allow you " + "to do that."); PHOTO_DIRECTORY.reload_profile(); } }, Note that we have tried to produce the least painful of clear message we can: we avoid both saying "You shouldn't be doing that," and a terse, "bad movie computer"-style message of "Access denied" or "Permission denied." We also removed from that method code to call offer_login() if a call came back not authenticated. This looked good on paper, but our code was making Ajax calls soon enough that the user would get an immediate, unprovoked, modal login dialog on loading the page. Adding a favicon.ico In terms of minor tweaks, some visually distinct favicon.ico (http://softpedia.com/ is one of many free sources of favicon.ico files, or the favicon generator at http://tools.dynamicdrive.com/favicon/ which can take an image like your company logo as the basis for an icon) helps your tabs look different at a glance from other tabs. Save a good, simple favicon in static/favicon.ico. The icon may not show up immediately when you refresh, but a good favicon makes it slightly easier for visitors to manage your pages among others that they have to deal with. It shows up in the address bar, bookmarks, and possibly other places. This brings us to the end of the minor tweaks; let us look at two slightly larger additions to the directory.
Read more
  • 0
  • 0
  • 1390

article-image-django-javascript-integration-jquery-place-editing-using-ajax
Packt
07 Jan 2011
8 min read
Save for later

Django JavaScript Integration: jQuery In-place Editing Using Ajax

Packt
07 Jan 2011
8 min read
Django JavaScript Integration: AJAX and jQuery Develop AJAX applications using Django and jQuery Learn how Django + jQuery = AJAX Integrate your AJAX application with Django on the server side and jQuery on the client side Learn how to handle AJAX requests with jQuery Compare the pros and cons of client-side search with JavaScript and initializing a search on the server side via AJAX Handle login and authentication via Django-based AJAX This will allow us to create a results page as shown: When someone clicks OK, the data is saved on the server, and also shown on the page. Let's get started on how this works. Including a plugin We include a jQuery plugin on a page by including jQuery, then including the plugin (or plugins, if we have more than one). In our base.html, we update: {% block footer_javascript_site %} <script language="JavaScript" type="text/javascript" src="/static/js/jquery.js"></script> <script language="JavaScript" type="text/javascript" src="/static/js/jquery-ui.js"></script> <script language="JavaScript" type="text/javascript" src="/static/js/jquery.jeditable.js"></script> {% endblock footer_javascript_site %} This is followed by the footer_javascript_section and footer_javascript_page blocks. This means that if we don't want the plugin ,which is the last inclusion, to be downloaded for each page, we could put it in overridden section and page blocks. This would render as including the plugin after jQuery. How to make pages more responsive We would also note that the setup, with three JavaScript downloads, is appropriate for development purposes but not for deployment. In terms of YSlow client-side performance optimization, the recommended best practice is to have one HTML/XHTML hit, one CSS hit at the top, and one JavaScript hit at the bottom. One of the basic principles of client-side optimization, discussed by Steve Souders (see http://developer.yahoo.com/yslow/) is,since HTTP requests slow the page down, the recommended best practice is to have one (preferably minifed) CSS inclusion at the top of the page, and then one (preferably minifed) JavaScript inclusion at the bottom of each page. Each HTTP request beyond this makes things slower, so combining CSS and/or JavaScript requests into a single concatenated file is low-hanging fruit to improve how quick and responsive your web pages appear to users. For deployment, we should minify and combine the JavaScript. As we are developing, we also have JavaScript included in templates and rendered into the delivered XHTML; this may be appropriate for development purposes. For deployment though, as much shared functionality as possible should be factored out into an included JavaScript fle. For content that can be delivered statically, such as CSS, JavaScript, and even non-dynamic images, setting far-future Expires/Cache-Control headers is desirable. (One practice is to never change the content of a published URL for the kind of content that has a far-future expiration set, and then if it needs updating, instead of changing the content at the same location, leave the content where it is, publish at a new location possibly including a version number, and reference the new location.) A template handling the client-side requirements Here's the template. Its view will render it with an entity and other information. At present it extends the base directly; it is desirable in many cases to have the templates that are rendered extend section templates, which in turn extend the base. In our simple application, we have two templates which are directly rendered to web pages. One is the page that handles both search and search results—and the other, the page that handles a profile, from the following template: {% extends "base.html" %} We include honorifics before the name, and post-nominals after. At this point we do not do anything to make it editable. {% extends "base.html" %} Following earlier discussion, we include honorifcs before the name, and post-nominals after. At this point we do not do anything to make it editable. {% block head_title %} {{ entity.honorifics }} {{ entity.name }} {{ entity.post_nominals }} {% endblock head_title %} {% block body_main %} There is one important point about Django and the title block. The Django developers do not fnd it acceptable to write a templating engine that produces errors in production if someone attempts to access an undefned value (by typos, for instance). As a result of this design decision, if you attempt to access an undefned value, the templating engine will silently insert an empty string and move on. This means that it is safe to include a value that may or may not exist, although there are ways to test if a value exists and is nonempty, and display another default value in that case. We will see how to do this soon. Let's move on to the main block, defned by the last line of code. Once we are in the main block, we have an h1 which is almost identical to the title block, but this time it is marked up to support editing in place. Let us look at the honorifics span; the name and post_nominals spans work the same way: <h1> <span id="Entity_honorifics_{{ entity.id }}" class="edit"> {% if entity.honorifics %} {{ entity.honorifics }} {% else %} Click to edit. {% endif %} </span> The class edit is used to give all $(".edit") items some basic special treatment with Jeditable; there is nothing magical about the class name, which could have been replaced by user-may-change-this or something else. edit merely happens to be a good name choice, like almost any good variable/function/object name. We create a naming convention in the span's HTML ID which will enable the server side to know which—of a long and possibly open-ended number of things we could intend to change—is the one we want. In a nutshell, the convention is modelname_feldname_instanceID. The frst token is the model name, and is everything up to the first underscore. (Even if we were only interested in one model now, it is more future proof to design so that we can accommodate changes that introduce more models.) The last token is the instance ID, an integer. The middle token, which may contain underscores (for example post_nominals in the following code), is the feld name. There is no specifc requirement to follow a naming convention, but it allows us to specify an HTML ID that the server-side view can parse for information about which feld on which instance of which model is being edited. We also provide a default value, in this case Click to edit, intended not only to serve as a placeholder, but to give users a sense on how this information can be updated. We might also observe that here and in the following code, we do not presently have checks against race conditions in place. So nothing here or in the following code will stop users from overwriting each others' changes. This may be taken as a challenge to refne and extend the solution to either prevent race conditions or mitigate their damage. <span id="Entity_name_{{ entity.id }}" class="edit"> {% if entity.name %} {{ entity.name }} {% else %} Click to edit. {% endif %} </span> <span id="Entity_post_nominals_{{ entity.id }}" class="edit"> {% if entity.post_nominals %} {{ entity.post_nominals }} {% else %} Click to edit. {% endif %} </span> </h1> This approach is an excellent frst approach but in practice is an h1 with three slots that say Click to edit on a profle, creating needless confusion. We move to a simplifed: <span id="Entity_name_{{ entity.id }}" class="edit"> {% if entity.name %} {{ entity.name }}jQuery In-place Editing Using Ajax {% else %} Click to edit. {% endif %} </span> <span id="Entity_post_nominals_{{ entity.id }}" class="edit"> {% if entity.post_nominals %} {{ entity.post_nominals }} {% else %} Click to edit. {% endif %} </span> </h1> Taken together, the three statements form the heading in this screenshot: If we click on the name (for instance) it becomes: The image is presently a placeholder; this should be expanded to allow an image to be uploaded if the user clicks on the picture (implementing consistent-feeling behavior whether or not we do so via the same plugin). We also need the view and urlpattern on the backend: <h1 class="edit" id="Entity_name_{{ entity.id }}"> {{ entity.name }} </h1>
Read more
  • 0
  • 0
  • 2160
article-image-creating-content-drupal-7
Packt
03 Dec 2010
3 min read
Save for later

Creating Content in Drupal 7

Packt
03 Dec 2010
3 min read
Drupal 7 First Look Learn the new features of Drupal 7, how they work and how they will impact you Get to grips with all of the new features in Drupal 7 Upgrade your Drupal 6 site, themes, and modules to Drupal 7 Explore the new Drupal 7 administration interface and map your Drupal 6 administration interface to the new Drupal 7 structure Complete coverage of the DBTNG database layer with usage examples and all API changes for both Themes and Modules         Read more about this book       (For more resources on Drupal 7, see here.) Creating content for your site is at the core of any Content Management System like Drupal. The primary changes for Drupal 7 relate to an updated interface. Let's look at the new interface in detail. Selecting a content type to create To create content in Drupal 7, first log in to your site and then click on Content from the site toolbar. Drupal will now display the new Content Administration page. Move mouse over the image to enlarge it. In Drupal 6, this page could be displayed by selecting Administer | Content Management | Content from the Navigation menu. From here, click on the Add new content link. Drupal will now display a page allowing you to select the type of content you want to create. Depending on the modules you have installed and enabled, you will have different content types available. In previous versions of Drupal, this page could be reached by selecting the Create Content link from the Navigation menu. You can also select the type of content to add using the shortcut bar. You can access the shortcut bar by clicking on the toggle at the far right of the toolbar: The shortcut bar has a list of links in it that can be used to quickly access commonly used functionality, and it appears as follows: You can customize the links in the shortcut bar and users can use either the default set of shortcuts or they can have their own. Now select the type of content you want to create. For this example, we will use the Basic page type. Content UI The interface to create content has been altered drastically from Drupal 6. Let's go through the interface in detail. The top section of the page should be familiar to experienced editors. This is the place to enter your title as well as the full text of the page. In a departure from previous versions, the node summary, which is used when multiple nodes are displayed on a page, is an entirely separate optional field.
Read more
  • 0
  • 1
  • 1543

article-image-user-extensions-and-add-ons-selenium-10-testing-tools
Packt
26 Nov 2010
6 min read
Save for later

User Extensions and Add-ons in Selenium 1.0 Testing Tools

Packt
26 Nov 2010
6 min read
Important preliminary points If you are creating an extension that can be used by all, make sure that it is stored in a central place, like a version control system. This will prevent any potential issues in the future when others in your team start to use it. User extensions Imagine that you wanted to use a snippet of code that is used in a number of different tests. You could use: type | locator | javascript{ .... } However, if you had a bug in the JavaScript you would need to go through all the tests that reused this snippet of code. This, as we know from software development, is not good practice and is normally corrected with a refactoring of the code. In Selenium, we can create our own function that can then be used throughout the tests. User extensions are stored in a separate file that we will tell Selenium IDE or Selenium RC to use. Inside there the new function will be written in JavaScript. Because Selenium's core is developed in JavaScript, creating an extension follows the standard rules for prototypal languages. To create an extension, we create a function in the following design pattern. Selenium.prototype.doFunctionName = function(){ . . . } The "do" in front of the function name tells Selenium that this function can be called as a command for a step instead of an internal or private function. Now that we understand this, let's see this in action. Time for action – installing a user extension Now that you have a need for a user extension, let's have a look at installing an extension into Selenium IDE. This will make sure that we can use these functions in future Time for action sections throughout this article. Open your favorite text editor. Create an empty method with the following text: Selenium.prototype.doNothing = function(){ . . . } Start Selenium IDE. Click on the Options menu and then click on Options. Place the path of the user-extension.js file in the textbox labeled Selenium IDE extensions. Click on OK. Restart Selenium IDE. Start typing in the Command textbox and your new command will be available, as seen in the next screenshot: What just happened? We have just seen how to create our first basic extension command and how to get this going in Selenium IDE. You will notice that you had to restart Selenium IDE for the changes to take effect. Selenium has a process that finds all the command functions available to it when it starts up, and does a few things to it to make sure that Selenium can use them without any issues. Now that we understand how to create and install an extension command let's see what else we can do with it. In the next Time for action, we are going to have a look at creating a randomizer command that will store the result in a variable that we can use later in the test. Time for action – using Selenium variables in extensions Imagine that you are testing something that requires some form of random number entered into a textbox. You have a number of tests that require you to create a random number for the test so you can decide that you are going to create a user extension and then store the result in a variable. To do this we will need to pass in arguments to our function that we saw earlier. The value in the target box will be passed in as the first argument and the value textbox will be the second argument. We will use this in a number of different examples throughout this article. Let's now create this extension. Open your favorite text editor and open the user-extension.js file you created earlier. We are going to create a function called storeRandom. The function will look like the following: Selenium.prototype.doStoreRandom = function(variableName){ random = Math.floor(Math.random()*10000000); storedVars[variableName] = random; } Save the file. Restart Selenium IDE. Create a new step with storeRandom and the variable that will hold the value will be called random. Create a step to echo the value in the random variable. What just happened? In the previous example, we saw how we can create an extension function that allows us to use variables that can be used throughout the rest of the test. It uses the storedVars dictionary that we saw in the previous chapter. As everything that comes from the Selenium IDE is interpreted as a string, we just needed to put the variable as the key in storedVars. It is then translated and will look like storedVars['random'] so that we can use it later. As with normal Selenium commands, if you run the command a number of times, it will overwrite the value that is stored within that variable, as we can see in the previous screenshot. Now that we know how to create an extension command that computes something and then stores the results in a variable, let's have a look at using that information with a locator. Time for action – using locators in extensions Imagine that you need to calculate today's date and then type that into a textbox. To do that you can use the type | locator | javascript{...} format, but sometimes it's just neater to have a command that looks like typeTodaysDate | locator. We do this by creating an extension and then calling the relevant Selenium command in the same way that we are creating our functions. To tell it to type in a locator, use: this.doType(locator,text); The this in front of the command text is to make sure that it used the doType function inside of the Selenium object and not one that may be in scope from the user extensions. Let's see this in action: Use your favorite text editor to edit the user extensions that you were using in the previous examples. Create a new function called doTypeTodaysDate with the following snippet: Selenium.prototype.doTypeTodaysDate = function(locator){ var dates = new Date(); var day = dates.getDate(); if (day < 10){ day = '0' + day; } month = dates.getMonth() + 1; if (month < 10){ month = '0' + month; } var year = dates.getFullYear(); var prettyDay = day + '/' + month + '/' + year; this.doType(locator, prettyDay); } Save the file and restart Selenium IDE. Create a step in a test to type this in a textbox. Run your script. It should look similar to the next screenshot: What just happened? We have just seen that we can create extension commands that use locators. This means that we can create commands to simplify tests as in the previous example where we created our own Type command to always type today's date in the dd/mm/yyyy format. We also saw that we can call other commands from within our new command by calling its original function in Selenium. The original function has do in front of it. Now that we have seen how we can use basic locators and variables, let's have a look at how we can access the page using browserbot from within an extension method.
Read more
  • 0
  • 0
  • 4221