Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Web Development

1802 Articles
article-image-structure-content-your-plone-site
Packt
15 Oct 2009
6 min read
Save for later

Structure the Content on your Plone Site

Packt
15 Oct 2009
6 min read
(For more resources on Plone, see here.) Real world information architecture tips Based on what your users need and/or want to see, you need to structure your content within topics, or high-level containers that are typically content-specific sections. As an example, we will take a look at http://plone.org. When visitors enter a Plone site, no matter how deep they go, the navigation tends to stay the same. The following screenshot shows that a visitor is in the Documentation section of the site, with the opportunity to drill down within this section for additional documentation topics: By default, Plone has a portlet that shows the navigation aids on the left-hand side of the browser, which helps the visitors navigate within the subject matter. In this example, there are several subsections below Development. Structuring your content When planning your site, you must first decide how you want to structure your content. The structuring can be worked out through brainstorming sessions with other people involved with your site, in order to come up with a structure suits your business objectives. Investigating other sites that share your organization's model could be a good starting point towards developing your final solution. To really understand how Plone can be an effective solution for your content delivery needs, we will take a look at how to implement Plone for a High School web site. In this type of structure, you will see how some content is targeted at all users, while other content is tailored to specific users. We will use the following high-level topics for demonstration purposes: Home News Events Academics Sports Clubs PTO (Parent-Teacher Organization) Alumni In order to create these sections, we will first create folders for the above sections, into which you will add content. Each of the above sections will be visible in your top-level navigation. Within each top-level folder, we will also create subfolders to help you to structure your content. To create a folder, go to your homepage, select Add new... and choose the Folder option from the drop-down list, as shown in the following screenshot: Specify the Title and the optional Description. In this case, we will create a folder for the Academics section: We're going to just keep the defaults here; we will cover the Settings tab shortly. Click on Save, and then make sure that your folder has been published: Now take a look at the overall navigation structure: There is now a new tab in your navigation bar, which represents a container for holding all of the content that will be part of the academics section of the site. You will follow the same process to create the rest of the top-level tabs. First, we will need to make a change to the default tab behavior in Plone. Specifically, we want to remove Users as a top-level navigation item. Removing it from the tab navigation does not mean that it no longer exists; we're just making sure that items that are more important to this specific site are shown to the visitors and users. To remove Users from the navigation bar, click on the Users tab, and then select Edit. Once you are in Edit mode, there is the section where you can select Settings. You can then select the Exclude from navigation checkbox. After saving your changes, you can see that the tab Users is no longer part of your navigation: Using the same process for adding new folders, we'll add Sports, Clubs and PTO. We end up with the following: Now that we have the top-level structure in place, we can focus on what will need to go within each topic. The process is similar, with the difference being that you need to be within the given topic before creating the next level of folders. When you create folders in the Home section, you have the ability to create top-level tabs. Creating folders within the other top-level folders you create allows you to be more specific for the given topic. We will use the example of the Sports top-level tab for creating an additional folder/site structure. We will need to create the following sub-folders: Football Basketball Soccer Track and Field Lacrosse Baseball Softball To do so, we must drill down into the Sports folder and add new folders within it. Once you have added these folders under the Sports section, the Navigation to the new folders is available in the leftmost side of your browser window: Note that the navigation shows only the contents of the current folder. This can be adjusted via the Manage portlets link, which is available on the home page, below the left and right columns. This link is also accessible via http://www.mysite.com/@@manage-portlets, where www.mysite.com is the name of your Plone site. Simply set the Start Level to 0 and save your changes. Now that the structure for the Sports folder is in place, let's take a look at how you can change the order of display of the folders. If the football season is over, it may make sense to move this category to the bottom of the navigation. To change the order of the Football folder, go to the Contents view under Sports, then click in the Order column for the Football row. The row will turn yellow, and the cursor will change to a four-headed arrow, which indicates that the content object can be moved. Drag the row up or down in the list, to the desired location. Now, when you click on the top level of Sports, the navigation listing appears in the new location that you have just defined: Now, let's take the new folder structure created under the Sports section, and create some more folders that are specific to each sub topic. Select a folder, and then go to the Contents tabbed page. In this example, we will create the following folders under the Soccer folder, which is under the Sports folder: Varsity Boys Girls Junior Varsity Boys Girls Boosters As identified in the preceding screenshot, the breadcrumbs navigation shows the progression through the site. You can also see how the navigation within the Sports section can grow to fit specific content. By understanding these concepts that apply creating folders for your navigation structure, you will be well on your way to having consistent navigation throughout your site.
Read more
  • 0
  • 0
  • 3576

article-image-schema-validation-oracle-jdeveloper-xdk-11g
Packt
15 Oct 2009
7 min read
Save for later

Schema Validation with Oracle JDeveloper - XDK 11g

Packt
15 Oct 2009
7 min read
JDeveloper built-in schema validation Oracle JDeveloper 11g has built-in support for XML schema validation. If an XML document includes a reference to an XML schema, the XML document may be validated with the XML schema using the built-in feature. An XML schema may be specified in an XML document using the xsi:noNamespaceSchemaLocation attribute or the xsi:namespaceSchemaLocation attribute. Before we discuss when to use which attribute, we need to define the target namespace. A schema is a collection of type definitions and element declarations whose names belong to a particular namespace called a target namespace. Thus, a target namespace distinguishes between type definitions and element declarations from different collections. An XML schema doesn't need to have a target namespace. If the XML schema has a target namespace, specify the schema's location in an XML document using the xsi:namespaceSchemaLocation attribute. If the XML schema does not have a target namespace, specify the schema location using the xsi:noNamespaceSchemaLocation attribute. The xsi:noNamespaceSchemaLocation and xsi:namespaceSchemaLocation attributes are a hint to the processor about the location of an XML schema document. The example XML schema document that we shall create is catalog.xsd and is listed here: <?xml version="1.0" encoding="utf-8"?><xsd:schema > <xsd:element name="catalog"type="catalogType"/> <xsd:complexType name="catalogType"> <xsd:sequence> <xsd:element ref="journal" minOccurs="0"maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:element name="journal" type="journalType"/> <xsd:complexType name="journalType"> <xsd:sequence> <xsd:element ref="article" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute name="title" type="xsd:string"/> <xsd:attribute name="publisher" type="xsd:string"/> <xsd:attribute name="edition" type="xsd:string"/> </xsd:complexType> <xsd:element name="article" type="articleType"/> <xsd:complexType name="articleType"> <xsd:sequence> <xsd:element name="title" type="xsd:string"/> <xsd:element name="author" type="xsd:string"/> </xsd:sequence> <xsd:attribute name="section" type="xsd:string"/> </xsd:complexType></xsd:schema> The XML document instance that we shall generate from the schema is catalog.xml and is listed as follows: <?xml version="1.0" encoding="utf-8"?><catalog><journal title="Oracle Magazine" publisher="OraclePublishing" edition="September-October 2008"> <article section="Features"> <title>Share 2.0</title> <author>Alan Joch</author> </article></journal><journal title="Oracle Magazine" publisher="OraclePublishing" edition="March-April 2008"> <article section="Oracle Developer"> <title>Declarative Data Filtering</title> <author>Steve Muench</author> </article></journal></catalog> Specify the XML schema location in the XML document using the following attribute declaration: xsi:noNamespaceSchemaLocation="catalog.xsd" The XML schema may be in any directory. The example XML document does not include any namespace elements. Therefore, the schema is specified with the xsi:noNamespaceSchemaLocation attribute in the root element catalog. The XML schema may be specified with a relative URL, or a file, or an HTTP URL. The xsi:noNamespaceSchemaLocation attribute we added specifies the relative path to the XML schema document catalog.xsd. To validate the XML document with the XML schema, right-click on the XML document and select Validate XML . The XML document gets validated with the XML schema and the output indicates that the XML document does not have any validation errors. To demonstrate validation errors, add a non-valid element to the XML document. As an example, add the following element to the catalog element after the first journal element: <article></article> To validate the modified XML document, right-click on the XML document and select Validate XML. The output indicates validation errors. All the elements after the non-valid element become non-valid. For example, the journal element is valid as a subelement of the catalog element, but because the second journal element is after the non-valid article element, the journal element also becomes non-valid as indicated in the validation output. XDK 11g also provides a schema validation-specific API known as XSDValidator to validate an XML document with an XML schema. The choice of validation method depends on the additional functionality required in the validation application. XSDValidator is suitable for validation if all that is required is schema validation. Setting the environment Create an application (SchemaValidation, for example) and a project (SchemaValidation, for example) in JDeveloper. To create an application and a project select File | New. In the New Gallery window, select Categories | General and Items | Generic Application. Click on OK. In the Create Generic Application window, specify an Application Name and click on Next. In the Name your Generic project window, specify a Project Name and click on Finish. An application and a project get created. Next, add some XDK 11g JAR files to the project classpath. Select the project node in Application Navigator, and select Tools | Project Properties. In the Project Properties window, select Libraries and Classpath. Click on the Add Library button to add a library. In the Add Library window, select the Oracle XML Parser v2 library and click on the OK button. The Oracle XML Parser v2 library gets added to the project Libraries. Select the Add JAR/Directory button to add JAR file xml.jar from the C:OracleMiddlewarejdevelopermodulesoracle.xdk_11.1.1 directory. First, create an XML document and an XML schema in JDeveloper. To create an XML document, select File | New. In the New Gallery window select Categories | General | XML. In the Items listed select XML Document, and click on the OK button. In the Create XML File wizard, specify the XML file name, catalog.xml, and click on the OK button. An XML document gets added to the SchemaValidation project in Application Navigator. To add an XML schema, select File | New, and General | XML in the New Gallery window. Select XML schema in the Items listed. Click on the OK button. An XML schema document gets added to SchemaValidation project. The example XML document, catalog.xml, consists of a journal catalog. Copy the XML document to the catalog.xml file in the JDeveloper project. The example XML document does not specify the location of the XML schema document to which the XML document must conform to, because we will be setting the XML schema document in the schema validation application. If the XML schema document is specified in the XML document and the schema validation application, the schema document set in the schema validation application is used. Next, copy the example XML schema document, catalog.xsd to catalog.xsd in the JDeveloper project Schema Validation. Each XML schema is required to be in the XML schema namespace http://www.w3.org/2001/XMLSchema. The XML schema namespace is specified with a namespace declaration in the root element, schema, of the XML schema. A namespace declaration is of the format > Next, we will create Java classes for schema validation. Select File | New and subsequently Categories | General and Items | Java Class in the New Gallery window to create a Java class for schema validation. Click on the OK button. In the Create Java Class window specify a Class Name, XMLSchemaValidator, and a package name, schemavalidation, and click on the OK button. A Java class gets added to the SchemaValidation project. Similarly, add Java classes, DOMValidator and SAXValidator. The schema validation applications are shown in the Application Navigator.
Read more
  • 0
  • 0
  • 5063

article-image-documenting-our-application-apache-struts-2-part-2
Packt
15 Oct 2009
9 min read
Save for later

Documenting our Application in Apache Struts 2 (part 2)

Packt
15 Oct 2009
9 min read
Documenting web applications Documenting an entire web application can be surprisingly tricky because of the many different layers involved. Some web application frameworks support automatic documentation generation better than others. It's preferable to have fewer disparate parts. For example, Lisp, Smalltalk, and some Ruby frameworks are little more than internal DSLs that can be trivially redefined to produce documentation from the actual application code. In general, Java frameworks are more difficult to limit to a single layer. Instead, we are confronted with HTML, JSP, JavaScript, Java, the framework itself, its configuration methodologies (XML, annotations, scripting languages, etc.), the service layers, business logic, persistence layers, and so on? Complete documentation generally means aggregating information from many disparate sources and presenting them in a way that is meaningful to the intended audience. High-level overviews The site map is obviously a reasonable overview of a web application. A site map may look like a simple hierarchy chart, showing a simple view of a site's pages without showing all of the possible links between pages, how a page is implemented, and so on. This diagram was created by hand and shows only the basic outline of the application flow. It represents minor maintenance overhead since it would need to be updated when there are any changes to the application. Documenting JSPs There doesn't seem to be any general-purpose JSP documentation methodology. It's relatively trivial to create comments inside a JSP page using JSP comments or a regular Javadoc comment inside a scriptlet. Pulling these comments out is then a matter of some simple parsing. This may be done by using one of our favorite tools, regular expressions, or using more HTML-specific parsing and subsequent massaging. Where it gets tricky is when we want to start generating documentation that includes elements such as JSP pages, which may be included using many different mechanisms—static includes, <jsp:include.../> tags, Tiles, SiteMesh, inserted via Ajax, and so on. Similarly, generating connections between pages is fraught with custom cases. We might use general-purpose HTML links, Struts 2 link tags, attach a link to a page element with JavaScript, ad infinitum/nauseum. When we throw in the (perhaps perverse) ability to generate HTML using Java, we have a situation where creating a perfectly general-purpose tool is a major undertaking. However, we can fairly easily create a reasonable set of documentation that is specific to our framework by parsing configuration files (or scanning a classpath for annotations), understanding how we're linking the server-side to our presentation views, and performing (at least limited) HTML/JSP parsing to pull out presentation-side dependencies, links, and anything that we want documented. Documenting JavaScript If only there was a tool such as Javadoc for JavaScript. The JsDoc Toolkit provides Javadoc-like functionality for JavaScript, with additional features to help handle the dynamic nature of JavaScript code. Because of the dynamic nature, we (as developers) must remain diligent in both in how we write our JavaScript and how we document it. Fortunately, the JsDoc Toolkit is good at recognizing current JavaScript programming paradigms (within reason), and when it can't, provides Javadoc-like tags we can use to give it hints. For example, consider our JavaScript Recipe module where we create several private functions intended for use only by the module, and return a map of functions for use on the webpage. The returned map itself contains a map of validation functions. Ideally, we'd like to be able to document all of the different components. Because of the dynamic nature of JavaScript, it's more difficult for tools to figure out the context things should belong to. Java is much simpler in this regard (which is both a blessing and a curse), so we need to give JsDoc hints to help it understand our code's layout and purpose. A high-level flyby of the Recipe module shows a layout similar to the following: var Recipe = function () { var ingredientLabel; var ingredientCount; // ... function trim(s) { return s.replace(/^s+|s+$/g, ""); } function msgParams(msg, params) { // ... } return { loadMessages: function (msgMap) { // ... }, prepare: function (label, count) { // ... }, pageValidators: { validateIngredientNameRequired: function (form) { // ... }, // ... } }; }(); We see several documentable elements: the Recipe module itself, private variables, private functions, and the return map which contains both functions and a map of validation functions. JsDoc accepts a number of Javadoc-like document annotations that allow us to control how it decides to document the JavaScript elements. The JavaScript module pattern, exemplified by an immediately-executed function, is understood by JsDoc through the use of the @namespace annotation. /** * @namespace * Recipe module. */ var Recipe = function () { // ... }(); We can mark private functions with the @private annotation as shown next: /** * @private * Trims leading/trailing space. */ function trim(s) { return s.replace(/^s+|s+$/g, ""); } It gets interesting when we look at the map returned by the Recipe module: return /** @lends Recipe */ { /** * Loads message map. * * <p> * This is generally used to pass in text resources * retrieved via <s:text.../> or <s:property * value="getText(...)"/> tags on a JSP page in lieu * of a normalized way for JS to get Java I18N resources * </p> */ loadMessages: function (msgMap) { _msgMap = msgMap; }, // ... The @lends annotation indicates that the functions returned by the Recipe module belong to the Recipe module. Without the @lends annotation, JsDoc doesn't know how to interpret the JavaScript in the way we probably intend the JavaScript to be used, so we provide a little prodding. The loadMessages() function itself is documented as we would document a Java method, including the use of embedded HTML. The other interesting bit is the map of validation functions. Once again, we apply the @namespace annotation, creating a separate set of documentation for the validation functions, as they're used by our validation template hack and not directly by our page code. /** * @namespace * Client-side page validators used by our template hack. * ... */ pageValidators: { /** * Insures each ingredient with a quantity * also has a name. * * @param {Form object} form * @type boolean */ validateIngredientNameRequired: function (form) { // ... Note also that we can annotate the type of our JavaScript parameters inside curly brackets. Obviously, JavaScript doesn't have typed parameters. We need to tell it what the function is expecting. The @type annotation is used to document what the function is expected to return. It gets a little trickier if the function returns different types based on arbitrary criteria. However, we never do that because it's hard to maintain. JsDoc has the typical plethora of command-line options, and requires the specification of the application itself (written in JavaScript, and run using Rhino) and the templates defining the output format. An alias to run JsDoc might look like the following, assuming the JsDoc installation is being pointed at by the ${JSDOC} shell variable: alias jsdoc='java -jar ${JSDOC}/jsrun.jar ${JSDOC}/app/run.js -t=${JSDOC}/templates/jsdoc' The command line to document our Recipe module (including private functions using the -p options) and to write the output to the jsdoc-out folder, will now look like the following: jsdoc -p -d=jsdoc-out recipe.js The homepage looks similar to a typical JavaDoc page, but more JavaScript-like: A portion of the Recipe module's validators, marked by a @namespace annotation inside the @lends annotation of the return map, looks like the one shown in the next image (the left-side navigation has been removed): We can get a pretty decent and accurate JavaScript documentation using JsDoc, with only a minimal amount of prodding to help with the dynamic aspects of JavaScript, which is difficult to figure out automatically. Documenting interaction Documenting interaction can be surprisingly complicated, particularly in today's highly-interactive Web 2.0 applications. There are many different levels of interactivity taking place, and the implementation may live in several different layers, from the JavaScript browser to HTML generated deep within a server-side framework. UML sequence diagrams may be able to capture much of that interactivity, but fall somewhat short when there are activities happening in parallel. AJAX, in particular, ends up being a largely concurrent activity. We might send the AJAX request, and then do various things on the browser in anticipation of the result. More UML and the power of scribbling The UML activity diagram is able to capture this kind of interactivity reasonably well, as it allows a single process to be split into multiple streams and then joined up again later. As we look at a simple activity diagram, we'll also take a quick look at scribbling, paper, whiteboards, and the humble digital camera. Don't spend so much time making pretty pictures! One of the hallmarks of lightweight, agile development is that we don't spend all of our time creating the World's Most Perfect Diagram™. Instead, we create just enough documentation to get our points across. One result of this is that we might not use a $1,000 diagramming package to create all of our diagrams. Believe it or not, sometimes just taking a picture of a sketched diagram from paper or a whiteboard is more than adequate to convey our intent, and is usually much quicker than creating a perfectly-rendered software-driven diagram. Yes, the image above is a digital camera picture of a piece of notebook paper with a rough activity diagram. The black bars here are used to indicate a small section of parallel functionality, a server-side search and some activity on the browser. The browser programming is informally indicated by the black triangles. In this case, it might not even be worth sketching out. However, for moderately more complicated usage cases, particularly when there is a lot of both server- and client-side activity, a high-level overview is often worth the minimal effort. The same digital camera technique is also very helpful in meetings where various documentation might be captured on a whiteboard. The resulting images can be posted to a company wiki, used in informal specifications, and so on.
Read more
  • 0
  • 0
  • 2864

article-image-html-php-and-content-posting-drupal-6
Packt
15 Oct 2009
9 min read
Save for later

HTML, PHP, and Content Posting in Drupal 6

Packt
15 Oct 2009
9 min read
Input Formats and Filters It is necessary to stipulate the type of content we will be posting, in any given post. This is done through the use of the Input format setting that is displayed when posting content to the site—assuming the user in question has sufficient permissions to post different types of content. In order to control what is and is not allowed, head on over to the Input formats link under Site configuration. This will bring up a list of the currently defined input formats, like this: At the moment, you might be wondering why we need to go to all this trouble to decide whether people can add certain HTML tags to their content. The answer to this is that because both HTML and PHP are so powerful, it is not hard to subvert even fairly simple abilities for malicious purposes. For example, you might decide to allow users the ability to link to their homepages from their blogs. Using the ability to add a hyperlink to their postings, a malicious user could create a Trojan, virus or some other harmful content, and link to it from an innocuous and friendly looking piece of HTML like this: <p>Hi Friends! My <a href="link_to_trojan.exe">homepage</a> is a great place to meet and learn about my interests and hobbies. </p> This snippet writes out a short paragraph with a link, supposedly to the author's homepage. In reality, the hyperlink reference attribute points to a trojan, link_to_trojan.exe. That's just HTML! PHP can do a lot more damage—to the extent that if you don't have proper security or disaster-recovery policies in place, then it is possible that your site can be rendered useless or destroyed entirely. Security is the main reason why, as you may have noticed from the previous screenshot, anything other than Filtered HTML is unavailable for use by anyone except the administrator. By default, PHP is not even present, let alone disabled. When thinking about what permissions to allow, it is important to re-iterate the tenet: Never allow users more permissions than they require to complete their intended tasks! As they stand, you might not find the input formats to your liking, and so Drupal provides some functionality to modify them. Click on the configure link adjacent to the Filtered HTML option, and this will bring up the following page: The Edit tab provides the option to alter the Name property of the input format; the Roles section in this case cannot be changed, but as you will see when we come around to creating our own input format, roles can be assigned however you wish to allow certain users to make use of an input format, or not. The final section provides a checklist of the types of Filters to apply when using this input format. In this previous screenshot, all have been selected, and this causes the input format to apply the: HTML corrector – corrects any broken HTML within postings to prevent undesirable results in the rest of your page. HTML filter – determines whether or not to strip or remove unwanted HTML. Line break converter – Turns standard typed line breaks (i.e. whenever a poster clicks Enter) into standard HTML. URL filter – allows recognized links and email addresses to be clickable without having to write the HTML tags, manually. The line break converter is particularly useful for users because it means that they do not have to explicitly enter <br> or <p> HTML tags in order to display new lines or paragraph breaks—this can get tedious by the time you are writing your 400th blog entry. If this is disabled, unless the user has the ability to add the relevant HTML tags, the content may end up looking like this: Click on the Configure tab, at the top of the page, in order to begin working with the HTML filter. You should be presented with something like this: The URL filter option is really there to help protect the formatting and layout of your site. It is possible to have quite long URLs these days, and because URLs do not contain spaces, there is nowhere to naturally split them up. As a result, a browser might do some strange things to cater for the long string and whatever it is; this will make your site look odd. Decide how many characters the longest string should be and enter that number in the space provided. Remember that some content may appear in the sidebars, so you can't let it get too long if they is supposed to be a fixed width. The HTML filter section lets you specify whether to Strip disallowed tags, or escape them (Escape all tags causes any tags that are present in the post to be displayed as written). Remember that if all the tags are stripped from the content, you should enable the Line break converter so that users can at least paragraph their content properly. Which tags are to be stripped is decided in the Allowed HTML tags section, where a list of all the tags that are to be allowed can be entered—anything else gets handled appropriately. Selecting Display HTML help forces Drupal to provide HTML help for users posting content—try enabling and disabling this option and browsing to this relative URL in each case to see the difference: filter/tips. There is quite a bit of helpful information on HTML in the long filter tips; so take a moment to read over those. The filter tips can be reached whenever a user expands the Input format section of the content post and clicks on More information about formatting options at the bottom of that section. Finally, the Spam link deterrent is a useful tool if the site is being used to bombard members with links to unsanctioned (and often unsavory) products. Spammers will use anonymous accounts to post junk (assuming anonymous users are allowed to post content) and enabling this for anonymous posts is an effective way of breaking them. This is not the end of the story, because we also need to be able to create input formats in the event we require something that the default options can't cater for. For our example, there are several ways in which this can be done, but there are three main criteria that need to be satisfied before we can consider creating the page. We need to be able to: Upload image files and attach them to the post. Insert and display the image files within the body of the post. Use PHP in order to dynamically generate some of the content (this option is really only necessary to demonstrate how to embed PHP in a posting for future reference). There are several methods for displaying image files within posts. The one we will discuss here, does not require us to download and install any contribution modules, such as Img_assist. Instead, we will use HTML directly to achieve this, specifically, we use the <img> tag. Take a look at the previous screenshot that shows the configure page of the Filtered HTML input format. Notice that the <img> tag is not available for use. Let's create our own input format to cater for this, instead of modifying this default format. Before we do, first enable the PHP Filter module under Modules in Site building so that it can easily be used when the time comes. With that change saved, you will find that there is now an extra option to the Filters section of each input format configuration page: It's not a good idea to enable the PHP evaluator for either of the default options, but adding it to one of our own input formats will be ok to play with. Head on back to the main input formats page under Site configuration (notice that there is an additional input format available, called PHP code) and click on Add input format. This will bring up the same configuration type page we looked at earlier. It is easy to implement whatever new settings you want, based on how the input format is to be used. For our example, we need the ability to post images and make use of PHP scripts, so make the new input format as follows: As we will need to make use of some PHP code a bit later on, we have enabled the PHP evaluator option, as well as prevented the use of this format for anyone but ourselves—normally, you would create a format for a group of users who require the modified posting abilities, but in this case, we are simply demonstrating how to create a new input format; so this is fine for now. PHP should not be enabled for anyone other than yourself, or a highly trusted administrator who needs it to complete his or her work. Click Save configuration to add this new format to the list, and then click on the Configure tab to work on the HTML filter. The only change required between this input format and the default Filtered HTML, in terms of HTML, is the addition of the <img> and <div> tags, separated by a space in the Allowed HTML tags list, as follows: As things stand at the moment, you may run into problems with adding PHP code to any content postings. This is because some filters affect the function of others, and to be on the safe side, click on the Rearrange tab and set the PHP evaluator to execute first: Since the PHP evaluator's weight is the lowest, it is treated first, with all the others following suit. It's a safe bet that if you are getting unexpected results when using a certain type of filter, you need to come to this page and change the settings. We'll see a bit more about this, in a moment. Now, the PHP evaluator gets dibs on the content and can properly process any PHP. For the purposes of adding images and PHP to posts (as the primary user), this is all that is needed for now. Once satisfied with the settings save the changes. Before building the new page, it is probably most useful to have a short discourse on HTML, because it is a requirement if you are to attempt more complex postings.  
Read more
  • 0
  • 1
  • 20066

article-image-documenting-our-application-apache-struts-2-part-1
Packt
15 Oct 2009
12 min read
Save for later

Documenting our Application in Apache Struts 2 (part 1)

Packt
15 Oct 2009
12 min read
Documenting Java Everybody knows the basics of documenting Java, so we won't go into much detail. We'll talk a bit about ways of writing code whose intention is clear, mention some Javadoc tricks we can use, and highlight some tools that can help keep our code clean. Clean code is one of the most important ways we can document our application. Anything we can do to increase readability will reduce confusion later (including our own). Self-documenting code We've all heard the myth of self-documenting code. In theory, code is always clear enough to be easily understood. In reality, this isn't always the case. However, we should try to write code that is as self-documenting as possible. Keeping non-code artifacts in sync with the actual code is difficult. The only artifact that survives a project is the executable, which is created from code, not comments. This is one of the reasons for writing self-documenting code. (Annotations, XDoclet, and so on, make that somewhat less true.) There are little things we can do throughout our code to make our code read as much like our intent as possible and make extraneous comments just that: extraneous. Document why, not what Over-commenting wastes everybody's time. Time is wasted in writing a comment, reading it, keeping that comment in sync with the code, and, most importantly, a lot of time is wasted when a comment is not accurate. Ever seen this? a += 1; // increment a This is the most useless comment in the world. Firstly, it's really obvious we're incrementing something, regardless of what that something is. If the person reading our code doesn't know what += is, then we have more serious problems than them not knowing that we're incrementing, say, an array index. Secondly, if a is an array index, we should probably use either a more common array index or make it obvious that it's an array index. Using i and j is common for array indices, while idx or index is less common. It may make sense to be very explicit in variable naming under some circumstances. Generally, it's nice to avoid names such as indexOfOuterArrayOfFoobars. However, with a large loop body it might make sense to use something such as num or currentIndex, depending on the circumstances. With Java 1.5 and its support for collection iteration, it's often possible to do away with the index altogether, but not always. Make your code read like the problem Buzzphrases like Domain Specific Languages (DSLs) and Fluent Interfaces are often heard when discussing how to make our code look like our problem. We don't necessarily hear about them as much in the Java world because other languages support their creation in more "literate" ways. The recent interest in Ruby, Groovy, Scala, and other dynamic languages have brought the concept back into the mainstream. A DSL, in essence, is a computer language targeted at a very specific problem. Java is an example of a general-purpose language. YACC and regular expressions are examples of DSLs that are targeted at creating parsers and recognizing strings of interest respectively. DSLs may be external, where the implementing language processes the DSL appropriately, as well as internal, where the DSL is written in the implementing language itself. An internal DSL can also be thought of as an API or library, but one that reads more like a "little language". Fluent interfaces are slightly more difficult to define, but can be thought of as an internal DSL that "flows" when read aloud. This is a very informal definition, but will work for our purposes Java can actually be downright hostile to some common DSL and fluent techniques for various reasons, including the expectations of the JavaBean specification. However, it's still possible to use some of the techniques to good effect. One typical practice of fluent API techniques is simply returning the object instance in object methods. For example, following the JavaBean specification, an object will have a setter for the object's properties. For example, a User class might include the following: public class User {private String fname;private String lname;public void setFname(String fname) { this.fname = fname; }public void setLname(String lname) { this.lname = lname; }} Using the class is as simple as we'd expect it to be: User u = new User();u.setFname("James");u.setLname("Gosling"); Naturally, we might also supply a constructor that accepts the same parameters. However, it's easy to think of a class that has many properties making a full constructor impractical. It also seems like the code is a bit wordy, but we're used to this in Java. Another way of creating the same functionality is to include setter methods that return the current instance. If we want to maintain JavaBean compatibility, and there are reasons to do so, we would still need to include normal setters, but can still include "fluent" setters as shown here: public User fname(String fname) {this.fname = fname;return this;}public User lname(String lname) {this.lname = lname;return this;} This creates (what some people believe is) more readable code. It's certainly shorter: User u = new User().fname("James").lname("Gosling"); There is one potential "gotcha" with this technique. Moving initialization into methods has the potential to create an object in an invalid state. Depending on the object this may not always be a usable solution for object initialization. Users of Hibernate will recognize the "fluent" style, where method chaining is used to create criteria. Joshua Flanagan wrote a fluent regular expression interface, turning regular expressions (already a domain-specific language) into a series of chained method calls: Regex socialSecurityNumberCheck =new Regex(Pattern.With.AtBeginning.Digit.Repeat.Exactly(3).Literal("-").Repeat.Optional.Digit.Repeat.Exactly(2).Literal("-").Repeat.Optional.Digit.Repeat.Exactly(4).AtEnd); Whether or not this particular usage is an improvement is debatable, but it's certainly easier to read for the non-regex folks. Ultimately, the use of fluent interfaces can increase readability (by quite a bit in most cases), may introduce some extra work (or completely duplicate work, like in the case of setters, but code generation and/or IDE support can help mitigate that), and may occasionally be more verbose (but with the benefit of enhanced clarity and IDE completion support). Contract-oriented programming Aspect-oriented programming (AOP) is a way of encapsulating cross-cutting functionality outside of the mainline code. That's a mouthful, but essentially it means is that we can remove common code that is found across our application and consolidate it in one place. The canonical examples are logging and transactions, but AOP can be used in other ways as well. Design by Contract (DbC) is a software methodology that states our interfaces should define and enforce precise specifications regarding operation. "Design by Contract" is a registered trademark of Interactive Software Engineering Inc. Other terms include Programming by Contract (PbC) or Contract Oriented Programming (COP). How does COP help create self-documenting code? Consider the following portion of a stack implementation: public void push(final Object o) {stack.add(o);} What happens if we attempt to push a null? Let's assume that for this implementation, we don't want to allow pushing a null onto the stack. /*** Pushes non-null objects on to stack.*/public void push(final Object o) {if (o == null) return;stack.add(o);} Once again, this is simple enough. We'll add the comment to the Javadocs stating that null objects will not be pushed (and that the call will fail/return silently). This will become the "contract" of the push method—captured in code and documented in Javadocs. The contract is specified twice—once in the code (the ultimate arbiter) and again in the documentation. However, the user of the class does not have proof that the underlying implementation actually honors that contract. There's no guarantee that if we pass in a null, it will return silently without pushing anything. The implied contract can change. We might decide to allow pushing nulls. We might throw an IllegalArgumentException or a NullPointerException on a null argument. We're not required to add a throwsclause to the method declaration when throwing runtime exceptions. This means further information may be lost in both the code and the documentation. Eiffel has language-level support for COP with the require/do/ensure/end construct. It goes beyond the simple null check in the above code. It actively encourages detailed pre- and post-condition contracts. An implementation's push() method might check the remaining stack capacity before pushing. It might throw exceptions for specific conditions. In pseudo-Eiffel, we'd represent the push() method in the following way: push (o: Object) require o /= null do -- push end A stack also has an implied contract. We assume (sometimes naively) that once we call the push method, the stack will contain whatever we pushed. The size of the stack will have increased by one, or whatever other conditions our stack implementation requires. Java, of course, doesn't have built-in contracts. However, it does contain a mechanism that can be used to get some of the benefits for a conceptually-simple price. The mechanism is not as complete, or as integrated, as Eiffel's version. However, it removes contract enforcement from the mainline code, and provides a way for both sides of the software to specify, accept, and document the contracts themselves. Removing the contract information from the mainline code keeps the implementation clean and makes the implementation code easier to understand. Having programmatic access to the contract means that the contract could be documented automatically rather than having to maintain a disconnected chunk of Javadoc. SpringContracts SpringContracts is a beta-level Java COP implementation based on Spring's AOP facilities, using annotations to state pre- and post-contract conditions. It formalizes the nature of a contract, which can ease development. Let's consider our VowelDecider that was developed through TDD. We can also use COP to express its contract (particularly the entry condition). This is a method that doesn't alter state, so post conditions don't apply here. Our implementation of VowelDecider ended up looking (more or less) like this: public boolean decide(final Object o) throws Exception {if ((o == null) || (!(o instanceof String))) {throw new IllegalArgumentException("Argument must be a non-null String.");}String s = (String) o;return s.matches(".*[aeiouy]+.*");} Once we remove the original contract enforcement code, which was mixed with the mainline code, our SpringContracts @Precondition annotation looks like the following: @Precondition(condition="arg1 != null && arg1.class.name == 'java.lang.String'",message="Argument must be a non-null String")public boolean decide(Object o) throws Exception {String s = (String) o;return s.matches(".*[aeiouy]+.*");} The pre-condition is that the argument must not be null and must be (precisely) a string. (Because of SpringContracts' Expression Language, we can't just say instanceof String in case we want to allow string subclasses.) We can unit-test this class in the same way we tested the TDD version. In fact, we can copy the tests directly. Running them should trigger test failures on the null and non-string argument tests, as we originally expected an IllegalArgumentException. We'll now get a contract violation exception from SpringContracts. One difference here is that we need to initialize the Spring context in our test. One way to do this is with JUnit's @BeforeClass annotation, along with a method that loads the Spring configuration file from the classpath and instantiates the decider as a Spring bean. Our class setup now looks like this: @BeforeClass public static void setup() {appContext = new ClassPathXmlApplicationContext("/com/packt/s2wad/applicationContext.xml");decider = (VowelDecider)appContext.getBean("vowelDecider");} We also need to configure SpringContracts in our Spring configuration file. Those unfamiliar with Spring's (or AspectJ's) AOP will be a bit confused. However, in the end, it's reasonably straightforward, with a potential "gotcha" regarding how Spring does proxying. <aop:aspectj-autoproxy proxy-target-class="true"/><aop:config><aop:aspect ref="contractValidationAspect"><aop:pointcut id="contractValidatingMethods"expression="execution(*com.packt.s2wad.example.CopVowelDecider.*(..))"/><aop:around pointcut-ref="contractValidatingMethods"method="validateMethodCall"/></aop:aspect></aop:config><bean id="contractValidationAspect"class="org.springcontracts.dbc.interceptor.ContractValidationInterceptor"/><bean id="vowelDecider"class="com.packt.s2wad.example.CopVowelDecider" /> The SpringContracts documentation goes into it a bit more and the Spring documentation contains a wealth of information regarding how AOP works in Spring. The main difference between this and the simplest AOP setup is that our autoproxy target must be a class, which requires CGLib. This could also potentially affect operation. The only other modification is to change the exception we're expecting to SpringContract's ContractViolationCollectionException, and our test starts passing. These pre- and post-condition annotations use the @Documented meta-annotation, so the SpringContracts COP annotations will appear in the Javadocs. It would also be possible to use various other means to extract and document contract information. Getting into details This mechanism, or its implementation, may not be a good fit for every situation. Runtime performance is a potential issue. As it's just some Spring magic, it can be turned off by a simple configuration change. However, if we do, we'll lose the value of the on-all-the-time contract management. On the other hand, under certain circumstances, it may be enough to say that once the contracts are consistently honored under all of the test conditions, the system is correct enough to run without them. This view holds the contracts more as an acceptance test, rather than as run-time checking. Indeed, there is an overlap between COP and unit testing as the way to keep code honest. As unit tests aren't run all the time, it may be reasonable to use COP as a temporary runtime unit test or acceptance test.
Read more
  • 0
  • 0
  • 2808

article-image-creating-new-types-plone-portlets
Packt
15 Oct 2009
4 min read
Save for later

Creating New Types of Plone Portlets

Packt
15 Oct 2009
4 min read
(For more resources on Plone, see here.) Plone makes it easy to create new types of portlets that include custom programming logic for your site. There are several ways to create custom portlets, but the simplest way to get started is to use the add-on product collective.portlet.tal which provides a new type of portlet, called a TAL Portlet. This portlet allows you to write simple bits of code using Zope's TAL templating language. Let's walk through a quick example of building a custom TAL portlet, which will show a randomly-selected news item from your site. Installing collective.portlet.tal Before you can add a TAL portlet, you must download the product from Plone.org/products and install the add-on product collective.portlet.tal on your site. The best way to do this is to modify your buildout.cfg file. Add collective.portlet.tal to the eggs and zcml sections of your buildout. Here's a code snippet with the changes made to it: [buildout] ... eggs = ... collective.portlet.tal [instance] recipe = plone.recipe.zope2instance ... zcml = collective.portlet.tal Once you've made these changes, re-run buildout by issuing the following command: $ ./bin/buildout Once you've added the product to your buildout, visit Site Setup and choose Add/Remove Products, to install collective.portlet.tal in your site. Finally, add a few news items to your site so that we have something for our new TAL portlet to find. Adding a simple TAL portlet With the collective.portlet.tal product in place, the following can happen: Navigate to your Plone site. Choose Manage Portlets in the right column. From the Add portlet... drop-down list, choose TAL Portlet. You'll see an empty text box in which you can enter a title. We will specify Featured News Item as our title. We'll soon see the code needed to feature a random one of our site's published news items. In addition to the Title text box, you'll also see an HTML text area titled TAL code. Conveniently, this comes pre-populated with some boilerplate HTML and TAL code. Skim this, so that you get a feel for how this looks and what the common HTML structure is like, for a portlet in Plone. As an immediate experiment, we will find the following snippet of code: <dd class="portletItem odd"> Body text</dd> We will modify this, slightly, to: <dd class="portletItem odd"> Is this thing on?</dd> Click on Save and navigate through the site, and you should see your first TAL portlet in action. Of course, there's nothing in this example that couldn't be accomplished with a static text portlet. So let's navigate back to the Featured News Item portlet and make it a bit more interesting and dynamic. Update the code in your TAL Portlet to include the following: <dl class="portlet portlet${portlet_type_name}" tal_define="newsitems python:context.portal_catalog (portal_type='News Item', review_state='published');" tal_condition="newsitems"> <dt class="portletHeader"> <span class="portletTopLeft"></span> <span> Featured News Item </span> <span class="portletTopRight"></span> </dt> <dd class="portletItem odd" tal_define="random_newsitem python:random.choice(newsitems)"> <a tal_content="random_newsitem/Title" href="[replaced by random news item link]" title="[replaced by random news item title]" tal_attributes="href random_newsitem/getURL; title random_newsitem/Title">[replaced by random news item title]</a> </dd> <dd class="portletFooter"> <span class="portletBotomLeft"></span> <span> <a href="http://example.com/news">More news...</a> </span> <span class="portletBottomRight"></span> </dd> </dl> Now, let's go into more detail on a few of these sections, so that you understand what's happening. If at any point you need more context, try reading the excellent ZPT reference manual at http://plone.org/documentation/tutorial/zpt.
Read more
  • 0
  • 0
  • 2158
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-how-bridge-client-server-gap-using-ajax-part-ii
Packt
15 Oct 2009
7 min read
Save for later

How to Bridge the Client-Server Gap using AJAX (Part II)

Packt
15 Oct 2009
7 min read
AJAX and events Suppose we wanted to allow each dictionary term name to control the display of the definition that follows; clicking on the term name would show or hide the associated definition. With the techniques we have seen so far, this should be pretty straightforward: $(document).ready(function() { $('.term').click(function() { $(this).siblings('.definition').slideToggle(); });}); When a term is clicked, this code finds siblings of the element that have a class of definition, and slides them up or down as appropriate. All seems in order, but a click does nothing with this code. Unfortunately, the terms have not yet been added to the document when we attach the click handlers. Even if we managed to attach click handlers to these items, once we clicked on a different letter the handlers would no longer be attached. This is a common problem with areas of a page populated by AJAX. A popular solution is to rebind handlers each time the page area is refreshed. This can be cumbersome, however, as the event binding code needs to be called each time anything causes the DOM structure of the page to change. We can implement event delegation, actually binding the event to an ancestor element that never changes. In this case, we'll attach the click handler to the document using .live() and catch our clicks that way: $(document).ready(function() { $('.term').live('click', function() { $(this).siblings('.definition').slideToggle(); });}); The .live() method tells the browser to observe all clicks anywhere on the page. If (and only if) the clicked element matches the .term selector, then the handler is executed. Now the toggling behavior will take place on any term, even if it is added by a later AJAX transaction. Security limitations For all its utility in crafting dynamic web applications, XMLHttpRequest (the underlying browser technology behind jQuery's AJAX implementation) is subject to strict boundaries. To prevent various cross-site scripting attacks, it is not generally possible to request a document from a server other than the one that hosts the original page. This is generally a positive situation. For example, some cite the implementation of JSON parsing by using eval() as insecure. If malicious code is present in the data file, it could be run by the eval() call. However, since the data file must reside on the same server as the web page itself, the ability to inject code in the data file is largely equivalent to the ability to inject code in the page directly. This means that, for the case of loading trusted JSON files, eval() is not a significant security concern. There are many cases, though, in which it would be beneficial to load data from a third-party source. There are several ways to work around the security limitations and allow this to happen. One method is to rely on the server to load the remote data, and then provide it when requested by the client. This is a very powerful approach as the server can perform pre-processing on the data as needed. For example, we could load XML files containing RSS news feeds from several sources, aggregate them into a single feed on the server, and publish this new file for the client when it is requested. To load data from a remote location without server involvement, we have to get a bit sneakier. A popular approach for the case of loading foreign JavaScript files is injecting <script> tags on demand. Since jQuery can help us insert new DOM elements, it is simple to do this: $(document.createElement('script')) .attr('src', 'http://example.com/example.js') .appendTo('head'); In fact, the $.getScript() method will automatically adapt to this technique if it detects a remote host in its URL argument, so even this is handled for us. The browser will execute the loaded script, but there is no mechanism to retrieve results from the script. For this reason, the technique requires cooperation from the remote host. The loaded script must take some action, such as setting a global variable that has an effect on the local environment. Services that publish scripts that are executable in this way will also provide an API with which to interact with the remote script. Another option is to use the <iframe> HTML tag to load remote data. This element allows any URL to be used as the source for its data fetching, even if it does not match the host page's server. The data can be loaded and easily displayed on the current page. Manipulating the data, however, typically requires the same cooperation needed for the <script> tag approach; scripts inside the <iframe> need to explicitly provide the data to objects in the parent document. Using JSONP for remote data The idea of using <script> tags to fetch JavaScript files from a remote source can be adapted to pull in JSON files from another server as well. To do this, we need to slightly modify the JSON file on the server, however. There are several mechanisms for doing this, one of which is directly supported by jQuery: JSON with Padding, or JSONP. The JSONP file format consists of a standard JSON file that has been wrapped in parentheses and prepended with an arbitrary text string. This string, the "padding", is determined by the client requesting the data. Because of the parentheses, the client can either cause a function to be called or a variable to be set depending on what is sent as the padding string. A PHP implementation of the JSONP technique is quite simple: <?php print($_GET['callback'] .'('. $data .')');?> Here, $data is a variable containing a string representation of a JSON file. When this script is called, the callback query string parameter is prepended to the resulting file that gets returned to the client. To demonstrate this technique, we need only slightly modify our earlier JSON example to call this remote data source instead. The $.getJSON() function makes use of a special placeholder character, ?, to achieve this. $(document).ready(function() { var url = 'http://examples.learningjquery.com/jsonp/g.php'; $('#letter-g a').click(function() { $.getJSON(url + '?callback=?', function(data) { $('#dictionary').empty(); $.each(data, function(entryIndex, entry) { var html = '<div class="entry">'; html += '<h3 class="term">' + entry['term'] + '</h3>'; html += '<div class="part">' + entry['part'] + '</div>'; html += '<div class="definition">'; html += entry['definition']; if (entry['quote']) { html += '<div class="quote">'; $.each(entry['quote'], function(lineIndex, line) { html += '<div class="quote-line">' + line + '</div>'; }); if (entry['author']) { html += '<div class="quote-author">' + entry['author'] + '</div>'; } html += '</div>'; } html += '</div>'; html += '</div>'; $('#dictionary').append(html); }); }); return false; });}); We normally would not be allowed to fetch JSON from a remote server (examples.learningjquery.com in this case). However, since this file is set up to provide its data in the JSONP format, we can obtain the data by appending a query string to our URL, using ? as a placeholder for the value of the callback argument. When the request is made, jQuery replaces the ? for us, parses the result, and passes it to the success function as data just as if this were a local JSON request. Note that the same security cautions hold here as before; whatever the server decides to return to the browser will execute on the user's computer. The JSONP technique should only be used with data coming from a trusted source.
Read more
  • 0
  • 0
  • 3204

article-image-layout-dojo-part-2
Packt
15 Oct 2009
12 min read
Save for later

Layout in Dojo: Part 2

Packt
15 Oct 2009
12 min read
GridContainer There are a lot of sites available that let you add a lot of rss feeds and assorted widgets to a personal page, and which then also let you arrange them by dragging the widgets themselves around the page. One of the most known examples is iGoogle, Google's personal homepage for users with a staggering amount of widgets that are easy to move around. This functionality is called a GridContainer in Dojo. If you're not familiar with the concept and have never used a service which lets you rearrange widgets, it works like this: The GridContainer defines a number of different columns, called zones. Each column can contain any number of child widgets, including other containers (like AccordionContainer or BorderContainer). Each child widget becomes draggable and can be dragged into a new position within its own column, or dragged to a new position in another column. As the widget gets dragged, it uses a semi-transparent 'avatar'. As the widget gets dragged, possible target drop zones open up and close themselves dynamically under the cursor, until the widget is dropped on one of them. When a widget is dropped, the target column automatically rearranges itself to make the new widget fit. Here is an example from test_GridContainer.html in /dojox/layout/tests/. This is what the GridContainer looks like from the beginning: It has three columns (zones) defined which contain a number of child widgets. One of them is a Calendar widget, which is then dragged to the second column from its original position in the third: Note the new target area being offered by the second column. This will be closed again if we continue to move the cursor over to the first column. Also, in the example above, transparency of 1.0 (none) is added to the avatar, which looks normal. Finally, the widget is dropped onto the second column, both the source and target column arrange their widgets according to whether one has been added or removed. The implications of this is that it becomes very simple to create highly dynamical interfaces. Some examples might be: An internal "dashboard" for management or other groups in the company which needs rearrangeable views on different data sources. Portlets done right. Using dojox.charting to create different diagrammatic views on data sources read from the server, letting the user create new diagrams and rearranging them in patterns or groups meaningful to the current viewer. A simple front-end for a CMS-system, where the editor widget is used to enter text, and the user can add, delete or change paragraphs as well as dragging them around and rearranging their order. An example of how to create a GridContainer using markup (abbreviated) is as follows: <div id="GC1" dojoType="dojox.layout.GridContainer" nbZones="3" opacity="0.7" allowAutoScroll="true" hasResizableColumns="false" withHandles="true" acceptTypes="dijit.layout.ContentPane, dijit.TitlePane, dijit.ColorPalette, dijit._Calendar"><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?1 !</div><div dojoType="dijit.TitlePane" title="Ergo">Non ergo erunt homines deliciis ...</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?2 !</div><div dojoType="dijit.layout.ContentPane" title="Intellectum">Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M....</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?3 !</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?4 !</div><div dojoType="dijit._Calendar"></div></div> The GridContainer wraps all of its contents.These are not added is not added in a hierarchical manner, but instead all widgets are declared inside the GridContainer element. When the first column's height is filled, the next widget in the list gets added to the next column, and so on. This is a quite unusual method of layout, and we might see some changes to this mode of layout since the GridContainer is very much beta [2008]. The properties for the GridContainer are the following: //i18n: Object//Contain i18n ressources.i18n: null,//isAutoOrganized: Boolean://Define auto organisation of children into the grid container.isAutoOrganized : true,//isRightFixed: Boolean//Define if the right border has a fixed size.isRightFixed:false,//isLeftFixed: Boolean//Define if the left border has a fixed size.isLeftFixed:false,//hasResizableColumns: Boolean//Allow or not resizing of columns by a grip handle.hasResizableColumns:true,//nbZones: Integer//The number of dropped zones.nbZones:1,//opacity: Integer//Define the opacity of the DnD Avatar.opacity:1,//minColWidth: Integer//Minimum column width in percentage.minColWidth: 20,//minChildWidth: Integer//Minimun children with in pixel (only used for IE6 that doesn't//handle min-width css propertyminChildWidth : 150,//acceptTypes: Array//The gridcontainer will only accept the children that fit to//the types.//In order to do that, the child must have a widgetType or a//dndType attribute corresponding to the accepted type.acceptTypes: [],//mode: String//location to add columns, must be set to left or right(default)mode: "right",//allowAutoScroll: Boolean//auto-scrolling enable inside the GridContainerallowAutoScroll: false,//timeDisplayPopup: Integer//display time of popup in milisecondstimeDisplayPopup: 1500,//isOffset: Boolean//if true : Let the mouse to its original location when moving//(allow to specify it proper offset)//if false : Current behavior, mouse in the upper left corner of//the widgetisOffset: false,//offsetDrag: Object//Allow to specify its own offset (x and y) onl when Parameter//isOffset is trueoffsetDrag : {}, ////withHandles: Boolean//Specify if there is a specific drag handle on widgetswithHandles: false,//handleClasses: Array//Array of classes of nodes that will act as drag handleshandleClasses : [], The property isAutoOrganized, which is set to true by default, can be set to false, which will leave holes in your source columns, and require you to manage the space in the target columns yourself. The opacity variable is the opacity for the 'avatar' of the dragged widget, where 1 is completely solid, and 0 is completely transparent. The hasResizableColumns variable also adds SplitContainer/BorderContainer splitters between columns, so that the user can change the size ratio between columns. The minColWidt/minChildWidth variables manage the minimum widths of columns and child widgets in relation to resizing events. The AcceptTypes variable is an important property, which lets you define which classes you allow to be dropped on a column. In the above example code, that string is set to dijit.layout.ContentPane, dijit.TitlePane, dijit.ColorPalette, dijit._Calendar. This makes it impossible to drop an AccordionContainer on a column. The reason for this is that certain things would want to be fixed, like status bars or menus, but still inside one of the columns. The withHandles variable can be set to true if you want each widget to get a visible 'drag handle' appended to it. RadioGroup The source code of dojox.layout.RadioGroup admits that it probably is poorly named, because it has little to do with radio buttons or groups of them, per se, even if this was probably the case when it was conceived. The RadioGroup extends the StackContainer, doing something you probably had ideas about the first time you saw it – adding flashy animations when changing which child container is shown. One example of how to use StackContainer and its derivatives is an information box for a list of friends. Each information box is created as a ContentPane which loads its content from a URL. As the user clicks on or hovers over the next friend on a nearby list, an event is triggered to show the next item (ContentPane) in the stack. Enter the RadioGroup, which defines its own set of buttons that mirror the ContentPanes which it wraps. The unit test dojox/layout/tests/test_RadioGroup.html defines a small RadioGroup in the following way: <div dojoType="dojox.layout.RadioGroup" style="width:300px; height:300px; float:left;" hasButtons="true"><div dojoType="dijit.layout.ContentPane" title="Dojo" class="dojoPane" style="width:300px; height:300px; "></div><div dojoType="dijit.layout.ContentPane" title="Dijit" class="dijitPane" style="width:300px; height:300px; "></div><div dojoType="dijit.layout.ContentPane" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "></div></div> As you can see, it does not take much space. In the test, the ContentPanes are filled with only the logos for the different parts of Dojo, defined as background images by CSS classes. The RadioGroup iterates over each child ContentPane, and creates a "hover button" for it, which is connected to an event handler which manages the transition, so if you don' t have any specific styling for your page and just want to get a quick mock-up done, the RadioGroup is very easy to work with. The default RadioGroup works very much like its parent class, StackContainer, mostly providing a simple wrapper that generates mouseover buttons. In the same file that defines the basic RadioGroup, there are two more widgets: RadioGroupFade and RadioGroupSlide. These have exactly the same kind of markup as their parent class, RadioGroup. RadioGroupFade looks like this in its entirety: dojo.declare("dojox.layout.RadioGroupFade", dojox.layout.RadioGroup, { // summary: An extension on a stock RadioGroup, that fades the //panes. _hideChild: function(page){ // summary: hide the specified child widget dojo.fadeOut({ node:page.domNode, duration:this.duration, onEnd: dojo.hitch(this,"inherited", arguments) }).play(); }, _showChild: function(page){ // summary: show the specified child widget this.inherited(arguments); dojo.style(page.domNode,"opacity",0); dojo.fadeIn({ node:page.domNode, duration:this.duration }).play(); }}); As you can see, all it does is override two functions from RadioGroup which manage how to show and hide child nodes upon transitions. The basic idea is to use the integral Dojo animations fadeIn and fadeOut for the effects. The other class, RadioGroupSlide, is a little bit longer, but not by much. It goes beyond basic animations and uses a specific easing function. In the beginning of its definition is this variable: // easing: Function// A hook to override the default easing of the pane slides.easing: "dojo.fx.easing.backOut", Later on, in the overridden _hide and _showChild functions, this variable is used when creating a standalone animation: ...this._anim = dojo.animateProperty({ node:page.domNode, properties: { left: 0, top: 0 }, duration: this.duration, easing: this.easing, onEnd: dojo.hitch(page,function(){ if(this.onShow){ this.onShow(); } if(this._loadCheck){ this._loadCheck(); } })});this._anim.play();   What this means is that it is very simple to change (once again) what kind of animation is used when hiding the current child and showing next, which can be very usable. Also, you can see that it is very simple to create your own subclass widget out of RadioGroup which can use custom actions when child nodes are changed. ResizeHandle The ResizeHandle tucks a resize handle, as the name implies, into the corner of an existing element or widget. The element which defines the resize handle itself need not be a child element or even adjacent to the element which is to receive the handle. Instead the id of the target element is defined as an argument to the ResizeHandle as shown here: <div dojoType="dijit.layout.ContentPane" title="Test window" style="width: 300px; height: 200px; padding:10px; border: 1px solid #dedede; position: relative; background: white;" id="testWindow"> ...<div id="hand1" dojoType="dojox.layout.ResizeHandle" targetId="testWindow"></div> </div> In this example, a simple ContentPane is defined first, with some custom styling to make it stand out a little bit. Further on in the same pages comes a ResizeHandle definition which sets the targetId property of the newly created ResizeHandle to that of the ContentPane ('testWindow'). The definition of the ResizeHandle class shows some predictable goodies along with one or two surprises: //targetContainer: DomNode//over-ride targetId and attch this handle directly to a//reference of a DomNodetargetContainer: null,//resizeAxis: String//one of: x|y|xy limit resizing to a single axis, default to xy ...resizeAxis: "xy",//activeResize: Boolean//if true, node will size realtime with mouse movement,//if false, node will create virtual node, and only resize target//on mouseUp.activeResize: false,//activeResizeClass: String//css class applied to virtual resize node.activeResizeClass: 'dojoxResizeHandleClone',//animateSizing: Boolean//only applicable if activeResize = false. onMouseup, animate the//node to the new size.animateSizing: true,//animateMethod: String//one of "chain" or "combine" ... visual effect only.combine will "scale"//node to size, "chain" will alter width, then heightanimateMethod: 'chain',//animateDuration: Integer//time in MS to run sizing animation. if animateMethod="chain",//total animation playtime is 2*animateDuration.animateDuration: 225,//minHeight: Integer//smallest height in px resized node can beminHeight: 100,//minWidth: Integer//smallest width in px resize node can beminWidth: 100, As could be expected, it is simple to change if the resizing is animated during mouse move or afterwards (activeResize: true/false). If afterwards, the animateDuration declares in milliseconds the length of the animation. A very useful property is the ability to lock the resizing action to just one of the two axes. The resizeAxis property defaults to xy, but can be set to only x or only y as well. Both restricts resizing to only one axis and also changes the resize cursor to show correct feedback to which axis is 'active' at the moment. If you at any point want to remove the handle, calling destroy() on it will remove it from the target node without any repercussions.
Read more
  • 0
  • 0
  • 3398

article-image-xpath-support-oracle-jdeveloper-xdk-11g
Packt
15 Oct 2009
11 min read
Save for later

XPath Support in Oracle JDeveloper - XDK 11g

Packt
15 Oct 2009
11 min read
With SAX and DOM APIs, node lists have to be iterated over to access a particular node. Another advantage of navigating an XML document with XPath is that an attribute node may be selected directly. With DOM and SAX APIs, an element node has to be selected before an element attribute can be selected. Here we will discuss XPath support in JDeveloper. What is XPath? XPath is a language for addressing an XML document's elements and attributes. As an example, say you receive an XML document that contains the details of a shipment and you want to retrieve the element/attribute values from the XML document. You don't just want to list the values of all the nodes, but also want to output the values of specific elements or attributes. In such a case, you would use XPath to retrieve the values of those elements and attributes. XPath constructs a hierarchical structure of an XML document, a tree of nodes, which is the XPath data model. The XPath data model consists of seven node types. The different types of nodes in the XPath data model are discussed in the following table: Node Type Description Root Node The root node is the root of the DOM tree. The document element (the root element) is a child of the root node. The root node also has the processing instructions and comments as child nodes. Element Node It represents an element in an XML document. The character data, elements, processing instruction, and comments within an element are the child nodes of the element node. Attribute Node It represents an attribute other than the valign="top"> Text Node The character data within an element is a text node. A text node has at least one character of data. A whitespace is also considered as a character of data.  By default, the ignorable whitespace after the end of an element and before the start of the following element is also a text node. The ignorable whitespace can be excluded from the DOM tree built by parsing an XML document. This can be done by setting the whitespace-preserving mode to false with the setPreserveWhitespace(boolean flag) method. Comment Node It represents a comment in an XML document, except the comments within the DOCTYPE declaration. Processing Instruction Node It represents a processing instruction in an XML document except the processing instruction within the DOCTYPE declaration. The XML declaration is not considered as a processing instruction node. Namespace Node It represents a namespace mapping, which consists of a . A namespace node consists of a namespace prefix (xsd in the example) and a namespace URI (http://www.w3.org/2001/XMLSchema in the example). Specific nodes including element, attribute, and text nodes may be accessed with XPath. XPath supports nodes in a namespace. Nodes in XPath are selected with an XPath expression. An expression is evaluated to yield an object of one of the following four types: node set, Boolean, number, or string. For an introduction on XPath refer to the W3C Recommendation for XPath (http://www.w3.org/TR/xpath). As a brief review, expression evaluation in XPath is performed with respect to a context node. The most commonly used type of expression in XPath is a location path . XPath defines two types of location paths: relative location paths and absolute location paths. A relative location path is defined with respect to a context node and consists of a sequence of one or more location steps separated by "/". A location step consists of an axis, a node test, and predicates. An example of a location step is: child::journal[position()=2] In the example, the child axis contains the child nodes of the context node. Node test is the journal node set, and predicate is the second node in the journal node set. An absolute location path is defined with respect to the root node, and starts with "/". The difference between a relative location path and an absolute location path is that a relative location path starts with a location step, and an absolute location path starts with "/". XPath in Oracle XDK 11g Oracle XML Developer's Kit 11g, which is included in JDeveloper, provides the DOMParser class to parse an XML document and construct a DOM structure of the XML document. An XMLDocument object represents the DOM structure of an XML document. An XMLDocument object may be retrieved from a DOMParser object after an XML document has been parsed. The XMLDocument class provides select methods to select nodes in an XML document with an XPath expression. In this article we shall parse an example XML document with the DOMParser class, obtain an XMLDocument object for the XML document, and select nodes from the document with the XMLDocument class select methods. The different select methods in theXMLDocument class are discussed in the following table: Method Name Description selectSingleNode(String XPathExpression) Selects a single node that matches an XPath expression. If more than one node matches the specified expression, the first node is selected. Use this method if you want to select the first node that matches an XPath expression. selectNodes(String XPathExpression) Selects a node list of nodes that match a specified XPath expression. Use this method if you want to select a collection of similar nodes. selectSingleNode(String XPathExpression, NSResolver resolver) Selects a single namespace node that matches a specified XPath expression. Use this method if the XML document has nodes in namespaces and you want to select the first node, which is in a namespace and matches an XPath expression. selectNodes(String XPathExpression, NSResolver resolver) Selects a node list of nodes that match a specified XPath expression. Use this method if you want to select a collection of similar nodes that are in a namespace. The example XML document that is parsed in this article has a namespace declaration for elements in the namespace with the prefix journal. For an introduction on namespaces in XML refer to the W3C Recommendation on Namespaces in XML 1.0 (http://www.w3.org/TR/REC-xml-names/). catalog.xml, the example XML document, is shown in the following listing: <?xml version="1.0" encoding="UTF-8"?><catalog title="Oracle Magazine" publisher="Oracle Publishing"><journal:journal journal_date="November-December 2008"> <journal:article journal_section="ORACLE DEVELOPER"> <title>Instant ODP.NET Deployment</title> <author>Mark A. Williams</author></journal:article><journal:article journal_section="COMMENT"> <title>Application Server Convergence</title> <author>David Baum</author> </journal:article></journal:journal><journal date="March-April 2008"> <article section="TECHNOLOGY"> <title>Oracle Database 11g Redux</title> <author>Tom Kyte</author> </article><article section="ORACLE DEVELOPER"> <title>Declarative Data Filtering</title> <author>Steve Muench</author> </article> </journal></catalog Setting the environment Create an application (called XPath, for example) and a project (called XPath) in JDeveloper. The XPath API will be demonstrated in a Java application. Therefore, create a Java class in the XPath project with File | New. In the New Gallery window select < >Categories | General and Items | Java Class. In the Create Java Class window, specify the class name (XPathParser, for example), the package name (xpath in the example application), and click on the OK button. To develop an application with XPath, add the required libraries to the project classpath. Select the project node in Application Navigator and select Tools | Project Properties. In the Project Properties window, select the Libraries and Classpath node. To add a library, select the Add Library button. Select the Oracle XML Parser v2 library. Click on the OK button in the Project Properties window. We also need to add an XML document that is to be parsed and navigated with XPath. To add an XML document, select File | New. In the New Gallery window, select Categories | General | XML and Items | XML Document. Click on the OK button. In the Create XML File window specify the file name catalog.xml in the File Name field, and click on the OK button. Copy the catalog.xml listing to the catalog.xml file in the Application Navigator. The directory structure of the XPath project is shown in the following illustration: XPath Search In this section, we shall select nodes from the example XML document, catalog.xml, with the XPath Search tool of JDeveloper 11g. The XPath Search tool consists of an Expression field for specifying an XPath expression. Specify an XPath expression and click on OK to select nodes matching the XPath expression. The XPath Search tool has the provision to search for nodes in a specific namespace. An XML namespace is a collection of element and attribute names that are identified by a URI reference. Namespaces are specified in an XML document using namespace declarations. A namespace declaration is an > To navigate catalog.xml with XPath, select catalog.xml in the Application Navigator and select Search | XPath Search. In the following subsections, we shall select example nodes using absolute location paths and relative location paths. Use a relative location path if the XML document is large and a specifi c node is required. Also, use a relative path if the node from which subnodes are to be selected and the relative location path are known. Use an absolute location path if the XML document is small, or if the relative location path is not known. The objective is to use minimum XPath navigation. Use the minimum number nodes to navigate in order to select the required node. Selecting nodes with absolute location paths Next, we shall demonstrate with various examples of selecting nodes using XPath. As an example, select all the title elements in catalog.xml. Specify the XPath expression for selecting the title elements in the Expression field of the Apply an XPath Expression on catalog.xml window. The XPath expression to select all title elements is /catalog/journal/article/title. Click on the OK button to select the title elements. The title elements get selected. Title elements from the journal:article elements in the journal namespace do not get selected because a namespace has not been applied to the XPath expression. As an other example, select the title element in the first article element using the XPath expression /catalog/journal/article[1]/title. We are not using namespaces yet. The XPath expression is specified in the Expression field. The title of the first article element gets selected as shown in the JDeveloper output: Attribute nodes may also be selected with XPath. Attributes are selected by using the "@" prefix. As an example, select the section attribute in the first article element in the journal element. The XPath expression for selecting the section attribute is /catalog/journal/article[1]/@section and is specified in the Expression field. Click on the OK button to select the section attribute. The attribute section gets outputted in JDeveloper. Selecting nodes with relative location paths In the previous examples, an absolute location is used to select nodes. Next, we shall demonstrate selecting an element with a relative location path. As an example, select the title of the first article element in the journal element. The relative location path for selecting the title element is child::catalog/journal/article[position()=1]/title. Specifying the axis as child and node test as catalog selects all the child nodes of the catalog node and is equivalent to an absolute location path that starts with /catalog. If the child nodes of the journal node were required to be selected, specify the node test as journal. Specify the XPath expression in the Expression field and click on the OK button. The title of the first article element in the journal element gets selected as shown here: Selecting namespace nodes XPath Search also has the provision to select elements and attributes in a namespace. To illustrate, select all the title elements in the journal element (that is, in the journal namespace) using the XPath expression /catalog/journal:journal/journal:article/title. First, add the namespaces of the elements and attributes to be selected in the Namespaces text area. Prefix and URI of namespaces are added with the Add button. Specify the prefix in the Prefix column, and the URI in the URI column. Multiple namespace mappings may be added. XPath expressions that select namespace nodes are similar to no-namespace expressions, except that the namespace prefixes are included in the expressions. Elements in the default namespace, which does not have a namespace prefix, are also considered to be in a namespace. Click on the OK button to select the nodes with XPath. The title elements in the journal element (in the journal namespace) get selected and outputted in JDeveloper. Attributes in a namespace may also be selected with XPath Search. As an example, select the section attributes in the journal namespace. Specify the XPath expression to select the section attributes in the Expression field and click on the OK button. Section attributes in the journal namespace get selected.
Read more
  • 0
  • 0
  • 5524

article-image-working-javascript-drupal-6-part-1
Packt
15 Oct 2009
11 min read
Save for later

Working with JavaScript in Drupal 6: Part 1

Packt
15 Oct 2009
11 min read
How Drupal handles JavaScript How is JavaScript typically used? Mostly, it is used to provide additional functionality to a web page, which is usually delivered to a web browser as an HTML document. The browser receives the HTML from the server and then begins the process of displaying the page. During this parsing and rendering process, the browser may request additional resources from the server such as images, CSS, or Flash. It then incorporates these elements into the document displayed to the user. In this process, there are two ways that JavaScript code can be sent from the server to the browser. First, the code can be placed directly inside the HTML. This is done by inserting code inside the <script> and </script> tags: <script type="text/javascript">alert('hello world');</script> This is called including the script inline. Second, the code can be loaded separately from the rest of the HTML. Again, this is usually done using the <script> and </script> tags. However, instead of putting the code between the tags, we use the src attribute to instruct the browser to retrieve an additional document from the server. <script type="text/javascript" src="some/script.js"></script> In this example, src="some/script.js" points the browser to an additional script file stored on the same server as the HTML document in which this script tag is embedded. So, if the HTML is located at http://example.com/index.html, the browser will request the script file using the URL http://example.com/some/script.js. The </script> tag is required When XML was first standardized, it introduced a shorthand notation for writing tags that have no content. Instead of writing <p></p>, one could simply write <p/>. While this notation is supported by all modern mainstream browsers, it cannot be used for <script></script> tags. Some browsers do not recognize <script/> and expect that any <script> tag will be accompanied by a closing </script> tag even if there is no content between the tags. If we were developing static HTML files, we would simply write HTML pages that include <script></script> tags anytime we needed to add some JavaScript to the page. But we're using Drupal, not static HTML, and the process for adding JavaScript in this environment is done differently. Where Drupal JavaScript comes from? As with most web content management systems, Drupal generates HTML dynamically. This is done through interactions between the Drupal core, modules, and the theme system. A single request might involve several different modules. Each module is responsible for providing information for a specific portion of the resulting page. The theme system is used to transform that information from PHP data structures into HTML fragments, and then compose a full HTML document. But this raises some interesting questions: What part of Drupal should be responsible for deciding what JavaScript is needed for a page? And where will this JavaScript come from? In some cases, it makes sense for the Drupal core to handle JavaScript. It could automatically include JavaScript in cases where scripts are clearly needed. JavaScript can also be used to modify the look and feel of a site. In that case, the script is really functioning as a component of a theme. It would be best to include the script as a part of a theme. JavaScript can also provide functional improvements, especially when used with AJAX and related technologies. These features can be used to make more powerful modules. In that case, it makes sense to include the script as a part of a module. So which one is the best: modules, themes, or core? Rather than deciding on your behalf, Drupal developers have made it possible to incorporate JavaScript into all three: The Drupal core handles including the core JavaScript support as needed. The Drupal and jQuery libraries are included automatically when necessary. When theme developers needs to add some JavaScript, they can do so within the theme. There is no need to tamper with the core, or to accompany a theme with a module. Finally, module developers can add JavaScript directly to a module. In this way, modules can provide advanced JavaScript functionality without requiring modification of the theme. In this article we will add scripts to themes and modules. As we get started, we will begin with a theme. Module or theme? How do you decide whether your script ought to go in a theme or in a module? Here's a basic guideline. If the script provides functionality specific to the layout details of a theme, it should be included in a theme. If the script provides general behavior that should work regardless of the theme, then it should be included in a module. Sometimes it is hard to determine when a script belongs to a theme and when it should to be placed in a module. In fact, the script we create here will be one such a case. We are going to create a script that provides a printer-friendly version of a page's main content. Once we have the script, we will attach it to a theme. Of course, if we want to provide this functionality across themes, we might instead create a module to house the script. We will start out simply with a JavaScript-enabled theme. Project overview: printer-friendly page content The JavaScript that we will write creates a pop-up printer-friendly window, and automatically launches the print dialog. This is usually launched from File | Print in your browser's menu. Once we write the script, we will incorporate it into a theme, and add a special printing feature to the page(s) displayed with that theme. As we walk through this process, we will also create our first theme. (Technically, it will be a subtheme derived from the Bluemarine theme.) By the end of this project, you should know how to create Drupal-friendly JavaScript files. You will also know how to create themes and add scripts to them. The first step in the process is to write the JavaScript. The printer script Our script will fetch the main content of a page and then open a new window, populating that window's document with the main content of the page. From there, it will open the browser's print dialog, prompting the user to print the document. Since this is our first script, we will keep it simple. The code will be very basic, employing the sort of classical procedural JavaScript that web developers have been using since the mid-1990's. But don't expect this to be the norm. To minimize clutter and maximize the reusability of our code, we will store this new script in its own script file. The file will be named printer_tool.js: // $Id$/*** Add printer-friendly tool to page.*/var PrinterTool = {};PrinterTool.windowSettings = 'toolbar=no,location=no,' +'status=no,menu=no,scrollbars=yes,width=650,height=400';/*** Open a printer-friendly page and prompt for printing.* @param tagID* The ID of the tag that contains the material that should* be printed.*/PrinterTool.print = function (tagID) {var target = document.getElementById(tagID);var title = document.title;if(!target || target.childNodes.length === 0) {alert("Nothing to Print");return;}var content = target.innerHTML;var text = '<html><head><title>' +title +'</title><body>' +content +'</body></html>';printerWindow = window.open('', '', PrinterTool.windowSettings);printerWindow.document.open();printerWindow.document.write(text);printerWindow.document.close();printerWindow.print();}; First, let's talk about some of the structural aspects of the code. Drupal coding standards In general, well-formatted code is considered a mark of professionalism. In an open source project such as Drupal, where many people are likely to view and contribute to the code, enforced coding standards can make reading and understanding what the code does easier. When contributing code to the Drupal project, developers adhere to a Drupal coding standard (http://drupal.org/coding-standards). Add-on modules and themes are expected to abide by these rules. It is advised that you follow the Drupal standards even in code that you do no anticipate submitting to the Drupal project. Along with keeping your code stylistically similar to Drupal's, it will also help you develop good coding habits for those occasions when you do contribute something to the community. For the most part, the official Drupal coding standards are focused on the PHP code. But many of these rules are readily applicable to JavaScript as well. Here are a few important standards: Every file should have a comment near the top that has the contents $Id$. This is a placeholder for the version control system to insert version information. Drupal uses CVS (Concurrent Versioning System) for source code versioning. Each time a file is checked into CVS, it will replace $Id$ with information about the current version of the software. To learn more about CVS, visit http://www.nongnu.org/cvs/. Indenting should be done with two spaces (and no tabs). This keeps the code compact, but still clear. Comments should be used wherever necessary. Doxygen-style documentation blocks (/** ... */) should be used to comment files and functions. Any complex or potentially confusing code should be commented with // or /* ... */. Comments should be written in sentences with punctuation. Control structure keywords (if, else, for, switch, and so on) should appear at the beginning of a line, and be followed by a single space (if (), not if()). Here's an example: if (a) {// Put code here.}else if (b) {// Put code here.}else {// Put code here.} Operators (+, =, *, &&, ||, and so on) should have a single space on each side, for example: 1 + 2. The exception to this rule is the member operator (.), which is used to access a property of an object. There should be no spaces surrounding these. Example: window.document (never window . document). Stylistic differences between PHP and JavaScript Not all PHP coding standards apply to JavaScript. PHP variables and function names are declared in all lower case with underscores (_) to separate words. JavaScript typically follows different conventions. JavaScript variables and functions are named using camel case (sometimes called StudlyCaps). For a variable or function, the first word is all lower case. Any subsequent words in the variable or function name are capitalized. Underscores are not used to separate words. Here are some examples: var myNewVariable = "Hello World";function helloWorld() { alert(myNewVariable);} While this convention is employed throughout the Drupal JavaScript code, there is currently no hard-and-fast set of JavaScript-specific coding conventions. The working draft, which covers most of the important recommendations, can be found at http://drupal.org/node/260140. Here is a summary of the more important (and widely followed) conventions: Variables should always be declared with the var keyword. This can go a long way towards making the scope of variables explicit. JavaScript has a particularly broad notion of scope. Functions inherit the scope of their parent context, which means a parent's variables are available to the children. Using var makes it easier to visually identify the scoping of a variable. It also helps to avoid ambiguous cases which may lead to hard-to-diagnose bugs or issues. Statements should always end with a semicolon (;). This includes statements that assign functions, for example, myFunction = function() {};. Our print function, defined earlier, exhibits this behavior. Why do we require trailing semicolons? In JavaScript, placing semicolons at the end of statements is considered optional. Without semicolons, the script interpreter is responsible for determining where the statement ends. It usually uses line endings to help determine this. However, explicitly using semicolons can be helpful. For example, JavaScript can be compressed by removing whitespace and line endings. For this to work, every line must end with a semicolon. When an anonymous function is declared, there should be a space between  the function and the parentheses, for example, function () {}, not function() {}. This preserves the whitespace that would be there in in a non-anonymous function declaration (function myFunction() {}). There are other conventions, many of which you will see here. But the ones mentioned here cover the most frequently needed. With coding standards behind us, let's take a look at the beginning of the printer_tool.js file.
Read more
  • 0
  • 0
  • 6280
article-image-layout-dojo-part-1
Packt
15 Oct 2009
17 min read
Save for later

Layout in Dojo: Part 1

Packt
15 Oct 2009
17 min read
Basic Dojo layout facts The Layout widgets in Dojo are varied in nature, but their most common use is as 'windows' or areas which organize and present other widgets or information. Several use the same kind of child elements the ContentPane. The ContentPane is a widget which can contain other widgets and plain HTML, reload content using Ajax and so on. The ContentPane can also be used stand-alone in a page, but is more usable inside a layout container of some sort. And what is a layout container? Well, it's a widget which contains ContentPanes, of course. A layout container can often contain other widgets as well, but most containers work very well with a different configuration of ContentPanes, which properly insulates the further contents. Take the TabContainer, for example. It is used to organize two or more ContentPanes, where each gets its own tab. When a user clicks on one of the tabs, the ContentPane inside it is shown and all others are hidden. Using BorderManager can bring the necessary CSS styling down to a minimum, while giving a simple interface for managing dynamic changes of child widgets and elements. ContentPane A ContentPane can look like anything of course, so it doesn't really help putting a screen-dump of one on the page. However, the interface is very good to know. The following arguments are detected by ContentPane and can be used when creating one either programmatically or by markup: // href: String //The href of the content that displays now. //Set this at construction if you want to load data externally //when the pane is shown.(Set preload=true to load it immediately.) //Changing href after creation doesn't have any effect; //see setHref(); href: "", //extractContent: Boolean //Extract visible content from inside of <body> .... </body> extractContent: false, //parseOnLoad: Boolean //parse content and create the widgets, if any parseOnLoad:true, //preventCache: Boolean //Cache content retreived externally preventCache:false, //preload: Boolean //Force load of data even if pane is hidden. preload: false, //refreshOnShow: Boolean //Refresh (re-download) content when pane goes from hidden to shown refreshOnShow: false, //loadingMessage: String //Message that shows while downloading loadingMessage: "<span class='dijitContentPaneLoading'>$ {loadingState}</span>", //errorMessage: String //Message that shows if an error occurs errorMessage: "<span class='dijitContentPaneError'>${errorState}</span>", You don't need any of those, of course. A simple way to create a ContentPane would be: var pane = new dojo.layout.ContentPane({}); And a more common example would be the following: var panediv = dojo.byId('panediv');var pane = new dojo.layout.ContentPane({ href: "/foo/content.html", preload: true}, panediv); where we would have an element already in the page with the id 'panediv'. As you see, there are also a couple of properties that manage caching and parsing of contents. At times, you want your ContentPane to parse and render any content inside it (if it contains other widgets), whereas other times you might not (if it contains a source code listing, for instance). You will see additional properties being passed in the creation of a ContentPane which are not part of the ContentPane itself, but are properties that give information specific to the surrounding Container. For example, the TabContainer wants to know which tab this is, and so on. Container functions All container widgets arrange other widgets, and so have a lot of common functionality defined in the dijit._Container class. The following functions are provided for all Container widgets: addChild: Adds a child widget to the container. removeChild: Removes a child widget from the container. destroyDescendants: Iterates over all children, calling destroy on each. getChildren: Returns an array containing references to all children. hasChildren: Returns a boolean. LayoutContainer The LayoutContainer is a widget which lays out children widgets according to one of five alignments: right, left, top, bottom, or client. Client means "whatever is left", basically. The widgets being organized need not be ContentPanes, but this is normally the case. Each widget then gets to set a layoutAlign property, like this: layoutAlign = "left". The normal way to use LayoutContainer is to define it using markup in the page, and then define the widgets to be laid out inside it. LayoutContainer has been superceeded by BorderContainer, and will be removed in Dojo version 2.0. SplitContainer The SplitContainer creates a horizontal or vertical split bar between two or more child widgets. A markup declaration of a SplitContainer can look like this: <div dojoType="dijit.layout.SplitContainer" orientation="vertical" sizerWidth="7" activeSizing="false" style="border: 1px solid #bfbfbf; float: left; margin-right: 30px; width: 400px; height: 300px;"> The SplitContainer must have a defined height and width. The orientation property is self-explanatory, as is sizerWidth. The property activeSizing means, if set to true, that the child widgets will be continually resized when the user changes the position of the sizer. This can be bad if the child widgets are complex or access remote information to render themselves, in which case the setting can be set to false, as in the above example. Then the resize event will only be sent to the child widgets when the user stops. Each child widget needs to define the sizeMin and sizeShare attributes. The sizeMin attribute defines the minimum size for the widget in pixels, but the sizeShare attribute is a relative value for the share of space this widget takes in relation to the other widget's sizeShare values. If we have three widgets inside the SplitPane with sizeShare values of 10, 40 and 50, they will have the same ratios in size as if the values had been 1:4:5. StackContainer The StackContainer hides all children widgets but only one at any given time, and is one of the base classes for both the Accordion and TabContainers. StackContainer exists as a separate widget to allow you to define how and when the child widgets are shown. Maybe you would like to define a special kind of control for changing between child widget views, or maybe you want other events in your application to make the Container show specific widgets. Either way, the StackContainer is one of the most versatile Containers, along with the BorderContainer. The following functions are provided for interacting with the StackContainer: back - Selects and shows the previous child widget. forward - Selects and shows the next child widget. getNextSibling - Returns a reference to the next child widget. getPreviousSibling - Returns a reference to the previous child widget. selectChild - Takes a reference to the child widget to select and show.   Here is the slightly abbreviated markup for the test shown above (test_StackContainer.html): <div id="myStackContainer" dojoType="dijit.layout.StackContainer" style="width: 90%; border: 1px solid #9b9b9b; height: 20em; margin: 0.5em 0 0.5em 0; padding: 0.5em;"> <p id="page1" dojoType="dijit.layout.ContentPane" title= "page 1">IT WAS the best of times, ....</p> <p id="page2" dojoType="dijit.layout.ContentPane" title= "page 2">There were a king with a large jaw ...</p> <p id="page3" dojoType="dijit.layout.ContentPane" title= "page 3">It was the year of Our Lord one thousand seven hundred and seventy- five. .../p></div> The StackContainer also publishes topics on certain events which can be caught using the messaging system. The topics are: [widgetId]-addChild [widgetId]-removeChild [widgetId]-selectChild [widgetId]-containerKeyPress Where [widgetId] is the id of this widget. So if you had a StackContainer defined in the following manner: <div id="myStackContainer" dojoType="dijit.layout.StackContainer">...</div> You can use the following code to listen to events from your StackContainer: dojo.subscribe("myStackContainer-addChild", this, function(arg){ var child = arg[0]; var index = arg[1];}); Compare with the following code from the StackContainer class itself: addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex) { // summary: Adds a widget to the stack this.inherited(arguments); if(this._started) { // in case the tab titles have overflowed from one line // to two lines this.layout(); dojo.publish(this.id+"-addChild", [child, insertIndex]); // if this is the first child, then select it if(!this.selectedChildWidget) { this.selectChild(child); } } }, Also declared in the class file for the StackContainer is the dijit.layout.StackController. This is a sample implementation of a separate widget which presents user controls for stepping forward, backward, and so on in the widget stack. What differentiates this widget from the Tabs in the TabContainer, for example, is that the widget is completely separate and uses the message bus to listen to events from the StackContainer. You can use it as-is, or subclass it as a base for you own controllers. But naturally, you can build whatever you want and connect the events to the forward() and back() function on the StackContainer. It's interesting to note that at the end of the files that define StackContainer, the _Widget base class for all widgets is extended in the following way: //These arguments can be specified for the children of a//StackContainer.//Since any widget can be specified as a StackContainer child,//mix them into the base widget class. (This is a hack, but it's//effective.)dojo.extend(dijit._Widget, {//title: String//Title of this widget.Used by TabContainer to the name the tab, etc.title: "",//selected: Boolean//Is this child currently selected?selected: false,//closable: Boolean//True if user can close (destroy) this child, such as//(for example) clicking the X on the tab.closable: false, //true if user can close this tab paneonClose: function(){//summary: Callback if someone tries to close the child, child//will be closed if func returns true return true; }}); This means that all child widgets inside a StackContainer (or Tab or AccordionContainer) can define the above properties, which will be respected and used accordingly. However, since the properties are applied to the _Widget superclass they are of course now generic to all widgets, even those not used inside any containers at all. The most commonly used property is the closable property, which adds a close icon to the widget and title, which defines a title for the tab. A lot of Dijits respond to keypress events, according to WAI rules. Let's look at the code that is responsible for managing key events in StackContainer and all its descendants: onkeypress: function(/*Event*/ e){ //summary: //Handle keystrokes on the page list, for advancing to next/previous button //and closing the current page if the page is closable. if(this.disabled || e.altKey ){ return; } var forward = null; if(e.ctrlKey || !e._djpage){ var k = dojo.keys; switch(e.charOrCode){ case k.LEFT_ARROW: case k.UP_ARROW: if(!e._djpage){ forward = false; } break; case k.PAGE_UP: if(e.ctrlKey){ forward = false; } break; case k.RIGHT_ARROW: case k.DOWN_ARROW: if(!e._djpage){ forward = true; } break; case k.PAGE_DOWN: if(e.ctrlKey){ forward = true; } break; case k.DELETE: if(this._currentChild.closable) { this.onCloseButtonClick(this._currentChild); } dojo.stopEvent(e); break; default: if(e.ctrlKey){ if(e.charOrCode == k.TAB) { this.adjacent(!.shiftKey).onClick(); dojo.stopEvent(e); } else if(e.charOrCode == "w") { if(this._currentChild.closable) { this.onCloseButtonClick(this._currentChild); } dojo.stopEvent(e); // avoid browser tab closing. } } } // handle page navigation if(forward !== null) { this.adjacent(forward).onClick(); dojo.stopEvent(e); } }}, The code is a very good example on how to handle key press events in Dojo in its own right, but for our purposes we can summarize in the following way: If UP, LEFT, or SHIFT+TAB is pressed, forward is set to false, and the last block of code will use that as an argument to the adjacent function which returns the prior child widget if false and the next child widget if true. In this case, the former. If DOWN, RIGHT, or TAB is pressed, forward will be set to true, which will declare the next child widget to be activated and shown. If DELETE or w is pressed and the current child widget is closable, it will be destroyed. TabContainer The TabContainer, which derives from StackContainer, organizes all its children into tabs, which are shown one at a time. As you can see in the picture below, the TabContainer can also manage hierarchical versions of itself. The TabContainer takes an argument property called tabPosition, which controls where the tab icons are displayed for each tab. Possible values are "top", "bottom", "left-h", "right-h", with "top" as default. There are no special functions provided for TabContainer, which adds very little logic to that provided from the StackContainer superclass. AccordionContainer The AccorionContainer shows a horizontal bar for each added child widget, which represents its collapsed state. The bar acts as a tab and also holds the title defined for the child widget. When the bar is clicked, an animation hides the current widget, and also animates in the widget whose bar was clicked. The abbreviated code for the test case above (test_accordionContainer.html) is here: <div dojoType="dijit.layout.AccordionContainer" style="width: 400px; height: 300px; overflow: hidden"> <div dojoType="dijit.layout.AccordionPane" title="a"> Hello World </div> <div dojoType="dijit.layout.AccordionPane" title="b"> <p> Nunc consequat nisi ... </p> <p> Sed arcu magna... </p> </div> <div dojoType="dijit.layout.AccordionPane" title="c"> <p>The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.</p> </div></div>  A funny thing about the AccordionContainer is that it requires not any old widget as a child node, but its own AccordionPane, as you see in the code above. However, the AccordionPane has ContentPane as superclass, and defines itself slightly differently due to the special looks of an accordion. Also, the AccordionPane does not currently support nested Layout widgets, even though single-level widgets are supported. BorderContainer The BorderContainer has replaced the functionality of both LayoutContainer and SplitContainer. Note that the outermost BorderContainer widget does not carry any layout information. This is instead delegated to each individual widget. As each child gets added to the BorderContainer, the layout is recalculated. Using the BorderContainer is a very good alternative to using CSS-based "tableless tables". For using the BorderContainer, you don't need any other rules, and the Container recalculates positioning automatically, without the need for additional CSS rules (except for the height/width case below) each time you add an element or widget to the area. Since BorderContainer widget replaces both SplitContainer and LayoutContainer, it both lets its child widgets declare where they are in relation to each other. Optionally, add resizing splitter between children. Also, instead of optionally declaring one child as "client", one child must now always be declared as "center". For some reason, the child widget now use region, instead of layoutAlign, so a child widget which would have been defined like this in LayoutContainer: <div dojoType="dijit.layout.ContentPane" layoutAlign="top">...</div> is now defined like this instead: <div dojoType="dijit.layout.ContentPane" region="top">...</div> All "side" widgets must define a width, in style, by CSS class or otherwise, and the same applies for top/bottom widgets, but with height. Center widgets must not declare either height or width, since they use whatever is left over from the other widgets. You can also use leading and trailing instead of right and left. The only difference is that when you change locale to a region that has text going from right to left (like Arabic and many others), this will arrange the widgets appropriate to the locale. The BorderContainer also takes an optional design property, which defines if the BorderContainer is a headline or sidebar. The headline is the default and looks like the picture below. headline means that the top and bottom widgets extend the full length of the container, whereas sidebar means the the right and left (or leading and trailing) widgets extend top to bottom. The sizeShare attribute for the ContentPanes used in the SplitContainer is deprecated in BorderContainer. All ContentPanes sizes are defined using regular techniques (direct stylin, classes, and so on). From the BorderContainer test located in dijit/tests/layout/test_BorderContainer_nested.html, we find the following layout: The (abbreviated) source code for the example is here: <div dojoType="dijit.layout.BorderContainer" style="border: 2px solid black; width: 90%; height: 500px; padding: 10px;"> <div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; width: 100px;"> left </div> <div dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;"> right </div> <div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;"> top bar </div> <div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;"> bottom bar </div> <div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 0px;"> <div dojoType="dijit.layout.BorderContainer" design="sidebar" style="border: 2px solid black; height: 300px;"> <div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; width: 100px;"> left </div> <div dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;"> right </div> <div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;"> top bar </div> <div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;"> bottom bar </div> <div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;"> main panel with <a href="http://www.dojotoolkit.org/"> a link</a>.<br /> (to check we're copying children around properly). <br /> <select dojoType="dijit.form.FilteringSelect"> <option value="1">foo</option> <option value="2">bar</option> <option value="3">baz</option> </select> Here's some text that comes AFTER the combo box. </div> </div> </div></div> You see here the recurring theme of using ContentPanes inside Containers. Also, the innermost "center" ContentPane wraps a new BorderContainer which has its own internal top/left layout widgets. Depending on what kind of application you are building, the BorderContainer might be a good starting point. Since you already know that you can change and reload the contents of individual ContentPanes, you are left with a layout in which each element can function as a lightweight Iframe with none of the negative side effects. DragPane The DragPane is a very simple idea. You have a very large area of elements to display, and want to let the user 'drag' the underlying pane around using the mouse. The DragPane can be used in instances where you have a lot of pictures to present. It can also be used to present text or other widgets that are too numerous to fit in your current designated area of screen real estate. The only property of DragPane is invert, which if set to true, inverts the axis of the drag of the mouse. Example: <div class="hugetext" id="container" invert="false" dojoType="dojox.layout.DragPane"> <p style="color:#666; padding:8px; margin:0;"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend sagittis turpis. purus purus in nibh. Phasellus in nunc. </p></div>
Read more
  • 0
  • 0
  • 3136

article-image-managing-posts-wordpress-plugin
Packt
14 Oct 2009
8 min read
Save for later

Managing Posts with WordPress Plugin

Packt
14 Oct 2009
8 min read
Programming the Manage panel The Manage Posts screen can be changed to show extra columns, or remove unwanted columns in the listing. Let's say that we want to show the post type—Normal, Photo, or Link. Remember the custom field post-type that we added to our posts? We can use it now to differentiate post types. Time for action – Add post type column in the Manage panel We want to add a new column to the Manage panel, and we will call it Type. The value of the column will represent the post type—Normal, Photo, or Link. Expand the admin_menu() function to load the function to handle Manage Page hooks: add_submenu_page('post-new.php', __('Add URL',$this->plugin_domain) , __('URL', $this->plugin_domain) , 1 ,'add-url', array(&$this, 'display_form') );// handle Manage page hooksadd_action('load-edit.php', array(&$this, 'handle_load_edit') );} Add the hooks to the columns on the Manage screen: // Manage page hooksfunction handle_load_edit(){ // handle Manage screen functions add_filter('manage_posts_columns', array(&$this, 'handle_posts_columns')); add_action('manage_posts_custom_column', array(&$this, 'handle_posts_custom_column'), 10, 2);} Then implement the function to add a new Column, remove the author and replace the date with our date format: // Handle Column headerfunction handle_posts_columns($columns){ // add 'type' column $columns['type'] = __('Type',$this->plugin_domain); return $columns;} For date key replacement, we need an extra function:     function array_change_key_name( $orig, $new, &$array ){ foreach ( $array as $k => $v ) $return[ ( $k === $orig ) ? $new : $k ] = $v; return ( array ) $return;} And finally, insert a function to handle the display of information in that column: // Handle Type column displayfunction handle_posts_custom_column($column_name, $id){ // 'type' column handling based on post type if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); echo $type ? $type : __('Normal',$this->plugin_domain); }} Don't forget to add the Manage page to the list of localized pages: // pages where our plugin needs translation$local_pages=array('plugins.php', 'post-new.php', 'edit.php');if (in_array($pagenow, $local_pages)) As a result, we now have a new column that displays the post type using information from a post custom field. What just happened? We have used the load-edit.php action to specify that we want our hooks to be assigned only on the Manage Posts page (edit.php). This is similar to the optimization we did when we loaded the localization files. The handle_posts_columns is a filter that accepts the columns as a parameter and allows you to insert a new column: function handle_posts_columns($columns){ $columns['type'] = __('Type',$this->plugin_domain); return $columns;} You are also able to remove a column. This example would remove the Author column: unset($columns['author']); To handle information display in that column, we use the handle_posts_custom_column action. The action is called for each entry (post), whenever an unknown column is encountered. WordPress passes the name of the column and current post ID as parameters. That allows us to extract the post type from a custom field: function handle_posts_custom_column($column_name, $id){ if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); It also allows us to print it out: echo $type ? $type : __('Normal',$this->plugin_domain); }} Modifying an existing column We can also modify an existing column. Let's say we want to change the way Date is displayed. Here are the changes we would make to the code: // Handle Column headerfunction handle_posts_columns($columns){ // add 'type' column $columns['type'] = __('Type',$this->plugin_domain); // remove 'author' column //unset($columns['author']); // change 'date' column $columns = $this->array_change_key_name( 'date', 'date_new', $columns ); return $columns;}// Handle Type column displayfunction handle_posts_custom_column($column_name, $id){ // 'type' column handling based on post type if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); echo $type ? $type : __('Normal',$this->plugin_domain); } // new date column handling if( $column_name == 'date_new' ) { the_time('Y-m-d <br > g:i:s a'); } }function array_change_key_name( $orig, $new, &$array ){ foreach ( $array as $k => $v ) $return[ ( $k === $orig ) ? $new : $k ] = $v; return ( array ) $return;} The example replaces the date column with our own date_new column and uses it to display the date with our preferred formatting. Manage screen search filter WordPress allows us to show all the posts by date and category, but what if we want to show all the posts depending on post type? No problem! We can add a new filter select box straight to the Manage panel. Time for action – Add a search filter box Let's start by adding two more hooks to the handle_load_edit() function. The restrict_manage_posts function draws the search box and the posts_where alters the database query to select only the posts of the type we want to show. // Manage page hooksfunction handle_load_edit(){ // handle Manage screen functions add_filter('manage_posts_columns', array(&$this, 'handle_posts_columns')); add_action('manage_posts_custom_column', array(&$this, 'handle_posts_custom_column'), 10, 2); // handle search box filter add_filter('posts_where', array(&$this, 'handle_posts_where')); add_action('restrict_manage_posts', array(&$this, 'handle_restrict_manage_posts'));} Let's write the corresponding function to draw the select box: // Handle select box for Manage pagefunction handle_restrict_manage_posts(){ ?> <select name="post_type" id="post_type" class="postform"> <option value="0">View all types</option> <option value="normal" <?php if( $_GET['post_type']=='normal') echo 'selected="selected"' ?>><?php _e ('Normal',$this->plugin_domain); ?></option> <option value="photo" <?php if( $_GET['post_type']=='photo') echo 'selected="selected"' ?>><?php _e ('Photo',$this->plugin_domain); ?></option> <option value="link" <?php if( $_GET['post_type']=='link') echo 'selected="selected"' ?>><?php _e ('Link',$this->plugin_domain); ?></option> </select> <?php} And finally, we need a function that will change the query to retrieve only the posts of the selected type: // Handle query for Manage pagefunction handle_posts_where($where){ global $wpdb; if( $_GET['post_type'] == 'photo' ) { $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Photo',$this->plugin_domain)."' )"; } else if( $_GET['post_type'] == 'link' ) { $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Link',$this->plugin_domain)."' )"; } else if( $_GET['post_type'] == 'normal' ) { $where .= " AND ID NOT IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' )"; } return $where;} What just happened? We have added a new select box to the header of the Manage panel. It allows us to filter the post types we want to show. We added the box using the restrict_manage_posts action that is triggered at the end of the Manage panel header and allows us to insert HTML code, which we used to draw a select box. To actually perform the filtering, we use the posts_where filter, which is run when a query is made to fetch the posts from the database. if( $_GET['post_type'] == 'photo' ){ $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Photo',$this->plugin_domain)."' )"; If a photo is selected, we inspect the WordPress database postmeta table and select posts that have the post-type key with the value, Photo. At this point, we have a functional plugin. What we can do further to improve it is to add user permissions checks, so that only those users allowed to write posts and upload files are allowed to use it. Quick referencemanage_posts_columns($columns): This acts as a filter for adding/removing columns in the Manage Posts panel. Similarly, we use the function, manage_pages_columns for the Manage Pages panel.manage_posts_custom_column($column, $post_id): This acts as an action to display information for the given column and post. Alternatively, manage_pages_custom_column for Manage Pages panel.posts_where($where): This acts as a filter for the where clause in the query that gets the posts.restrict_manage_posts: This acts as an action that runs at the end of the Manage panel header and allows you to insert HTML.
Read more
  • 0
  • 0
  • 3365

article-image-audio-fields-drupal
Packt
14 Oct 2009
5 min read
Save for later

Audio Fields in Drupal

Packt
14 Oct 2009
5 min read
FileField remixed If you haven't examined FileField, you'll have to do so by downloading the FileField module from http://drupal.org/project/filefield and enable it on the Modules administration page (by browsing to Administer | Site building | Modules, at /admin/build/modules). Now create a new content type named Album by going to Administer | Content management | Content types | Add content type (at /admin/content/types/add). We'll next add a FileField to this by editing the new Album type and selecting the Add field tab (at /admin/content/types/album/add_field). Call it Song, select the File for the Field type, press Continue, and press Continue again (leaving the Widget type as File Upload). In the Permitted upload file extensions, enter mp3 for now. If you wish, you may enter a new File path as well such as audio. Uploaded files would then be saved to that path. Note that you have access to the Token module's features here. So, for instance you may enter something like audio/[user-raw], which will replace [user-raw] with the username of the node's creator: Finally, select Unlimited for the Number of values, since we'll allow a single album to contain many songs. We'll also check the Required checkbox so that each album will hold at least one song. Finally, we will ensure that the Default listed value is Listed, and that we select the Enforce Default radio button for How should the list value be handled? This will force a node to always list files when displayed. We need to list our files, although we plan ultimately to control display of an album's songs in the player: Now we can add an album node with a few songs by going to Create content | Album (at /node/add/album). Uploading is simple. At this point, we only have a link displayed for our files. Our next task is to create an inline player for the audio. One possibility would be to override the theme function. However, we have other tools available that will make our job easier and even ensure cross-browser compatibility, better accessibility, and valid HTML: jQuery Media to the rescue The jQuery Media plug-in, written by Mike Alsup at http://www.malsup.com/jquery/media/, is a perfect solution. It will convert any link to media into the browser-specific code required for displaying the media. The jQuery Media module is a configurable wrapper for this plug-in. We'll also need a media player. For this exercise, we'll again use the JW FLV Media Player developed by Jeroen Wijering. This excellent player is free for non-commercial use, and has a very inexpensive licensing fee for other uses. First, download that player from http://jeroenwijering.com/ and install the player.swf file somewhere in your site's directory tree. If you install it in the site's www root folder, the module will work with little extra configuration. But you can install it in the files directory, your theme folder, or another convenient place if you need it for your environment. Just remember where you put it for future reference. Next, download and enable the jQuery Media module from http://drupal.org/project/jquery_media. You may wish to also install the jQ module from http://drupal.org/project/jq, which consolidates jQuery plug-ins installed on your site. The configuration is simple. You'll just need to enter the filepath of your media player, which can be different than the Flash Video player entered earlier, if desired. Go to the jQuery Media Administration page by browsing to Administer | Site configuration | jQuery Media Administration (at /admin/settings/jquery_media). Open the Default players (within Extra settings) and enter the filepath of your media player in the MP3 Player (mp3Player) text field: Now just check the Album box in Node types, and set the width and height within Default settings. In most cases, you would be done and the audio would be displayed automatically with no further configuration. However, we're assuming you plan to use this module in conjunction with videos, which may have already set a width and height. That means we'll need to do some more customization. Note: You do not need to do any of this, unless you have video and audio files on the site both using jQuery Media. We need to change the class of our field and add a new invocation script. However, we don't want to affect the class of our existing video files. So add the following somewhere in the phptemplate_preprocess_filefield_file function, creating that function if necessary. (If you haven't already done that, then create function phptemplate_preprocess_filefield_file(&$variables) in template.php. $node = node_load($file['nid']); if ($node->type == 'album') { $variables['classes'] = 'filefield-file-song'; if (module_exists('jquery_media')) { jquery_media_add(array('media class' => '.filefield-file-song a', 'media height' => 20, 'media width' => 200)); } } else { $variables['classes'] = 'filefield-file'; } Then you'll need to change a line in filefield_file.tpl.php. (If you haven't already created that file, create it in your theme directory, and copy the code from the theme_filefield_file function that is found in /sites/all/modules/filefield/filefield_formater.inc.) The original line in question reads as follows: return '<div class="filefield-file clear-block">'. $icon . l($file['filename'], $url) .'</div>'; However, we can rewrite that line to read: <div id="filefield-file-file-<?php print $id; ?>" class="filefield-file clear-block" <?php print $style; ?> > In either case, simply replace class="filefield-file clear-block" with class=" clear-block".
Read more
  • 0
  • 0
  • 1863
article-image-implementing-document-management-alfresco-3-part2
Packt
14 Oct 2009
4 min read
Save for later

Implementing Document Management in Alfresco 3- part2

Packt
14 Oct 2009
4 min read
Library services Library services are common document management functions for controlling the users through permissions, for creating multiple instances of a document(versioning), and for providing users with access into a document to make the changes (checking-in or checking-out). Versioning You might have more than one person who can edit a document. What if somebody edits a document and removes a useful piece of information? Well, you can make use of the versioning features of Alfresco to resolve such issues. Versioning allows the history of previous versions of a content to be kept. The content needs to be Versionable, in order for versions to be kept. You can enable versioning in four different ways: Individually: To enable versioning for an individual content object item, go to the View Details page and click on the Allow Versioning link. The next screenshot illustrates how to enable versioning on an individual content item. Using Smart Spaces: A business rule can be set for a space to allow versioning of all of the content or selected content within that space. By Type: By default, versioning is disabled for all of the content types in the Alfresco content model. Versioning can be enabled for a specific content type, irrespective of the location of the content. Globally: Alfresco can be configured globally to enable versioning for all content throughout the site. Enable versioning for sample file that you have already uploaded to the system. Go to the Intranet > Marketing Communications > Switch to open source ECM > 02_Drafts space and view the details of Alfresco_CIGNEX.doc file. Click on the Allow Versioning link to enable versioning, as shown in the following screenshot. You will immediately notice that a version with a version number of 1.0 is created. At the time of writing this article (Alfresco version 3.1), reverting back to an older version of the content is not supported. There is a plan to support this feature in future releases of Alfresco. The workaround is to download the older version and upload it again as the current version. For a checked out content, the version is updated when the content is checked in. The version number is incremented from the version number of the content object that was checked out. Auto Versioning Auto versioning can be enabled by editing the content properties and selecting the Auto Version checkbox. If auto versioning is enabled, then each Save of the content results in an incremented version number, when the content is edited directly from the repository. Each Update (upload) of the content also results in a new version (with an incremented version number) being created. If auto versioning is not enabled, then the version number is incremented only when the content is checked in. Check In and Check Out By using the versioning feature, you can ensure that all of the changes made to a document are saved. You might have more than one person who can edit a document. What if two people edit a document at once, and you get into a mess with two new versions? To resolve this issue, you'll need to use the library services. Library services provide the ability to check out a document, reserving it for one user to edit, while others can only access the document in read-only mode. Once the necessary changes have been made to the document, the user checks in the document, and can either replace the original, or create a new version of the original. Check Out locks the item and creates a working copy that can be edited (both the content and the details). Check In replaces the original item with the working copy, and releases the lock.
Read more
  • 0
  • 0
  • 1993

article-image-content-editing-and-management-open-souce-cms
Packt
14 Oct 2009
11 min read
Save for later

Content Editing and Management in an Open Souce CMS

Packt
14 Oct 2009
11 min read
There are exciting things ahead in this article, so let's get started. Adding content to our site Adding, updating, and deleting page content is at the heart of a CMS. We will use the Joomla! content management system for our examples in this article. Joomla! is a very popular and powerful CMS. Let's see how we can manage content with Joomla!. Time for action-adding a page Log in to the administration section of Joomla!. It is generally athttp://yoursite.com/joomla/administrator/. Click on the large icon that says Add New Article. We want to create a page about Surya Namaskara, or Sun Salutation, one of the most popular yoga postures. Enter Surya Namaskara in the Title field, and Sun Salutation in the Alias field. We have already created a few sections and categories in Joomla!. Select Posturesas Section, and Featured as Category from the drop downs. The Word-like area below is a content editor. It is also known as the WYSIWYG (What You See Is What You Get) editor. Type in the following text in the area that looks like a white page. We took this text from Wikipedia, but you can type a statement of your choice. Surya Namaskara or Sun Salutation (lit. "salute to the sun"), is a common sequence of Hatha yoga asanas. Its origins lie in a worship of Surya, the Hindu solar deity. Don't see a Word-like editor? If you don't see a Word-like text editor, you may be missing some browser plug-ins. Your browser may warn you of missing plug-ins. In such a case, go ahead and install the missing plug-ins. If it still does not work, go toSite | Global Configuration | Site | Site Settings | Default WYSIWYG Editor and select TinyMCE or XStandard. You can also configure the editor per user from User Manager. Press Enter after the first paragraph. Add two more sentences like this: Surya Namaskara is an excellent exercise for the whole body. Mastering this asana will help you stay fit forever. "Asana" is the Sanskrit word for posture. Yoga postures are called Asanas. We want to highlight that Surya Namaskara is an excellent exercise for the whole body. Select that portion of text and click on the B icon to make it bold. You will immediately see the result in the editing window. At this stage, your editing window will look like this. If you want to write additional text, go ahead and add it. Click on the large Save icon at the top right of the page when you are done. Now our content is saved. Click on the Preview link in the Joomla! menu bar and you will see the content on the site's home page. Here's how it will look: What just happened? We used Joomla! to create our first content page. We added a page title, an alias, and the section and category this page belongs to. We then used a Word-like editor to enter text for our page. We emphasized keywords by making them bold. This was done by selecting the keywords, and clicking on the B icon button in the toolbar. Notice that we can use this editor to apply a variety of other formatting to selected text. This kind of text editor is called aWYSIWYG editor. What is WYSIWYG? Why is it important?  WYSIWYG (pronounced 'wize,wig) is an acronym for What You See Is What You Get.The Word-like content editor we saw is WYSIWYG because our page looks the same in the editor as it does on the site. The fonts, formatting, colors, and alignments—all work consistently between the editing interface and the actual site.  Most CMSs come with a WYSIWYG editor. Such editors make it very easy for authors to add content and the formatting style that they like. These formatting options look and behave in a way similar to Microsoft Word or OpenOffice Writer. But the complexity of options provided may vary between CMSs. The following image shows the WYSIWYG editor toolbars of Joomla! (top) and WordPress (bottom). As you see, WordPress offers a simpler editor, but with lesser options. An amateur user will find it easier to work with an editor with fewer choices. As a matter of fact, WordPress's editor toolbar shows only the first row of options by default. You can enable a second row by clicking on the last button in first row: Show / Hide Kitchen Sink. On the other hand, Joomla! comes ready with all options visible. This is useful for a professional who wants better control over content formatting. Evaluate how important is it for you to have a WYSIWYG editor. Also, see if the CMS comes with it by default, or you have to add it via a plug-in or extension. For example, Drupal does not have a WYSIWYG editor module by default; but you can easily add it via a module. This also means some CMSs may not have a WYSIWYG editor. So, if there is no WYSIWYG editor, how do you add content? Well, if your content does not require a fancy format, you can live with simple textual content. Else, you can always use HTML. Surya Namaskara or Sun Salutation (lit. "salute to the sun"), is a common sequence of Hatha yoga asanas. Its origins lie in a worship of Surya, the Hindu solar deity. Do I need to learn HTML?  HTML is the language to layout and format web site pages. If you know HTML, it will be easier to manage your CMS. If HTML is not an option, a WYSIWYG editor can be really helpful. Here are some links for learning the basics of HTML:http://www.html.net/tutorials/html/http://www.w3schools.com/html/DEFAULT.asp Adding images We have added the basic content to our page. Now, we will try to include some pictures in our page. Images add a lot of meaning to the content, apart from adding a decorative value. Let's add an image to our page now. Time for action-adding images If you are not already logged in to the Joomla! administration, log in now. Click on Site in the main menu. That should open a submenu of site management options. Click on Media Manager. You will see previews of current images in Joomla!. Click on the stories folder to go into it. You will now see images within this folder. Let's create a new folder here to store images of different asanas/postures. In the Create Folder text box near the top right side, type in asanas and click on the button. This should create a new folder within stories. Click on it to move inside. We can now upload an image here. Click within the text box of the Upload File section at the page end. This will bring up a dialog window to select a file you want to upload. We want to upload an image for Surya Namaskara. Select an image of your choice. Now click on the Start Upload button.                                               File uploading requires correct permissions on the server To upload files to your site, you require correct permissions on yourserver. In technical terms, this is called making a folder world-writable or changing mode to 777. You can change folder permissions using an FTPapplication, or your site's control panel. Technically, it's sufficient to give a 666permission—read-and-write permission to the owner, group, and others—butnormally everyone gives a 777 permission, including execute permission for allthree. Here's a screenshot of setting these permissions using FireFTP, an FTPextension for the Firefox browser. The file upload operation may take a few seconds to complete, depending on image size. Once the image is uploaded, you will see its thumbnail in the list. Upload more images if you want to. Finally, your folder may look like this. We are now ready to insert an image in our page. Select Content  Article Manager  from the main menu. Click on the Surya Namaskara page to edit it. Inside our WYSIWYG editor, keep your cursor where you want to insert the image. Click on the Image button below the WYSIWYG editor. A window will open up with a thumbnail list of images available. Click on the b we created earlier. Click and select an image you want to insert. Add a description and title. Click on the Insert button at the top right. That will insert our image into the content area. Re-size it using the handles on the corners if you wish. Here's how it will look: Congratulations! You have successfully added an image to our page. What just happened?  We uploaded an image from our computer and added it to a page. In the process, we learned about the Media Manager, creating folders, and uploading files to Joomla!. We also learned how to select images to use on a page and even saw image insertion options.  Adding an image involved multiple activities. We had to first add it to the Media Manager.Because this was the first time we were adding an image, we also created a new folder. It was as simple as typing in a name and clicking a button.  We added images within folders since it will help us manage the images better. Once we add an image to the Media Manager, we can use that image on as many pages as we want. The Image button on the content editing screen allows us to select images to use on that page. It also helps us to add captions and correctly align inserted images with the text. You can also upload images using that image selection window itself.We took the Media Manager route to learn more. You can also upload images using that image selection window itself.We took the Media Manager route to learn more. Have a go hero-image formatting options  We have learned enough about inserting images to content now. It is time we try out something else. Once you insert an image, click on it, and then click on the small photo icon in the WYSIWYG editor's toolbar. Go ahead and try out different image properties, different alignment options, spacing, caption, and alternative text. See how the result changes in the preview.                                                       Don't let your images sink your site!                                                     Make sure your images are optimized and sized for web usage. Avoid changing the width and height via image properties. If you want to show a smaller image than the one you uploaded, resize it using photo editing software and use that new version. Large images take longer to load and can make your site slow.                                                      Have a go hero-adding a video  Our Yoga site may also require videos. Look around and find how a video can be added to the page.  Completed? Alright! We have now looked at how to edit a page and insert images/videos into it. Let's see the other options we have in editing and maintaining site content.
Read more
  • 0
  • 0
  • 1619
Modal Close icon
Modal Close icon