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
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Web Development

1797 Articles
article-image-manually-translating-your-joomla-sites-content-your-desired-language
Packt
28 Oct 2010
5 min read
Save for later

Manually Translating Your Joomla! Site's Content into Your Desired Language

Packt
28 Oct 2010
5 min read
Joomla! 1.5 Top Extensions Cookbook Over 80 great recipes for taking control of Joomla! Extensions Set up and use the best extensions available for Joomla! Covers extensions for just about every use of Joomla! Packed with recipes to help you get the most of the Joomla! extensions Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible        The reader would benefit from the previous article on Joomla! 1.5 Top Extensions for Using Languages. Getting ready... Joom!Fish is the most popular extension for building multilingual Joomla! websites. Download the latest version of Joom!Fish from http://joomlacode.org/gf/download/frsrelease/11315/45280/JoomFish2.0.4.zip, and install it from the Extensions | Install/Uninstall screen. It installs one component, two modules, and several plugins. How to do it... After installation, carry out the following steps: From the Joomla! administration panel, click on Components | Joom!Fish | Control Panel. This shows the Joom!Fish :: The multilingual Content Manager for Joomla! screen. Click on Language Configuration. This shows the Joom!Fish Language Manager screen, and lists all the installed languages. In the Active column, enable the checkboxes to activate the required languages. If you don't see an image for a language, type the image's URL in the Image filename field. Then click the icon displayed in the Config column. This shows the Joom!Fish Language Manager - Translate Configuration screen. In this screen, you can translate some common phrases, for example Offline Message, Site Name, Global Site Meta Description, Global Site Meta Keywords, a help site URL, mail settings, and so on. Type in the translations and click on the Save button in the toolbar. Now click on Translation, select Bengali in the Languages drop-down list, and select Categories in the Content elements drop-down list. This shows the translatable categories. Click on a category name and you should see the Translate screen, with the original text and a textbox to insert your translation. Type your translation in the Translate fields, enable the Published checkbox and then click on the Save button in the toolbar. Follow the same process for translating other categories. When finished translating all categories, select Contents in the Content elements drop-down list on the Translate screen. This shows the list of available articles for translation. Click an article title to translate. This shows the Translate screen with the original text and textboxes for translation. Type the translations in the Translation fields, enable the Published checkbox, and click on the Save button in the toolbar. Similarly, change types in the Content elements drop-down box and translate other content including Modules, Menus, Contacts, Banners, and so on. When finished translating, click on Extensions | Module Manager. This shows the Module Manager screen, listing the installed modules. From the list, click on the Language Selection module. This shows the Module: [Edit] screen: Select Yes in the Published field and select a module position from the Position drop-down list. From the Module Parameters section, in the Appearance of language selector drop-down list select how you want to display the language selection box. You can choose from Drop down of names, Drop down of names with current language flag, ul-list of names, ul-list of names with flag, ul-list of images, and Raw display of images. Preview the site's frontend and you should see the site in the default language, with the language selection box at the specified position. From the language selection module, click another case, in my case Bangla, to show the site content in that language. Visitors to your site can now switch to any active language through this language selection module. Note that the URL of the site now appends language code, for example, http://www.yourjoomlasite.com/index.php?lang=bn, where bn stands for the Bangla language. There's more... Note that in Joom!Fish, you can translate almost anything—articles, modules, menus, sections, categories, and so on. These translations are done through content elements. You can see any component or module by clicking on Components | Joom!Fish | Content Elements. You can download content elements for new extensions from http://extensions.joomla.org/extensions/extension-specific/joomfish-extensions and http://joomlacode.org/gf/project/joomfish/frs/. After downloading content elements, click on the Install button on Content Elements screen. This shows the Joom!Fish::Content Element Installer screen. Click on the Browse button, select the content element file, and then click on the Upload File & Install button. This installs the content and you can translate the content for that particular component or module. Summary This article covered: Manually translating your site's content into your desired language Further resources on this subject: Adding an Event Calendar to your Joomla! Site using JEvents Showing your Google calendar on your Joomla! site using GCalendar Joomla! 1.5 Top Extensions: Adding a Booking System for Events Joomla! 1.5 Top Extensions for Using Languages
Read more
  • 0
  • 0
  • 2356

article-image-joomla-15-top-extensions-using-languages
Packt
28 Oct 2010
5 min read
Save for later

Joomla! 1.5 Top Extensions for Using Languages

Packt
28 Oct 2010
5 min read
  Joomla! 1.5 Top Extensions Cookbook Over 80 great recipes for taking control of Joomla! Extensions Set up and use the best extensions available for Joomla! Covers extensions for just about every use of Joomla! Packed with recipes to help you get the most of the Joomla! extensions Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible        Introduction One of the greatest features of Joomla! is that you can build a multilingual website. The Joomla! interface can be displayed in many languages. You can simply download the translation pack for the required language and install that to Joomla!. If you don't have a translation pack for your desired language, you can translate it by editing language files directly or by using the translation manager component. The translation manager component allows you to visually translate your site's interface into any language, right from the Joomla! administration area. After completing the translation, you can pack the translation and share it with others, so that they can install the translation in other Joomla! sites. Besides translating the Joomla! interface, you can translate a site's contents into your desired language. The GTranslate component allows you to translate your site's content into 55 languages using Google's translation service. Adding a language to your site Joomla! can build a multilingual site. A site interface can be in multiple languages, using different locales. In this recipe, you will learn how to add an additional language to a Joomla! site. Getting ready... Joomla! translations are available in major languages. First, decide which language you want to add to your site. For example, we want to add French to a Joomla! website. A French translation for Joomla! 1.5 is available to download at the Joomla! Extensions Directory, http://extensions.joomla.org/extensions/languages/translations-for-joomla. Download this extension from http://joomlacode.org/gf/project/french/frs/, and install it from the Extensions | Install/Uninstall screen. How to do it... After installation, follow the steps as shown: From the Joomla! administration panel, click on Extensions | Language Manager. This will show the Language Manager screen, listing the installed languages for the site: Note that the default language for the site is marked with a yellow star in the Default column. To make the newly-installed language, French (Fr), the default language for your site, select the language and click on the Default button in the toolbar. Preview the site's frontend and you will find the site's interface (not content) in French. For example, the Login Form module will look like the following screenshot: For changing the language of the administration panel, in the Language Manager screen click on Administrator, select a language from the list, and set that as the default language for the administrator backend. See also... Adding a translation will only show the Joomla! interfaces in that language. The content of the site is not translated or displayed in the selected language. Also note that we still don't have a mechanism to select our desired language. All of these things can be done using the Joom!Fish extension, which is discussed in the recipe Manually Translating Your Joomla! Site's Content into Your Desired Language. Translating language files for your site Joomla!'s translations are available in most major languages. However, you may like to change the translations and have your own translation in your desired language. In that case, Joomla! provides a mechanism to translate the Joomla! interface language. In this recipe, you will learn how to translate language files for your site from the administration backend. Getting ready... Translation Manager is a popular extension that can help you translate the site's language files right from the administration backend, without opening a text editor. Download this extension from http://joomlacode.org/gf/project/joomla_1_5_tr1/frs/ and install it from the Extensions | Install/Uninstall screen. How to do it... After installation, follow the steps as shown: From the Joomla! administration panel, click on Components | Translation Manager. This will show the Translation Manager screen, listing all of the installed languages for the site and the administration backend. < For changing any language translation, select that language, for example Site [en-GB] English(United Kingdom), and click on the View Files button. This will show the language files for that language. Now select a file, such as, com_banners, and click on the Edit button. This shows the string editing screen for the com_banners.ini file. Change the strings accordingly, and click on the Save button in the toolbar. For adding a new language, click on New in the Translation Manager screen. This will show the Create New Language screen: In the Language Details section, configure the following: Client: Select who will be the client for this translation—Administrator, Installation, or Site. If you want to translate for the administrator interface, select Administrator. We want to translate the site's frontend, therefore we select Site. Language ISO tag: Type the ISO tag for the language. For example, if we want to translate it into Bengali, type ISO code bn-BD. Name: Type language name, that is Bangla. Description: Type a short description for the translation. Legacy Name: Type the traditional name of the language, for example, bn for bn-BD. Language Locales: Type the locale code for the language. Windows Code page: Specify the code page for the language. The default is iso-8859-1. For the Bangla language it will be utf-8. PDF Font: Specify the font family to be used for displaying the PDF in that language. Right-to-Left: Specify Yes if the language is to be read from right to left (for example, Arabic). In the Author Details section, provide the translator's name (probably your name), e-mail address, website URL, version number for the translation, creation date, the copyright holder's name, and URL to the license document. When done, click on the Save button in the toolbar. This saves the language definition and you will see the language name on the Translation Manager screen:
Read more
  • 0
  • 0
  • 2082

article-image-tips-and-tricks-joomla-multimedia
Packt
27 Oct 2010
7 min read
Save for later

Tips and Tricks for Joomla! Multimedia

Packt
27 Oct 2010
7 min read
  Joomla! 1.5 Multimedia Build media-rich Joomla! web sites by learning to embed and display Multimedia content Build a livelier Joomla! site by adding videos, audios, images and more to your web content Install, configure, and use popular Multimedia Extensions Make your web site collaborate with external resources such as Twitter, YouTube, Google, and Flickr with the help of Joomla! extensions Follow a step-by-step tutorial to create a feature-packed media-rich Joomla! site         Read more about this book       (For more resources on Joomla!, see here.) Using another folder name for images in Joomla! Tip: If you do decide to use another folder name for your media directory, it is important to leave the current /images directory on the server as this can often be used by other components.   Organizing your content Tip: The organization of your website media content is of utmost importance. Just like with your Joomla! Articles, the correct structure of your files can save you time and frustration down the line when you want to easily find an image or media file.   Creating a new directory using Joomla! Media Manager Tip: While creating a new directory using Joomla! Media Manager, a forward slash is already pre-populated, so you only need to enter the name of the directory and nothing else.   Uploading and downloading files Tip: FTP programs offer you the most flexibility in managing your website files, but it is important to take care when using FTP programs. By connecting to your directory structure on the web server, you are navigating amongst core Joomla! files. You can download a file in a similar manner, or you might need to double-click on the file to start downloading it.   Uploading a new file with Joomla! Media Manager Tip: To upload a new file, make sure you are residing in the correct remote directory for upload. Browse to a file on your computer and simply drag this file over into your web browser.   Location of the Joomla! Template CSS files Tip: The Joomla! Template CSS file is usually located in the following directory /templates/yourtemplate/css/template.css. If you are using a pre-built Joomla! Template, you may see multiple CSS files inside the CSS directory. It is important to note that the names of these CSS files may differ between Joomla! Templates, but the template.css file is the standard naming convention for the main CSS file.   Adding an image using the Joomla! Article Image button Tip: Images can be easily added to new and existing Joomla! Articles (and Modules) by using the Image button, which is an extended editor plugin that is configured to be turned on with new Joomla! installations.   Adjusting your Joomla! template images Tip: The images for a Joomla! Template are generally located in the <Your Joomla Home Folder>/templates/<yourtemplate>/images directory. If you would like to adjust certain images in your template, the easiest way to do this is by viewing the template in your site browser and then making the necessary adjustments to the images.   Audio in Joomla! Articles Tip: It is good practice to make a blank .html file and upload it to your new audio directory. This will help stop anyone from being able to directly view all of the files inside your new audio directory. If you cannot create a new .html file, copy an existing Joomla! .html file that resides in the images directory.   Backup of site database Tip: Before installing any third-party code into your Joomla! website, make sure you take a backup of your site database and file set before installing extensions.   Dealing with complex HTML code Tip: Make sure you don't have your WYSIWYG editor turned on in your Joomla! Articles when entering complex HTML code into your Joomla! Articles.   Joomla! Plugin tags Tip: It is worth noting that Joomla! Plugin tags work with and without the WYSIWYG editor turned on.   Video podcast for Joomla! Tip: Creating a video podcast for Joomla! will allow you to display and promote your site or products to many users. Due to the nature of a podcast, they do not even have to be on your website to view the video podcasts, if produced correctly.   Multimedia enhancements with Shadowbox Tip: Shadowbox is a multi-use media plugin for your Joomla! website, so it may be all that you need for your multimedia requirements. The extension can be downloaded at http://extensions.joomla.org by searching for "Shadow".   Inserting custom code into your Joomla! Articles Tip: When starting to insert custom code into your Joomla! Articles, it is important to turn off WYSIWYG editors for your user account. This is because these editors cannot always process the custom HTML code. If the code is not recognized by the editor when loading in the content, it will remove the code altogether. The editor settings can be adjusted in the Global Configuration, or on a user basis via the User Manager.   Extension titles in Joomla! Extension Directory (JED) listings Tip: Due to lengthy URLs and the possibility that Joomla! Extension Directory (JED) listings could change at any time, search terms for the following extensions have been included, rather than direct links to the extensions. Performing a search on the JED for the related terms will help you find these extensions easily. The letters after the extension titles denote the following: M = Module C = Component P = Plugin L = Language T = Template   Publishing your Twitter tweets in your Joomla! site Tip: The JTweet extension is a module that publishes your Twitter tweets in your Joomla! site. The jTweet module now requires the JB Library plugin in order to work. The JB Library plugin loads the jQuery library automatically into the head of your template. The jQuery library is required for the jTweet module.   Mobilebot for Joomla 1.5 Tip: Mobilebot 1.0 for Joomla! 1.5.x can detect visitors using mobile devices and change the Joomla! Template automatically.   If you install an extension and do not use it, then remove it. Tip: Besides keeping your Joomla! site organized and uncluttered, it is best to remove code/files/folders from your server that are not being used. Leaving older code lying around can create security vulnerabilities.   Keep Joomla! up-to-date. Tip: Joomla! releases are made available for a reason and it is important to stay up-to-date with the software. With a well-structured design to the framework, there are now very few reasons to go near the core codework. Upgrading is usually an easy process, compared to some other web platforms. Remember to take a backup of your site files before performing any upgrade work, and to take regular backups whenever you can.   Content parameters Tip: The Article Manager in Joomla! contains a "Global Parameter" setting that sets the default options for your Joomla! Articles. You can override these within each article, but it is good practice to set these globally first, so you don't have to go back and adjust them later on.   HTTP status errors Tip: Joomla! uses the /templates/system/error.php file to handle several HTTP status errors, including "403 Forbidden", "404 Not Found", and "500 Internal Server" errors.   Uninstalling Extensions for Joomla! 1.5 Tip: Extensions for Joomla! 1.5 can be uninstalled easily by clicking on the Manage menu item on the Extension Manager page.   Summary In this article we highlighted some of the tips and tricks which can be of great use while working with Joomla! Multimedia. Further resources on this subject: Joomla! 1.5 Top Extensions Cookbook [Book] Joomla! Social Networking with JomSocial [Book] Joomla! 1.5 JavaScript jQuery [Book]
Read more
  • 0
  • 0
  • 1442
Visually different images

article-image-jquery-user-interface-plugins-tooltip-plugins
Packt
27 Oct 2010
6 min read
Save for later

jQuery User Interface Plugins: Tooltip Plugins

Packt
27 Oct 2010
6 min read
  jQuery Plugin Development Beginner's Guide Build powerful, interactive plugins to implement jQuery in the best way possible Utilize jQuery's plugin framework to create a wide range of useful jQuery plugins from scratch Understand development patterns and best practices and move up the ladder to master plugin development Discover the ins and outs of some of the most popular jQuery plugins in action A Beginner's Guide packed with examples and step-by-step instructions to quickly get your hands dirty in developing high quality jQuery plugins         Read more about this book       (For more resources on jQuery, see here.) Before we get started, there is another little thing worth mentioning: provide many different opportunities to introduce new concepts and ideas, even while keeping the complexity of the whole plugin at a minimum. We can now go on to create our plugin, starting with basic functionalities, and subsequently adjusting its goals. We will add new, improved functionalities that, however, do not make the whole code look too difficult to understand—even after some time or for someone who's just starting out with jQuery. Tooltip plugins in general A lot has been said about tooltip plugins, but it's worth repeating the most important points with particular regard to the way tooltips are supposed to work, and how we want our tooltip to behave. First of all, we might want to get an idea of what tooltips look like and a sample of what we will accomplish by the end of this article. Here is an example: Also, with some more work and proper application of effects, images, and other relatively advanced techniques, we can also obtain something more complex and nicer looking, thus giving the user the chance to specify the style and behavior for the tooltip, as follows: The idea is actually very simple. The elements we have selected will trigger an event every time we hover the mouse pointer over them. The tooltip will then pop out, right at the mouse cursor position, retrieving the text portion from the title attribute of the said element. Finally, whenever we move the mouse over the same element, the plugin will move and follow the mouse cursor until it goes off the boundaries of the element. Positioning the tooltip The first problem we have to face is, of course, how to make the tooltip appear in the right position. It would be no trouble at all if we just had to make some text, image, or anything else show up. We've done it many times and it's no problem at all—just make their positioning absolute and set the right top and side distances. However, we need to take into account the fact that we don't know exactly where the mouse cursor might be and, as such, we need to calculate distances based upon the mouse cursor position itself. So, how can we do it? It's simple enough; we can use some of the JavaScript event properties to obtain the position. Unfortunately, Internet Explorer always tries to put a spoke in our wheel. In fact, the magnificent browser does not (according to this table, which is quite accurate: http://www.quirksmode.org/dom/w3c_cssom.html#mousepos) support pageX and pageY, which would normally return the mouse coordinates relative to the document. So we need to think about a workaround for Internet Explorer, as jQuery (from version 1.0.4 onwards) does not normalize some of the event properties according to W3C standards (http://api.jquery.com/category/events/event-object/). The following diagram (also provided in the " target="_blank">code bundle) should clarify what the visible viewport is (that is, the browser window—the red box): Whenever we scroll down, different parts of the document (blue) are shown through the browser window and hidden due to space constraints. The scroll height (green) is the part of the document currently not displayed. Custom jQuery selectors Suppose we have a page with some text written in, which also contains a few links to both internal pages (that is, pages on the same server) and external websites. We are presented with different choices in terms of which elements to apply the tooltip to (referring to links as an example, but they apply to any kind of element as well), as follows: All the links All the links with a specific class (for example, tooltip) All the links with the title attribute not empty All the links pointing to internal pages All the links pointing to external websites Combinations of the above We can easily combine the first three conditions with the others (and with themselves) using CSS selectors appropriately. For example: $("a"), all the links $("a.tooltip"), links having a tooltip class $("a[title]"), links with a title attribute (still have to check if empty) $("a.tooltip[title]"), links with a tooltip class and a title attribute As for internal and external pages, we have to work with jQuery selectors instead. Time for action – creating custom jQuery selectors Although jQuery makes it easy to select elements using standard CSS selectors, as well as some other selectors, jQuery's own selectors are the ones that help the developer to write and read code. Examples of custom selectors are :odd, :animated, and so on. jQuery also lets you create your own selectors! The syntax is as follows: // definition$.expr[':'].customselector = function(object, index,properties, list) { // code goes here};// call$("a:customselector") The parameters are all optional except for the first one (of course!), which is required to perform some basic stuff on the selected object: object: Reference to current HTML DOM element (not jQuery, beware!) index: Zero-based loop index within array properties: Array of metadata about the selector (the 4th argument contains the string passed to the jQuery selector) list: Array of DOM elements to loop through The return value can be either: true: Include current element false: Exclude current element Our selector (for external links detection) will then look, very simply, like the following code: $.expr[':'].external = function(object) { if(object.hostname) // is defined return(object.hostname != location.hostname); else return false;}; Also note that, to access the jQuery object, we have to use the following (since object refers to the DOM element only!): $.expr[':'].sample = function(object) { alert('$(obj).attr(): ' + $(object).attr("href") + 'obj.href: ' + object.href);}; Merging pieces together We have slowly created different parts of the plugin, which we need to merge in order to create a working piece of code that actually makes tooltips visible. So far we have understood how positioning works and how we can easily place an element in a determined position. Also, we have found out we can create our own jQuery selectors, and have developed a simple yet useful custom selector with which we are able to select links pointing to either internal or external pages. It needs to be placed at the top of the code, inside the closure, as we will make use of the dollar symbol ($) and it may conflict with other software.
Read more
  • 0
  • 0
  • 1835

article-image-installation-and-introduction-k2-content-construction-kit
Packt
27 Oct 2010
5 min read
Save for later

Installation and Introduction of K2 Content Construction Kit

Packt
27 Oct 2010
5 min read
  Joomla! 1.5 Cookbook Over 60 quick and direct recipes to help you overcome common Joomla! queries. Find quick solutions to common Joomla! problems Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible Look at recipes that cover the portions of Joomla! 1.6 that are brand new Over 60 practical recipes covering a range of site management and core Joomla! activities Generally speaking, a basic article is a simple matter to create and manage. When a site gets large with a lot of articles, it can be unwieldy. This need is filled by a Content Construction Kit or CCK. Several good CCK's exist in the Joomlasphere and each has its own unique means to accomplish the task of content management and creation. For our purposes we'll look at the CCK known as K2. K2 provides you an integrated solution that features rich content forms - extending the basic article. This is an article with additional fields that can contain the article images, videos, image galleries or even attachments. Add nested-level categories and tags to that, and you have a very powerful system. In this article we'll look at the installation and use of K2. Installation and introduction of K2 In this recipe you will go through the steps to install and configure K2 in your Joomla! site. Getting ready You will want to download K2 from the following URL: http://getk2.org Additionally, you may want to have a development site to install and learn this on rather than your production site. How to do it... Installation of K2 works like any other Joomla! extension. Be sure and backup your files and database before beginning - this way you can easily roll back should something go wrong. Download K2. Log in to your Joomla! site as the Super Administrator. Click Extensions | Install / Uninstall. Browse, locate, and upload the K2 package. Install.Installation of K2 should be complete. If you are not running the Joom!Fish language translation extension on your site, you will see an informational message stating that K2 did not install the content elements. Joom!Fish is used to translate your site into other languages. If you have no plans on using this, then ignore the message. Now when you go to Components, you'll see the K2 icon. Clicking it will show you this screen: The next step is to bring all of our current content (articles, media, and so on) into K2. While in the K2 Dashboard, look at the upper right-hand side for the Import Joomla! content button. You will see this message (or a similar one depending on your K2 version): Click Ok to start the process. Once complete, you'll see all your content now shows up in the K2 Items menu. Here are the sample Joomla! data items that have been imported. Keep in mind that all of your pre-existing Joomla! sections, categories, and articles are still in the core Joomla! areas. All these items are simply duplicated in K2 now. If you have existing content take a few minutes and go into the Article Manager of Joomla! and unpublish them. You may need to update menu links to your new K2 categories and articles as necessary. Additionally, you'll note that the main Joomla! administrator page has been updated to include the K2 dashboard. Further configuration of K2 K2 has a powerful, nested-category system. It offers you the ability to configure in detail, each category, allowing any category to inherit from another category's parameter settings. Let's use this feature of K2 to configure a master category that will allow other categories to inherit the settings. This means you can change one category and affect them all at the same time – which is quite time-saving. A word of caution, this could impact your search engine-friendly URLs depending on the extension you use to create them. Open the K2 Dashboard. Select Categories. Click New in the upper right-hand side. Fill in the following details: Title is the title of your category Title Alias is the internal reference Parent category should be left as –None-- - all other categories will inherit from this category Inherit parameter options from category should be left as –None-- Associated "Extra Fields" Group should be left as None. Published is Yes Access Level is Public I have filled mine out and the following screenshot is the completed Details section. For now, this is all you'll need to do. Later recipes will utilize this: This is my master category that all other categories will seek out their parameters from. The reason for this will be clear shortly. When you have finished, save the category. How it works... K2 is nearly a content management system, like Joomla!, in itself. It actually substitutes many of the native Joomla! functions like article management, section, and category as well as providing some access control functions. When using K2, you will no longer use many of the native Joomla! menus, but rather you will use the K2 version of the tools. If you install this component, it has the ability to pull in all the data (users, articles) into K2 through the import feature. There's more... In the previous recipe, we set up a master category; now we'll configure it here.
Read more
  • 0
  • 0
  • 2563

article-image-managing-articles-using-k2-content-construction-kit
Packt
27 Oct 2010
8 min read
Save for later

Managing Articles Using the K2 Content Construction Kit

Packt
27 Oct 2010
8 min read
  Joomla! 1.5 Cookbook The reader would benefit from the previous article on Installation and Introduction of K2 Working with items AKA articles The power of K2 is in the idea of categorizing your data, thus making it easier to manage. This will be especially helpful as your site grows in content. Many sites are fully article-based and it is not uncommon to see a site with thousands of articles on it. In this section, we'll tackle some more category-specific recipes. You may have noticed by now that data does not show up as typical articles do in Joomla!. In other words, if you added an item, set it published and featured, it may not be displayed on your site because you have not set up a menu item to your K2 content. K2 will need to be added to your menu structure to display the items (articles) in K2. The first recipe will take into account a site that has been in operation for a while and has K2 added to it. Getting ready This section assumes you have installed K2 and have content on your site. How to do it... Make sure you have a full backup of the database and the files. Log in as the administrator. Open the K2 Dashboard. If you DID NOT import your content in, (see the first recipe), do so now. If you have ALREADY imported your content using the Import Joomla! Content button - DO NOT import again. You run the risk of duplicating all your content. Should this happen, you can go in and delete the duplicate items. This can be a time-consuming process. Open Article Manager | Content | Article Manager. Select all your articles from the Article Manager and unpublish. Open Menu Manager and find your Home menu.Now that we have unpublished content, we'll need to replace the traditional Joomla! content items with K2 content. Opening the Menu Manager and selecting the Home menu item will show this: As you can see under K2 there are several choices to display content on your site. I will choose Item | Item as my display mode. This will show my visitors content in article form. You can pick what works best for you. Now returning to the instructions: After choosing Menu Item Type - click Save. Open K2 Dashboard. Select Items.Here is a partial screenshot of the items in our sample site. As you can see, it now starts to take on a bit more traditional Joomla! look. I can choose featured articles, publish them, or note. Set the order they show up in, the category they belong to and more. When you import content, from Joomla!, the articles retain their identity from Section and Category configuration. For example, the Joomla! Community Portal listed in the preceding screenshot as belonging to the category Latest has a parent category of News. When you imported the content, sections became the new K2 top-level categories. All existing categories become subcategories of the new top level categories. As we added K2 to a working site with sections and category data already in place, I want to make sure they inherit from our master category. In our sample site, we see the following screen when we open the K2 categories from the K2 Dashboard: We instruct the new top-level categories to follow the master category as the model for the rest. The following instructions will show you how. Open K2 Dashboard. Click Categories. Open your imported top-level categories - for this site it's About Joomla! and News. Each of these has sub-categories. Click About Joomla! (or your equivalent). Change the Inherit parameter options from category to MASTER CATEGORY USE AS INHERIT ONLY. Make sure the Parent category stays set to –None--. Click Save.When done, it will look like this: Extra fields Did you notice the Associated "Extra Fields Group" is set to - None - ? You can change this parent category group to use an extra fields group and still keep the master category parameters. Each of the subcategories will inherit from the master category. By doing this, you can still control all the categories parameters simply by changing the master category. How it works... The category system as described here for K2 is a giant access-control system allowing you the flexibility to structure your site and data as you need. It also offers a means to control the 'look and feel' of the articles from a central place. When you import a Joomla! site into K2 you bring all the sections, content, articles, and other associated parts into it. Sections become new parent categories and the old categories become subcategories. This can be a bit confusing at first. One suggestion is to write out on paper what you want the site to look like, and then lay out your categories. You might find that the structure you had can be more user-friendly using K2 and you will want to change. This category system offers you nearly unlimited means to nest articles. In essence, a category can have unlimited categories under it. There is a limit to this in terms of management, but you get the idea. There's more... Using tags in K2 will give you the ability to improve your Search Engine Optimization or SEO on your site. Additionally, the use of tags will allow you to give your users the ability to follow the tags to other articles. In this section we'll review how to use Tags in K2. Tags are keywords or terms that are assigned to your content. This enables your visitors to quickly locate what they need by one word descriptions. Using Tags in K2 Tags can be created before an article is written or on the fly. I prefer on the fly as it will match the article. You can think of a tag almost as a dynamic index. Every time a tag is added to an article, it will show up in the K2 Tag Cloud module if you are using it. The more a single tag, such as Joomla!, is used in the content, the larger it appears in the K2 Cloud module. K2 Tag Clouds can benefit your search engine optimization and a navigational element. Here is an example of our K2 Tag Cloud: This is an image of our K2 Tag Cloud module. The more often a tag is added to an article, the larger it appears. Setting up your site for Tag Clouds K2 installs the K2 Tools module by default. The module has many functions, but for our purposes here, we'll use the Tag module. Log in to the Administrator Console of Joomla!. Click Extensions | Module Manager. Click New to create a new module. Find this for your new item: Once in there, give it a name and select its module location. On the right under Parameters, pull down the Select module functionality drop-down list as follows: Select Tag Cloud as shown in the preceding screenshot. Leave all the root categories set for none - this will enable K2 to pull in all the categories. Click Save. This particular module, has many functions and you can set up a new module to use any of the great tools built into it. Next you will want to add some tags to articles. As I said at the beginning of this article, you have two different ways to do this. You may add them to the article or you may add them to the Tag Manager. Let's quickly review the latter method. Open K2 Dashboard. Click Tags. You may see a list of tags there. If you wish to delete them, simply check the ones you want to remove and click Delete in the upper right-hand corner. Otherwise just leave them. Click New which will open the Details box. Fill in the tag; make sure it's published and click Save. This is an example of a filled out tag box (before save). Adding Tags on the fly This model allows you to tag the content as soon as you create it. If there are tags available, already such as those from the previous step, then you can add them. Open K2 Dashboard. Click Items. Select an item or click New to create an item. The field Tags will be blank, you can start to type in a field, such as K2 Content Creation Kit (as shown in the preceding screenshot). If it exists, then it will be available to be able to click and add. If there are no tags available, then simply type one in and click Return or add a comma. Here is an example item with tags. Here we have four tags, Security x, PHP x, Joomla x, K2 Content Creation Kit x. Any item (article) that has these tags will be easily found by both users and search bots. Let's see how our Tag Cloud looks now: You probably notice the changes, especially the addition of the new tag K2 Content Creation Kit. Clicking on that tag will yield two articles, and clicking on the Security tag yields three. Search engines can follow these links to better categorize your site. Users can get a sense of what is more important in terms of content from your site and it helps them navigate. Closing on this, I strongly suggest you spend time picking tags that are important on your site and is relevant to the purpose of it.
Read more
  • 0
  • 0
  • 3069
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 €14.99/month. Cancel anytime
article-image-php-5-social-networking-implementing-public-messages
Packt
26 Oct 2010
7 min read
Save for later

PHP 5 Social Networking: Implementing Public Messages

Packt
26 Oct 2010
7 min read
PHP 5 Social Networking Create a powerful and dynamic Social Networking website in PHP by building a flexible framework   Build a flexible Social Networking framework using PHP which can be extended to fit the needs of any Social Networking site Develop a suitable structure for our framework, with MVC to structure the architecture and a Registry to store core Objects Allow users to connect and communicate with each other using communication with friends list, flexible user profiles, messages, discussions, and much more Plan marketing and scaling strategies, to entice more users and ensure the site can cope with the demand Packed with real-world code and clear explanation, this book uses an ongoing case study for creating a Social Networking framework Throughout the course of this article we will be using a social networking site for keepers of pet dinosaurs (of course nobody owns a real pet dinosaur, but for the sake of this article, let's pretend!), which we will call DinoSpace. Public messages The status stream fully supports public messages and streaming them to the Dino Space members. What we don't yet have, however, is support for users to post messages on the profiles of other users, so, let's add that in now. Controller A user should only be able to post a message on another user's profile if they are connected. The post message form should only be displayed if the users are connected. Similarly, a public message post should only be processed if the two users are connected. The controller also needs to display messages that have been posted on a user's profile too. Displaying profile messages If we look at our Profilestatusescontroller (controllers/profile/ profilestatusescontroller.php), in the listRecentStatuses method, we have our query for listing recent profile statuses: $sql = "SELECT t.type_reference, t.type_name, s.*, p.name as poster_name FROM statuses s, status_types t, profile p WHERE t.ID=s.type AND p.user_id=s.poster AND p.user_id={$user} ORDER BY s.ID DESC LIMIT 20"; At the moment, this query pulls in any posts on a user's profile by the user whose profile it is. If that user has made a post on someone else's profile, the message instead shows on the user's own profile, which we don't want. We need to change this to pull in the profiles table twice, once for the user who made the post, and again for the user whose profile is being viewed. We will also want to only pull in posts made on the user's profile, and not posts made by the user on another user's profile (though this is something we can expand on in the future, perhaps to indicate that a user has made a post on the profile of another user). The following query should meet our requirements nicely: $sql = "SELECT t.type_reference, t.type_name, s.*, pa.name as poster_name FROM statuses s, status_types t, profile p, profile pa WHERE t.ID=s.type AND p.user_id=s.profile AND pa.user_id=s.poster AND p.user_id={$user} ORDER BY s.ID DESC LIMIT 20"; Now, if we view a user's profile, we see their own status updates, and messages posted on their profile by other users, as shown in the following screenshot: Displaying the post message box The listRecentStatuses method we were just editing is the method we need to edit to display the post message box. This box should only be displayed if the user is logged in, and is connected to the user. If the user is viewing their own profile, then they should see a box to update their own status: // post status / public message box if( $this->registry->getObject('authenticate')->isLoggedIn() == true ) { $loggedInUser = $this->registry->getObject('authenticate')- >getUser()->getUserID(); If the logged in user is viewing their own profile, then we add the update template to the view, so they can update their status: if( $loggedInUser == $user ) { $this->registry->getObject('template')->addTemplateBit('status_ update', 'profile/statuses/update.tpl.php' ); } else { If the user isn't viewing their own profile, but is logged in, we get any connections the user has: require_once( FRAMEWORK_PATH . 'models/relationships.php' ); $relationships = new Relationships( $this->registry ); $connections = $relationships->getNetwork( $user, false ); if( in_array( $loggedInUser, $connections ) ) { If the user is connected to the user whose profile they are viewing, then we allow them to post a message on the users profile with the post template: $this->registry->getObject('template')->addTemplateBit( 'status_update', 'profile/statuses/post.tpl.php' ); } else { If the user isn't connected to the user, or isn't logged in, then we simply remove the template tag from the view so they don't see any update or post box on the page: $this->registry->getObject('template')->getPage()- >addTag( 'status_update', '' ); } } } else { $this->registry->getObject('template')->getPage()- >addTag( 'status_update', '' ); } Now, we need to process status updates and profile posts, and create the templates that make up the final aspect of our view. Process a new message The same logic that we used to determine whether the user should see a post form is what we need to use to determine if we should process a status update, or public message submission. Status model To save the status update or public profile post in the database, we will need a status model; as with our previous models, this simply needs to represent the fields from the database, with setter methods for these fields, and a save method to insert a new record into the database. In the future, we may wish to extend this to pull in statuses from the database, and save changes to them, as well as deleting statuses, perhaps if the owner of the message or the owner of the profile the message was posted on wishes to edit or delete it. The following is suitable code for our status model (models/status.php): <?php /** * Status model */ class Status { /** * The registry object */ private $registry; /** * Statuses ID */ private $id; /** * Poster of the status update / profile message */ private $poster; /** * The profile the status update / profile message was posted on */ sprivate $profile; /** * Type of status */ private $type; /** * The update / profile message itself */ private $update; /** * Reference for the type of status */ private $typeReference = 'update'; /** * Constructor * @param Registry $registry the registry object * @param int $id ID of the status update / profile message * @return void */ public function __construct( Registry $registry, $id=0 ) { $this->registry = $registry; $this->id = 0; } /** * Set the poster of the status / profile message * @param int $poster the id of the poster * @return void */ public function setPoster( $poster ) { $this->poster = $poster; } /** * Set the profile that the message / status is posted on * @param int $profile the profile ID * @return void */ public function setProfile( $profile ) { $this->profile = $profile; } /** * Set the status / profile message itself * @param String $status * @return void */ public function setStatus( $status ) { $this->status = $status; } /** * Set the type of status / profile message * @param int $type * @return void */ public function setType( $type ) { $this->type = $type; } /** * Set the type reference, so we can get the type ID from the database * @param String $typeReference the reference of the type * @return void */ public function setTypeReference( $typeReference ) { $this->type = $typeReference; } /** * Generate the type of status based of the type reference * @return void */ public function generateType() { $sql = "SELECT * FROM status_types WHERE type_reference='{$this->typeReference}'"; $this->registry->getObject('db')->executeQuery( $sql ); $data = $this->registry->getObject('db')->getRows(); $this->type = $data['ID']; } /** * Save the status / profile message * @return void */ public function save() { if( $this->id == 0 ) { $insert = array(); $insert['update'] = $this->status; $insert['type'] = $this->type; $insert['poster'] = $this->poster; $insert['profile'] = $this->profile; $this->registry->getObject('db')- >insertRecords( 'statuses', $insert ); $this->id = $this->registry->getObject('db')->lastInsertID(); } } } ?> Now that we have some functionality to easily insert the status into the database, we need to update our profile controller to process the new status update.
Read more
  • 0
  • 0
  • 2348

article-image-php-5-social-networking-private-messages
Packt
26 Oct 2010
7 min read
Save for later

PHP 5 Social Networking: Private Messages

Packt
26 Oct 2010
7 min read
PHP 5 Social Networking We obviously need to keep private messages separate from the rest of the site, and ensure that they are only accessible to the sender and the receiver. While we could alter the public messages feature developed earlier, this would raise a few issues, such as being more difficult to tell whether the message being sent or read was private, and when using the Internet in a public area, the message would be shown on the area of the social network the user would most likely be visiting, which isn't ideal for private information. Because private messages will be separate from statuses, and won't need to make use of other media types to make them more interesting (though, we could set them up to make use of other media if we wanted), it makes sense for us to also use separate database tables and models for this feature. Database Our database needs provisions for the sender of the message, the recipient of the message, the subject of the message, and of course the message itself. We should also provide for if the message has been read, when the message was sent, and an ID for the message. The following illustrates a suitable structure for a messages table in our database:   Field Type Description ID Integer, Autoincrement, Primary Key Reference ID for the message Sender Integer The sender of the message Recipient Integer The recipient of the message Subject Varchar The subject the message relates to Sent Timestamp When the message was sent Message Longtext The contents of the message itself Read Boolean Indicates whether the message has been read or not More than one recipient? This database structure, and the code that follows, only supports one recipient per message. Our users might want to send to more than one recipient—feel free to add this functionality if you wish. Message model As with the majority of our database access, we require a model (models/message. php) to create, update, and retrieve message-related data from the database and encapsulate it within itself. It would also be helpful if the model pulled in a little more information from the database, including: A more user friendly representation of the date (we can get this via the MySQL DATE_FORMAT function) The name of the sender, by joining the messages table to the profile table The name of the recipient, by joining the messages table to the profile table again The first part of our model simply defines the class variables: <?php /** * Private message class */ class Message { /** * The registry object */ private $registry; /** * ID of the message */ private $id=0; /** * ID of the sender */ private $sender; /** * Name of the sender */ private $senderName; /** * ID of the recipient */ private $recipient; /** * Name of the recipient */ private $recipientName; /** * Subject of the message */ private $subject; /** * When the message was sent (TIMESTAMP) */ private $sent; /** * User readable, friendly format of the time the message was sent */ private $sentFriendlyTime; /** * Has the message been read */ private $read=0; /** * The message content itself */ private $message; The constructor takes the registry and ID of the message as parameters, if the ID has been defined, then it queries the database and sets the class variables. The database query here also formats a copy of the date into a friendlier format, and looks up the names of the sender and recipient of the message: /** * Message constructor * @param Registry $registry the registry object * @param int $id the ID of the message * @return void */ public function __construct( Registry $registry, $id=0 ) { $this->registry = $registry; $this->id = $id; if( $this->id > 0 ) { $sql = "SELECT m.*, DATE_FORMAT(m.sent, '%D %M %Y') as sent_friendly, psender.name as sender_name, precipient.name as recipient_name FROM messages m, profile psender, profile precipient WHERE precipient.user_id=m.recipient AND psender.user_id=m.sender AND m.ID=" . $this->id; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->numRows() > 0 ) { $data = $this->registry->getObject('db')->getRows(); $this->sender = $data['sender']; $this->recipient = $data['recipient']; $this->sent = $data['sent']; $this->read = $data['read']; $this->subject = $data['subject']; $this->message = $data['message']; $this->sentFriendlyTime = $data['sent_friendly']; $this->senderName = $data['sender_name']; $this->recipientName = $data['recipient_name']; } else { $this->id = 0; } } } Next, we have setter methods for most of the class variables: /** * Set the sender of the message * @param int $sender * @return void */ public function setSender( $sender ) { $this->sender = $sender; } /** * Set the recipient of the message * @param int $recipient * @return void */ public function setRecipient( $recipient ) { $this->recipient = $recipient; } /** * Set the subject of the message * @param String $subject * @return void */ public function setSubject( $subject ) { $this->subject = $subject; } /** * Set if the message has been read * @param boolean $read * @return void */ public function setRead( $read ) { $this->read = $read; } /** * Set the message itself * @param String $message * @return void */ public function setMessage( $message ) { $this->message = $message; } The save method takes the class variables that directly relate to the messages table in the database and either inserts them as a new record, or updates the existing record: /** * Save the message into the database * @return void */ public function save() { if( $this->id > 0 ) { $update = array(); $update['sender'] = $this->sender; $update['recipient'] = $this->recipient; $update['read'] = $this->read; $update['subject'] = $this->subject; $update['message'] = $this->message; $this->registry->getObject('db')->updateRecords( 'messages', $update, 'ID=' . $this->id ); } else { $insert = array(); $insert['sender'] = $this->sender; $insert['recipient'] = $this->recipient; $insert['read'] = $this->read; $insert['subject'] = $this->subject; $insert['message'] = $this->message; $this->registry->getObject('db')->insertRecords( 'messages', $insert ); $this->id = $this->registry->getObject('db')->lastInsertID(); } } One getter method that we need, is to return the user ID of the recipient, so we can check that the currently logged in user has permission to read the message: /** * Get the recipient of the message * @return int */ public function getRecipient() { return $this->recipient; } We should also provide a method to delete the message from the database, should the user wish to delete a message: /** * Delete the current message * @return boolean */ public function delete() { $sql = "DELETE FROM messages WHERE ID=" . $this->id; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->affectedRows() > 0 ) { $this->id =0; return true; } else { return false; } } Finally, we have a toTags method, which converts all of the non-object and non-array variables into template tags, so when we create a view message method in the controller, we simply need to construct the message object and call the toTags method: /** * Convert the message data to template tags * @param String $prefix prefix for the template tags * @return void */ public function toTags( $prefix='' ) { foreach( $this as $field => $data ) { if( ! is_object( $data ) && ! is_array( $data ) ) { $this->registry->getObject('template')->getPage()->addTag( $prefix.$field, $data ); } } } } ?> Messages model Similar to how we have a model for representing a single relationship and another for representing a number of relationships, we also need a model to represent a number of messages within the site. This is to handle the lookup of a user's private message inbox. <?php /** * Messages model */ class Messages { /** * Messages constructor * @param Registry $registry * @return void */ public function __construct( Registry $registry ) { $this->registry = $registry; } /** * Get a users inbox * @param int $user the user * @return int the cache of messages */ public function getInbox( $user ) { $sql = "SELECT IF(m.read=0,'unread','read') as read_style, m.subject, m.ID, m.sender, m.recipient, DATE_FORMAT(m.sent, '%D %M %Y') as sent_friendly, psender.name as sender_name FROM messages m, profile psender WHERE psender.user_id=m.sender AND m.recipient=" . $user . " ORDER BY m.ID DESC"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } } ?>
Read more
  • 0
  • 0
  • 2647

article-image-joomla-15-top-extensions-adding-booking-system-events
Packt
25 Oct 2010
4 min read
Save for later

Joomla! 1.5 Top Extensions: Adding a Booking System for Events

Packt
25 Oct 2010
4 min read
Joomla! 1.5 Top Extensions Cookbook Over 80 great recipes for taking control of Joomla! Extensions Set up and use the best extensions available for Joomla! Covers extensions for just about every use of Joomla! Packed with recipes to help you get the most of the Joomla! extensions Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible Getting ready... The Seminar for Joomla! component allows visitors to register for events. Download this component from http://seminar.vollmar.ws/downloads/com_Seminar_V1.3.0.zip, and install it from the Extensions | Install/Uninstall screen in the Joomla! administration panel. How to do it... Once installed, follow these steps to allow registration for events: From the Joomla! administration panel, select Components | Seminar. It shows the Events screen, listing the available events. To create event categories, click on Categories and then click on New. This shows you the Category: [New] screen. On the Category: [New] screen, type in the Title and Alias, and select Yes in the Published radio box. Then select the Access Level, Image, and Image Position. Enter a description for the category. Click on Save in the toolbar. Repeat this step to add as many categories as you need. Click on Events and then click on New. It will show you the New Event screen. Type the Title of the event. Then select Begin, End, Closing Date, and the time of the event. Select Yes in the Display field if you want to show this information. Type a brief description of the event, and the place of the event. Select an organizer from the Organiser drop-down list. Then type the maximum number of participants in the Max. Particip. field. Also, select what to do when the number of participants exceeds this number. When this is done, click on Additional Settings. This shows you the Additional Settings screen. In the Additional Settings section, you can add an additional description. In the Description box, add descriptions to particular groups of visitors. The syntax to add messages for different groups is shown above the text box. Select an image for the event overview. Then type the tutor's name, target group, and the fees per person. Then click on General Input Fields. This will show the following screen: In the General Input Fields section, you can include additional fields. To add additional fields, follow the syntax provided. When this is done, click on Files. This shows the following screen for file upload. Click on the Browse button and select the file to upload. Type a description of the file and select the group that can view it. When this is done, click on the Save button in the toolbar. Select Menus | Main Menu, and then click on New. This will show you the Menu Item: [New] wizard. In the Select Menu Item Type section, select Seminar and provide a title for the menu item on the next screen. Then save the menu item. Preview the site's frontend, as a user logged in to the frontend, and click on the menu item for the seminar. This will display the following screen showing your added event. The overview of the event shows the overview image, event title, category, reservation information, and an indicator for the booking status. Click on the event title, it will show you the event details, as shown in the following screenshot: Select the spaces to be booked. Then type your Name and Email address and click on the Book button. This books your space for the event. You can view your booking by clicking the My Bookings tab, as shown in the following screenshot. Note that your participation status is indicated through a color-coded indicator. There's more... Most of the features of Seminar for the Joomla! component can be configured from the Settings screen. For example, you can configure who can book events, what happens when booking exceeds the number of seats, who can rate the events from the frontend, which folder will store images of the events, the maximum file upload size, the file extensions allowed for uploads, and so on. Summary This article showed you how to allow visitors to register for an event. Further resources on this subject: Adding an Event Calendar to your Joomla! Site using JEvents Showing your Google calendar on your Joomla! site using GCalendar Joomla! 1.5 Top Extensions for Using Languages Manually Translating Your Joomla! Site's Content into Your Desired Language
Read more
  • 0
  • 0
  • 1694

article-image-php-5-social-networking-integrating-media-profile-posts
Packt
22 Oct 2010
13 min read
Save for later

PHP 5 Social Networking: Integrating Media in Profile Posts

Packt
22 Oct 2010
13 min read
Since different status types will use different status tables, we should use a left join to connect the tables, so we can keep just a single query to look up the statuses. It also pulls in the extra information when it is required. Let's get started with extending our profiles and the status stream! Changes to the view Since all of the media types we are going to support require at least one additional database field in a table that extends the statuses table, we are going to need to display any additional fields on the post status form. The standard type of status doesn't require additional fields, and new media types that we haven't discussed, which we may wish to support in the future, may require more than one additional field. To support a varying number of additional fields depending on the type, we could use some JavaScript (in this case, we will use the jQuery framework) to change the form depending on the context of the status. Beneath the main status box, we can add radio buttons for each of the status types, and depending on the one the user selects, the JavaScript can show or hide the additional fields, making the form more relevant. Template Our update status template needs a few changes: We need to set the enctype on the form, so that we can upload files (for posting images) We need radio buttons for the new types of statuses We need additional fields for those statuses The changes are highlighted in the following code segment: <p>Tell your network what you are up to</p> <form action="profile/statuses/{profile_user_id}" method="post" enctype="multipart/form-data"> <textarea id="status" name="status"></textarea> <br /> <input type="radio" name="status_type" id="status_checker_update" class="status_checker" value="update" />Update <input type="radio" name="status_type" id="status_checker_video" class="status_checker" value="video" />Video <input type="radio" name="status_type" id="status_checker_image" class="status_checker" value="image" />Image <input type="radio" name="status_type" id="status_checker_link" class="status_checker" value="link" />Link <br /> <div class="video_input extra_field"> <label for="video_url" class="">YouTube URL</label> <input type="text" id="" name="video_url" class="" /><br /> </div> <div class="image_input extra_field"> <label for="image_file" class="">Upload image</label> <input type="file" id="" name="image_file" class="" /><br /> </div> <div class="link_input extra_field"> <label for="link_url" class="">Link</label> <input type="text" id="" name="link_url" class="" /><br /> <label for="link_description" class="">Description</label> <input type="text" id="" name="link_description" class="" /><br /> </div> <input type="submit" id="updatestatus" name="updatestatus" value="Update" /> </form> These changes also need to be made to the post template, for posting on another user's profile. jQuery to enhance the user experience For accessibility purposes, we need this form to function regardless of whether the user has JavaScript enabled on their browser. To that end, we should use JavaScript to hide the unused form elements. So, even if the user has JavaScript disabled, they can still use all aspects of the form. We can then use JavaScript to enhance the user experience, toggling which aspects of the form are hidden or shown. <script type="text/javascript"> $(function() { First, we hide all of the extended status fields. $('.extra_field').hide(); $("input[name='status_type']").change(function(){ When the user changes the type of status, we hide all of the extended fields. $('.extra_field').hide(); We then show the fields directly related to the status type they have chosen. $('.'+ $("input[name='status_type']:checked").val() + '_input').show(); }); }); </script> View in action If we now take a look at our status updates page for our profile, we have some radio buttons that we can use to toggle elements of the form. Images To process images as a new status type, we will need a new database table and a new model to extend from the main status model. We will also need some new views, and to change the profile and status stream controllers (though we will make those changes after adding the three new status types). Database table The database table for images simply needs two fields:     Field Type Description ID Integer, Primary key To relate to the main statuses table Image Varchar The image filename These two fields will be connected to the statuses table via a left join, to bring in the image filename for statuses that are images. Model The model needs to extend our statuses model, providing setters for any new fields, call the parent constructor, call the parent setTypeReference method to inform that it is an image, call the parent save method to save the status, and then insert a new record into the image status table with the image information. Class, variable, and constructor Firstly, we define the class as an extension of the status class. We then define a variable for the image, and construct the object. The constructor calls the parent setTypeReference method to ensure it generates the correct type ID for an image, and then calls the parent constructor so it too has reference to the registry object. This file is saved as /models/imagestatus.php. <?php /** * Image status object * extends the base status object */ class Imagestatus extends status { private $image; /** * Constructor * @param Registry $registry * @param int $id * @return void */ public function __construct( Registry $registry, $id = 0 ) { $this->registry = $registry; parent::setTypeReference('image'); parent::__construct( $this->registry, $id ); } To call a method from an object's parent class, we use the parent keyword, followed by the scope resolution operator, followed by the method we wish to call. Processing the image upload When dealing with image uploads, resizing, and saving, there are different PHP functions that should be used depending on the type of the image. To make this easier and to provide a centralized place for dealing with image uploads and other image-related tasks, we should create a library file (lib/images/imagemanager. class.php) to make this easier. Let's discuss what an image manager library file should do to make our lives easier: Process uploading of an image from $_POST data Verify the type of file and the file extension Process images from the file system so that we can modify them Display an image to the browser Resize an image Rescale an image by resizing either the x or y co-ordinate, and scaling the other co-ordinate proportionally Get image information such as size and name Save the changes to the image The following is the code required to perform the above-mentioned tasks: <?php /** * Image manager class * @author Michael Peacock */ class Imagemanager { /** * Type of the image */ private $type = ''; /** * Extensions that the user can upload */ private $uploadExtentions = array( 'png', 'jpg', 'jpeg', 'gif' ); /** * Mime types of files the user can upload */ private $uploadTypes = array( 'image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png' ); /** * The image itself */ private $image; /** * The image name */ private $name; public function __construct(){} We need a method to load a local image, so that we can work with images saved on the servers file system. /** * Load image from local file system * @param String $filepath * @return void */ public function loadFromFile( $filepath ) { Based on the path to the image, we can get information on the image including the type of image (getimagesize gives us an array of information on the image; the second element in the array is the type). $info = getimagesize( $filepath ); $this->type = $info[2]; We can then compare the image type to various PHP constants, and depending on the image type (JPEG, GIF, or PNG) we use the appropriate imagecreatefrom function. if( $this->type == IMAGETYPE_JPEG ) { $this->image = imagecreatefromjpeg($filepath); } elseif( $this->type == IMAGETYPE_GIF ) { $this->image = imagecreatefromgif($filepath); } elseif( $this->type == IMAGETYPE_PNG ) { $this->image = imagecreatefrompng($filepath); } } We require a couple of getter methods to return the height or width of the image. /** * Get the image width * @return int */ public function getWidth() { return imagesx($this->image); } /** * Get the height of the image * @return int */ public function getHeight() { return imagesy($this->image); } We use a simple resize method that resizes the image to the dimensions we request. /** * Resize the image * @param int $x width * @param int $y height * @return void */ public function resize( $x, $y ) { $new = imagecreatetruecolor($x, $y); imagecopyresampled($new, $this->image, 0, 0, 0, 0, $x, $y, $this->getWidth(), $this->getHeight()); $this->image = $new; } Here we use a scaling function that takes a height parameter to resize to and scales the width accordingly. /** * Resize the image, scaling the width, based on a new height * @param int $height * @return void */ public function resizeScaleWidth( $height ) { $width = $this->getWidth() * ( $height / $this->getHeight() ); $this->resize( $width, $height ); } Similar to the above method, this method takes a width parameter, resizes the width, and rescales the height based on the width. /** * Resize the image, scaling the height, based on a new width * @param int $width * @return void */ public function resizeScaleHeight( $width ) { $height = $this->getHeight() * ( $width / $this->getWidth() ); $this->resize( $width, $height ); } The following is another scaling function, this time to rescale the image to a percentage of its current size: /** * Scale an image * @param int $percentage * @return void */ public function scale( $percentage ) { $width = $this->getWidth() * $percentage / 100; $height = $this->getheight() * $percentage / 100; $this->resize( $width, $height ); } To output the image to the browser from PHP, we need to check the type of the image, set the appropriate header based off the type, and then use the appropriate image function to render the image. After calling this method, we need to call exit() to ensure the image is displayed correctly. /** * Display the image to the browser - called before output is sent, exit() should be called straight after. * @return void */ public function display() { if( $this->type == IMAGETYPE_JPEG ) { $type = 'image/jpeg'; } elseif( $this->type == IMAGETYPE_GIF ) { $type = 'image/gif'; } elseif( $this->type == IMAGETYPE_PNG ) { $type = 'image/png'; } header('Content-Type: ' . $type ); if( $this->type == IMAGETYPE_JPEG ) { imagejpeg( $this->image ); } elseif( $this->type == IMAGETYPE_GIF ) { imagegif( $this->image ); } elseif( $this->type == IMAGETYPE_PNG ) { imagepng( $this->image ); } } To load an image from $_POST data, we need to know the post field the image is being sent through, the directory we wish to place the image in, and any additional prefix we may wish to add to the image's name (to prevent conflicts with images with the same name). /** * Load image from postdata * @param String $postfield the field the image was uploaded via * @param String $moveto the location for the upload * @param String $name_prefix a prefix for the filename * @return boolean */ public function loadFromPost( $postfield, $moveto, $name_prefix='' ) { Before doing anything, we should check that the file requested is actually a file that has been uploaded (and that this isn't a malicious user trying to access other files). if( is_uploaded_file( $_FILES[ $postfield ]['tmp_name'] ) ) { $i = strrpos( $_FILES[ $postfield ]['name'], '.'); if (! $i ) { //'no extention'; return false; } else { We then check that the extension of the file is in our allowed extensions array. $l = strlen( $_FILES[ $postfield ]['name'] ) - $i; $ext = strtolower ( substr( $_FILES[ $postfield ]['name'], $i+1, $l ) ); if( in_array( $ext, $this->uploadExtentions ) ) { Next, we check if the file type is an allowed file type. if( in_array( $_FILES[ $postfield ]['type'], $this->uploadTypes ) ) { Then, we move the file, as it has already been uploaded to our server's temp folder, to our own uploads directory and load it into our image manager class for any further processing we wish to make. $name = str_replace( ' ', '', $_FILES[ $postfield ]['name'] ); $this->name = $name_prefix . $name; $path = $moveto . $name_prefix.$name; move_uploaded_file( $_FILES[ $postfield ]['tmp_name'] , $path ); $this->loadFromFile( $path ); return true; } else { // 'invalid type'; return false; } } else { // 'invalid extention'; return false; } } } else { // 'not uploaded file'; return false; } } The following getter method is used to return the name of the image we are working with: /** * Get the image name * @return String */ public function getName() { return $this->name; } Finally, we have our save method, which again must detect the type of image, to work out which function to use. /** * Save changes to an image e.g. after resize * @param String $location location of image * @param String $type type of the image * @param int $quality image quality /100 * @return void */ public function save( $location, $type='', $quality=100 ) { $type = ( $type == '' ) ? $this->type : $type; if( $type == IMAGETYPE_JPEG ) { imagejpeg( $this->image, $location, $quality); } elseif( $type == IMAGETYPE_GIF ) { imagegif( $this->image, $location ); } elseif( $type == IMAGETYPE_PNG ) { imagepng( $this->image, $location ); } } } ?> Using the image manager library to process the file upload Now that we have a simple, centralized way of processing file uploads and resizing them, we can process the image the user is trying to upload as their extended status. /** * Process an image upload and set the image * @param String $postfield the $_POST field the image was uploaded through * @return boolean */ public function processImage( $postfield ) { require_once( FRAMEWORK_PATH . 'lib/images/imagemanager.class.php' ); $im = new Imagemanager(); $prefix = time() . '_'; if( $im->loadFromPost( $postfield, $this->registry- >getSetting('upload_path') . 'statusimages/', $prefix ) ) { $im->resizeScaleWidth( 150 ); $im->save( $this->registry->getSetting('upload_path') . 'statusimages/' . $im->getName() ); $this->image = $im->getName(); return true; } else { return false; } } Saving the status This leaves us with the final method for saving the status. This calls the parent object's save method to create the record in the statuses table. Then it gets the ID, and inserts a new record into the images table with this ID as the ID. /** * Save the image status * @return void */ public function save() { // save the parent object and thus the status table parent::save(); // grab the newly inserted status ID $id = $this->getID(); // insert into the images status table, using the same ID $extended = array(); $extended['id'] = $id; $extended['image'] = $this->image; $this->registry->getObject('db')->insertRecords( 'statuses_images', $extended ); } } ?>
Read more
  • 0
  • 0
  • 1959
article-image-showing-your-google-calendar-your-joomla-site-using-gcalendar
Packt
21 Oct 2010
3 min read
Save for later

Showing your Google calendar on your Joomla! site using GCalendar

Packt
21 Oct 2010
3 min read
To use a Google calendar with GCalendar, you must make the Google Calendar publicly available. To do so, select the Make this calendar public checkbox on the Share this calendar tab on the Settings screen. Getting ready... The GCalendar extension allows you to display your Google calendar inside the Joomla! site. Visit http://g4j.laoneo.net/content/extensions/download/cat_view/20-joomla-15x/21-gcalendar.html and download the latest version of the GCalendar suite. Once downloaded, extract the ZIP package and you will get an installation file for one component, three modules, and two plugins. Install these from the Extensions | Install/Uninstall screen. How to do it... After installation, follow these steps: From the Joomla! administration panel, select Components | GCalendar. This shows you the Google calendar manager screen. Click on the Tools link of the Google calendar manager screen, and then click on the System check link. This checks the system requirements and connectivity with Google and shows you the results. Resolve any issue raised by a system check. Then click on the GCalendars link, followed by clicking on Please login to connect to Google data. You will see the Google authorization page. Click on the Grant access button on the Google accounts page. You will see the list of calendars under Google Calendar. If you are not logged in to Google already, the Google Login page will be shown. Enter the username and password for your Google account (or create one if you don't have an account) and click on the Sign In button. Select the calendars you want to use on your Joomla! site, and click on the Add button in the toolbar. The calendars are added and you will see them in the list. Now select Menus | Main Menu, and click on the New button on the Menu Item Manager: [mainmenu] screen. This will show you the Menu Item: [New] screen. Select Internal Link | GCalendar | GCalendar. It will show the Menu Item: [New] screen, as shown in the following screenshot: Type a Title for the menu, and select Yes in the Published field. From the Parameters (Basic) section, select a calendar, select the default view, the day the week starts on, and then the date format. You can also add text to display before and after the calendar. Then click on the Save button in the toolbar. Preview the site's frontend and click on the menu item. This shows the Google calendar. As you see, you can change the view of the calendar by clicking on any of the view icons shown above the calendar. You can also go to a specific date or month. Summary Google Calendar is gaining popularity. If you are a user of Google Calendar, you already know how flexible it is. In this article, you saw how to display your Google calendar on your Joomla! site. In the next article we will add a Booking System for Events. Further resources on this subject: Adding an Event Calendar to your Joomla! Site using JEvents Joomla! 1.5 Top Extensions: Adding a Booking System for Events Joomla! 1.5 Top Extensions for Using Languages Manually Translating Your Joomla! Site's Content into Your Desired Language
Read more
  • 0
  • 0
  • 3585

article-image-adding-event-calendar-your-joomla-site-using-jevents
Packt
21 Oct 2010
2 min read
Save for later

Adding an Event Calendar to your Joomla! Site using JEvents

Packt
21 Oct 2010
2 min read
Getting ready... There are many extensions to add event calendars to Joomla!. However, JEvents is the most feature-rich and popular extension. Download this extension from http://www.jevents.net/jevents-download and install it from the Extensions | Install/Uninstall screen. How to do it... After installing JEvents, follow these steps to add the calendar: From the Joomla! administration panel, select Components | JEvents. This will show you the JEvents:: Control Panel screen. Click on the Manage Categories icon in the Control Panel screen. This will show you the Categories screen, listing all the available categories, if any. Click on the New button in the toolbar. It will show you a form similar to that in the following screenshot: Enter a Title, select the parent category (if any), then select Access Level and Administrator, select Yes in Published field, and type a brief description of the category. From the Event Colour field, choose the color for the events in this category. Then click on the Save icon in the toolbar. Repeat the step to create another category. To go back to the Control Panel page, click on the CPanel icon on the Categories screen. Then click on the Manage Calendars icon in the Control Panel screen. That shows the Calendars screen. Click on the New button. This shows you a form similar to the one in the following screenshot: Type a Unique Identifier (name) for the calendar, select the default category and Access Level, select No for the Is Default field, and click on Create Calendar from Scratch. This creates a new calendar. Go back to the Control Panel page, and click on the Manage Events icon. This will shows you the Events screen. Click on the New button in the toolbar, and you will get the Edit Event screen. On the Edit Event screen, first select a calendar and then type the subject of the event. Then select a category, a color for the event, and the access level. In the Activity field briefly describe the activity, and then fill in the Location, Contact, and Extra Info fields. Then click on the Calendar tab.
Read more
  • 0
  • 0
  • 2515

article-image-displaying-data-grids-ext-js
Packt
15 Oct 2010
9 min read
Save for later

Displaying Data with Grids in Ext JS

Packt
15 Oct 2010
9 min read
What is a grid? Ext JS grids are similar to a spreadsheet; there are two main parts to each spreadsheet: Columns Rows Here our columns are Title, Released, Genre, and Price. Each of the rows contains movies such as The Big Lebowski, Super Troopers, and so on. The rows are really our data; each row in the grid represents a record of data held in a data store. GridPanel is databound Like many Ext JS Components, the GridPanel class is bound to a data store which provides it with the data shown in the user interface. So the first step in creating our GridPanel is creating and loading a store. The data store in Ext JS gives us a consistent way of reading different data formats such as XML and JSON, and using this data in a consistent way throughout all of the Ext JS widgets. Regardless of whether this data is originally provided in JSON, XML, an array, or even a custom data type of our own, it's all accessed in the same way thanks to the consistency of the data store and how it uses a separate reader class which interprets the raw data. Instead of using a pre-configured class, we will explicitly define the classes used to define and load a store. The record definition We first need to define the fields which a Record contains. A Record is a single row of data and we need to define the field names, which we want to be read into our store. We define the data type for each field, and, if necessary, we define how to convert from the raw data into the field's desired data type. What we will be creating is a new class. We actually create a constructor which will be used by Ext JS to create records for the store. As the 'create' method creates a constructor, we reference the resulting function with a capitalized variable name, as per standard CamelCase syntax: var Movie = Ext.data.Record.create([ 'id', 'coverthumb', 'title', 'director', 'runtime', {name: 'released', type: 'date', dateFormat: 'Y-m-d'}, 'genre', 'tagline', {name: 'price', type: 'float'}, {name: 'available', type: 'bool'} ]); Each element in the passed array defines a field within the record. If an item is just a string, the string is used as the name of the field, and no data conversion is performed; the field's value will be whatever the Reader object (which we will learn more about soon) finds in the raw data. If data conversion is required, then a field definition in the form of an object literal instead of a string may contain the following config options: Name: The name by which the field will be referenced. type: The data type in which the raw data item will be converted to when stored in the record. Values may be 'int', 'float', 'string', 'date', or 'bool'. dateFormat: If the type of data to be held in the field is a date type, then we need to specify a format string as used by the Date.parseDate function. Defining the data type can help to alleviate future problems, instead of having to deal with all string type data defining the data type, and lets us work with actual dates, Boolean values, and numbers. The following is a list of the built in data types:   Field type Description Information string String data   int Number Uses JavaScript's parseInt function float Floating point number Uses JavaScript's parseFloat function boolean True/False data   date Date data dateFormat config required to interpret incoming data. Now that the first step has been completed, and we have a simple Record definition in place, we can move on to the next step of configuring a Reader that is able to understand the raw data. The Reader A store may accept raw data in several different formats. Raw data rows may be in the form of a simple array of values, or an object with named properties referencing the values, or even an XML element in which the values are child nodes. We need to configure a store with a Reader object which knows how to extract data from the raw data that we are dealing with. There are three built in Reader classes in Ext JS. ArrayReader The ArrayReader class can create a record from an array of values. By default, values are read out of the raw array into a record's fields in the order that the fields were declared in the record definition we created. If fields are not declared in the same order that the values occur in the rows, the field's definition may contain a mapping config which specifies the array index from which we retrieve the field's value. JsonReader This JSONReader class is the most commonly used, and can create a record from raw JSON by decoding and reading the object's properties. By default, the field's name is used as the property name from which it takes the field's value. If a different property name is required, the field's definition may contain a mapping config which specifies the name of the property from which to retrieve the field's value. XmlReader An XMLReader class can create a record from an XML element by accessing child nodes of the element. By default, the field's name is used as the XPath mapping (not unlike HTML) from which to take the field's value. If a different mapping is required, the field's definition may contain a mapping config which specifies the mapping from which to retrieve the field's value. Loading our data store In our first attempt, we are going to create a grid that uses simple local array data stored in a JavaScript variable. The data we're using below in the movieData variable is taken from a very small movie database of some of my favorite movies. The data store needs two things: the data itself, and a description of the data—or what could be thought of as the fields. A reader will be used to read the data from the array, and this is where we define the fields of data contained in our array. The following code should be placed before the Ext JS OnReady function: var movieData = [ [ 1, "Office Space", "Mike Judge", 89, "1999-02-19", 1, "Work Sucks", "19.95", 1 ],[ 3, "Super Troopers", "Jay Chandrasekhar", 100, "2002-02-15", 1, "Altered State Police", "14.95", 1 ] //...more rows of data removed for readability...// ]; var store = new Ext.data.Store({ data: movieData, , reader: new Ext.data.ArrayReader({idIndex: 0}, Movie) }); If we view this code in a browser we would not see anything—that's because a data store is just a way of loading and keeping track of our data. The web browser's memory has our data in it. Now we need to configure the grid to display our data to the user. Displaying structured data with a GridPanel Displaying data in a grid requires several Ext JS classes to cooperate: A Store: A data store is a client-side analogue of a database table. It encapsulates a set of records, each of which contains a defined set of fields. A Record definition: This defines the fields (or "columns" in database terminology) which make up each record in the Store. Field name and datatype are defined here. A Reader which uses a Record definition to extract field values from a raw data object to create the records for a Store. A ColumnModel which specifies the details of each column, including the column header to display, and the name of the record field to be displayed for each column. A GridPanel: A panel subclass which provides the controller logic to bind the above classes together to generate the grid's user interface. If we were to display the data just as the store sees it now, we would end up with something like this: Now that is ugly—here's a breakdown of what's happening: The Released date has been type set properly as a date, and interpreted from the string value in our data. It's provided in a native JavaScript date format—luckily Ext JS has ways to make this look pretty. The Price column has been type set as a floating point number. Note that there is no need to specify the decimal precision. The Avail column has been interpreted as an actual Boolean value, even if the raw data was not an actual Boolean value. As you can see, it's quite useful to specify the type of data that is being read, and apply any special options that are needed so that we don't have to deal with converting data elsewhere in our code. Before we move on to displaying the data in our grid, we should take a look at how the convert config works, as it can come in quite useful. Converting data read into the store If we need to, we can convert data as it comes into the store, massage it, remove any quirky parts, or create new fields all together. This should not be used as a way to change the display of data; that part will be handled elsewhere. A common task might be to remove possible errors in the data when we load it, making sure it's in a consistent format for later actions. This can be done using a convert function, which is defined in the 'convert' config by providing a function, or reference to a function. In this case we are going to create a new field by using the data from another field and combining it with a few standard strings. var store = new Ext.data.Store({ data: movieData, reader: new Ext.data.ArrayReader({id:'id'}, [ 'id', 'title', 'director', {name: 'released', type: 'date', dateFormat: 'Y-m-d'}, 'genre', 'tagline', 'price', 'available', {name:'coverthumb',convert:function(v, rawData){ return 'images/'+rawData[0]+'m.jpg'; }} ]) }); This convert function when used in this manner will create a new field of data that looks like this: 'images/5m.jpg' We will use this new field of data shortly, so let's get a grid up and running.
Read more
  • 0
  • 0
  • 7972
article-image-creating-our-first-jquery-plugin
Packt
14 Oct 2010
7 min read
Save for later

Creating Our First jQuery Plugin

Packt
14 Oct 2010
7 min read
  jQuery Plugin Development Beginner's Guide A practical straightforward guide for creating your first jQuery plugin Utilize jQuery's plugin framework to create a wide range of useful jQuery plugins from scratch Understand development patterns and best practices and move up the ladder to master plugin development Discover the ins and outs of some of the most popular jQuery plugins in action A Beginner's Guide packed with examples and step-by-step instructions to quickly get your hands dirty in developing high quality jQuery plugins         Read more about this book       (For more resources on jQuery, see here.) Defining our own default plugin structure To make things easier to remember and apply, we are going to start off with the definition of what we will be referring to when speaking of the basic template that all the plugins we are going to develop should conform to. Actually, we have already had a quick look at it earlier in the previous chapter, but there's something more definitely worth saying. From now on, we will call the following code the default structure for our plugins. This is what we will promptly copy and paste into each file we're going to write a plugin into. jQuery.fn.PLUGINNAME = function() { return this.each(function() { // code });} Needless to say, the this.each loop iterates all of the matching elements. We return the jQuery object (this) to allow chaining. We extend the jQuery.fn object; all of the code will be put inside the function. Also: The file name of every plugin we're going to develop will bejquery.PLUGINNAME.js. For the moment, remember to always avoid referring to the jQuery object with the dollar sign ($), to prevent possible conflicts with other libraries. We'll get to using aliases very soon. All of the functions that we write to make our plugin work should be private and not accessible from outside, in an attempt to avoid cluttering and possible backwards incompatibility. If not from the very start, at least at the end, a user will be able to specify options to control the plugin behavior. Default options for the plugin will be publicly accessible to allow for easier customization with minimal code. The directory that the plugin resides in will also contain two other files, by default: index.html: This is our test page. jquery.js: This is the jQuery library that we need to make things work. Setting the basics for our first plugin As our first plugin, we might want to create something uncomplicated but somewhat impressive: what about something that, when the cursor is hovering over an element, substitutes the text contained with some words of our choice? Time for action – our first plugin, Part I Getting started in creating jQuery plugins in not difficult at all. For example, creating this simple plugin should help us in understanding how things actually work. Given that our plugin name is txtHover, create all the directories and files we need by default, and copy over the jquery.js file. Copy the default structure for our plugins to the plugin file and make sure the function is named accordingly. It should look like this: jQuery.fn.txtHover = function() { return this.each(function() { // code });}; Nothing's easier to do than change the text contained in some element. Inside the plugin function, write the following to let the trick happen: jQuery(this).text("Text changed"); To test this in action, we can modify the HTML document to look like this: <!DOCTYPE html><html><head> <script src="jquery.js"></script> <script src="jquery.txthover.js"></script> <script> $(document).ready(function() { $("p#one").txtHover(); }); </script></head><body> <p id="one">Some text.</p></body></html> Unfortunately, the result is neither fancy nor satisfactory—something we've experienced earlier too. But we're just getting started; we won't stop here this time! What just happened? The plugin is working correctly so far. When the page loads, the text is changed to what we had defined into the plugin code. However, there are a couple of things to pay attention to: The function text() from the jQuery API expects either one or no arguments to be passed: if there is no argument the function returns the current content of the selected element. The text string passed as an argument substitutes the element text otherwise. There are, however, some similarities with the html() function, which treats the text it operates on as if it were HTML code. That is, passing any tag to the html() function results in having the element possibly containing other elements after the operation (also, the same applies for getting HTML code from within the element), whereas the this function will just treat the HTML code as plain text and not affect any element hierarchy. The fact that the text cannot be changed, unless we directly modify the code of the plugin. Getting a step farther Despite the good realization, our plugin still misses the point. Our goal was to activate the text substitution whenever the mouse pointer hovered over the text to be replaced, whereas our current implementation does it right after the page is loaded. We put it inside the "document ready" statement, after all! Time for action – our first plugin, Part II: Hovering By adding little pieces of code one at a time, we can easily understand what we are going to do and which is the best layout for our plugin. Activating the plugin whenever the mouse pointer hovers over the selected elements is surely another little step that adds up to reach our final goal. Back to our plugin file, we have to change the code so that the whole mechanism activates when the hover event is triggered. jQuery provides a function called hover(), which we can use to achieve our objective: jQuery.fn.txtHover = function() { return this.each(function() { jQuery(this).hover(function() { jQuery(this).text("Mouse hovered"); }); });}; Now, on to testing. Once the mouse pointer hovers over the text, it is effectively replaced by our string. But even if the mouse is moved, the text doesn't revert to the original. In fact, looking at the hover documentation, we see the function can also take a second argument, that is, the pointer to a function to be executed when the mouse goes off the element. Our modified code will now look like the following: jQuery.fn.txtHover = function() { return this.each(function() { var oldTxt = jQuery(this).text(); jQuery(this).hover(function() { jQuery(this).text("Mouse hover"); }, function() { jQuery(this).text(oldTxt); }); });}; The result is somewhat better now: the text is changed when we leave the pointer on the paragraph, and is changed again to its original form once the pointer is moved away. What just happened? We might be a little more satisfied with this evolution of our plugin, even though it's far from complete. Its functioning is fairly straightforward: we have made use of a variable (oldTxt) to store the old content, and we then have proceeded to using two anonymous functions (function(){ }), passed as arguments to the hover() function, to handle the mouse hover event (write our string) and the mouse out event (text back to original). There's still something to do though: We have used far too many instances of $(this) in our code and, on a larger scale application, a lot of memory would be wasted this way. It will be incredibly better for performance to make up a variable and use it every time we refer to the element with $(this). The text cannot be changed, unless we directly modify the code of the plugin. Have a go hero – html () versus text () Read the documentation for the html() function. Create a plugin that, once the mouse pointer hovers over an element, displays the HTML code of its content. The content should then change back to normal once the mouse pointer is moved away from that space. What happens if the html() and text() functions are used one inside the other, that is, $(sel).text($(sel).html()) or $(sel).html($(sel).text())? Just play around a little bit.
Read more
  • 0
  • 0
  • 3756

article-image-marshalling-data-services-extdirect
Packt
14 Oct 2010
9 min read
Save for later

Marshalling Data Services with Ext.Direct

Packt
14 Oct 2010
9 min read
What is Direct? Part of the power of any client-side library is its ability to tap nearly any server-side technology. That said, with so many server-side options available there were many different implementations being written for accessing the data. Direct is a means of marshalling those server-side connections, creating a 'one-stop-shop' for handling your basic Create, Read, Update, and Delete actions against that remote data. Through some basic configuration, we can now easily create entire server-side API's that we may programmatically expose to our Ext JS applications. In the process, we end up with one set of consistent, predefined methods for managing that data access. Building server-side stacks There are several examples of server-side stacks already available for Ext JS, directly from their site's Direct information. These are examples, showing you how you might use Direct with a particular server-side technology, but Ext provides us with a specification so that we might write our own. Current stack examples are available for: PHP .NET Java ColdFusion Ruby Perl These are examples written directly by the Ext team, as guides, as to what we can do. Each of us writes applications differently, so it may be that our application requires a different way of handling things at the server level. The Direct specification, along with the examples, gives us the guideposts we need for writing our own stacks when necessary. We will deconstruct one such example here to help illustrate this point. Each server-side stack is made up of three basic components: Configuration— denoting which components/classes are available to Ext JS API— client-side descriptors of our configuration Router— a means to 'route' our requests to their proper API counterparts To illustrate each of these pieces of the server-side stack we will deconstruct one of the example stacks provided by the Ext JS team. I have chosen the ColdFusion stack because: It is a good example of using a metadata configuration DirectCFM (the ColdFusion stack example) was written by Aaron Conran, who is the Senior Software Architect and Ext Services Team Leader for Ext, LLC Each of the following sections will contain a "Stack Deconstruction" section to illustrate each of the concepts. These are to show you how these concepts might be written in a server-side language, but you are welcome to move on if you feel you have a good grasp of the material. Configuration Ultimately the configuration must define the classes/objects being accessed, the functions of those objects that can be called, and the length (number) of arguments that the method is expecting. Different servers will allow us to define our configuration in different ways. The method we choose will sometimes depend upon the capabilities or deficiencies of the platform we're coding to. Some platforms provide the ability to introspect components/classes at runtime to build configurations, while others require a far more manual approach. You can also include an optional formHandler attribute to your method definitions, if the method can take form submissions directly. There are four basic ways to write a configuration. Programmatic A programmatic configuration may be achieved by creating a simple API object of key/value pairs in the native language. A key/value pair object is known by many different names, depending upon the platform to which we're writing for: HashMap, Structure, Object, Dictionary, or an Associative Array. For example, in PHP you might write something like this: $API = array( 'Authors'=>array( 'methods'=>array( 'GetAll'=>array( 'len'=>0 ), 'add'=>array( 'len'=>1 ), 'update'=>array( 'len'=>1 ) ) ) ); Look familiar? It should, in some way, as it's very similar to a JavaScript object. The same basic structure is true for our next two methods of configuration as well. JSON and XML For this configuration, we can pass in a basic JSON configuration of our API: { Authors:{ methods:{ GetAll:{ len:0 }, add:{ len:1 }, update:{ len:1 } } } } Or we could return an XML configuration object: <Authors> <methods> <method name="GetAll" len="0" /> <method name="add" len="1" /> <method name="update" len="1" /> </methods> </Authors> All of these forms have given us the same basic outcome, by providing a basic definition of server-side classes/objects to be exposed for use with our Ext applications. But, each of these methods require us to build these configurations basically by hand. Some server-side options make it a little easier. Metadata There are a few server-side technologies that allow us to add additional metadata to classes and function definitions, using which we can then introspect objects at runtime to create our configurations. The following example demonstrates this by adding additional metadata to a ColdFusion component (CFC): <cfcomponent name="Authors" ExtDirect="true"> <cffunction name="GetAll" ExtDirect="true"> <cfreturn true /> </cffunction> <cffunction name="add" ExtDirect="true"> <cfargument name="author" /> <cfreturn true /> </cffunction> <cffunction name="update" ExtDirect="true"> <cfargument name="author" /> <cfreturn true /> </cffunction> </cfcomponent> This is a very powerful method for creating our configuration, as it means adding a single name/value attribute (ExtDirect="true") to any object and function we want to make available to our Ext application. The ColdFusion server is able to introspect this metadata at runtime, passing the configuration object back to our Ext application for use. Stack deconstruction—configuration The example ColdFusion Component provided with the DirectCFM stack is pretty basic, so we'll write one slightly more detailed to illustrate the configuration. ColdFusion has a facility for attaching additional metadata to classes and methods, so we'll use the fourth configuration method for this example, Metadata. We'll start off with creating the Authors.cfc class: <cfcomponent name="Authors" ExtDirect="true"> </cfcomponent> Next we'll create our GetAll method for returning all the authors in the database: <cffunction name="GetAll" ExtDirect="true"> <cfset var q = "" /> <cfquery name="q" datasource="cfbookclub"> SELECT AuthorID, FirstName, LastName FROM Authors ORDER BY LastName </cfquery> <cfreturn q /> </cffunction> We're leaving out basic error handling and stuff, but these are the basics behind it. The classes and methods we want to make available will all contain the additional metadata. Building your API So now that we've explored how to create a configuration at the server, we need to take the next step by passing that configuration to our Ext application. We do this by writing a server-side template that will output our JavaScript configuration. Yes, we'll actually dynamically produce a JavaScript include, calling the server-side template directly from within our <script> tag: <script src="Api.cfm"></script> How we write our server-side file really depends on the platform, but ultimately we just want it to return a block of JavaScript (just like calling a .js file) containing our API configuration description. The configuration will appear as part of the actions attribute, but we must also pass the url of our Router, the type of connection, and our namespace. That API return might look something like this: Ext.ns("com.cc"); com.cc.APIDesc = { "url": "/remote/Router.cfm", "type": "remoting" "namespace": "com.cc", "actions": { "Authors": [{ "name": "GetAll", "len": 0 },{ "name": "add", "len": 1 },{ "name": "update", "len": 1 }] } }; This now exposes our server-side configuration to our Ext application. Stack deconstruction—API The purpose here is to create a JavaScript document, dynamically, of your configuration. Earlier we defined configuration via metadata. The DirectCFM API now has to convert that metadata into JavaScript. The first step is including the Api.cfm in a <script> tag on the page, but we need to know what's going on "under the hood." Api.cfm: <!--- Configure API Namespace and Description variable names ---> <cfset args = StructNew() /> <cfset args['ns'] = "com.cc" /> <cfset args['desc'] = "APIDesc" /> <cfinvoke component="Direct" method="getAPIScript" argumentcollection="#args#" returnVariable="apiScript" /> <cfcontent reset="true" /> <cfoutput>#apiScript#</cfoutput> Here we set a few variables, that will then be used in a method call. The getAPIScript method, of the Direct.cfc class, will construct our API from metadata. Direct.cfc getAPIScript() method: <cffunction name="getAPIScript"> <cfargument name="ns" /> <cfargument name="desc" /> <cfset var totalCFCs = '' /> <cfset var cfcName = '' /> <cfset var CFCApi = '' /> <cfset var fnLen = '' /> <cfset var Fn = '' /> <cfset var currFn = '' /> <cfset var newCfComponentMeta = '' /> <cfset var script = '' /> <cfset var jsonPacket = StructNew() /> <cfset jsonPacket['url'] = variables.routerUrl /> <cfset jsonPacket['type'] = variables.remotingType /> <cfset jsonPacket['namespace'] = ARGUMENTS.ns /> <cfset jsonPacket['actions'] = StructNew() /> <cfdirectory action="list" directory="#expandPath('.')#" name="totalCFCs" filter="*.cfc" recurse="false" /> <cfloop query="totalCFCs"> <cfset cfcName = ListFirst(totalCFCs.name, '.') /> <cfset newCfComponentMeta = GetComponentMetaData(cfcName) /> <cfif StructKeyExists(newCfComponentMeta, "ExtDirect")> <cfset CFCApi = ArrayNew(1) /> <cfset fnLen = ArrayLen(newCFComponentMeta.Functions) /> <cfloop from="1" to="#fnLen#" index="i"> <cfset currFn = newCfComponentMeta.Functions[i] /> <cfif StructKeyExists(currFn, "ExtDirect")> <cfset Fn = StructNew() /> <cfset Fn['name'] = currFn.Name/> <cfset Fn['len'] = ArrayLen(currFn.Parameters) /> <cfif StructKeyExists(currFn, "ExtFormHandler")> <cfset Fn['formHandler'] = true /> </cfif> <cfset ArrayAppend(CFCApi, Fn) /> </cfif> </cfloop> <cfset jsonPacket['actions'][cfcName] = CFCApi /> </cfif> </cfloop> <cfoutput><cfsavecontent variable="script">Ext.ns('#arguments. ns#');#arguments.ns#.#desc# = #SerializeJson(jsonPacket)#;</ cfsavecontent></cfoutput> <cfreturn script /> </cffunction> The getAPIScript method sets a few variables (including the 'actions' array), pulls a listing of all ColdFusion Components from the directory, loops over that listing, and finds any components containing "ExtDirect" in their root meta. With every component that does contain that meta, it then loops over each method, finds methods with "ExtDirect" in the function meta, and creates a structure with the function name and number of arguments, which is then added to an array of methods. When all methods have been introspected, the array of methods is added to the 'actions' array. Once all ColdFusion Components have been introspected, the entire packet is serialized into JSON, and returned to API.cfm for output. One item to note is that the script, when introspecting method metadata, also looks for a "ExtFormHandler" attribute. If it finds the attribute, it will include that in the method struct prior to placing the struct in the 'actions' array.
Read more
  • 0
  • 0
  • 3970