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
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - CMS and E-Commerce

830 Articles
article-image-anatomy-typo3-extension
Packt
14 Oct 2009
8 min read
Save for later

Anatomy of TYPO3 Extension

Packt
14 Oct 2009
8 min read
TYPO3 Extension Categories All TYPO3 extensions are classified into several predefined categories. These categories do not actually differentiate the extensions. They are more like hints for users about extension functionality. Often, it is difficult for the developer to decide which category an extension should belong to. The same extension can provide PHP code that fits into many categories. An extension can contain Frontend (FE) plugins, Backend (BE) modules, static data, and services, all at once. While it is not always the best solution to make such a monster extension, sometimes it is necessary. In this case, the extension author should choose the category that best fits the extension's purpose. For example, if an extension provides a reservation system for website visitors, it is probably FE related, even if it includes a BE module for viewing registrations. If an extension provides a service to log in users, it is most likely a service extension, even if it logs in FE users. It will be easier to decide where the extension fits after we review all the extension categories in this article. Choosing a category for an extension is mandatory. While the TYPO3 Extension Manager can still display extensions without a proper category, this may change and such extensions may be removed from TER (TYPO3 Extension Repository) in the future. The extension category is visible in several places. Firstly, extensions are sorted and grouped by category in the Extension Manager. Secondly, when an extension is clicked in the Extension Manager, its category is displayed in the extension details. If an extension's category is changed from one to another, it does not affect extension functionality. The Extension Manager will show the extension in a different category. So, categories are truly just hints for the user. They do not have any significant meaning in TYPO3. So, why do we care and talk about them? We do so because it is one of those things that make a good extension. If an extension developer starts making a new extension, they should do it properly from the very beginning. And one of the first things to do properly is to decide where an extension belongs. So, let's look into the various extension categories in more detail. Category: Frontend Extensions that belong to the Frontend category provide functionality related to the FE. It does not mean that they generate website output. Typically, extensions from the FE category extend FE functionality in other ways. For example, they can transform links from standard /index.php?id=12345 to /news/new-typo3-bookis-out.htm. Or, they can filter output and clean it up, compress, add or remove HTML comments, and so on. Often, these extensions use one or more hooks in the FE classes. For example, TSFE has hooks to process submitted data, or to post‑filter content (and many others). Examples of FE extensions are source_optimization and realurl. Category: Frontend plugins Frontend plugins is possibly the most popular extension category. Extensions from this category typically generate content for the website. They provide new content objects, or extend existing types of content objects. Typical examples of extensions from the Frontend plugins category are tt_news, comments, ratings, etc. Category: Backend Extensions from the Backend category provide additional functionality for TYPO3 Backend. Often, they are not seen inside TYPO3 BE, but they still do some work. Examples of such extensions are various debugging extensions (such as rlmp_ filedevlog) and extensions that add or change the pop-up menu in the BE (such as extra_page_cm_options system extension). This category is rarely used because extensions belonging to it are very special. Category: Backend module Extensions from this category provide additional modules for TYPO3 BE. Typical examples are system extensions such as beuser (provides Tools | Users module) or tstemplate (provides Web | Template module). Category: Services Services extend core TYPO3 functionality. Most known and most popular service extensions are authentication services. TYPO3 Extension Repository contains extensions to authenticate TYPO3 users over phpBB, vBulletine, or LDAP user databases. Services are somewhat special and will not be covered in this article. Extension developers who are interested in the development of services should consult appropriate documentation on the typo3.org website. Category: Examples Extensions from this category provide examples. There are not many, and are typically meant for beginners or for those who want to learn a specific feature of TYPO3, or features that another TYPO3 extension provides. Category: Templates Extensions from this category provide templates. Most often, they have preformatted HTML and CSS files in order to use them with the templateautoparser extension or map with TemplaVoila. Sometimes, they also contain TypoScript templates, for example, tmpl_andreas01 and tmpl_andreas09 extensions. Once installed, they provide pre‑mapped TemplaVoila templates for any website, making it easy to have a website up and running within minutes. Category: Documentation Documentation extensions provide TYPO3 documentation. Normally, TYPO3 extensions contain documentation within themselves, though sometimes, a document is too big to be shipped with extensions. In such cases, it is stored separately. There is an unofficial convention to start an extension key for such extensions with the doc_ prefix (that is, doc_indexed_search). Category: Miscellaneous Everything else that does not fit into any other category goes here; typical examples are skins. But do not put your extension here if you just cannot decide where it fits. In all probability, it should go into one of the other categories, not into Miscellaneous. Extension Files TYPO3 extensions consist of several files. Some of these files have predefined names, and serve a predefined purpose. Others provide code or data but also follow certain naming conventions. We will review all the predefined files in this article and see what purpose they serve. We will look into the files according to their logical grouping. While reading this section, you can take any extension from the typo3conf/ext/ directory at your TYPO3 installation and check the contents of each discussed file. Some files may be missing if the extension does not use them. There is only one file which is mandatory for any TYPO3 extension, ext_emconf.php. We will start examining files starting from this one. Common Files All files from this group have predefined names, and TYPO3 expects to find certain information in them. Hacking these files to serve another purpose or to have a different format usually results in incompatibility with other extensions or TYPO3 itself. While it may work in one installation, it may fail in others. So, avoid doing anything non-standard with these files. ext_emconf.php This is the only required file for any TYPO3 extension. And this is the only file that should be modified with great care. If it is corrupt, TYPO3 will not load any extension. This file contains information on the TYPO3 Extension Manager. This information tells the Extension Manager what the extension does, provides, requires, and conflicts with. It also contains a checksum for each file in the extension. This checksum is updated automatically when the extension is sent to TER (TYPO3 Extension Repository). The server administrator can easily check if anyone has hijacked the extension files by looking into the extension details in the Extension Manager. The modified files are shown in red. Here is a tip. If you (as an extension developer) send your own extension directly to the customer (bypassing TER upload), or plan to use it on your own server, always update the ext_emconf.php file using the Backup/Delete function of the Extension Manager. This will ensure that TYPO3 shows up-to-date data in the Extension Manager. Here is an example of a ext_emconf.php file from the smoothuploader extension: <?php ############################################################# # Extension Manager/Repository config file for ext: ↵ # "smoothuploader" # Auto generated 29-02-2008 12:36 # Manual updates: # Only the data in the array - anything else is removed by ↵ # next write. # "version" and "dependencies" must not be touched! ############################################################# $EM_CONF[$_EXTKEY] = array( 'title' => 'SmoothGallery Uploader', 'description' => 'Uploads images to SmoothGallery', 'category' => 'plugin', 'author' => 'Dmitry Dulepov [Netcreators]', 'author_email' => 'dmitry@typo3.org', 'shy' => '', 'dependencies' => 'rgsmoothgallery', 'conflicts' => '', 'priority' => '', 'module' => '', 'state' => 'beta', 'internal' => '', 'uploadfolder' => 0, 'createDirs' => '', 'modify_tables' => 'tx_rgsmoothgallery_image', 'clearCacheOnLoad' => 0, 'lockType' => '', 'author_company' => 'Netcreators BV', 'version' => '0.3.0', 'constraints' => array( 'depends' => array( 'rgsmoothgallery' => '1.1.1-', ), 'conflicts' => array( ), 'suggests' => array( ), ), '_md5_values_when_last_written' => 'a:12:{s:9:...;}', 'suggests' => array( ), ); ?> The variable _md5_values_when_last_written is shortened in the listing above.
Read more
  • 0
  • 0
  • 3221

article-image-content-rules-syndication-and-advanced-features-plone-3-intranet
Packt
27 Jul 2010
8 min read
Save for later

Content Rules, Syndication, and Advanced Features of Plone 3 Intranet

Packt
27 Jul 2010
8 min read
(For more resources on Plone, see here.) Content rules Plone features a usability layer around Zope's event system, allowing plain users to create rules tied to the most used event handlers. These rules are composed of tasks that get triggered when an event is raised in our site. Content rules are defined site-wide in the Content rules configlet, and they are available for use in any folderish object in our site. Once the rule is created, it can be locally assigned to any folder object in the site. Rules play a very important role in intranets. We can use them as a mechanism for notification, and they also help in adding dynamism to our intranet. One of the most demanded features in an intranet is the ability to be aware when content is added, changed, or even deleted. The notification of this change to the users can be achieved via content rules assigned strategically, or by user demand in any folder or intranet application, such as forums or in a blog. We can use content types to help us model some of our corporate processes or daily tasks. Move or copy objects to other folders (done by users), just in case some of our processes require this kind of an action. We can find other interesting uses of content rules in our intranet, such as executing an action when a state transition is triggered. All these actions can be carried out programmatically, but the power of content rules lie in that they can be executed thorough the Plone UI and by any experienced user. We can access the manage rules form via the Rules tab in any folder. If we don't have any rules created, the form will address us to create them in the content rules configlet. This control panel configlet will aid us to create and manage content rules of our site: The form is divided into two parts. The first is dedicated to global settings applied to all rules. In this version, there is only one setting in this category to enable and disable the rules in the whole site. If deselected, the whole rule system is disabled and no rules will be executed in the site. The other part of the form is reserved for the rule management interface. Here we can find the already created rules, manage them, and create new ones. We can display them by type using the selector on the right. Adding a new rule Click on the Add content rule button. It will open a new form with the following fields: Title: Title of the rule. Description: Summary of the rule. Triggering event: Starts the execution of the rule. Enabled: Whether or not this rule is enabled. Stop executing rules: Defines if the engine should continue the execution of other rules. It is useful if we assign several rules to a container and the execution of a particular rule excludes any other rule execution. By default, these are the available events: Object added to this container Object modified Object removed from this container Workflow state changed After creating one rule at least, the configlet will let us manage the existing rules, allowing us to perform the standard edit, delete, enable, and disable actions. But this is only the first step. We've created the rule and assigned an event to it. Now it's time to configure the task, which the rule will perform. There are two items to configure—conditions and actions. We can add as many conditions as we want to, and modify the order in which they can be applied. We can add the following types of conditions: Content type: Apply the rule only if an object of this type has triggered the event File extension: Execute the action only if a file content type that has this extension has triggered the event Workflow state: Apply only if a content type in the workflow state specified has triggered the event User's group: Execute only if a user member of a specific group triggers the event User's role: Same as User's group, but by a user having a specific role in that context The actions that a rule can execute are limited but they cover the most useful use cases: Logger: Output a message to the message system log Notify user: Notify the user via a status message Copy to folder: The object that triggers the event is copied to the specified folder Move to folder: The object that triggers the event is moved to the specified folder Delete object: The object that triggers the event is deleted Transition workflow state: An attempt to change workflow of the object that triggers the event via the specified transition Send e-mail: Send e-mail to a specific user By default, only managers can define and apply new content rules, but we can allow more user roles to access their creation. Assigning rules to folderish objects Once the rule is created, we can assign them to any of Plone's folderish content types. Just go to any folderish object and click on the Rules tab. Just use the drop-down box Assign rule here to choose from the available rules and click on Add. We can review what rules are assigned in this container and manage them as well. We can enable, disable, and choose whether to apply them to subfolders or only to current folders, and of course, unassign them. Making any content type rule aware All folderish default content types of Plone are content rule aware. However, not all third-party content types are content rule aware. This is because either they are old or simply do not enable this feature in the content type declaration. In the case of third-party content types, which are not content rule aware, we can enable their awareness by following these instructions: Add an object of the desired content type anywhere in our site, if we haven't created it yet. Find it in the ZMI and access the Interfaces tab. Once there, find the interface plone.contentrules. engine.interfaces.IRuleAssignable in the Available marker interfaces fieldset. Select it and click on the Add button. By doing so, we are assigning an additional marker interface to that content type, which will enable (mark) this instance of the content type (that is, make it aware of the content rule). From this moment onwards, the selected object will have available the Rules tab, and in consequence, we can assign rules to it. Syndication Plone has always paid special attention to syndication, making its folderish content types syndicable. Collections export their contents automatically in a view that all collections have—RSS view. But we can also enable syndication for single folders on our site. Using RSS feeds in our intranet is the recommended approach for keeping our users posted about the changes in syndicated folders, if they are collections or plain folders. Enabling folder syndication For enabling syndication for a particular folder, we need to access the view, synPropertiesForm, from the folder we want to be syndicable. For example, if we want to access this view in the ITStaff folder, we should browse the URL: http://localhost:8080/intranet/ITStaff/synPropertiesForm This view is hidden by default, although we can make it visible in order to allow users to enable folder syndication by themselves. We can make it visible by accessing the portal_actions tool in the ZMI. Go to the object action category and choose syndication. Then just make this action visible by enabling the Visible attribute and choose who will be able to access this view by selecting the item permissions in the Permissions selection box. Once in the synPropertiesForm form, we should click on the Enable syndication button. Then another form is shown to allow us to configure how the publication of the feed will be performed. Following are the syndication details available: Update period: How often the feed will be updated Update frequency: How many times the update will occur inside the period specified in the previous field Update base: When the update will take place Maximum items: How many items the feed will show Accessing a secure RSS feed Syndication was conceived to access information from public resources. Inside an intranet, it will be very common that the folder we want to enable for syndication will be not published, and in consequence, the feed associated will be private. The problem is that there are few feed readers that support feed authentication and even using them. We will have to enable HTTP authentication in our site's PAS configuration, which is not recommended. So we propose two workarounds. We can use a feed enabled browser to browse our intranet and our feeds as well. With this approach, if we are logged in, then we will have access to authenticated feeds. Firefox and Internet Explorer already have this feature. The second approach is to have a special workflow state for the syndicated folders inside our site for being accessible without authentication as anonymous users. Obviously this workaround will make the folder content visible to anonymous users, and it's not an option when privacy of the contained information is a must.
Read more
  • 0
  • 0
  • 3211

article-image-categories-and-attributes-magento-part-2
Packt
22 Oct 2009
7 min read
Save for later

Categories and Attributes in Magento: Part 2

Packt
22 Oct 2009
7 min read
Time for action: Creating Attributes In this section we will create an Attribute set for our store. First, we will create Attributes. Then, we will create the set. Before you begin Because Attributes are the main tool for describing your Products, it is important to make the best use of them. Plan which Attributes you want to use. What aspects or characteristics of your Products will a customer want to search for? Make those Attributes. What aspects of your Products will a customer want to choose? Make these Attributes, too. Attributes are organized into Attribute Sets. Each set is a collection of Attributes. You should create different sets to describe the different types of Products that you want to sell. In our coffee store, we will create two Attribute Sets: one for Single Origin coffees and one for Blends. They will differ in only one way. For Single Origin coffees, we will have an Attribute showing the country or region where the coffee is grown. We will not have this Attribute for blends because the coffees used in a blend can come from all over the world. Our sets will look like the following: Single Origin Attribute set Blended Attribute set Name Name Description Description Image Image Grind Grind Roast Roast Origin SKU SKU Price Price Size Size   Now, let's create the Attributes and put them into sets. The result of the following directions will be several new Attributes and two new Attribute Sets: If you haven't already, log in to your site's backend, which we call the Administrative Panel: Select Catalog | Attributes | Manage Attributes. list of all the Attributes is displayed. These attributes have been created for you. Some of these Attributes (such as color, cost, and description) are visible to your customers. Other Attributes affect the display of a Product, but your customers will never see them. For example, custom_design can be used to specify the name of a custom layout, which will be applied to a Product's page. Your customers will never see the name of the custom layout. We will add our own attributes to this list. Click the Add New Attribute button. The New Product Attribute page displays: There are two tabs on this page: Properties and Manage Label / Options. You are in the Properties tab. The Attribute Properties section contains settings that only the Magento administrator (you) will see. These settings are values that you will use when working with the Attribute. The Frontend Properties section contains settings that affect how this Attribute will be presented to your shoppers. We will cover each setting on this page. Attribute Code is the name of the Attribute. Your customers will never see this value. You will use it when managing the Attribute. Refer back to the list of Attributes that appeared in Step 2. The Attribute identifier appears in the first column, labelled Attribute Code. The Attribute Code must contain only lowercase letters, numbers, and the underscore character. And, it must begin with a letter. The Scope of this Attribute can be set as Store View, Website, or Global. For now, you can leave it set to the default—Store View. The other values become useful when you use one Magento installation to create multiple stores or multiple web sites. That is beyond the scope of this quick-start guide. After you assign an Attribute set to a Product, you will fill in values for the Attributes. For example, suppose you assign a set that contains the attributes color, description, price, and image. You will then need to enter the color, description, price, and image for that Product. Notice that each of the Attributes in that set is a different kind of data. For color, you would probably want to use a drop-down list to make selecting the right color quick and easy. This would also avoid using different terms for the same color such as "Red" and "Magenta". For description, you would probably want to use a freeform text field. For price, you would probably want to use a field that accepts only numbers, and that requires you to use two decimal places. And for image, you would want a field that enables you to upload a picture. The field Catalog Input Type for Store Owner enables you to select the kind of data that this Attribute will hold: In our example we are creating an Attribute called roast. When we assign this value to a Product, we want to select a single value for this field from a list of choices. So, we will select Dropdown. If you select Dropdown or Multiple Select for this field, then under the Manage Label/Options tab, you will need to enter the list of choices (the list of values) for this field. If you select Yes for Unique Value, then no two products can have the same value for this Attribute. For example, if I made roast a unique Attribute, that means only one kind of coffee in my store could be a Light roast, only one kind of coffee could be a French roast, only one could be Espresso, and so on. For an Attribute such as roast, this wouldn't make much sense. However, if this Attribute was the SKU of the Product, then I might want to make it unique. That would prevent me from entering the same SKU number for two different Products. If you select Yes for Values Required, then you must select or enter a value for this Attribute. You will not be able to save a Product with this Attribute if you leave it blank. In the case of roast, it makes sense to require a value. Our customers would not buy a coffee without knowing what kind of roast the coffee has. Input Validation for Store Owner causes Magento to check the value entered for an Attribute, and confirm that it is the right kind of data. When entering a value for this Attribute, if you do not enter the kind of data selected, then Magento gives you a warning message. The Apply To field determines which Product Types can have this Attribute applied to them. Remember that the three Product Types in Magento are Simple, Grouped, and Configurable. Recall that in our coffee store, if a type of coffee comes in only one roast, then it would be a Simple Product. And, if the customer gets to choose the roast, it would be a Configurable Product. So we want to select at least Simple Product and Configurable Product for the Apply To field: But what about Grouped Product? We might sell several different types of coffee in one package, which would make it a Grouped Product. For example, we might sell a Grouped Product that consists of a pound of Hawaiian Kona and a pound of Jamaican Blue Mountain. We could call this group something like "Island Coffees". If we applied the Attribute roast to this Grouped Product, then both types of coffee would be required to have the same roast. However, if Kona is better with a lighter roast and Blue Mountain is better with a darker roast, then we don't want them to have the same roast. So in our coffee store, we will not apply the Attribute roast to Grouped Products. When we sell coffees in special groupings, we will select the roast for each coffee. You will need to decide which Product Types each Attribute can be applied to. If you are the store owner and the only one using your site, you will know which Attributes should be applied to which Products. So, you can safely choose All Product Types for this setting.
Read more
  • 0
  • 0
  • 3197

article-image-jasperreports-36-creating-report-model-beans-java-applications
Packt
26 Jun 2010
3 min read
Save for later

JasperReports 3.6: Creating a Report from Model Beans of Java Applications

Packt
26 Jun 2010
3 min read
(For more resources on JasperReports, see here.) Getting ready You need a Java JAR file that contains class files for the JavaBeans required for this recipe. A custInvoices.jar file is contained in the source code (chap4). Unzip the source code file for this article and copy the Task5 folder from the unzipped source code to a location of your choice. How to do it... Let's start using Java objects as data storage units. Open the ModelBeansReport.jrxml file from the Task5 folder of the source code for this article (chapt 4). The Designer tab of iReport shows a report containing data in the Title, Column Header, Customer Group Header1 and Detail 1 sections, as shown in the following screenshot: If you have not made any database connection so far in your iReport installation, you will see an Empty datasource shown selected in a drop-down list just below the main menu. Click on the Report Datasources icon, shown encircled to the right of the drop-down list in the following screenshot: A new window named Connections / Datasources will open, as shown next. This window lists an Empty data source as well as the datasources you have made so far. Click the New button at the top-right of the Connections / Datasources window. This will open a new Datasource selection window, as shown in the following screenshot: Select JavaBeans set datasource from the datasource types, as shown next. Click the Next button. A new window named JavaBeans set datasource will open, as shown in the following screenshot: Enter CustomerInvoicesJavaBeans as the name of your new connection in the text box beside the Name field, as shown in the following screenshot: Enter com.CustomerInvoicesFactory as the name of the factory class in the text box beside the Factory class field, as shown in the following screenshot: This com.CustomerInvoicesFactory class provides iReport with access to JavaBeans that contain your data. Enter getBeanCollection as the name of the static method in the text box beside The static method... field, as shown in the following screenshot: Leave the rest of the fields at their default values. Click the Test button to test your new connection to the JavaBeans datasource. You will see an Exception message dialog. This exception message occurs because iReport can't find your factory class. Dismiss the message box by clicking OK. Click the Save button at the bottom of the JavaBeans set datasource window and close the Connections / Datasources window as well.
Read more
  • 0
  • 0
  • 3196

article-image-logos-inkscape
Packt
03 Nov 2010
6 min read
Save for later

Logos in Inkscape

Packt
03 Nov 2010
6 min read
  Inkscape 0.48 Essentials for Web Designers Use the fascinating Inkscape graphics editor to create attractive layout designs, images, and icons for your website The first book on the newly released Inkscape version 0.48, with an exclusive focus on web design Comprehensive coverage of all aspects of Inkscape required for web design Incorporate eye-catching designs, patterns, and other visual elements to spice up your web pages Learn how to create your own Inkscape templates in addition to using the built-in ones Written in a simple illustrative manner, which will appeal to web designers and experienced Inkscape users alike        Here's an example of a web page with a logo as a major design element: Logos as the cornerstone of the design Logos are the graphical representation or emblem for a company or organization—sometimes even individuals use them to promote instant recognition. They can be a graphic (a combination of symbols or icons), a combination of graphics and text, or graphical forms of text. Why are they important in web design? Since most companies want to be recognized by their logo alone—the logo is the critical piece of the design. It needs prominent placement to work flawlessly with the design. Best practices for creating logos There are a lot of guidelines and principles to the best logo designs. And they start with some simple ideas that have been reworked and discussed intensely since the start of the Internet. But it never hurts to review the best practices. You want your company logos to be: Simple: That's right, you want to keep them clean, simple, neat, and intensely easy to recreate. If you nail this attribute, the others listed below will be easy to achieve. Memorable: Think of all the great company logos. You remember them in your mind's eye very easily right? That's because they are unique and in essence simple. These two attributes together make some of the best company logos today. Timeless: These logos will last many years. This not only saves the company or individual money, but it also increases the memorability of the logo and brand of the company. Versatile: Any logo that can be used in print (color and black and white), digital media, television, any size, letterhead, billboards, and small iconic statements along the bottom of web pages or promotional materials—is a successful logo. You never know where a logo might be placed, especially on the web. You want something that can be used in a prominent location on the company web site itself, but also something that works in a small thumbnail space for social media or cell phone applications. Appropriate: We want the logo to be appropriate for the company it is representing. The right colors, images, and more will go along way in giving the company credibility immediately upon first glance by any consumer or potential client. It can also prove to be a great indication of the services one can expect from the company itself. Seems easy enough right? It is, after some practice and some processes are in place. It never hurts to have a loose process to work with clients to determine their needs and wants in a logo. Some may already have a logo and want to keep parts of the design and revamp others while other clients might be so new they haven't ever had a logo before. As a start, here's a brief process for working with clients and discussing logos. Information gathering There's no better place to start than to open the floor for discussion. Here's just the start of what you can ask or gather from your client in an initial information gathering meeting: Does the client already have a logo? If yes, do they intend to keep that logo to use in the web design? Again if yes, get the source files. Hopefully they are in vector graphic format so they are scalable and usable right away in the web design. Are they interested in a logo redesign? This can be beneficial if they are rebranding themselves as a business or having a 'grand re-opening' of some sort. It can breathe life into a stale business and sometimes garner some new interest. If yes, is it a complete (open to anything) redesign? Or are there certain elements that need to stay? Sometimes color is important, or a certain font or even a certain graphical element needs to stay within the logo. Listen and take notes; it is important to work with the client to try to fulfill their needs as much as possible. If the client is open to a complete redesign, brainstorm a bit with them about their needs and wants. Colors, fonts, graphical ideas. Don't be afraid to bring out some paper and pencils and start sketching some ideas. Sometimes it can be most productive to work through some rough ideas this way to get a feel for what the client likes most and not. Consider it a working session. Try to understand where the client wants to use this logo most prominently. Keeping that in mind you will design something that is versatile and could be used in most mediums; you still want to know where they plan to use it the most. That way, you can tailor the logo as much as possible for that space—especially if you can use more color. What are the primary goals of the company? What is their mission statement? Does the client already have brand guidelines to consider? Creating initial designs After the initial informational session it is your turn to start designing. Take the paper and pencil sketches (if you had any) from the initial meeting and expand on them. In fact, spend a bit more time with your team and flesh out a few more of those ideas in a true brainstorming session. It can be beneficial to start this way first before jumping on to the computer and getting caught in details like typeface and effects. Once you have some solid ideas, bring it over to the computer and start designing. Focus on only three of your best ideas. That way you bring only your best to the client to review and discuss. Much like with the web design process, the logo design process takes a very similar route. You bring design mock ups to your client to review, give feedback, redesign, and then you go back and design some more—all until you get approvals. And then you—being an Inkscape expert—can build and then export the logo in any number of vector formats for use in almost any medium.
Read more
  • 0
  • 0
  • 3193

article-image-drupal-6-performance-optimization-using-views-and-panels-caching
Packt
19 Feb 2010
5 min read
Save for later

Drupal 6 Performance Optimization Using Views and Panels Caching

Packt
19 Feb 2010
5 min read
Views caching The Views 2 module allows you to cache your Views data and content. You can cache Views data per View. We're going to enable caching on one of our existing Views, and also create a brand new View and set caching for that as well using the test content we just generated. This will show you a nice integration of the Devel functionality with the Views module and then how caching works with Views. Go to your Site building | Views configuration page and you'll see many of your default and custom views listed. We have a view on this site for our main photo gallery. The view is named photo_gallery in our View listing. Go ahead and click on one of your Views edit links to get into edit mode for a View. In our Views 2 interface mode, we'll see our tabs for default, Page, and/or Block View display. I'm going to click on my Page tab to see my View's page settings. Under my Basic settings configuration, I'll see a link for Caching. Currently, our Caching link states None, meaning that no caching has been configured for this view. Click on the None link. Select the Time-based radio button. This will enable Time-based caching for our View page. Click the Update default display button. The next caching options configuration screen will ask you to set the amount of time for both, your View Query results and for your View Rendered output. Query results refer to the amount of time raw queries should be cached. Rendered output is the amount of time the View HTML output should be cached. So basically, you can cache both your data and your frontend HTML output. Set them both to the default of 1 hour. You can also set one to a specific time and the other to None. Go ahead and tweak these settings to your own requirements. I'm leaving both set to the default of 1 hour. Click on the Update button to save your caching options settings. You are now caching your View. Save your View by clicking on the Save button. The next time you look at your View interface you should see the caching time notation listed under your Basic settings. It will say 1 hour/1 hour for this setting. Once you enable Views caching, if you make a change to your View settings and configuration, the results and output of the View may not update while you have caching enabled. So, while in Views development you may want to disable caching and set it to None. Otherwise, this next section will show you how to disable your Views cache while you are in development. To see the performance results of this, you can use the Devel module's functionality again. When you load your View after you enable caching, you should see a decrease in the amount of ms (milliseconds) needed to build your Views plugin, data, and handlers. So, if your Views plugin build loaded in 27.1 ms before you enabled caching, you may notice that it changes to something less—for example, in my case it now shows that it loads in 2.8 ms. You can immediately see a slight performance increase with your View build. Let's go ahead and build a brand new View using the test content that we generated with the Devel module and then enable caching for this View as well. Go to your Views admin and follow these steps: Add a new View. Name the View, add a description and a tag if applicable. Click on Next. I'm going to create a View that filters my blog entries and lists the new blog entries in post date order using the Devel content I generated. Add a Page display to your new View. Name the page View. Give the page View a title. Give your View an HTML list style. Set the View to display 5 posts and to use a full pager. Set your caching to Time-based (following instructions above in the first view we edited). Give the view a path. Add a Node: Title field and set the field to be linked to its node. Add a filter in order to filter by Node:Type and then select Blog entry. Set your Sort criteria to sort by Node:Post date in ascending order by hour. Your settings should look similar to this: Save your View by clicking on the Save button. Your new View will be visible at the Page path you gave it and it will also be caching the content and data it presents. Again, if you refresh your View page each time you should notice that the plugins, data, and handlers build times decrease or stay very similar and consistent in load times. You should also notice that the Devel database queries status is telling you that it's using the cached results and cached output for the View build times and the MySQL statements. You should see the following code sitting below your page content on the View page you are looking at. It will resemble this: Views plugins build time: 23.509979248 msViews data build time: 55.7069778442 msViews handlers build time: 1.95503234863 msSELECT node.nid AS nid,node_data_field_photo_gallery_photo.field_photo_gallery_photo_fidAS node_data_field_photo_gallery_photo_field_photo_gallery_photo_fid,node_data_field_photo_gallery_photo.field_photo_gallery_photo_listAS node_data_field_photo_gallery_photo_field_photo_gallery_photo_list,node_data_field_photo_gallery_photo.field_photo_gallery_photo_dataAS node_data_field_photo_gallery_photo_field_photo_gallery_photo_data,node.type AS node_type,node.vid AS node_vid,node.title AS node_title,node.created AS node_createdFROM {node} nodeLEFT JOIN {content_type_photo} node_data_field_photo_gallery_photo ONnode.vid = node_data_field_photo_gallery_photo.vidWHERE (node.status <> 0) AND (node.type in ('%s'))ORDER BY node_created ASCUsed cached resultsUsed cached output
Read more
  • 0
  • 0
  • 3182
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-blackberry-enterprise-server-5-activating-devices-and-users
Packt
03 Mar 2011
11 min read
Save for later

BlackBerry Enterprise Server 5: Activating Devices and Users

Packt
03 Mar 2011
11 min read
BlackBerry Enterprise Server 5 Implementation Guide Simplify the implementation of BlackBerry Enterprise Server in your corporate environment Install, configure, and manage a BlackBerry Enterprise Server Use Microsoft Internet Explorer along with Active X plugins to control and administer the BES with the help of Blackberry Administration Service Troubleshoot, monitor, and offer high availability of the BES in your organization Updated to the latest version – BlackBerry Enterprise Server 5 Implementation Guide       BlackBerry Enterprise users must already exist on the Microsoft Exchange Server. As with the administrative users, to make tasks and management of device users easier, we can create groups and add users to the groups, and then assign policies to the whole group rather than individual users. Again, users can be part of multiple groups and we will see how the policies are affected and applied when users are in more than one group. Creating users on the BES 5.0 We will go through the following steps to create users on the BES 5.0: Within the BlackBerry Administration Service, navigate to the BlackBerry solution management section. Expand User and select Create a user. We can now search for the user we want to add either by typing the user's display name or e-mail address. Enter the search criteria and select Search. We then have the ability to add the user to any group we have already created; in our case we only have an administrative group. We have three options on how the user will be created, with regards to how the device for the user will be activated: With activation password: This will allow us to set an activation password along with the expiry time of the activation password for the user With generated activation password: The system will autogenerate a password for activation, based on the settings we have made in our BlackBerry Server (shown further on in this article) Without activation password: This will create just a user who will have no pre-configured method for assigning a device For this example, we will select Create a user without activation password. Once we have covered the theory and explored the settings within this article regarding activating devices, we will return to the other two options. We can create a user even if the search results do not display the user—generally this occurs when the Exchange Server has not yet synched the user account to the BlackBerry Configuration Database, typically when new users are added. This method is shown in Lab. Groups can be created to help manage users within our network and simplify tasks. Next we are going to look at creating a group that will house users—all belonging to our Sales Team. Creating a user-based group To create a user-based group, go through the following steps: Expand Group, select Create a group, in the Name field enter Sales Team, and click on Save. Select View group list. Click on Sales Team. Select Add users to group membership. Select the user we have just created by placing a tick in the checkbox next to the user's name, and click on Add to group membership. We can click on View group membership to confirm the addition of our user to the group. We will be adding more users to this group later on in the Lab when we import the users via a text file. Preparing to distribute a BlackBerry device Before we can distribute a BlackBerry device to a user using various methods, we need to address a few more settings that will affect how the device will initially be populated. By default when a device is activated for a user, the BlackBerry Enterprise Server will prepopulate/synchronize the BlackBerry device with the headers of 200 e-mail messages from the previous five days. We can alter these settings so that headers and the full body of the e-mail message can be synched to the device for up to a maximum of 750 messages over the past 14 days. In the BlackBerry Administration Service, under Servers and components expand BlackBerry Domain | Component view | Email and select the BES instance. On the right-hand pane select the Messaging tab. Scroll down and select Edit instance. To ensure that both headers and the full e-mail message is populated to the BlackBerry Device, in the Message prepopulation settings, change the Send headers only drop-down to False. Change the Prepopulation by message age to a max of 14 days, by entering 14. We can change the number of e-mails that are prepopulated on the device by changing the number of Prepopulation by message count, again a max of 750. By making the preceding two values to zero, we can ensure that no previous e-mails are populated on the device. Within the same tab, we can set our Messaging options, which we will examine next. We have the ability to set: A Prepended disclaimer (goes before the body of the message) An Appended disclaimer (goes after the user's signature) We can enter the text of our disclaimer in the space provided, then choose what happens if there is a conflict. The majority of these settings can also be set at a user level (settings made on the server override any settings made by the user, that's why it is best practice to have these set on the server level), which we will see later in Lab. If user setting exists then we need to notify the server how to deal with a potential conflict. The default setting is to use the user's disclaimer first then the one set on the server. Bear in mind, the default setting will show both the user's disclaimer and then the server disclaimer on the e-mail message. Wireless message reconciliation should be set to True—the BlackBerry Enterprise Server synchronizes e-mail message status changes between the BlackBerry device and Outlook on the user's computer. The BES reconciles e-mail messages that are moved from one folder to another, deleted messages, and also changes the status of read and unread messages. By default the BES performs a reconcile every 30 minutes; the reconcile is in effect checking that for a particular user the Outlook and the BlackBerry have the same information in their databases. If this is set to False then the above mentioned changes will only take effect when the device is plugged in to Desktop Manager or Web Desktop Access. We have the option of setting the maximum size for a single attachment or multiple attachments in KB. We can also specify the maximum download size for a single attachment. Rich content turned on set to True allows e-mail messages that contain HTML and rich content to be delivered to BlackBerry devices; having it set to False would mean all messages are delivered in plain text. This will save a lot of resources on the server(s) housing the BES components. We can set the same principle for downloading inline images. Remote search turned on set to True—this will allow users to search the Microsoft Exchange server for e-mails from their BlackBerry devices. In BES 5, we have a new feature that allows the user, when on his device-prior to sending out a meeting request—to check if a potential participant is available at that time or not. (Microsoft Exchange 2007 users need to make some changes to support this feature; see the BlackBerry website for further details on the hot fixes required.) Free busy lookup turned on is set to True if you want the above service. If system resources are being utilized heavily, this feature can be turned off by selecting False. Hard deletes reconciliation allows users to delete e-mail messages permanently in Microsoft Outlook (by holding the shift + del keys). You can also configure the BES to remove permanently deleted messages from the user's BlackBerry device. You must have wireless reconciliation turned on for this to work. Now that we have prepared our messaging environment, we are ready to activate our first user. Activating users When it comes to activating users, we have five options to choose from: BlackBerry Administration Service: We can connect the device to a computer and log on to the BAS to assign and activate a device for a user Over the Wireless Network (OTA): We can activate a BlackBerry to join our BES without needing it to be physically connected to our organization Over the LAN: A user who has BlackBerry Desktop Manager running on his or her computer in the corporate LAN can activate the device by plugging the device into his or her machine and running the BlackBerry Desktop Manager BlackBerry Web Desktop Manager: This is a new feature of BES 5 that allows users to connect the device to a computer and log in to the BlackBerry Web Desktop Manager to activate the device, with no other software required Over your corporate organization's Wi-Fi network: You can activate Wi-Fi-enabled BlackBerry devices over your corporate Wi-Fi network Before we look at each of the options available to us, let's examine what enterprise activation is and how it works along with its settings; this will also help us choose the best option for activating devices for users and avoid errors during the enterprise activation. Understanding enterprise activation To allow a user's device to join the BlackBerry Enterprise Server, we need to activate the device for the user when we create a user and assign the user an activation password. The user will enter his or her corporate e-mail address and the activation password into the device in the Enterprise Activation screen, which can be reached on the device by going to Options | Advance Options | Enterprise Activation. Once the user types in the information and selects Activate, the BlackBerry device will generate an ETP.dat message. It is important that if you have any virus scanning or e-mail sweeping systems running in your organization, we ensure that this type of filename with extension is added to the safe list. Please note that this ETP.dat message is only generated when we activate a device over the air. If we use other methods where the device is plugged in via a cable to activate it, NO ETP.dat file is generated. The ETP.dat message is then sent to the user's mailbox on the Exchange Server over the wireless network. To ensure that the activation occurs smoothly, make sure the device has good battery life and the wireless coverage on the device is less than 100db. This can be checked by pressing the following combination on the device Alt + NMLL. The BlackBerry Enterprise Server then confirms that the activation password is correct and generates a new permanent encryption key and sends it to the BlackBerry device. The BlackBerry Policy service then receives a request to send out an IT policy. Service books control the wireless synchronization data. Data is now transferred between the BlackBerry device and the user's mailbox using a slow synch process. The information that is sent to the BlackBerry device is stored in databases on the device, and each application database is shown with a percentage completed next to it during the slow synch. Once the activation is complete, a message will pop up on the device stating 'Activation complete'. The device is now fully in synch with the user's mailbox and is ready to send and receive data. Now that we have got a general grasp of the device activation process, we are going to look at the five options mentioned previously, in more detail. Activating a device using BlackBerry Administration Service This method provides a higher level of control over the device, but is more labor-intensive on the administrator as it requires no user interaction. Connect the device to a computer that can access the BlackBerry Administration Service, and log in to the service using an account that has permissions to assign devices. Under the Devices section, expand Attached devices. Click on Manage current device and then select Assign current device. This will then prompt you to search for the user's account that we want to assign the device to. Once we have found the user, we can click on User and then select Associate user and finally click on Assign current device.
Read more
  • 0
  • 0
  • 3166

article-image-creating-simple-skin-using-dotnetnuke
Packt
08 Sep 2010
5 min read
Save for later

Creating a Simple Skin using DotNetNuke

Packt
08 Sep 2010
5 min read
Introduction In DNN, skinning is a term that refers to the process of customizing the look and feel of the DNN portal. One of the powerful features of DNN is that the functionality of the portal is separated from the presentation of the portal. This means we can change the appearance of the portal without affecting how the portal works. To create a skin in DNN we will work with three kinds of files: HTML, ASCX, and CSS. The HTML or ASCX file describes the layout of the page and the CSS file provides the styling. If you have worked with HTML and CSS before than you will be able to immediately get started. However, if you are familiar with ASCX (and as a DNN developer that is likely) you can achieve the same results faster than HTML. In the recipes, we will show primarily ASCX skinning with some brief examples of HTML skinning. Skin Objects Before we start looking at the recipes, we need a quick word about Skin Objects. Skin Objects are used in both HTML and ASCX skin files as placeholders for different kinds of dynamic functionality. In HTML skins, you place text tokens such as [CURRENTDATE] in your code and when the code is parsed by the skin engine it will insert the matching skin object. If you are working in ASCX, you register skin objects as controls that you place directly in your code. DNN offers many different skin objects such as CurrentDate, Logo, Login link, and others and we'll see many of these in action in the recipes of this article. Downloading and installing a skin Often the easiest way to start skinning is to download an existing skin package and see the different files used for skinning. In this recipe we will download an excellent skin created by Jon Henning from a site called CodePlex that demonstrates the most common skin objects and layouts. Another reason for starting with an existing skin is that it allows incremental development. We can start with a fully functional skin, deploy it to our DNN portal and then edit the source files right on the server. In this way the changes we make are immediately displayed and problems are easily spotted and fixed. However, as applying a skin can affect the entire site, it is best to create and test skins on a development DNN site before using them on a production site. Finally, it should also be noted that as a skin is really just another type of extension in DNN, you are already familiar with some of these steps. How to do it... Open your favorite web browser and go to the site http://codeendeavortemplate.codeplex.com/. Click on Downloads in the toolbar. Scroll down a little and click on the CodeEndeavors Template Skin link. When prompted with the License Agreement, click I Agree. The File download dialog will ask if you want to Open or Save. Click on Save and select a temporary folder to hold the ZIP file. That's all we need from the CodePlex site, so close the browser. To install the skin on the DNN site, begin by logging in as the SuperUser. Look at the Control Panel and make sure you're in Edit mode. Look under the Host menu and select Extensions. Scroll to the bottom and click on the link Install Extension Wizard. The wizard will prompt for the ZIP file (called the extension package). Click on the Browse button and select the file you just downloaded (for example CodeEndeavors.TemplateSkin.install.v01.01.07.00.zip). Click on Open then click on Next. The wizard will display the Extension information. Click on Next. The wizard will display the Release Notes. Click on Next. On the license page, check Accept License? and click on Next. Now the install script will run, creating the skin. At the end you should see the message "Installation successful". Click on Return. To make the skin active, select Skins under the Admin menu. (Move the mouse over the image to enlarge.) From the Skins drop-down lists, select CodeEndeavors.TemplateSkin. For this article, we will use the Index skin for our examples. Click on the Apply link under the index skin to make it active. To see the skin files, you can look in the root folder of the DNN instance under Portals_defaultSkinsCodeEndeavors.TemplateSkin. Here is a summary of the key files you are likely to see in a skin like this: File name Description animated.ascx An ASCX skin file. container.ascx An ASCX container file. index.html An HTML skin file. skin.css The stylesheet for the skin. container.css The stylesheet for the container. TemplateSkin.dnn The manifest file for the skin package. thumbnail_animated.jpg A preview image of the ASCX skin. thumbnail_container.jpg A preview image of the ASCX container. thumbnail_index.jpg A preview image of the HTML skin. license.txt The text of the license agreement. releasenotes.txt The text of the release notes. version.txt The version number. Images folder A folder holding the graphic images supporting a skin or container.
Read more
  • 0
  • 0
  • 3143

article-image-integrating-facebook-magento
Packt
21 Jan 2011
4 min read
Save for later

Integrating Facebook with Magento

Packt
21 Jan 2011
4 min read
  Magento 1.4 Themes Design Customize the appearance of your Magento 1.4 e-commerce store with Magento's powerful theming engine Install and configure Magento 1.4 and learn the fundamental principles behind Magento themes Customize the appearance of your Magento 1.4 e-commerce store with Magento's powerful theming engine by changing Magento templates, skin files and layout files Change the basics of your Magento theme from the logo of your store to the color scheme of your theme Integrate popular social media aspects such as Twitter and Facebook into your Magento store Facebook (http://www.facebook.com) is a social networking website that allows people to add each other as 'friends' and to send messages and share content. Move the mouse over the image to enlarge it. As with Twitter, there are two options you have for integrating Facebook with your Magento store: Adding a 'Like' button to your store's product pages to allow your customers to show their appreciation for individual products on your store. Integrating a widget of the latest news from your store's Facebook profile. Adding a 'Like' button to your Magento store's product pages The Facebook 'Like' button allows Facebook users to show that they approve of a particular web page and you can put this to use on your Magento store. Getting the 'Like' button markup To get the markup required for your store's 'Like' button, go to the Facebook Developers website at: http://developers.facebook.com/docs/reference/ plugins/like. Fill in the form below the description text with relevant values, leaving the URL to like field as URLTOLIKE for now, and setting the Width to 200: Click on the Get Code button at the bottom of the form and then copy the code that is presented in the iframe field: The generated markup should look like the following: <iframe src="http://www.facebook.com/plugins/like.php?href= URLTOLIKE&amp;layout=standard&amp;show_faces=true&amp;width= 200&amp;action=like&amp;colorscheme=light&amp;height=80" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:200px; height:80px;" allowTransparency="true"> </iframe> You now need to replace the URLTOLIKE in the previous markup to the URL of the current page in your Magento store. The PHP required to do this in Magento looks like the following: <?php $currentUrl = $this->helper(‘core/url’)->getCurrentUrl(); ?> The new Like button markup for your Magento store should now look like the following: <iframe src="http://www.facebook.com/plugins/like.php?href= ".<?php $currentUrl = $this->helper(‘core/url’)->getCurrentUrl(); ?>". &amp;layout=standard&amp;show_faces=true&amp;width=200&amp;action= like&amp;colorscheme=light&amp;height=80» scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:200px; height:80px;" allowTransparency="true"> </iframe> Open your theme's view.phtml file in the /app/design/frontend/default/m2/ template/catalog/product directory and locate the lines that read: <div class="std"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?> </div></div> Insert the code generated by Facebook here, so that it now reads the following: <div class="std"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?> </div> <iframe src="http://www.facebook.com/plugins/like.php?href=<?php echo $this->helper('core/url')->getCurrentUrl();?>&amp;layout= standard&amp;show_faces=true&amp;width=200&amp;action=like&amp; colorscheme=light&amp;height=80" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:200px; height:80px;" allowTransparency="true"> </iframe> </div> Save and upload this file back to your Magento installation and then visit a product page within your store to see the button appear below the brief description of the product: That's it, your product pages can now be liked on Facebook!
Read more
  • 0
  • 0
  • 3139

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-showcasing-personnel-facultystaff-directory-using-plone-3
Packt
18 Jan 2010
6 min read
Save for later

Showcasing Personnel with Faculty/Staff Directory using Plone 3

Packt
18 Jan 2010
6 min read
(For more resources on Plone, see here.) Faculty/Staff Directory is practically a departmental web site in a box, but it doesn't stop there. The product is general enough to serve in non-academic settings as well. It is also not limited to people; it has been repurposed to such diverse applications as cataloguing tea leaves. It really is a general-purpose taxonomy engine—albeit with an academic bent in many of its naming choices. This article is an exploration of a product that will likely provide the framework for much of your site. We'll tour its features, get ideas on how they're commonly used in a school setting, and, finally, get a sneak peek into the future of the product. Install the product Faculty/Staff Directory depends on several other products: membrane, Relations, and archetypes.schemaextender. Thus, the easiest way to get it, as documented in its readme, is by adding Products.FacultyStaffDirectory to your buildout.cfg, like so: [buildout]eggs = ...(other eggs)... Products.FacultyStaffDirectory Then, shut down Zope, and run buildout. After starting up Zope again, install FacultyStaffDirectory in the Add-on Products control panel, and you're ready to go. Test drive Faculty/Staff Directory Faculty/Staff Directory (FSD) is tremendously flexible; you can use it as a simple list of phone numbers or as the foundation supporting the rest of your site. In this section, we take FSD for a spin, with ample pit stops along the way to discuss alternative design possibilities. Keep in mind that FSD's features are given to creative repurposing. We'll not only see their typical uses but some more inventive ones as well. Create a directory and choose global roles Faculty/Staff Directory centers around the idea of collecting people in a central folder called, fittingly, a faculty/staff directory. Our first step is to create that folder. Once you've installed FSD in the Add-on Products control panel, choose a place in your site where you would like to place a personnel directory, and add a faculty/staff directory there. You'll be prompted for two things: Title (which is usually something like People) and a selection of Roles. These roles, part of FSD's optional user-and-group integration, are granted site-wide to all people in the directory. Thus, as with the similarly scoped roles in the Users and Groups control panel, it's best to use them sparingly: choose only Member or, if you don't intend the people represented in your Directory to log in, no roles at all. Most roles should be assigned on a per-folder basis using the Sharing tab, and FSD provides facilities for that as well, as we discuss later in the Integrate users and groups section. Add people Now that you have a place to keep them, it's time to add actual personnel. FSD represents people through the aptly named Person type. A fully tricked-out person might look like this: People, without exception, live directly inside the faculty/staff directory—though they often appear to be elsewhere, as we will soon see. Each person can track the following information: Basic Information   Access Account ID Doubling as the object ID (or "short name") of the person, this field should contain the person's institution-wide login name. If you choose to take advantage of FSD's user-and-group integration, this is how logged-in users are matched with their Person objects. The name of this field and its validation requirements can be changed (and should be, in most deployments) in the Faculty/Staff Directory control panel under Site Setup. Name First, middle, and last names, as well as a suffix such as Ph. D or Jr. Image A picture of the person in GIF, JPEG, or PNG format, for use on their page and in some listings. It will be automatically scaled as necessary. Classifications Classifications are FSD's most prominent way to group people. This is a convenient place to assign one or more when creating a person. Departments Another way of grouping people. See Group People, below, for an in-depth comparison of all the various types of groupings. Password If the Person objects provide user passwords option in the FSD control panel is on, one can log into the Plone site using the Access Account ID as a username and the contents of this field as a password. Personal Assistant(s) Other people who should have access to edit this person's information (excluding password and the fields under User Settings). Contact Information   Email This email address is run through Plone's spam armoring, as yet not widely cracked, before being displayed to visitors. An alternative armoring method ("somebody AT here DOT edu") is available from the FSD control panel under Site Setup. Street Address City State Postal Code Phone The required format of the Office Phone field, along with its example text, can be set in the FSD control panel-a must for installations outside the United States and Canada. Professional Information   Job Titles As many job titles as you care to provide, one per line. These are all listed on the person's page. Biography A rich text field for the person's biographical information. Since this field can contain all the formatting you can muster-headings, images, and all-it is a wonderful thing to abuse. Fill it with lists of published journal articles, current projects, and anything else appropriate to show on the person's page. Education A plain text field where every line represents a conferred degree, certification, or such. Web Sites A list of URLs, one per line, to display on the person's page. There is no option to provide link text for these URLs, so you may wish to embed links in the Biography field instead. Committees Specialties The committees and specialties to which this person belongs. See the full discussion of FSD's various methods of grouping people under Group People, below. User Settings   Language Content Editor If you leave FSD's user-and-group integration enabled for the Person type, these duplications of the standard Plone options will apply. Integration can be disabled on a type-by-type basis in the FSD control panel under Site Setup. That's a lot of information, but you can fill out only what you'll use. Fields left blank will be omitted from directory pages, labels and all. For more thorough customization, you can write a Faculty/Staff Directory extender product to hide inapplicable fields from your content providers or to collect information that FSD doesn't ordinarily track. Here's how to add people to the directory: From within the directory, pull down the Add new… menu, and choose Person. Fill out some of the person's attributes. Be sure to assign at least one classification to each person, but don't worry about departments, specialties, or committees yet, as we're about to cover them in detail.
Read more
  • 0
  • 0
  • 3133

article-image-ajaxdynamic-content-and-interactive-forms-joomla
Packt
16 Oct 2009
13 min read
Save for later

AJAX/Dynamic Content and Interactive Forms in Joomla!

Packt
16 Oct 2009
13 min read
AJAX: an acronym that Jesse James Garret of AdaptivePath.com came up with in 2005. Just a few short years later, it seems like every site has a "taste" of AJAX in it. If you're totally new to AJAX, I'll just point out that, at its core, AJAX is nothing very scary or horrendous. AJAX isn't even a new technology or language. Essentially, AJAX stands for: Asynchronous JavaScript and XML, and it is the technique of using JavaScript and XML to send and receive data between a web browser and a web server. The biggest advantage this technique has is that you can dynamically update a piece of content on your web page or web form with data from the server (preferably formatted in XML), without forcing the entire page to reload. The implementation of this technique has made it obvious to many web developers that they can start making advanced web applications (sometimes called RIAs—Rich Interface Applications) that work and feel more like software applications than web pages. Keep in mind that the word AJAX is starting to have its own meaning (as you'll also note its occasional use here as well as all over the Web as a proper noun rather than an all-cap acronym). For example, a Microsoft web developer may use VBScript instead of JavaScript to serve up Microsoft Access database data that is transformed into JSON (not XML) using a .NET server-side script. Today, that guy's site would still be considered an AJAX site rather than an "AVAJ" site (yep, AJAX just sounds cooler). In fact, it's getting to the point where just about anything on a web site (that isn't in Flash) that slides, moves, fades, or pops up without rendering a new browser window is considered an "Ajaxy" site. In truth, a large portion of these sites don't truly qualify as using AJAX, they're just using straight-up JavaScripting. Generally, if you use cool JavaScripts in your Joomla! site, it will probably be considered Ajaxy, despite not being asynchronous or using any XML. Want more info on this AJAX business? The w3schools site has an excellent introduction to AJAX, explaining it in straightforward simple terms. They even have a couple of great tutorials that are fun and easy to accomplish even if you only have a little HTML, JavaScript and server-side script (PHP or ASP) experience (no XML experience required): http://w3schools.com/ajax/. Preparing for dynamic content and interactive forms Gone are the days of clicking, submitting, and waiting for the next page to load, or manually compiling your own content from all your various online identities to post in your site. A web page using AJAX techniques (if applied properly) will give the user a smoother and leaner experience. Click on a drop-down option and check-box menus underneath are immediately updated with the relevant choices—no submitting, no waiting. Complicated forms that, in the past, took two or three screens to process can be reduced into one convenient screen by implementing the form with AJAX. As wonderful as this all sounds, I must again offer a quick disclaimer: I understand that, like with drop-down menus and Flash, you may want AJAX to be in your site, or your clients are demanding that AJAX be in their sites. Just keep in mind, AJAX techniques are best used in situations where they truly benefit a user's experience of a page; for example, being able to painlessly add relevant content via an extension or cutting a lengthy web process form down from three pages to one. In a nutshell, using an AJAX technique simply to say your site is an AJAX site is probably not a good idea. You should be aware that, if not implemented properly, some uses of AJAX can compromise the security of your site. You may inadvertently end up disabling key web browser features (such as back buttons or the history manager). Then there's all the basic usability and accessibility issues that JavaScript in general can bring to a site. Some screen readers may not be able to read a new screen area that's been generated by JavaScript. If you cater to users who rely on tabbing through content, navigation may be compromised once new content is updated. There are also interface design problems that AJAX brings to the table (and Flash developers can commiserate). Many times, in trying to limit screen real estate and simplify a process, developers actually end up creating a form or interface that is unnecessarily complex and confusing, especially when your user is expecting a web page to, well, act like a normal web page. Remember to check in with Don't Make Me Think: This is the Steve Krug book I recommend for help with any interface usability questions you may run into.Really interested in taking on AJAX? For you programmers, I highly recommend "AJAX and PHP: Building Responsive Web Applications", Cristian Darie, Bogdan Brinzarea, Filip Chereches-Tosa, and Mihai Bucica, Packt Publishing. In it, you'll learn the ins and outs of AJAX development, including handling security issues. You'll also do some very cool stuff, such as make your own Google-style auto-suggest form and a drag-and-drop sortable list (and that's just two of the many fun things to learn in the book). So, that said, you're now all equally warned and armed with all the knowledgeable resources I can think to throw at you. Let's get to it: how exactly do you go about getting something Ajaxy into your Joomla! site? Joomla! extensions Keep in mind, extensions are not part of your template. They are additional files with Joomla!-compatible PHP code, which are installed separately into their own directories in your Joomla! 1.5 installation. Once installed, they are available to be used with any template that is also installed in your Joomla! installation. Even though these are not part of your template, you might have to prepare your template to be fully compatible with them. Some extensions may have their own stylesheets, which are installed in their extension directory. Once you've installed an extension, you may want to go into your own template's stylesheet so that it nicely displays XHTML objects and content that the extension may output into your site. Extensions are any component, module or plugin that you install into your Joomla! 1.5 installation. Components control content that displays in the main type="component" jdoc tag in your template. Note that components may also have module settings and the ability to display content in assigned module positions. The poll component is a good example of a component that also has module settings. Modules are usually smaller and lighter and only display in module positions. Plugins generally help you out more on the backend of your site, say to switch WYSIWYG editors or with enabling OpenID logins, but as we'll see, some plugins can affect the display of your site to users as well. Deciding where AJAX is best used On the whole, we're going to look at the most popular places where AJAX can really aid and enrich your site's user experience. We'll start with users adding comments to articles and pages and streamlining that process. We'll then take a look at a nice plugin that can enhance pagination for people reading long articles on your site. We'll then move on to the RSS Reader module, which can enhance the content in your modules (and even makes your users have fun arranging them). Finally, we'll realize that AJAX isn't just for impressing your site users. You, as an administrator, can (and do) take advantage of AJAX as well. Please note: These extensions were chosen by me based on the following criteria: 1. They provided some useful enhancement to a basic site.2. They, at the time of this writing, were free and received very good feedback on Joomla!.org's extensions site: http://extensions.Joomla.org. In the next few pages, I'll walk you through installing these extensions and discuss any interesting insights for doing so, and benefits of their enhancements (and some drawbacks). But you must use the extension links provided to make sure you download the latest stable versions of these extensions and follow the extension author's installation guides when installing these into your Joomla! site. If you run into any problems installing these extensions, please contact the extension's author for support. Always be sure to take the normal precaution of backing up your site before installation, at least for any non-stable extensions you may decide to try. Installing the Joomla! comment component Chances are, if you've invested in Joomla! 1.5 as your CMS, you need some powerful capabilities. Easy commenting with "captcha" images to reduce spam is always helpful: http://extensions.Joomla.org/extensions/contacts-&-feedback/comments/4389/details To install this extension (and the other few coming up), you have to basically go to Extensions | Install/Uninstall and upload the extension's ZIP file. You'll then proceed to the plugin, component, and/or modules panel and activate the extension so that it is ready to be implemented on your site. Upon installing this comment component, to my surprise, it told me that it was for an older version of Joomla! Everything on the download page seemed to indicate it worked with 1.5. The installation error did mention that I just needed to activate the System Legacy plugin and it would work. So I did, and the comment form appeared on all my article pages. This may seem like a step backward, but for extensions like this, which are very useful, if they work well and stay stable in Legacy Mode, a developer may have made the decision to leave well enough alone. The developer will most likely eventually upgrade the extension (especially if Legacy Mode goes away in future versions of Joomla!). Just be sure to sign up for updates or check back on any extensions you use if you do upgrade your site. You should do this regardless of whether your extensions run natively or in Legacy Mode. The advantage of AJAX in a comment form is that a user isn't distracted and comments post smoothly and right away (a bit of instant gratification for the user, even if you never "confirm" the post and it never gets actually published for other viewers). This extension outputs tables, but for the ease of handling robust comments and having a great admin area to manage them, I'll make do. The following screenshot shows the Joomla! comment component appearing in an article page: As you can see in my previous image, I have some strong styles that are trying to override the component's styles. A closer look at the output HTML will give me some class names and objects that I can target with CSS. The administration panel's Component | Joomla! Comment | Other Component settings page also allows quite a few customization options. The Layout tab also offers several included style sheets to select from as well as the option to copy the CSS sheet out to my template's directory (the component will do this automatically). This way, I can amend it with my own specific CSS, giving my comment form a better fit with my template's design. Installing the core design Ajax Pagebreak plugin If your site has long articles that get broken down regularly in to three or more pages, Pagebreak is a nice plugin that uses Ajax to smoothly load the next page. It's a useful feature that will also leave your site users with a little "oh wow" expression. http://www.greatJoomla.com/news/plugins/demo-core-design-ajaxpagebreak-plugin.html After successfully installing this plugin, I headed over to the Extensions | Plugin Manager and activated it. I then beefed out an article (with Lorem Ipsum) and added page breaks to it on the Home Page. It's hard to see in a screenshot, but it appears below the Prev and Next links without a full browser redraw. I've set my site up with SEO-friendly URLs, and this plugin does amend the URLs with a string; that is, http://yoururl.com/1.5dev/menu-item-4?start=1. I'm not sure how this will really affect the SEO "friendliness" value of my URL, but it does give me a specific URL to give to people if I want to send them to a targeted page, which is very good for accessibility. One thing to note, the first page of the article is the original URL; that is, http://yoururl.com/1.5dev/menu-item-4. The second page then appends ?start=1, the third page becomes ?start=2, and so on. Just be aware that when sending links out to people, it is always best to pull the URL directly from the site so that you know it's correct! Installing the AJAX RSS Reader Version 3 with Draggable Divs module RSS feeds are a great way to bring together a wide variety of content as well as bring all your or your organization's "social network happenings" to one place in your own site. I like to use RSS feeds to get people interested in knowing what an organization is doing (or tweeting), or reading, and so on. Having links and lists of what's currently going on can compel users to link to you, join your group, follow you, and become a friend, a fan, or whatever. This AJAX powered module has the extra feature of being draggable and somewhat editable. This is a nice way to draw a user in to the feeds and let them play with them and arrange the information to their taste. Sometimes, sorting and reorganizing makes you see connections and possibilities that you didn't see before. The next image may seem confusing, but it's a screenshot of the top div box being dragged and dropped: http://extensions.Joomla!.org/extensions/394/details AJAX: It's not just for your site's users I've already mentioned, when applied properly, how AJAX can aid in interface usability. Joomla! attempts to take advantage of this within its Administration panel by enhancing it with relevant information and compressing multiple page forms into one single screen area. Here's a quick look at how Joomla! already uses AJAX to enhance its Administration panel forms: The following image shows how the image uploader uses a "lightbox" div layer effect so that you can keep track of where you are in the content editor. In the next image, you can see how Joomla! helps keep the administration area cleared up by using smooth-sliding accordion panels. This helps you see everything on one page and have access to just what you need, when you need it.
Read more
  • 0
  • 0
  • 3125

article-image-developing-entity-metadata-wrappers
Packt
07 Aug 2013
8 min read
Save for later

Developing with Entity Metadata Wrappers

Packt
07 Aug 2013
8 min read
(For more resources related to this topic, see here.) Introducing entity metadata wrappers Entity metadata wrappers, or wrappers for brevity, are PHP wrapper classes for simplifying code that deals with entities. They abstract structure so that a developer can write code in a generic way when accessing entities and their properties. Wrappers also implement PHP iterator interfaces, making it easy to loop through all properties of an entity or all values of a multiple value property. The magic of wrappers is in their use of the following three classes: EntityStructureWrapper EntityListWrapper EntityValueWrapper The first has a subclass, EntityDrupalWrapper, and is the entity structure object that you'll deal with the most. Entity property values are either data, an array of values, or an array of entities. The EntityListWrapper class wraps an array of values or entities. As a result, generic code must inspect the value type before doing anything with a value, in order to prevent exceptions from being thrown. Creating an entity metadata wrapper object Let's take a look at two hypothetical entities that expose data from the following two database tables: ingredient recipe_ingredient The ingredient table has two fields: iid and name. The recipe_ingredient table has four fields: riid, iid , qty , and qty_unit. The schema would be as follows: Schema for ingredient and recipe_ingredient tables To load and wrap an ingredient entity with an iid of 1 and, we would use the following line of code: $wrapper = entity_metadata_wrapper('ingredient', 1); To load and wrap a recipe_ingredient entity with an riid of 1, we would use this line of code: $wrapper = entity_metadata_wrapper('recipe_ingredient', 1); Now that we have a wrapper, we can access the standard entity properties. Standard entity properties The first argument of the entity_metadata_wrapper function is the entity type, and the second argument is the entity identifier, which is the value of the entity's identifying property. Note, that it is not necessary to supply the bundle, as identifiers are properties of the entity type. When an entity is exposed to Drupal, the developer selects one of the database fields to be the entity's identifying property and another field to be the entity's label property. In our previous hypothetical example, a developer would declare iid as the identifying property and name as the label property of the ingredient entity. These two abstract properties, combined with the type property, are essential for making our code apply to multiple data structures that have different identifier fields. Notice how the phrase "type property" does not format the word "property"? That is not a typographical error. It is indicating to you that type is in fact the name of the property storing the entity's type. The other two, identifying property and label property are metadata in the entity declaration. The metadata is used by code to get the correct name for the properties on each entity in which the identifier and label are stored. To illustrate this, consider the following code snippet: $info = entity_get_info($entity_type);$key = isset($info['entity keys']['name']) ? $info['entity keys']['name'] : $info['entity keys']['id'];return isset($entity->$key) ? $entity->$key : NULL; Shown here is a snippet of the entity_id() function in the entity module. As you can see, the entity information is retrieved at the first highlight, then the identifying property name is retrieved from that information at the second highlight. That name is then used to retrieve the identifier from the entity. Note that it's possible to use a non-integer identifier, so remember to take that into account for any generic code. The label property can either be a database field name or a hook. The entity exposing developer can declare a hook that generates a label for their entity when the label is more complicated, such as what we would need for recipe_ingredient. For that, we would need to combine the qty, qty_unit, and the name properties of the referenced ingredient. Entity introspection In order to see the properties that an entity has, you can call the getPropertyInfo() method on the entity wrapper. This may save you time when debugging. You can have a look by sending it to devel module's dpm() function or var_dump: dpm($wrapper->getPropertyInfo());var_dump($wrapper->getPropertyInfo()); Using an entity metadata wrapper The standard operations for entities are CRUD: create, retrieve, update, and delete. Let's look at each of these operations in some example code. The code is part of the pde module's Drush file: sites/all/modules/pde/pde.drush.inc. Each CRUD operation is implemented in a Drush command, and the relevant code is given in the following subsections. Before each code example, there are two example command lines. The first shows you how to execute the Drush command for the operation. ; the second is the help command. Create Creation of entities is implemented in the drush_pde_entity_create function. Drush commands The following examples show the usage of the entity-create ( ec) Drush command and how to obtain help documentation for the command: $ drush ec ingredient '{"name": "Salt, pickling"}'$ drush help ec Code snippet $entity = entity_create($type, $data);// Can call $entity->save() here or wrap to play and save$wrapper = entity_metadata_wrapper($type, $entity);$wrapper->save(); In the highlighted lines we create an entity, wrap it, and then save it. The first line uses entity_create, to which we pass the entity type and an associative array having property names as keys and their values. The function returns an object that has Entity as its base class. The save() method does all the hard work of storing our entity in the database. No more calls to db_insert are needed! Whether you use the save() method on the wrapper or on the Entity object really depends on what you need to do before and after the save() method call. For example, if you need to plug values into fields before you save the entity, it's handy to use a wrapper. Retrieve The retrieving (reading) of entities is implemented in the drush_pde_print_entity() function. Drush commands The following examples show the usage of the entity-read (er) Drush command and how to obtain help documentation for the command. $ drush er ingredient 1$ drush help er Code snippet $header = ' Entity (' . $wrapper->type();$header .= ') - ID# '. $wrapper->getIdentifier().':';// equivalents: $wrapper->value()->entityType()// $wrapper->value()->identifier()$rows = array();foreach ($wrapper as $pkey => $property) { // $wrapper->$pkey === $property if (!($property instanceof EntityValueWrapper)) { $rows[$pkey] = $property->raw() . ' (' . $property->label() . ')'; } else { $rows[$pkey] = $property->value(); }} On the first highlighted line, we call the type() method of the wrapper, which returns the wrapped entity's type. The wrapped Entity object is returned by the value() method of the wrapper. Using wrappers gives us the wrapper benefits, and we can use the entity object directly! The second highlighted line calls the getIdentifier() method of the wrapper. This is the way in which you retrieve the entity's ID without knowing the identifying property name. We'll discuss more about the identifying property of an entity in a moment. Thanks to our wrapper object implementing the IteratorAggregate interface , we are able to use a foreach statement to iterate through all of the entity properties. Of course, it is also possible to access a single property by using its key. For example, to access the name property of our hypothetical ingredient entity, we would use $wrapper->name. The last three highlights are the raw(), label(), and value() method calls. The distinction between these is very important, and is as follows: raw(): This returns the property's value straight from the database. label(): This returns value of an entity's label property. For example, name. value(): This returns a property's wrapped data: either a value or another wrapper. Finally, the highlighted raw() and value() methods retrieve the property values for us. These methods are interchangeable when simple entities are used, as there's no difference between the storage value and property value. However, for complex properties such as dates, there is a difference. Therefore, as a rule of thumb, always use the value() method unless you absolutely need to retrieve the storage value. The example code is using the raw() method only so we that can explore it, and all remaining examples in this book will stick to the rule of thumb. I promise! Storage value: This is the value of a property in the underlying storage media. for example, database. Property value: This is the value of a property at the entity level after the value is converted from its storage value to something more pleasing. For example, date formatting of a Unix timestamp. Multi-valued properties need a quick mention here. Reading these is quite straightforward, as they are accessible as an array. You can use Array notation to get an element, and use a foreach to loop through them! The following is a hypothetical code snippet to illustrate this: $output = 'First property: ';$output .= $wrapper->property[0]->value();foreach ($wrapper->property as $vwrapper) { $output .= $vwrapper->value();} Summary This article delved into development using entity metadata wrappers for safe CRUD operations and entity introspection. Resources for Article: Further resources on this subject: Microsoft SQL Server 2008 R2 MDS: Creating and Using Models [Article] EJB 3 Entities [Article] ADO.NET Entity Framework [Article]
Read more
  • 0
  • 0
  • 3124
article-image-managing-orders-joomla-and-virtuemart
Packt
26 Oct 2009
6 min read
Save for later

Managing orders in Joomla! and VirtueMart

Packt
26 Oct 2009
6 min read
Our shop is now ready for customers. They can register to the shop and get some permissions to browse products and place orders. After building the catalog, one of the big tasks of the shop administrator is to manage the orders. Managing an order includes viewing the order, ensuring that payment is made, shipping the product to customers ship to address, and setting the appropriate status of the order. Whenever the status of the order changes, the shop administrator can also notify the customer about its status. When the product is delivered, the status should also be changed. Sometimes, you need to change the status when the customer refunds it for some reason. Viewing the orders To view the list of orders placed, click on Orders | List Orders. You get the Order List screen: The Order List screen shows all of the orders placed so far in that store. It shows the latest order first. As you can see, it shows the order number, name of customer, date of order, date last modified, status of the order, and total price of the order. As there may be hundreds of orders per day, you need to filter the orders and see which ones need urgent attention. You can filter the orders by their status. For example, clicking on the Pending link will show all of the orders which are pending. Viewing the list of pending orders, you may enquire why those are pending. Some may be pending for not making the payment, or you may be waiting for some offline payment. For example, when the Money Order payment method is used, the order needs to remain Pending until you receive the money order. Once you get the payment, you can change the order status to Confirmed. Viewing an order's details In the Order List screen, you will get an overview of each order. However, sometimes it may be necessary to view the details of an order. For viewing an order's details, in the Order List screen, click on the order number link under the Order Number column. This shows details of the order: In the Order Details page, you will first see the order number, order date, order status, its current status, and IP address from where the order was placed. There is a box section from where you can update the order's status and view the order's history. Then, you get the Bill To and Ship To addresses. After the Bill To and Ship To addresses, you get the list of ordered items and their prices. You can also add a new product to this order from this section. This section also shows taxes added, and shipping and handling fees: After the product items, you get another section which shows shipping information and payment method used: In the Shipping Information section, you get the carrier used, shipping mode applied, shipping price, shipping and handling fees, and shipping taxes. The payment section shows what method was used and when the payment was made. It shows the payment history for this order. It also shows how much of a coupon discount was applied to this order. As an administrator of the shop, you can change the values in the fields where an update icon () is displayed. At the bottom, you see the customer's comment. Customers may provide comments while placing the order. These comments may be very much valuable for the shop owner. For example, the customer may want the product to be delivered in a special way. The customer can express that in this comment. For printing the purchase orders, you may use a printer friendly view. To see the purchase order in a printer friendly view, click on the Print View link at top. This formats the purchase order as a plain document, and also shows a printer icon. Click on that printer icon to print the purchase order. Understanding an order's status How is the order management workflow maintained? Mainly, this is based on the order status. After receiving an order from the customer, it passes several statuses. An order's life cycle is shown in the following diagram: These order status types are defined in advance. At the very outset of starting the shop, the workflow should be clearly defined. Managing order status types You can view the existing order status types from Orders | List Order Status Types. This shows the List Order Status Types screen: As you see from the screen on the previous page, there are five status types. We may add another status type of Delivered. For adding a new order status type, click on the New icon in the toolbar, or on Orders | Add Order Status Type. Both brings the Order Status screen: In the Order Status screen, first type the Order Status Code. For the Delivered status, assign D as code. Then, type the name of the status type in the Order Status Name text box. In the Description text area, you may provide a brief description of the order status type. At the end, specify a list order value. Then, click on the Save icon in the toolbar. This adds the new Delivered order status type. You can create as many order status types as you need. Changing an order's status As indicated earlier, while fulfilling the order, the shop owner needs to update the status of the order, and communicate that status change to the customer. You can change an order's status from two places. In the Order List screen, you can see the orders and also change status. For changing the status of an order, select an order status type from drop-down list in the Status column. Then, click on the Update Status button to save the change. If you want to notify the customer about this     status change, select the Notify Customer? checkbox. One disadvantage of updating the order status from the Order List screen is that you cannot add a note on changing the status. The other way of updating the order status provides this advantage. For using this, click on the order number link in the Order List screen. The order details page will open. On the right side, you will see a box from where you can update the order status. Can you see the Comment text area in the following screen? As you can see, from the Order Status Change tab, you can change the status, write a comment, notify the customer about the status change, and can also add the comment with that notification.
Read more
  • 0
  • 0
  • 3109

article-image-designing-facebook-clone-and-creating-colony-using-ruby
Packt
25 Aug 2010
14 min read
Save for later

Designing the Facebook Clone and Creating Colony using Ruby

Packt
25 Aug 2010
14 min read
(For more resources on Ruby, see here.) Main features Online social networking services are complex applications with a large number of features. However, these features can be roughly grouped into a few common categories: User Community Content-sharing Developer User features are features that relate directly to and with the user. For example, the ability to create and share their own profiles, and the ability to share status and activities are user features. Community features are features that connect users with each other. An example of this is the friends list feature, which shows the number of friends a user has connected with in the social network. Content sharing features are quite easy to understand. These are features that allow a user to share his self-created content with other users, for example photo sharing or blogging. Social bookmarking features are those features that allow users to share content they have discovered with other users, such as sharing links and tagging items with labels. Finally, developer features are features that allow external developers to access the services and data in the social networks. While the social networking services out in the market often try to differentiate themselves from each other in order to gain an edge over their competition, in this article we will be building a stereotypical online social networking service. We will be choosing only a few of the more common features in each category, except for developer features, which for practical reasons will not be implemented here. Let's look at these features we will implement in Colony, by category. User User features are features that relate directly to users: Users' activities on the system are broadcast to friends as an activity feed. Users can post brief status updates to all users. Users can add or remove friends by inviting them to link up. Friendship in both ways need to be approved by the recipient of the invitation. Community Community features connect users with each other: Users can post to a wall belonging to a user, group, or event. A wall is a place where any user can post on and can be viewed by all users. Users can send private messages to other users. Users can create events that represent an actual event in the real world. Events pull together users, content, and provide basic event management capabilities, such as RSVP. Users can form and join groups. Groups represent a grouping of like-minded people and pulls together users and content. Groups are permanent. Users can comment on various types of shared and created content including photos, pages, statuses, and activities. Comments are textual only. Users can indicate that they like most types of shared and created content including photos, pages, statuses, and activities. Content sharing Content sharing features allow users to share content, either self-generated or discovered, with other users: Users can create albums and upload photos to them Users can create standalone pages belonging to them or attached pages belonging to events and groups Online social networking services grew from existing communications and community services, often evolving and incorporating features and capabilities from those services. Designing the clone Now that we have the list of features that we want to implement for Colony, let's start designing the clone. Authentication, access control, and user management Authentication is done through RPX, which means we delegate authentication to a third party provider such as Google, Yahoo!, or Facebook. Access control however is still done by Colony, while user management functions are shared between the authentication provider and Colony. Access control in Colony is done on all data, which prevents user from accessing data that they are not allowed to. This is done through control of the user account, to which all other data for a user belongs. In most cases a user is not allowed access to any data that does not belong to him/her (that is not shared to everyone). In some cases though access is implicit; for example, an event is accessible to be viewed only if you are the organizer of the event. As before, user management is a shared responsibility between the third party provider and the clone. The provider handles password management and general security while Colony stores a simple set of profile information for the user. Status updates Allowing you to send status updates about yourself is a major feature of all social networking services. This feature allows the user, a member of the social networking service, to announce and define his presence as well as state of mind to his network. In Colony, only the user's friends can read the statuses. Remember that a user's friend is someone validated and approved by the user and not just anyone off the street who happens to follow that user. Status updates belong to a single user but are viewable to all friends as a part of the user's activity feed. User activity feeds and news feeds Activity feeds, activity streams, or life streams are continuous streams of information on a user's activities. Activity feeds go beyond just status updates; they are a digital trace of a user's activity in the social network, which includes his status updates. This include public actions like posting to a wall, uploading photos, and commenting on content, but not private actions like sending messages to individuals. The user's activity feed is visible to all users who visit his user page. Activity feeds are a subset of news feeds that is an aggregate of activity feeds of the user and his network. News feeds give an insight into the user's activities as well as the activities of his network. In the design of our clone, the user's activity feed is what you see when you visit the user page, for example http://colony.saush. com/user/sausheong, while the news feed is what you see when you first log in to Colony, that's the landing page. This design is quite common to many social networking services. Friends list and inviting users to join One of the reasons why social networking services are so wildly successful is the ability to reach out to old friends or colleagues, and also to see friends of your friends. To clone this feature we provide a standard friends list and an option to search for friends. Searching for friends allows you to find other users in the system by their nicknames or their full names. By viewing a user's page, we are able to see his friends and therefore see his friend's user pages as well. Another critical feature in social networking services is the ability to invite friends and spread the word around. In Colony we tap on the capabilities of Facebook and invite friends who are already on Facebook to use Colony. While there is a certain amount of irony (using another social networking service to implement a feature of your social networking service), it makes a lot of practical sense, as Facebook is already one of the most popular social networking services on the planet. To implement this, we will use Facebook Connect. However, this means if the user wants to reach out and get others to join him in Colony he will need to log into Facebook to do so. As with most features, the implementation can be done in many ways and Facebook Connect (or any other type of third-party integration for that matter) is only one of them. Another popular strategy is to use web mail clients such as Yahoo! Mail or Gmail, and extract user contacts with the permission of the user. The e-mails extracted this way can be used as a mailing list to send to potential users. This is in fact a strategy used by Facebook. Posting to the wall A wall is a place where users can post messages. Walls are meant to be publicly read by all visitors. In a way it is like a virtual cork bulletin board that users can pin their messages on to be read by anyone. Wall posts are meant to be short public messages. The Messages feature can be used to send private messages. A wall can belong to a user, an event, or a group and each of these owning entities can have only one wall. This means any post sent to a user, event, or group is automatically placed on its one and only wall. A message on a wall is called a post, which in Colony is just a text message (Facebook's original implementation was text only but later extended to other types of media). Posts can be remarked on and are not threaded. Posts are placed on the wall in a reverse chronological order in a way that the latest post remains at the top of the wall. Sending messages The messaging feature of Colony is a private messaging mechanism. Messages are sent by senders and received by recipients. Messages that are received by a user are placed into an inbox while messages that the user sent are placed into a sent box. For Colony we will not be implementing folders so these are the only two message folders that every user has. Messages sent to and received from users are threaded and ordered by time. We thread the messages in order to group different messages sent back and forth as part of an ongoing conversation. Threaded messages are sorted in chronological order, where the last received message is at the bottom of the message thread. Attending events Events can be thought of as locations in time where people can come together for an activity. Social networking services often act as a nexus for a community so organizing and attending events is a natural extension of the features of a social networking service. Events have a wall, venue, date, and time where the event is happening, and can have event-specific pages that allow users to customize and market their event. In Colony we categorize users who attend events by their attendance status. Confirmed users are users who have confirmed their attendance. Pending users are users who haven't yet decided to attend the event. Declined users are users who have declined to attend the event after they have been invited. Declinations are explicit; there is an invisible group of users who are in none of the above three types. Attracting users to events or simply keeping them informed is a critical part of making this or any feature successful. To do so, we suggest events to users and display the suggested events in the user's landing page. The suggestion algorithm is simple, we just go through each of the user's friends and see which other events they have confirmed attending, and then suggest that event to the user. Besides suggestions, the other means of discovering events are through the activity feeds (whenever an event is created, it is logged as an activity and published on the activity feed) and through user pages, where the list of a user's pages are also displayed. All events are public, as with content created within events like wall posts and pages. Forming groups Social networking services are made of people and people have a tendency to form groups or categories based on common characteristics or interests. The idea of groups in Colony is to facilitate such grouping of people with a simple set of features. Conceptually groups and events are very similar to each other, except that groups are not time-based like events, and don't have a concept of attendance. Groups have members, a wall, and can have specific pages created by the group. Colony's capabilities to attract users to groups are slightly weaker than in events. Colony only suggests groups in the groups page rather than the landing page. However, groups also allow discovery through activity feeds and through user pages. Colony has only public groups and no restriction on who can join these public groups. Commenting on and liking content Two popular and common features in many consumer focused web applications are reviews and ratings. Reviews and ratings allow users to provide reviews (or comments) or ratings to editorial or user-generated content. The stereotypical review and ratings feature is Amazon.com's book review and rating, which allows users to provide book reviews as well as rate the book from one to five stars. Colony's review feature is called comments. Comments are applicable to all user-generated content such as status updates, wall posts, photos, and pages. Comments provide a means for users to review the content and give critique or encouragement to the content creator. Colony's rating feature is simple and follows Facebook's popular rating feature, called likes. While many rating features provide a range of one to five stars for the users to choose, Colony (and Facebook) asks the user to indicate if he likes the content. There is no dislike though, so the fewer number of likes a piece of content, the less popular it is. Colony's comments and liking feature is applicable to all user-generated content such as statuses, photos, wall posts, activities, and pages. Sharing photos Photos are one of the most popular types of user-generated content shared online, with users uploading 3 billion photos a month on Facebook; it's an important feature to include in Colony. The basic concept of photo sharing in Colony is that each user can have one or more albums and each album can have one or more photos. Photos can be commented, liked, and annotated. Blogging with pages Colony's pages are a means of allowing users to create their own full-page content, and attach it to their own accounts, a page, or a group. A user, event, or group can own one or more pages. Pages are meant to be user-generated content so the entire content of the page is written by the user. However in order to keep the look and feel consistent throughout the site, the page will be styled according to Colony's look and feel. To do this we only allow users to enter Markdown, a lightweight markup language that takes many cues from existing conventions for marking up plain text in e-mail. Markdown converts its marked-up text input to valid, well-formed XHTML. We use it here in Colony to let users write content easily without worrying about layout or creating a consistent look and feel. Technologies and platforms used We use a number of technologies in this article, mainly revolving around the Ruby programming language and its various libraries. In addition to Ruby and its libraries we also use mashups, which are described next. Mashups While the main features in the applications are all provided for, sometimes we still depend on other services provided by other providers. In this article we use four such external services—RPX for user web authentication, Gravatar for avatar services, Amazon Web Services S3 for photo storage, and Facebook Connect for reaching out to users on Facebook. Facebook Connect Facebook has a number of technologies and APIs used to interact and integrate with their platform, and Facebook Connect is one of them. Facebook Connect is a set of APIs that let users bring their identity and information into the application itself. We use Facebook Connect to send out requests to a user's friends, inviting them to join our social network. Note that for the user invitation feature, once a user has logged in through Facebook with RPX, he is considered to have logged into Facebook Connect and therefore can send invitations immediately without logging in again. Summary In this article, we described some of the essential features of Facebook and we categorized the features into User, Community, and Content sharing features. After that, we went into a high level discussion on these various features and how we implement them in our Facebook clone, Colony. After that, we went briefly into the various technologies used in the clone. In the next article, we will be building the Facebook clone using Ruby. Further resources on this subject: Building the Facebook Clone using Ruby [article] URL Shorteners – Designing the TinyURL Clone with Ruby [article]
Read more
  • 0
  • 0
  • 3107
Modal Close icon
Modal Close icon