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

How-To Tutorials - Web Development

1802 Articles
article-image-creating-your-course-presenter
Packt
30 Jan 2013
16 min read
Save for later

Creating Your Course with Presenter

Packt
30 Jan 2013
16 min read
(For more resources related to this topic, see here.) Animating images and objects Animating your objects is done on the Animations ribbon. Please note that this ribbon is different on PowerPoint 2010 than it is on PowerPoint 2007. Just about everything you do will be the same, however the locations and names of some things may be different. For the purpose of this book, we're going to look at PowerPoint 2010, but we will tell you about the differences. Getting ready To start we'll need a slide with a couple of objects on it. You can copy a slide from an existing presentation, putting it into a new presentation to experiment with. I'm going to use the first slide from our "Mary Had a Little Lamb" presentation. So that we can do anything we want to with this slide, I'm going to add a few buttons and an arrow to it, giving us some more objects to work with. When animating objects, it can be extremely useful to group them. This causes the animation to act on the group of objects as if they are one object. To group two or more objects, select them together, then right-click on one of the objects. Click on the Group button; it will open another fly-out menu, then click on Group. How to do it... Animations can only be done to already existing objects. Often, it is easiest to place all the objects on the slide before beginning the animations. That makes it easier to see how the animations will react with one another. For animating images and objects, perform the following steps: Open up the Selections pane by clicking on the Selection Pane button in the Arrange section of the Format ribbon. This will help you keep track of the various objects on the slide and their order of layering. To rename the objects, click on the name in the Selections pane and type in a new name. The small button to the right-hand side of each object's name is for making the object visible or invisible. Open the Animation pane in the Animations ribbon. For PowerPoint 2010, click on the Animation Pane button in the Advanced Animation section of the ribbon. For PowerPoint 2007, click on the Custom Animation button in the Animations section of the Animations ribbon. Adding an animation to a particular object consists of selecting the object and then selecting the animation for it. On the 2010 ribbon, you can add an animation either by clicking on the animation's icon in the center part of the ribbon, or by clicking on the Add Animation button in the Advanced Animations section of the ribbon. Clicking on this button opens the Animation drop-down menu, as shown in the following screenshot: Select the animation you want by clicking on it. How it works... When you first open the Selection pane, the objects will all appear with names such as Rounded Rectangle 12, TextBox 13, and Picture 14. This numbering will be sequential in the order that the objects have been added to that slide. The order in which the objects appear in the pane is the order in which they are layered in the slide. The top object that is listed is the top one in the order. To change the order, right-click on the object and select Bring to Top or Send to Bottom on the context-sensitive menu. PowerPoint works like a desktop publishing program in the same way that it handles the ordering and layering of the objects. If you were doing the design that you are doing in PowerPoint on paper, gluing blocks of text, pictures, and other objects to the paper would have caused some of them to overlap others. This is the concept of "layering". Every object that you put on a slide is layered even if none of them overlap each other. When they do overlap each other, the objects that were added later overlap the earlier ones. This can be changed by changing the object order, using Bring to Top, Send Forward, Send Backward, and Send to Bottom in the context-sensitive menu. The Animation dropbox itself shows the most popular animations and is divided into four, color-coded sections for the type of animation that is to be added, as follows: The Entrance animations are green The Emphasis animations are yellow or gray The Exit animations are red The Motion Paths animations are multicolored In addition, there are links at the bottom of the dialog box to access more animations than the ones shown in the dropbox. Selecting an animation automatically adds it to the Animations pane, so that you can see it. The animations you have added will be listed in the Animations pane in the order in which they run. There will be an icon of a mouse as well, to show that the animation is intended to run with the click of a mouse. The numbers to the left-hand side of the animation tell you what order they are in. If an animation does not have a number to its left-hand side, it is set to run with the previous one. If it has a clock face to the left-hand side, it is intended to run after the previous animation, as shown in the following screenshot: Even though we're setting the animations to start with a mouse click, that won't actually be happening in the Flash video. Later we'll be sequencing the animations, syncing them with the narration. We will need them to be activated by a mouse click in order to do this. There's more… There are a number of different changes you can make to how your animations are run. Animation timing Articulate offers the capability to precisely time your animations, which is much easier than what PowerPoint offers. This makes it easier to match the timing of the animations with the narration. Perform the following steps: By right-clicking on any of the animations, you can access a context-sensitive menu, which allows you to select the animations to run on a mouse click, concurrent with the previous animation or after the previous animation. This can be done using options such as Start On Click, Start With Previous, and Start After Previous, as shown in the following screenshot: For some animations you can change other settings, such as the direction that the object enters the slide from. This is done by clicking on Effect Options... in the context-sensitive menu. When the dialog box opens, you can set Direction or any other setting particular to that animation in the upper part of the dialog box. You can add sound effects to the animation using the Sound drop-down menu in the lower part of the dialog box. Clicking on Timing in the context-sensitive menu opens a dialog box that allows you to change the speed with which the animations run, as shown in the following screenshot: There are five settings available in the Speed drop-down menu, from very slow to very fast. As you can see from the preceding screenshot, the program tells you how long the animation will run for at each speed. Using the Repeat drop-down menu, you can set the animation to repeat itself a set number of times until the slide ends or until the next mouse click. The context-sensitive menu also allows you to open an advanced timeline by clicking on Show Advanced Timeline, which will allow you to further fine-tune your animation and its timing, including adding a delay between it and the previous animation. The timeline view allows you to see how the overlap and running of your animations will come out in terms of seconds. You never want to have the first animation in the slide run automatically; you only want to have it run on the mouse click. Setting it to Start With Previous or Start After Previous is not compatible with Flash animation. Multiple animations Multiple animations can be used for a single object. You can bring the item in with an entrance animation, have a second animation performed on it for emphasis, and then have it exit with an exit animation. These can either be one after the other, or with other things happening in between them. These additional animations are added in the same way that the first animation was added in the main part of this recipe. Additional animations will show up in the list in the order in which they were added. They will also play in this order. Checking your animations To check your animation, you can click on the Play button at the top of the Animation pane. If you would like to run it as a slide slow, you will need to click on the Slide Show icon, which is located in the information bar at the bottom of the PowerPoint window, as shown in the following screenshot: A word about style Your viewers are not going to be impressed by presentations filled with too many animations that are all too common. Therefore, it is of utmost importance to use animations with discretion. They are a great way to add additional objects to a slide, if they can do so without being a distraction. Adding audio narration to your slides Articulate Presenter allows the use of two different types of audio in your presentation. The first is the audio track, which provides background music for your presentation. The second is narration. This program automatically adjusts the volume of your background music whenever there is narration, avoiding competition between the two. There are two ways of creating your narration in Articulate Presenter, either by recording the narration right into the presentation, or by having your narration recorded professionally and importing it into your presentation. In this section, we will look at how both of these methods are accomplished. Getting ready To record narration directly into your presentation, you will need a microphone connected to your computer. It is worthwhile buying a good quality microphone, especially if you are going to be doing a large number of presentations. The sound quality that you can get off a good quality microphone is better than a cheap one. You don't want to use the microphone that's in your webcam. Not only is this not a high-quality microphone, but the distance between you and the microphone will make you sound like you're speaking from inside a tunnel. Ideally, a microphone should be between three to six inches from your mouth, pointed directly at your mouth. Avoid moving your head from side to side as you speak, as this will make your volume level go up and down. The following are some of the key points to look at before you add an audio narration to your slide: A windscreen on your microphone is a good investment as it will help prevent the noise from your breathing on it. You may also want to consider a desktop mic stand so that you don't have to hold it in your hand. Before recording your narration, it's a good idea to have it written out. Many people think that they can do it off the cuff, but when they get in front of the mic, they forget everything that they were going to say. A great place to write out your script is in the notes area at the bottom of the PowerPoint screen. How to do it... We are going to record the narration directly into the presentation using Articulate Presenter's built-in recording function. Perform the following steps to do so: Before recording your narration, you need to ensure that your presentation is ready to receive your recording. To do this, open the Presentation Options dialog box from the Articulate ribbon. On the Other tab, make sure that the Show notes pane on narration window and Record narration for one slide at a time checkboxes under the Recording section are both checked, as shown in the following screenshot: Open the recording screen by clicking on the Record Narration button in the Narration section of the Articulate ribbon. If you have not yet saved your presentation, you will be asked to do so before the Record Narration screen opens. Your PowerPoint screen will seem to disappear when you open the recording screen. Don't worry, you haven't lost it; when you finish recording your narration, it will appear again. If you are using multiple monitors for your computer, the Narration recording screen will always appear on the far right monitor. So if you have something there that you will need to access, you may want to move it before entering the record mode. To begin recording, click on the START RECORDING button on the Articulate ribbon. While you are recording, the START RECORDING button changes to STOP RECORDING. When you have finished recording the narration for the slide, click on the STOP RECORDING button. If you click on the START RECORDING button again after you've stopped recording, it will start the recording again, overwriting what you just recorded. As you are recording, the length of the recording you are making will show in the yellow message bar and will be broken down into hours, minutes, seconds, and tenths of a second. You can check your recording using the Play and Stop buttons to the right-hand side of the START RECORDING button. These buttons are identified with the standard graphical symbols for play and record. Now that you have recorded the narration for the first slide, you can move to the next slide using the right and left arrow buttons to the right-hand side of the Record and Play buttons. You can also select which slide to edit using the drop-down menu located below these buttons. To the right-hand side of the Play and Record buttons, there is an area for selecting the slide that you want to record the narration for. To verify which slides you have already recorded, click on the small arrow pointing downwards below the slide number in the ribbon. This will open a dropbox with a list of all the slides and thumbnails. All the slides that have a narration recorded will show a small icon of a microphone. Above this, they will tell you the duration of the narration that you have recorded, as shown in the following screenshot: To exit the narration recorder and return to PowerPoint, click on the Save & Close button on the ribbon. How it works... Your narrations will be saved in a new file, which has the same name as you gave your presentation, with the .ppta filename extension. The file will be automatically created at this time, if the program has not already created it. If you have to move your presentation for any reason, be sure to move this file along with the .ppta file, which is the presentation. Otherwise you will lose your narrations. There's more... Not only can you record narrations, but you can also import them into the presentation. You may choose to do this using professional "voice" for a specific voice style or for a more professional presentation. Importing narrations into your presentation If you decide to use professionally recorded narrations using professional talent, you will probably not be able to record them with Articulate's recorder. This isn't a problem, as you can very easily import those recordings into your presentation. There are some technical requirements for your recordings. They must be recorded in either the .wav or .mp3 format. Between the two, you are better off using the .wav format files as they are not compressed like the .mp3 files. This means that your finished presentation will be a bigger file, but it will provide a better sound quality for editing. They must be recorded at a sampling rate of 44.1 kHz, 16-bit resolution, and either stereo or mono. Many recording studios and artists prefer to use a resolution of 32 bits, however if you attempt to import 32- bit files into an Articulate presentation, all you will hear is a screech. Perform the following steps for importing narrations: To import these files, click on the Import Audio button in the Narration section of the Articulate ribbon. This will open the Import Audio dialog box. This dialog box contains a simple chart showing the slide numbers, the slide names, and the audio track for the narration. If you have recorded a narration for a slide, it will state the existing narration; if you have no narration, this column will be empty. Select the slide that you wish to import an audio file to by clicking on it. Then click on the Browse... button at the bottom of the screen. This will open a standard, Windows open file dialog box, where you can search for and select your audio file for that particular narration. You can select multiple narration files to be imported at once. Simply select the first file you need in the Windows open file dialog box, then hold down the Shift key and select the last. If the files are not sequentially located in the folder, you can hold down the Ctrl key, select each file individually, and then import them all together. When you do this, a new dialog box will open, allowing you to put the audio files in their correct order. The list of files will be shown in the central part of the dialog box. To change the order, select the file you wish to move, and use the Up, Down, Top, Bottom, and Reverse buttons on the right-hand side of the dialog box to move them as you need to. If you do not get the order of your narration files correct in the dialog box, you will need to individually change the audio files associated with the slides, as there is no way of moving them around in the Import Audio dialog box. Summary This article covered the basics of creating a simple course using Presenter by itself. It taught us the basics of inserting media elements and assets. Resources for Article : Further resources on this subject: Python Multimedia: Video Format Conversion, Manipulations and Effects [Article] Using Web Pages in UPK 3.5 [Article] Adding Flash to your WordPress Theme [Article]
Read more
  • 0
  • 0
  • 1556

article-image-layout-extnet
Packt
30 Jan 2013
16 min read
Save for later

Layout with Ext.NET

Packt
30 Jan 2013
16 min read
(For more resources related to this topic, see here.) Border layout The Border layout is perhaps one of the more popular layouts. While quite complex at first glance, it is popular because it turns out to be quite flexible to design and to use. It offers common elements often seen in complex web applications, such as an area for header content, footer content, a main content area, plus areas to either side. All are separately scrollable and resizable if needed, among other benefits. In Ext speak, these areas are called Regions, and are given names of North, South, Center, East, and West regions. Only the Center region is mandatory. It is also the one without any given dimensions; it will resize to fit the remaining area after all the other regions have been set. A West or East region must have a width defined, and North or South regions must have a height defined. These can be defined using the Width or Height property (in pixels) or using the Flex property which helps provide ratios. Each region can be any Ext.NET component; a very common option is Panel or a subclass of Panel. There are limits, however: for example, a Window is intended to be floating so cannot be one of the regions. This offers a lot of flexibility and can help avoid nesting too many Panels in order to show other components such as GridPanels or TabPanels, for example. Here is a screenshot showing a simple Border layout being applied to the entire page (that is, the viewport) using a 2-column style layout: We have configured a Border layout with two regions; a West region and a Center region. The Border layout is applied to the whole page (this is an example of using it with Viewport. Here is the code: <%@ Page Language="C#" %> <!DOCTYPE html> <html> <head runat="server"> <title>Border Layout Example</title> </head> <body> <ext:ResourceManager runat="server" Theme="Gray" /> <ext:Viewport runat="server" Layout="border"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="200" Collapsible="true" /> <ext:Panel Region="Center" Title="Center content" /> </Items> </ext:Viewport> </body> </html> The code has a Viewport configured with a Border layout via the Layout property. Then, into the Items collection two Panels are added, for the West and Center regions. The value of the Layout property is case insensitive and can take variations, such as Border, border, borderlayout, BorderLayout, and so on. As regions of a Border layout we can also configure options such as whether you want split bars, whether Panels are collapsible, and more. Our example uses the following: The West region Panel has been configured to be collapsible (using Collapsible="true"). This creates a small button in the title area which, when clicked, will smoothly animate the collapse of that region (which can then be clicked again to open it). When collapsed, the title area itself can also be clicked which will float the region into appearance, rather than permanently opening it (allowing the user to glimpse at the content and mouse away to close the region). This floating capability can be turned off by using Floatable="false" on the Panel. Split="true" gives a split bar with a collapse button between the regions. This next example shows a more complex Border layout where all regions are used: The markup used for the previous is very similar to the first example, so we will only show the Viewport portion: <ext:Viewport runat="server" Layout="border"> <Items> <ext:Panel Region="North" Split="true" Title="North" Height="75" Collapsible="true" /> <ext:Panel Region="West" Split="true" Title="West" Width="150" Collapsible="true" /> <ext:Panel runat="server" Region="Center" Title="Center content" /> <ext:Panel Region="East" Split="true" Title="East" Width="150" Collapsible="true" /> <ext:Panel Region="South" Split="true" Title="South" Height="75" Collapsible="true" /> </Items> </ext:Viewport> Although each Panel has a title set via the Title property, it is optional. For example, you may want to omit the title from the North region if you want an application header or banner bar, where the title bar could be superfluous. Different ways to create the same components The previous examples were shown using the specific Layout="Border" markup. However, there are a number of ways this can be marked up or written in code. For example, You can code these entirely in markup as we have seen You can create these entirely in code You can use a mixture of markup and code to suit your needs Here are some quick examples: Border layout from code This is the code version of the first two-panel Border layout example: <%@ Page Language="C#" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { var viewport = new Viewport { Layout = "border", Items = { new Ext.Net.Panel { Region = Region.West, Title = "West", Width = 200, Collapsible = true, Split = true }, new Ext.Net.Panel { Region = Region.Center, Title = "Center content" } } }; this.Form.Controls.Add(viewport); } </script> <!DOCTYPE html> <html> <head runat="server"> <title>Border Layout Example</title> </head> <body> <form runat="server"> <ext:ResourceManager runat="server" Theme="Gray" /> </form> </body> </html> There are a number of things going on here worth mentioning: The appropriate panels have been added to the Viewport's Items collection Finally, the Viewport is added to the page via the form's Controls Collection If you are used to programming with ASP.NET, you normally add a control to the Controls collection of an ASP.NET control. However, when Ext.NET controls add themselves to each other, it is usually done via the Items collection. This helps create a more optimal initialization script. This also means that only Ext.NET components participate in the layout logic. There is also the Content property in markup (or ContentControls property in code-behind) which can be used to add non-Ext.NET controls or raw HTML, though they will not take part in the layout. It is important to note that configuring Items and Content together should be avoided, especially if a layout is set on the parent container. This is because the parent container will only use the Items collection. Some layouts may hide the Content section altogether or have other undesired results. In general, use only one at a time, not both because the Viewport is the outer-most control; it is added to the Controls collection of the form itself. Another important thing to bear in mind is that the Viewport must be the only top-level visible control. That means it cannot be placed inside a div, for example it must be added directly to the body or to the <form runat="server"> only. In addition, there should not be any sibling controls (except floating widgets, like Window). Mixing markup and code The same 2-panel Border layout can also be mixed in various ways. For example: <%@ Page Language="C#" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { this.WestPanel.Title = "West"; this.WestPanel.Split = true; this.WestPanel.Collapsible = true; this.Viewport1.Items.Add(new Ext.Net.Panel { Region = Region.Center, Title = "Center content" }); } </script> <!DOCTYPE html> <html> <head runat="server"> <title>Border Layout Example</title> </head> <body> <ext:ResourceManager runat="server" /> <ext:Viewport ID="Viewport1" runat="server" Layout="Border"> <Items> <ext:Panel ID="WestPanel" runat="server" Region="West" Width="200" /> </Items> </ext:Viewport> </body> </html> In the previous example, the Viewport and the initial part of the West region have been defined in markup. The Center region Panel has been added via code and the rest of the West Panel's properties have been set in code-behind. As with most ASP. NET controls, you can mix and match these as you need. Loading layout items via User Controls A powerful capability that Ext.NET provides is being able to load layout components from User Controls. This is achieved by using the UserControlLoader component. Consider this example: <ext:Viewport runat="server" Layout="Border"> <Items> <ext:UserControlLoader Path="WestPanel.ascx" /> <ext:Panel Region="Center" /> </Items> </ext:Viewport> In this code, we have replaced the West region Panel that was used in earlier examples with a UserControlLoader component and set the Path property to load a user control in the same directory as this page. That user control is very simple for our example: <%@ Control Language="C#" %> <ext:Panel runat="server" Region="West" Split="true" Title="West" Width="200" Collapsible="true" /> In other words, we have simply moved our Panel from our earlier example into a user control and loaded that instead. Though a small example, this demonstrates some useful reuse capability. Also note that although we used the UserControlLoader in this Border layout example, it can be used anywhere else as needed, as it is an Ext.NET component. The containing component does not have to be a Viewport Note also that the containing component does not have to be a Viewport. It can be any other appropriate container, such as another Panel or a Window. Let's do just that: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="150" Collapsible="true" /> <ext:Panel Region="Center" Title="Center content" /> </Items> </ext:Window> The container has changed from a Viewport to a Window (with dimensions). It will produce this: More than one item with the same region In previous versions of Ext JS and Ext.NET you could only have one component in a given region, for example, only one North region Panel, one West region Panel, and so on. New to Ext.NET 2 is the ability to have more than one item in the same region. This can be very flexible and improve performance slightly. This is because in the past if you wanted the appearance of say multiple West columns, you would need to create nested Border layouts (which is still an option of course). But now, you can simply add two components to a Border layout and give them the same region value. Nested Border layouts are still possible in case the flexibility is needed (and helps make porting from an earlier version easier). First, here is an example using nested Border layouts to achieve three vertical columns: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="100" Collapsible="true" /> <ext:Panel Region="Center" Layout="Border" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="Inner West" Width="100" Collapsible="true" /> <ext:Panel Region="Center" Title="Inner Center" /> </Items> </ext:Panel> </Items> </ext:Window> This code will produce the following output: The previous code is only a slight variation of the example preceding it, but has a few notable changes: The Center region Panel has itself been given the layout as Border. This means that although this is a Center region for the window that it is a part of, this Panel is itself another Border layout. The nested Border layout then has two further Panels, an additional West region and an additional Center region. Note, the Title has also been removed from the outer Center region so that when they are rendered, they line up to look like three Panels next to each other. Here is the same example, but without using a nested border Panel and instead, just adding another West region Panel to the containing Window: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="100" Collapsible="true" /> <ext:Panel Region="West" Split="true" Title="Inner West" Width="100" Collapsible="true" /> <ext:Panel Region="Center" Title="Center content" Border="false" /> </Items> </ext:Window> Regions are not limited to Panels only A common problem with layouts is to start off creating more deeply nested controls than needed and the example earlier shows that it is not always needed. Multiple items with the same region helps to prevent nesting Border Layouts unnecessarily. Another inefficiency typical with the Border layout usage is using too many containing Panels in each region. For example, there may be a Center region Panel which then contains a TabPanel. However, as TabPanel is a subclass of Panel it can be given a region directly, therefore avoiding an unnecessary Panel to contain the TabPanel: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="False"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="100" Collapsible="True" /> <ext:TabPanel Region="Center"> <Items> <ext:Panel Title="First Tab" /> <ext:Panel Title="Second Tab" /> </Items> </ext:TabPanel> </Items> </ext:Window> This code will produce the following output: The differences with the nested Border layout example shown earlier are: The outer Center region has been changed from Panel to TabPanel. TabPanels manage their own items' layout so Layout="Border" is removed. The TabPanel also has Border="false" taken out (so it is true by default). The inner Panels have had their regions, Split, and other border related attributes taken out. This is because they are not inside a nested Border layout now; they are tabs. Other Panels, such as TreePanel or GridPanel, can also be used as we will see. Something that can be fiddly from time to time is knowing which borders to take off and which ones to keep when you have nested layouts and controls like this. There is a logic to it, but sometimes a quick bit of trial and error can also help figure it out! As a programmer this sounds minor and unimportant, but usually you want to prevent the borders becoming too thick, as aesthetically it can be off-putting, whereas just the right amount of borders can help make the application look clean and professional. You can always give components a class via the Cls property and then in CSS you can fine tune the borders (and other styles of course) as you need. Weighted regions Another feature new to Ext.NET 2 is that regions can be given weighting to influence how they are rendered and spaced out. Prior versions would require nested Border layouts to achieve this. To see how this works, consider this example to put a South region only inside the Center Panel: To achieve this output, if we used the old way—the nested Border layouts—we would do something like this: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="100" Collapsible="true" /> <ext:Panel Region="Center" Layout="Border" Border="false"> <Items> <ext:Panel Region="Center" Title="Center" /> <ext:Panel Region="South" Split="true" Title="South" Height="100" Collapsible="true" /> </Items> </ext:Panel> </Items> </ext:Window> In the preceding code, we make the Center region itself be a Border layout with an inner Center region and a South region. This way the outer West region takes up all the space on the left. If the South region was part of the outer Border layout, then it would span across the entire bottom area of the window. But the same effect can be achieved using weighting. This means you do not need nested Border layouts; the three Panels can all be items of the containing window, which means a few less objects being created on the client: <ext:Window runat="server" Layout="Border" Height="200" Width="400" Border="false"> <Items> <ext:Panel Region="West" Split="true" Title="West" Width="100" Collapsible="true" Weight="10" /> <ext:Panel Region="Center" Title="Center" /> <ext:Panel Region="South" Split="true" Title="South" Height="100" Collapsible="true" /> </Items> </ext:Window> The way region weights work is that the region with the highest weight is assigned space from the border before other regions. If more than one region has the same weight as another, they are assigned space based on their position in the owner's Items collection (that is first come, first served). In the preceding code, we set the Weight property to 10 to the West region only, so it is rendered first and, thus, takes up all the space it can before the other two are rendered. This allows for many flexible options and Ext.NET has an example where you can configure different values to see the effects of different weights: http://examples.ext.net/#/Layout/BorderLayout/Regions_Weights/ As the previous examples show, there are many ways to define the layout, offering you more flexibility, especially if generating from code-behind in a very dynamic way. Knowing that there are so many ways to define the layout, we can now speed up our look at many other types of layouts. Summary This article covered one of the numerous layout options available in Ext.NET, that is, the Border layout, to help you organize your web applications. Resources for Article : Further resources on this subject: Your First ASP.NET MVC Application [Article] Customizing and Extending the ASP.NET MVC Framework [Article] Tips & Tricks for Ext JS 3.x [Article]
Read more
  • 0
  • 0
  • 4842

article-image-eloquent-relationships
Packt
28 Jan 2013
12 min read
Save for later

Eloquent relationships

Packt
28 Jan 2013
12 min read
(For more resources related to this topic, see here.) 1 — Eloquent relationships ActiveRecord is a design pattern that describes an object-oriented way of interacting with your database. For example, your database's users table contains rows and each of these rows represents a single user of your site. Your User model is a class that extends the Eloquent Model class. When you query a record from your database, an instantiation of your User model class is created and populated with the information from the database. A distinct advantage of ActiveRecord is that your data and the business logic that is related to the data are housed within the same object. For example, it's typical to store the user's password in your model as a hash, to prevent it from being stored as plaintext. It's also typical to store the method, which creates this password hash within your User class. Another powerful aspect of the ActiveRecord pattern is the ability to define relationships between models. Imagine that you're building a blog site and your users are authors who must be able to post their writings. Using an ActiveRecord implementation, you are able to define the parameters of the relationship. The task of maintaining this relationship is then simplified dramatically. Simple code is the easy code to change. Difficult to understand code is the easy code to break. As a PHP developer, you're probably already familiar with the concept of database normalization. If you're not, normalization is the process of designing databases so that there is little redundancy in the stored data. For example, you wouldn't want to have both a users table which contains the user's name and a table of blog posts which also contains the author's name. Instead, your blog post record would refer to the user using their user ID. In this way we avoid synchronization problems and a lot of extra work! There are a number of ways in which relationships can be established in normalized database schemas. One-to-one relationship When a relationship connects two records in a way that doesn't allow for more records to be related, it is a one-to-one relationship. For example, a user record might have a one-to-one relationship with a passport record. In this example, a user record is not permitted to be linked to more than one passport record. Similarly, it is not permitted for a passport record to relate to more than one user record. How would the database look? Your users table contains information about each user in your database. Your passports table contains passport numbers and a link to the user which owns the passport. In this example, each user has no more than one passport and each passport must have an owner. The passports table contains its own id column which it uses as a primary key. It also contains the column user_id, which contains the ID of the user to whom the passport belongs. Last but not least, the passports table contains a column for the passport number. First, let's model this relationship in the User class: class User extends Eloquent { public function passport() { return $this->has_one('Passport'); } } We created a method named passport() that returns a relationship. It might seem strange to return relationships at first. But, you'll soon come to love it for the flexibility it offers. You'll notice that we're using the has_one() method and passing the name of the model as a parameter. In this case, a user has one passport. So, the parameter is the name of the passport model class. This is enough information for Eloquent to understand how to acquire the correct passport record for each user. Now, let's look at the Passport class: class Passport extends Eloquent { public function users() { return $this->belongs_to('User'); } } We're defining the passport's relationship differently. In the User class, we used the has_one() method. In the Passport class we used belongs_to(). It's vital to identify the difference early so that understanding the rest of the relationships is more simple. When a database table contains a foreign key, it is said that it belongs to a record in another table. In this example, our passports table refers to records in the users table through the foreign key user_id. Consequently, we would say that a passport belongs to a user. Since this is a one-to-one relationship the user has one (has_one()) passport. Let's say that we want to view the passport number of the user with the id of 1. $user = User::find(1); If(is_null($user)) { echo "No user found."; return; } If($user->passport) { echo "The user's passport number is " . $user->passport->number; } else { echo "This user has no passport."; } In this example, we're dutifully checking to make sure that our user object was returned as expected. This is a necessary step that should not be overlooked. Then, we check whether or not the user has a passport record associated with it. If a passport record for this user exists, the related object will be returned. If it doesn't exist, $user->passport will return null. In the preceding example, we test for the existence of a record and return the appropriate response. One-to-many relationships One-to-many relationships are similar to one-to-one relationships. In this relationship type, one model has many of other relationships, which in turn belongs to the former. One example of a one-to-many relationship is a professional sports team's relationship to its players. One team has many players. In this example, each player can only belong to one team. The database tables have the same structure. Now, let's look at the code which describes this relationship. class Team extends Eloquent { public function players() { return $this->has_many('Player'); } } class Player extends Eloquent { public function team() { return $this->belongs_to('Team'); } } This example is almost identical to the one-to-one example. The only difference is that the team's players() relationship uses has_many() rather than has_one(). The has_one() relationship returns a model object. The has_many() relationship returns an array of model objects. Let's display all of the players on a specific team: $team = Team::find(2); if(is_null($team)) { echo "The team could not be found."; } if(!$team->players) { echo "The team has no players."; } foreach($team->players as $player) { echo "$player->name is on team $team->name. "; } Again, we test to make sure that our team could be found. Then, we test to make sure that the team has players. Once we know that for sure, we can loop through those players and echo their names. If we tried to loop through the players without first testing and if the team had players, we'd get an error. Many-to-many relationships The last relationship type that we're going to cover is the many-to-many relationship. This relationship is different in that each record from each table could potentially be tied simultaneously to each record in another. We aren't storing foreign keys in either of these tables. Instead, we have a third table that exists solely to store our foreign keys. Let's take a look at the schema. Here we have a students table and a courses table. A student can be enrolled in many courses and a course can contain many students. The connection between students and courses is stored in a pivot table. A pivot table is a table that exists to connect two tables specifically for many-to-many relationships. Standard convention for naming a pivot table is to combine the names of both of the related tables, singularized, alphabetically ordered, and connected with an underscore. This gives us the table name course_student. This convention is not only used by Laravel and it's a good idea to follow the naming conventions covered in this document as strictly as possible as they're widely used in the web-development industry. It's important to notice that we're not creating a model for the pivot table. Laravel allows us to manage these tables without needing to interact with a model. This is especially nice because it doesn't make sense to model a pivot table with business logic. Only the students and courses are a part of our business. The connection between them is important, but only to the students and to the course. It's not important for its own sake. Let's define these models, shall we? class Student extends Eloquent { public function courses() { return $this->has_many_and_belongs_to('Course'); } } class Course extends Eloquent { public function students() { return $this->has_many_and_belongs_to('Student'); } } We have two models, each with the same type of relationship to each other. has_many_and_ belongs_to is a long name. But, it's a fairly simple concept. A course has many students. But, it also belongs to (belongs_to) student records and vice-versa. In this way, they are considered equal. Let's look at how we'll interact with these models in practice: $student = Student::find(1); if(is_null($student)) { echo "The student can't be found."; exit; } if(!$student->courses) { echo "The student $student->name is not enrolled in any courses."; exit; } foreach($student->courses as $course) { echo "The student $student->name is enrolled in the course $course->name."; } Here you can see that we can loop through the courses much the same way we could with the one-to-many relationship. Any time a relationship includes the word many, you know that you'll be receiving an array of models. Conversely, let's pull a course and see which students are a part of it. $course = Course::find(1); if(is_null($course)) { echo "The course can't be found."; exit; } if(!$course->students) { echo "The course $course->name seems to have no students enrolled."; exit; } foreach($course->students as $student) { echo "The student $student->name is enrolled in the course $course->name."; } The relationship functions exactly the same way from the course side. Now that we have established this relationship, we can do some fun things with it. Let's look at how we'd enroll a new student into an existing course: $course = Course::find(13); if(is_null($course)) { echo "The course can't be found."; exit; } $new_student_information = array( 'name' => 'Danielle' ); $course->students()->insert($new_student_information); Here we're adding a new student to our course by using the method insert(). This method is specific to this relationship type and creates a new student record. It also adds a record to the course_student table to link the course and the new student. Very handy! But, hold on. What's this new syntax? $course->students()->insert($new_student_information); Notice how we're not using $course->students->insert(). Our reference to students is a method reference rather than a property reference. That's because Eloquent handles methods that return relationship objects differently from other model methods. When you access a property of a model that doesn't exist, Eloquent will look to see if you have a function that matches that property's name. For example, if we try to access the property $course->students, Eloquent won't be able to find a member variable named $students. So it'll look for a function named students(). We do have one of those. Eloquent will then receive the relationship object from that method, process it, and return the resulting student records. If we access a relationship method as a method and not as a property, we directly receive the relationship object back. The relationship's class extends the Query class. This means that you can operate on a relationship object in the same way that you can operate on a query object, except that it now has new methods that are specific to the relationship type. The specific implementation details aren't important at this point. It's just important to know that we're calling the insert() method on the relationship object returned from $course->students(). Imagine that you have a user model and it has many relationships and belongs to a role model. Roles represent different permission groupings. Example roles might include customer, admin, super admin, and ultra admin. It's easy to imagine a user form for managing its roles. It would contain a number of checkboxes, one for each potential role. The name of the checkboxes is role_ids[] and each value represents the ID of a role in the roles table./p> When that form is posted we'll retrieve those values with the Input::get() method. $role_ids = Input::get('role_ids'); $role_ids is now an array that contains the values 1, 2, 3, and 4. $user->roles()->sync($role_ids); The sync() method is specific to this relationship type and is also perfectly suited for our needs. We're telling Eloquent to connect our current $user to the roles whose IDs exist within the $role_ids array. Let's look at what's going on here in further detail. $user->roles() is returning a has_ many_and_belongs_to relationship object. We're calling the sync() method on that object. Eloquent now looks at the $role_ids array and acknowledges it as the authoritative list of roles for this user. It then removes any records that shouldn't exist in the role_user pivot table and adds records for any role that should exist in the pivot table. Summary In this article we discussed three types of Eloquent relationships—one-to-one relationship, one-to-many relationship, and many-to-many ralationship. Resources for Article : Further resources on this subject: Modeling Relationships with GORM [Article] Working with Simple Associations using CakePHP [Article] NHibernate 2: Mapping relationships and Fluent Mapping [Article]
Read more
  • 0
  • 0
  • 3766

article-image-packaging-content-types-and-feeds-importers
Packt
25 Jan 2013
8 min read
Save for later

Packaging Content Types and Feeds Importers

Packt
25 Jan 2013
8 min read
(For more resources related to this topic, see here.) Features Let's get started. First, we will look at some background information on what Features does. The code that the Features module will give us is in the form of module files sitting in a module folder that we can save to our /sites/all/modules directory, as we would do for any other contributed module. Using this method, we will have the entire configuration that we spent hours on building, saved into a module file and in code. The Features module will keep track of the tweaks we make to our content type configuration or importer for us. If we make changes to our type or importer we simply save a new version of our Features module. The Features module configuration and the setup screen is at Structure | Features or you can go to this path: admin/structure/features. There is no generic configuration for Features that you need to worry about setting up. If you have the Feeds module installed as we do, you'll see two example features that the Feeds module provides—Feeds Import and Feeds News. You can use these provided features or create your own. We're going to create our own in the next section. You should see the following screen at this point: Building a content type feature We have two custom content types so far on our site, Fire Department and Organization Type. Let's package up the Fire Department content type as a feature so that the Features module can start to keep track of each content type configuration and any changes we make going forward. Creating and enabling the feature First click on the Create Feature tab on your Features administration screen. The screen will load a new create feature form. Now follow these steps to create your first feature. We're going to package up our Fire Department content type: Enter a name for your feature. This should be something specific such as Fire Department Content Type. Add a description for the feature. This should be something like This feature packages up our Fire Department Content type configuration. You can create a specific package for your feature. This will help to organize and group your features on the main Features admin screen. Let's call this package Content Types. Version your feature. This is very important as your feature is going to be a module. It's a good idea to version number your feature each time you make a change to it. Our first version will be 7.x-1.0. Leave the URL of update XML blank for now. By this point you should see the following: Now we're going to add our components to the feature. As this feature will be our Fire Department content type configuration, we need to choose this content type as our component. In the drop-down box select Content types: node. Now check the Fire Department checkbox. When you do this you'll see a timer icon appear for a second and then magically all of your content type fields, associated taxonomy, and dependencies will appear in the table to the right. This means that your feature is adding the entire content type configuration. Features is a smart module. It will automatically associate any fields, taxonomy or other dependencies and requirements to your specific feature configuration. As our content type has taxonomy vocabulary associated with it (in the form of the term reference fields) you'll notice that both country and fire_department_type are in the Taxonomy row of the feature table. You should now see the following: Now click on the Download feature button at the bottom of the screen to download the actual module code for our Fire Department feature module. Clicking on Download feature will download the .tar file of the module to your local computer. Find the .tar file and then extract it into your /sites/all/modules/directory. For organizational best practices, I recommend placing it into a / custom directory within your /sites/all/modules as this is really a custom module. So now you should see a folder called fire_department_content_ type in your /sites/all/modules/custom folder. This folder contains the feature module files that you just downloaded. Now if you go back to your main Features administration screen you will see a new tab titled Content Types that contains your new feature module called Fire Department Content Type. Currently this feature is disabled. You can notice the version number in the same row. Go ahead and check the checkbox next to your feature and then click on the Save settings button. What you are doing here is enabling your feature as a module on your site and now your content type's configuration will always be running from this codebase. When you click on Save settings, your feature should now be enabled and showing Default status. When a feature is in Default state this means that your configuration (in this case the Fire Department content type) matches your feature modules codebase. This specific feature is now set up to keep track of any changes that may occur to the content type. So for example if you added a new field to your content type or tweaked any of its existing fields, display formatters or any other part of its configuration, that feature module would have a status of Overridden. We'll demonstrate this in the next section. The custom feature module Before we show the overridden status however, let's take a look at the actual custom feature module code that we've saved. You'll recall that we added a new folder for our Fire Department content type feature to our /sites/all/modules/custom folder. If you look inside the feature module's folder you'll see the following files that are the same as the constructs of a Drupal module: fire_department_content_type.features.field.inc fire_department_content_type.features.inc fire_department_content_type.features.taxonomy.inc fire_department_content_type.info fire_department_content_type.module Anyone familiar with Drupal modules should see here that this is indeed a Drupal module with info, .module, and .inc files. If you inspect the .info file in an editor you'll see the following code (this is an excerpt): name = Fire Department Content Type description = This feature packages up our Fire Department Content type configuration core = 7.x package = Content Types version = 7.x-1.0 project = fire_department_content_type dependencies[] = features The brunt of our module is in the fire_department_content_type.features. field.inc file. This file contains all of our content type's fields defined as a series of the $fields array (see the following excerpt of code): /** * @file * fire_department_content_type.features.field.inc */ /** * Implements hook_field_default_fields(). */ function fire_department_content_type_field_default_fields() { $fields = array(); // Exported field: 'node-fire_department-body'. $fields['node-fire_department-body'] = array( 'field_config'=>array( 'active'=>'1', 'cardinality'=>'1', 'deleted'=>'0', 'entity_types'=>array( 0 =>'node', ), 'field_name'=>'body', 'foreign keys'=>array( 'format'=>array( 'columns'=>array( 'format'=>'format', ), 'table'=>'filter_format' If you view the taxonomy.inc file you'll see two arrays that return the vocabs which we're referencing via the term references of our content type. As you can see, this module has packaged up our entire content type configuration. It's beyond the scope of this book to get into more detail about the actual module files, but you can see how powerful this can be. If you are a module developer you could actually add code to the specific feature module's files to extend and expand your content type directly from the code. This would then be synced to your feature module codebase. Generally, you do not use this method for tweaking your feature but you do have access to the code and can make tweaks to the feature code. What we'll be doing is overriding our feature from the content type configuration level. Additionally, if you load your module's admin screen on your site and scroll down until you see the new package called Content Types, you'll see your feature module enabled here on the modules admin screen: If you disable the Features module here, it will also disable the feature from your Features admin screen. The best practice dictates that you should first disable a Features module via the Features admin screen. This will then disable the module from the modules admin screen.
Read more
  • 0
  • 0
  • 2078

article-image-securing-portal-contents
Packt
24 Jan 2013
8 min read
Save for later

Securing Portal Contents

Packt
24 Jan 2013
8 min read
(For more resources related to this topic, see here.) Introduction This article discusses the configurations aimed at providing security features to portals and all the related components. We will see that we can work using either the web console or the XML configuration files. As you would expect, the latter is more flexible in most instances. Many of the configuration snippets shown in the article are based on Enterprise Deployment Descriptors (DD). Keep in mind that XML always remains the best option for configuring a product. We will configure GateIn in different ways to show how to adapt some of the internal components for your needs. Enterprise Deployment Descriptors (DD) are configuration files related to an enterprise application component that must be deployed in an application server. The goal of the deployment descriptor is to define how a component must be deployed in the container, configuring the state of the application and its internal components. These configuration files were introduced in the Java Enterprise Platform to manage the deployment of Java Enterprise components such as Web Applications, Enterprise Java Beans, Web Services, and so on. Typically, for each specific container, you have a different definition of the descriptor depending on vendors and standard specifications. Typically, a portal consists of pages related to a public section and a private section. Depending on the purpose, of course, we can also work with a completely private portal. The two main mechanisms used in any user-based application are the following: Authentication Authorization In this article we will discuss authorization: how to configure and manage permissions for all the objects involved in the portal. As an example, a User is a member of a Group, which provides him with some authorizations. These authorizations are the things that members of the Groups can do in the portal. On the other side, as an example, a page is defined with some permissions, which says which Groups can access it. Now, we are going to see how to configure and manage these permissions, for the pages, components in a page, and so on in the portal. Securing portals The authorization model of the portal is based on the association between the following actors: groups, memberships, users, and any content inside the portal (pages, categories, or portlets). In this recipe, we will assign the admin role against a set of pages under a specific URL of the portal. This configuration can be found in the default portal provided with GateIn so you can take the complete code from there. Getting ready Locate the web.xml file inside your portal application. How to do it... We need to configure the web.xml file assigning the admin role to the following pages under the URL http://localhost:8080/portal/admin/* in the following way: <security-constraint> <web-resource-collection> <web-resource-name> admin authentication </web-resource-name> <url-pattern>/admin/*</url-pattern> <http-method>POST</http-method> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> The role must be declared in a different section under the security-constraint tag through the security-role tag. The role-name tag defines the id of the role: <security-role> <description>the admin role</description> <role-name>admin</role-name> </security-role> How it works... GateIn allows you to add different roles for every sections of the portal simply by adding a path expression that can include a set of sub-pages using wildcard notation (/*). This is done by first defining all the needed roles using the security-role element, and then defining a security-constraint element for each set of pages that you want to involve. PicketLink is also for users and memberships, and can manage the organization of the groups. There's more... Configuring GateIn with JAAS GateIn uses JAAS (Java Authentication Authorization Service) as the security model. JAAS (Java Authentication Authorization Service) is the most common framework used in the Java world to manage authentication and authorization. The goal of this framework is to separate the responsibility of users' permissions from the Java application. In this way, you can have a bridge for permissions management between your application and the security provider. For more information about JAAS, please see the following URL: http://docs.oracle.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html Java EE Application servers and JSP/servlet containers, such as JBoss and Tomcat, also support JAAS with specific deployment descriptors. The default JAAS module implemented in GateIn synchronizes the users and roles from the database. In order to add your portal to a specific realm, add the following snippet in web.xml: <login-config> . . . <realm-name>gatein-domain</realm-name> . . . </login-config> Notice that a realm can be managed by JAAS or another authorization framework—it is not important which is used for the Java Enterprise Edition. gatein-domain is the ID of the default GateIn domain that we will use as the default reference for the following recipes. See also The Securing with JBoss AS recipe The Securing with Tomcat recipe Securing with JBoss AS In this recipe, we will configure GateIn with JAAS using JBoss AS (5.x and 6.x). Getting ready Locate the WEB-INF folder inside your portal application. How to do it... Create a new file named jboss-web.xml in the WEB-INF folder with the following content: <jboss-web> <security-domain> java:/jaas/gatein-domain </security-domain> </jboss-web> How it works... This is the JNDI URL where the JAAS module will be referenced. This URL will automatically search the JAAS modules called gatein-domain. The configuration of the modules can be found inside the file gatein-jboss-beans.xml. Usually, this file is inside the deployed <PORTAL_WAR_ROOT>/META-INF, but it could be placed anywhere inside the deploy directory of JBoss, thanks to the auto-discovery feature provided by the JBoss AS. Here is an example: <deployment > <application-policy name="gatein-domain"> <authentication> <login-module code= "org.gatein.wci.security.WCILoginModule" flag="optional"> <module-option name="portalContainerName"> portal </module-option> <module-option name="realmName"> gatein-domain </module-option> </login-module> <login-module code= "org.exoplatform.web.security.PortalLoginModule" flag="required"> ……….. </application-policy> </deployment> JAAS allows adding several login modules, which will be executed in cascade mode according to the flag attribute. The following represents a description of the valid values for the flag attribute and their respective semantics as mentioned in the Java standard API: Required: The LoginModule is required to succeed. If it succeeds or fails, authentication still continues to proceed to the next LoginModule in the list. Requisite: The LoginModule is required to succeed. If it succeeds, authentication continues on the next LoginModule in the list. If it fails, the control immediately returns to the application and the authentication process does not proceed to the next LoginModule. Sufficient: The LoginModule is not required to succeed. If it does succeed, the control immediately returns to the application and the authentication process does not proceed to the next LoginModule. If it fails, authentication continues forward to the next LoginModule Optional: The LoginModule is not required to succeed. If it succeeds or fails, authentication still continues to proceed to the next LoginModule. Look at the recipe Choosing the JAAS modules for details about each login module. See also The Securing portals recipe The Securing with Tomcat recipe The Choosing the JAAS modules recipe Securing with Tomcat In this recipe, we will configure a JAAS realm using Tomcat 6.x.x/7.x.x. Getting ready Locate the declaration of the realm inside <PORTAL_WAR_ROOT>/META-INF/context.xml. How to do it… Change the default configuration for your needs, as described in the previous recipe. The default configuration is the following: <Context path='/portal' docBase='portal' debug='0' reloadable='true' crossContext='true' privileged='true'> <Realm className= 'org.apache.catalina.realm.JAASRealm' appName='gatein-domain' userClassNames= 'org.exoplatform.services.security.jaas.UserPrincipal' roleClassNames= 'org.exoplatform.services.security.jaas.RolePrincipal' debug='0' cache='false'/> <Valve className= 'org.apache.catalina.authenticator.FormAuthenticator' characterEncoding='UTF-8'/> </Context> ; Change the default configuration of the JAAS domain that is defined in the TOMCAT_ HOME/conf/jaas.conf file. Here is the default configuration: <gatein-domain { org.gatein.wci.security.WCILoginModule optional; org.exoplatform.services.security.jaas.SharedStateLoginModule required; org.exoplatform.services.security.j2ee.TomcatLoginModule required; }; How it works… As we have seen in the previous recipe, we can configure the modules in Tomcat using a different configuration file. This means that we can change and add login modules that are related to a specific JAAS realm. The context.xml file is stored inside the web application. If you don't want to modify this file, you can add a new file called portal.xml in the conf folder to override the current configuration. See also The Security with JBoss AS recipe The Choosing the JAAS modules recipe
Read more
  • 0
  • 0
  • 1853

article-image-getting-your-course-ready-new-semester
Packt
22 Jan 2013
10 min read
Save for later

Getting Your Course Ready for a New Semester

Packt
22 Jan 2013
10 min read
(For more resources related to this topic, see here.) Introduction Getting your course ready for students at the beginning of each semester can be a daunting task. You'll need to verify links to external content, make sure that previous materials have been copied successfully to your new course, and modify the existing assignment dates, among other tasks. You get the point—there are quite a few things you need to take care of before students ever see your course. This article offers recipes for streamlining this process to make setting up your course as stress-free as possible. The first two recipes deal with getting materials into your course, whether you're copying an entire course from a previous semester or importing a compatible course cartridge provided by a textbook publisher. You may be surprised to know that course cartridges created for other Learning Management Systems ( LMSs) , such as Blackboard and Moodle, can often be imported without any trouble! Other recipes in the article focus on making quick work of date changes and external link validation. We'll wrap up the article by previewing everything from the student's view. Please note that the recipes in this article, as well as the rest of the book, are written for Version 10.0 of the Desire2Learn Learning Environment. While many of the recipes are also applicable to earlier versions of the system, you may need to modify the steps to follow along. Copying course materials from a previous semester Copying materials, activities, and settings from one course to another can save you a considerable amount of time when preparing for the start of a new semester. The learning environment's Import /Export /Copy Components tool allows you to easily clone an entire course or select just the parts of the original course that you want to use in a new course. In this recipe, we will discuss copying materials from an existing course within the system. We will use the same tool to import a course cartridge from a publisher in the next recipe. Getting ready The Desire2Learn (D2L) Learning Environment is highly customizable, and each organization that uses it can customize many aspects of the user experience. This recipe assumes that your school has allowed the use of the Import/Export/Copy Components tool for your specific role within the system. In order to complete this recipe, you'll also need access to two courses—an empty course that we will be copying materials to and another one that contains the materials we will be copying. To copy materials from one course to another, your role in both courses needs to allow the use of the Copy Components function. For example, you wouldn't be able to copy quizzes from a class in which you are enrolled as a student into one that you are teaching. How to do it... We will be working with two courses in this recipe – a new, empty course and an existing course that contains the materials to be copied. Remember to start by accessing the destination course or the course that you want to copy materials to. Start by accessing the destination course from My Homepage. Click on the Edit Course link in the course navigation bar. Click the Import/Export/Copy Components link under the Site Resources heading. Select the option Copy Components from Another Org Unit and then click on Start. Locate the course from which we will be copying materials by clicking on the Search for offering link. If needed, use the search tool at the top of the list of courses to help locate the course. You can also click on any of the column headers to sort the list of courses based on that field (clicking twice reverses the order). Check the radio button to the left of the course, and click on the Add Selected button. Within a few seconds, the page updates to display all of the available components from the course we just selected. To clone an entire course, check the Select All Components box, and click on the Continue button. Since we chose to clone an entire course, we can continue on our way by clicking on the Finish button. Depending on the amount of materials being copied and the server load, the copy process may take a few seconds to several minutes. When the Done button becomes active, it means that the process has completed. As each tool finishes copying, you'll see its progress indicator change into a green checkmark. Anything that didn't copy successfully will be noted in the summary. How it works… We start off by accessing the destination course. The Search for Offering screen displays a list of all of the courses you currently have access to copy from. If you've been teaching for a while, this list may be quite large. The search and filtering tools at the top of the course offering list may be helpful if you are having difficulty finding the correct course from the list. In this recipe, we copied all the available components from the source offering by choosing the Select All Components option. However, you can copy individual tools or even individual items within those tools by choosing the Select individual items to copy option. If you decide to copy specific components, then you need to select those items on the Choose Components to Copy screen, as shown in the following screenshot: There's more... If you're copying large course files or complex question libraries, there's a chance that your browser will time out before the copy process is complete. If this happens, there are a few things you can do to complete the task: Break up the copy process into several smaller jobs. If, for example, you're getting error messages while copying Course Files, try only copying half of the files, then return to the tool and try the second half later. The current server load can greatly impact the time it takes to copy components. You may want to try copying the components during an off-peak time. If you experience a browser time-out while copying Course Files, you might want to visit File Manager and look for duplicate or large files in the source course. Deleting unnecessary files can speed up the process significantly. Your Desire2Learn administrator has access to other ways of cloning a course or copying files. If you continue to experience difficulty with the tool, talking with your friendly admin would be a great idea! Importing a publisher's course cartridge Publishers frequently offer complimentary course cartridges to instructors who adopt their textbooks. The content of these cartridges varies greatly, but can include content and files, assessments, web links, and more. In this recipe, we will walk through the process of importing a course cartridge into an existing Desire2Learn Learning Environment course. Getting ready In order to complete this recipe, you'll need either a publisher's cartridge or an export from another Desire2Learn Learning Environment course. These files come in the form of .zip archives. Publishers typically offer different versions of cartridges for several of the major learning management systems. While you may not always find a version of a particular cartridge formatted for the Desire2Learn Learning Environment, you may be surprised to know that versions made for other systems, such as Blackboard 6 and WebCT, will typically work just fine. Check with your system administrator, if you have any difficulties importing a cartridge. You will also need access to the Import/Export/Copy Components tool. You will need to talk with your Desire2Learn system administrator if your role in the current course does not include access to the tool. How to do it... Start off by accessing the destination course from the My Home page. Click on the Edit Course link in the course's navigation bar. Access the Import/Export/Copy Components tool by clicking on the link under the Site Resources heading. Select the option to Import Components. Then, select the from a File option and choose the cartridge to import by clicking on the Choose File button. Click on the Start button after locating and selecting the file: Click on the Continue button on the Preprocessing screen when it becomes available. Import the entire cartridge's contents by choosing the Select All Components checkbox and then clicking on the Continue button. Click on the Continue button on the Confirm Import Selections screen. The process is complete when all of the progress indicators have changed to green checkmarks. Click on Finish, then Done when the components are finished copying. How it works... We start off by accessing the Import/Export/Copy Components tool in the destination course. After selecting the .zip folder to import, the system uploads and pre-processes the archive's manifest file. Depending on the complexity of the cartridge and the size of the archive, this can happen very quickly or it may take quite some time. After the pre-process action is complete, we choose to import the entire cartridge into the course, just as we did in the previous recipe. While this is often the easiest approach, it is possible to pick and choose individual components (such as Quizzes or Grades) or even individual items (such as specific quizzes or grade items), as we will discuss in the following section. Once you verify the components to be imported, it's just a matter of waiting for the progress indicators to become green checkmarks. Any item not able to be imported will be displayed on screen at the end of the process. You probably won't run into too many problems unless you are importing extremely large or complex cartridges, but it is always a good idea to verify that everything was successful before clicking on the Done button. There's more... In the last two scenarios, we have seen examples of copying and importing entire courses. While this is common at the beginning of the semester, there may be times when you will need only certain parts of another course. Suppose, for example, you only want the question library portion of a publisher's course cartridge. Luckily, this is easily accomplished by selecting individual components on the Choose Components to Copy screen instead of the All Components option. In the following screenshot, I have chosen to copy all the available Content items, but only selected Discussions and Dropbox folders: After selecting the components to copy and clicking on the Continue button, I'm prompted to select the individual quizzes I want to copy into my course. Clicking on the Expand All link shows a list of all quizzes, and selecting individual items to be imported is as easy as checking the option next to the item titles. Since I've chosen to also import selected Dropbox folders, I would complete a similar process for selecting those items on the next screen: I should point out one "gotcha" that frequently causes trouble for new users of the Desire2Learn Learning Environment. Items under the Content heading are frequently linked to uploaded documents or system-generated HTML files, which are stored in the File Manager. Unfortunately, selecting the items under Content doesn't copy these associated files, so you need to manually select these files under Course Files. Since this can be a somewhat tricky task depending on how you've organized your files, you may find it easier to copy everything and delete what you do not need. See also The Copying course materials from a previous semester recipe
Read more
  • 0
  • 0
  • 1622
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-creating-and-configuring-basic-mobile-application
Packt
17 Jan 2013
3 min read
Save for later

Creating and configuring a basic mobile application

Packt
17 Jan 2013
3 min read
(For more resources related to this topic, see here.) How to do it... Follow these steps: Inside your Magento Admin Panel, navigate to Mobile | Manage Apps on the main menu. Click on the Add App button in the top-right corner. The New App screen will be shown. Since we have to create a separate application for each mobile device type, let's choose our first targeted platform. Under the Device Type list, we can choose iPad, iPhone, or Android. For the purpose of this recipe, since the procedure is almost the same for all device types, I will choose Android. After choosing the desired Device Type, click on the Continue button, and click on the General tab under Manage Mobile App. First we have to fill in the box named App Name. Choose an appropriate name for your mobile application and insert it there. Under the Store View list, make sure to choose our earlier defined Store View with updated mobile theme exceptions, our mobile copyright information, and category thumbnail images. Set the Catalog Only App option to No. Click on the Save and Continue Edit button in the top-right corner of the screen. Now you will notice a warning message from Magento that says something like the following: Please upload an image for "Logo in Header" field from Design Tab. Please upload an image for "Banner on Home Screen" field from Design Tab. Don't worry, Magento expects us to add some basic images that we prepared for our mobile app. So let's add them. Click on the Design tab on the left-hand side of the screen. Locate the Logo in Header label and click on the Browse... button on the right to upload the prepared small header logo image. Make sure to upload the image with proper dimensions for the selected device type (iPhone, iPad, or Android). In the same way, click on the Browse... button on the right of the Banner on Home Screen label and choose the appropriate prepared and resized banner image. Now, let's click on the Save and Continue Edit button in order to save our settings. How it works For each device type, we will have to create a new Magento Mobile application in our Magento Mobile Admin Panel. When we once select Device Type and click on the Save button, we are unable to change Device Type later for that application. If we have chosen the wrong Device Type, the only solution is to delete this app and to create a new one with the proper settings. The same applies with our chosen Store View when configuring new app. There's more... When our configuration is saved for the first time, auto-generated App Code will appear on the screen and that will be the code which will uniquely identify our Device Type—the assigned application to be properly recognized with Magento Mobile. For example, defand1 means that this application is the first defined application for the default Store View targeted on android (def = default store view, and=android). How to use mobile application as catalog only Under step 7 we set Catalog Only App to No, but sometimes, if we don't need checkout and payment in our mobile app, but we want to use it just as catalog to show products to our mobile customers, we just need to set the Catalog Only option to Yes. Summary So this is how we create the basic configuration for our mobile app Resources for Article : Further resources on this subject: Integrating Twitter with Magento [Article] Integrating Facebook with Magento [Article] Getting Started with Magento Development [Article]
Read more
  • 0
  • 0
  • 4028

article-image-building-your-first-application
Packt
10 Jan 2013
12 min read
Save for later

Building Your First Application

Packt
10 Jan 2013
12 min read
(For more resources related to this topic, see here.) Improving the scaffolding application In this recipe, we discuss how to create your own scaffolding application and add your own configuration file. The scaffolding application is the collection of files that come with any new web2py application. How to do it... The scaffolding app includes several files. One of them is models/db.py, which imports four classes from gluon.tools (Mail, Auth, Crud, and Service), and defines the following global objects: db, mail, auth, crud, and service. The scaffolding application also defines tables required by the auth object, such as db.auth_user. The default scaffolding application is designed to minimize the number of files, not to be modular. In particular, the model file, db.py, contains the configuration, which in a production environment, is best kept in separate files. Here, we suggest creating a configuration file, models/0.py, that contains something like the following: from gluon.storage import Storage settings = Storage() settings.production = False if settings.production: settings.db_uri = 'sqlite://production.sqlite' settings.migrate = False else: settings.db_uri = 'sqlite://development.sqlite' settings.migrate = True settings.title = request.application settings.subtitle = 'write something here' settings.author = 'you' settings.author_email = 'you@example.come' settings.keywords = '' settings.description = '' settings.layout_theme = 'Default' settings.security_key = 'a098c897-724b-4e05-b2d8-8ee993385ae6' settings.email_server = 'localhost' settings.email_sender = 'you@example.com' settings.email_login = '' settings.login_method = 'local' settings.login_config = '' We also modify models/db.py, so that it uses the information from the configuration file, and it defines the auth_user table explicitly (this makes it easier to add custom fields): from gluon.tools import * db = DAL(settings.db_uri) if settings.db_uri.startswith('gae'): session.connect(request, response, db = db) mail = Mail() # mailer auth = Auth(db) # authentication/authorization crud = Crud(db) # for CRUD helpers using auth service = Service() # for json, xml, jsonrpc, xmlrpc, amfrpc plugins = PluginManager() # enable generic views for all actions for testing purpose response.generic_patterns = ['*'] mail.settings.server = settings.email_server mail.settings.sender = settings.email_sender mail.settings.login = settings.email_login auth.settings.hmac_key = settings.security_key # add any extra fields you may want to add to auth_user auth.settings.extra_fields['auth_user'] = [] # user username as well as email auth.define_tables(migrate=settings.migrate,username=True) auth.settings.mailer = mail auth.settings.registration_requires_verification = False auth.settings.registration_requires_approval = False auth.messages.verify_email = 'Click on the link http://' + request.env.http_host + URL('default','user', args=['verify_email']) + '/%(key)s to verify your email' auth.settings.reset_password_requires_verification = True auth.messages.reset_password = 'Click on the link http://' + request.env.http_host + URL('default','user', args=['reset_password']) + '/%(key)s to reset your password' if settings.login_method=='janrain': from gluon.contrib.login_methods.rpx_account import RPXAccount auth.settings.actions_disabled=['register', 'change_password', 'request_reset_password'] auth.settings.login_form = RPXAccount(request, api_key = settings.login_config.split(':')[-1], domain = settings.login_config.split(':')[0], url = "http://%s/%s/default/user/login" % (request.env.http_host, request.application)) Normally, after a web2py installation or upgrade, the welcome application is tar-gzipped into welcome.w2p, and is used as the scaffolding application. You can create your own scaffolding application from an existing application using the following commands from a bash shell: cd applications/app tar zcvf ../../welcome.w2p * There's more... The web2py wizard uses a similar approach, and creates a similar 0.py configuration file. You can add more settings to the 0.py file as needed. The 0.py file may contain sensitive information, such as the security_key used to encrypt passwords, the email_login containing the password of your smtp account, and the login_config with your Janrain password (http://www.janrain.com/). You may want to write this sensitive information in a read-only file outside the web2py tree, and read them from your 0.py instead of hardcoding them. In this way, if you choose to commit your application to a version-control system, you will not be committing the sensitive information The scaffolding application includes other files that you may want to customize, including views/layout.html and views/default/users.html. Some of them are the subject of upcoming recipes. Building a simple contacts application When you start designing a new web2py application, you go through three phases that are characterized by looking for the answer to the following three questions: What data should the application store? Which pages should be presented to the visitors? How should the page content, for each page, be presented? The answer to these three questions is implemented in the models, the controllers, and the views respectively. It is important for a good application design to try answering those questions exactly in this order, and as accurately as possible. Such answers can later be revised, and more tables, more pages, and more bells and whistles can be added in an iterative fashion. A good web2py application is designed in such a way that you can change the table definitions (add and remove fields), add pages, and change page views, without breaking the application. A distinctive feature of web2py is that everything has a default. This means you can work on the first of those three steps without the need to write code for the second and third step. Similarly, you can work on the second step without the need to code for the third. At each step, you will be able to immediately see the result of your work; thanks to appadmin (the default database administrative interface) and generic views (every action has a view by default, until you write a custom one). Here we consider, as a first example, an application to manage our business contacts, a CRM. We will call it Contacts. The application needs to maintain a list of companies, and a list of people who work at those companies. How to do it... First of all we create the model. In this step we identify which tables are needed and their fields. For each field, we determine whether they: Must contain unique values (unique=True) Contain empty values (notnull=True) Are references (contain a list of a record in another table) Are used to represent a record (format attribute) From now on, we will assume we are working with a copy of the default scaffolding application, and we only describe the code that needs to be added or replaced. In particular, we will assume the default views/layout.html and models/db.py. Here is a possible model representing the data we need to store in models/db_contacts.py: # in file: models/db_custom.py db.define_table('company', Field('name', notnull=True, unique=True), format='%(name)s') db.define_table('contact', Field('name', notnull=True), Field('company', 'reference company'), Field('picture', 'upload'), Field('email', requires=IS_EMAIL()), Field('phone_number', requires=IS_MATCH('[d-() ]+')), Field('address'), format='%(name)s') db.define_table('log', Field('body', 'text',notnull=True), Field('posted_on', 'datetime'), Field('contact', 'reference contact')) Of course, a more complex data representation is possible. You may want to allow, for example, multiple users for the system, allow the same person to work for multiple companies, and keep track of changes in time. Here, we will keep it simple. The name of this file is important. In particular, models are executed in alphabetical order, and this one must follow db.py. After this file has been created, you can try it by visiting the following url: http://127.0.0.1:8000/contacts/appadmin, to access the web2py database administrative interface, appadmin. Without any controller or view, it provides a way to insert, select, update, and delete records. Now we are ready to build the controller. We need to identify which pages are required by the application. This depends on the required workflow. At a minimum we need the following pages: An index page (the home page) A page to list all companies A page that lists all contacts for one selected company A page to create a company A page to edit/delete a company A page to create a contact A page to edit/delete a contact A page that allows to read the information about one contact and the communication logs, as well as add a new communication log Such pages can be implemented as follows: # in file: controllers/default.py def index(): return locals() def companies(): companies = db(db.company).select(orderby=db.company.name) return locals() def contacts(): company = db.company(request.args(0)) or redirect(URL('companies')) contacts = db(db.contact.company==company.id).select( orderby=db.contact.name) return locals() @auth.requires_login() def company_create(): form = crud.create(db.company, next='companies') return locals() @auth.requires_login() def company_edit(): company = db.company(request.args(0)) or redirect(URL('companies')) form = crud.update(db.company, company, next='companies') return locals() @auth.requires_login() def contact_create(): db.contact.company.default = request.args(0) form = crud.create(db.contact, next='companies') return locals() @auth.requires_login() def contact_edit(): contact = db.contact(request.args(0)) or redirect(URL('companies')) form = crud.update(db.contact, contact, next='companies') return locals() @auth.requires_login() def contact_logs(): contact = db.contact(request.args(0)) or redirect(URL('companies')) db.log.contact.default = contact.id db.log.contact.readable = False db.log.contact.writable = False db.log.posted_on.default = request.now db.log.posted_on.readable = False db.log.posted_on.writable = False form = crud.create(db.log) logs = db( db.log.contact==contact.id).select(orderby=db.log.posted_on) return locals() def download(): return response.download(request, db) def user(): return dict(form=auth()) Make sure that you do not delete the existing user, download, and service functions in the scaffolding default.py. Notice how all pages are built using the same ingredients: select queries and crud forms. You rarely need anything else. Also notice the following: Some pages require a request.args(0) argument (a company ID for contacts and company_edit, a contact ID for contact_edit, and contact_logs). All selects have an orderby argument. All crud forms have a next argument that determines the redirection after form submission. All actions return locals(), which is a Python dictionary containing the local variables defined in the function. This is a shortcut. It is of course possible to return a dictionary with any subset of locals(). contact_create sets a default value for the new contact company to the value passed as args(0). The contacts_logs retrieves past logs after processing crud.create for a new log entry. This avoid unnecessarily reloading of the page, when a new log is inserted. At this point our application is fully functional, although the look-and-feel and navigation can be improved.: You can create a new company at: http://127.0.0.1:8000/contacts/default/company_create You can list all companies at: http://127.0.0.1:8000/contacts/default/companies You can edit company #1 at: http://127.0.0.1:8000/contacts/default/company_edit/1 You can create a new contact at: http://127.0.0.1:8000/contacts/default/contact_create You can list all contacts for company #1 at: http://127.0.0.1:8000/contacts/default/contacts/1 You can edit contact #1 at: http://127.0.0.1:8000/contacts/default/contact_edit/1 And you can access the communication log for contact #1 at: http://127.0.0.1:8000/contacts/default/contact_logs/1 You should also edit the models/menu.py file, and replace the content with the following: response.menu = [['Companies', False, URL('default', 'companies')]] The application now works, but we can improve it by designing a better look and feel for the actions. That's done in the views. Create and edit file views/default/companies.html: {{extend 'layout.html'}} <h2>Companies</h2> <table> {{for company in companies:}} <tr> <td>{{=A(company.name, _href=URL('contacts', args=company.id))}}</td> <td>{{=A('edit', _href=URL('company_edit', args=company.id))}}</td> </tr> {{pass}} <tr> <td>{{=A('add company', _href=URL('company_create'))}}</td> </tr> </table> response.menu = [['Companies', False, URL('default', 'companies')]] Here is how this page looks: Create and edit file views/default/contacts.html: {{extend 'layout.html'}} <h2>Contacts at {{=company.name}}</h2> <table> {{for contact in contacts:}} <tr> <td>{{=A(contact.name, _href=URL('contact_logs', args=contact.id))}}</td> <td>{{=A('edit', _href=URL('contact_edit', args=contact.id))}}</td> </tr> {{pass}} <tr> <td>{{=A('add contact', _href=URL('contact_create', args=company.id))}}</td> </tr> </table> Here is how this page looks: Create and edit file views/default/company_create.html: {{extend 'layout.html'}} <h2>New company</h2> {{=form}} Create and edit file views/default/contact_create.html: {{extend 'layout.html'}} <h2>New contact</h2> {{=form}} Create and edit file: views/default/company_edit.html: {{extend 'layout.html'}} <h2>Edit company</h2> {{=form}} Create and edit file views/default/contact_edit.html: {{extend 'layout.html'}} <h2>Edit contact</h2> {{=form}} Create and edit file views/default/contact_logs.html: {{extend 'layout.html'}} <h2>Logs for contact {{=contact.name}}</h2> <table> {{for log in logs:}} <tr> <td>{{=log.posted_on}}</td> <td>{{=MARKMIN(log.body)}}</td> </tr> {{pass}} <tr> <td></td> <td>{{=form}}</td> </tr> </table> Here is how this page looks: Notice that in the last view, we used the function MARKMIN to render the content of the db.log.body, using the MARKMIN markup. This allows embedding links, images, anchors, font formatting information, and tables in the logs. For details about the MARKMIN syntax we refer to: http://web2py.com/examples/static/markmin.html.
Read more
  • 0
  • 0
  • 7105

article-image-adding-geographic-capabilities-geoplaces-theme
Packt
03 Jan 2013
6 min read
Save for later

Adding Geographic Capabilities via the GeoPlaces Theme

Packt
03 Jan 2013
6 min read
(For more resources related to this topic, see here.) Introducing the GeoPlaces theme The GeoPlaces theme (http://templatic.com/app-themes/geo-places-city-directory-WordPress-theme/), by Templatic (http://templatic.com), is a cool theme that allows you to create and manage a city directory website. For a live demo of the site, visit http://templatic.com/demos/?theme=geoplaces4. An overview of the GeoPlaces theme The GeoPlaces theme is created as an out-of-the-box solution for city directory websites. It allows end users to submit places and events to your site. Best of all, you can even monetize the site by charging a listing fee. Some of the powerful features include the following: Widgetized homepage Menu widgets Featured events and listings Custom fields Payment options Price packages page view Let's now move on to the setting up of the theme. Setting up the GeoPlaces theme We'll start with the installation of the GeoPlaces theme. Installation The steps for installing the GeoPlaces theme are as follows: You will first have to purchase and download your theme (in a zip folder) from Templatic. Unzip the zipped file and place the GeoPlaces folder in your wp-content/themes folder. Log in to your WordPress site, which you have set up, and activate the theme. Alternatively, you can upload the theme by uploading the theme's zip folder via the admin interface, by going to Appearance | Install Themes | Upload. If everything goes well, you should see the following on the navigation bar of your admin page: If you see the previous screenshot in your navigation, than you are ready to move on to the next step. Populating the site with sample data After a successful installation of the theme, you can go ahead and play around with the site by creating sample data. GeoPlaces themes come with a nifty function that allows you to populate your site with sample data. Navigate to wp-admin/themes.php and you should see the following: Notice the message box asking if you want to install and populate your site with sample data. Click on the large green button and sample data will automatically be populated. Once done, you should see the following: You can choose to delete the sample data should you want to. But for now, let's leave the sample data for browsing purposes. Playing with sample data Now that we have populated the site with sample data, its time to explore it. Checking out cities With our site populated with sample data, let's take our WordPress site for a spin: First, navigate to your homepage; you should be greeted by a splash page that looks as follows: Now select New York and you will be taken to a page with a Google Map that looks like the following screenshot: GeoPlaces leverages on the Google Maps API to provide geographic capabilities to the theme. Feel free to click on the map and other places, such as Madison Square Park. If you click on Madison Square Park you will see a page that describes Madison Square Park. More importantly, on the right hand side of the page, you should see something like the following: Notice the Address row? The address is derived from the Google Maps API. How does it work? Let's try adding a place to find out. Adding a place from the frontend Here's how we can add a "place" from the frontend of the site: To add a place, you must first sign in. Sign in from the current page by clicking on the Sign In link found at the top right-hand side of the page. Sign in with your credentials. Notice that you remain on the frontend of the site as opposed to the administration side. Now click on the Add place link found on the upper right-hand side of the webpage. You should see the following: You will be greeted by a long webpage that requires you to fill up various fields that are required for listing a page. You should take note of this, as shown in the following screenshot: Try typing Little Italy in the Address field and click on the Set address on map button. You should notice that the map is now marked, and the Address Latitude and Address Longitude fields are now filled up for you. Your screen for this part of the webpage should now look as follows: The geographically related fields are now filled up. Continue to fill up the other fields, such as the description of this listing, the type of Google map view, special offers, e-mail address, website, and other social media related fields. With these steps, you should have a new place listing in no time. Adding a place from the admin side What you have just done is added a place listing from the frontend, as an end user (although you are logged in as admin). So, how do you add a place listing from the admin side of your WordPress site? Firstly, you need to log in to your site if you have not yet done so. Next, navigate to your admin homepage, and go to Places | Add a Place. You will see a page that resembles the Create a New Post page. Scroll down further and you should notice that the forms filled here are exactly the same as those you see in the frontend of the site. For example, fields for the geographic information are also found on this page: Adding a city from the admin side To add a city, all you have to do is to log in to the admin side of the site via /wpadmin. Once logged in, go to GeoPlaces | Manage City and click on Add City. From there you'll be able to fill up the details of the city. Summary We saw how to manage our WordPress site, covering topics such as populating the site with sample data, adding place listings, and adding a city. You should have a general idea of the geographic capabilities of the theme and how to add a new placelisting. Notice how the theme takes the heavy lifting away by providing built-in geographic functionalities through the Google Maps API. We also understood how themes and plugins can be used to extend WordPress. Resources for Article : WordPress Mobile Applications with PhoneGap: Increasing Traffic to Your Blog with WordPress MU 2.8: Part2 [Article] WordPress 3: Designing your Blog [Article] Adapting to User Devices Using Mobile Web Technology [Article]
Read more
  • 0
  • 0
  • 2883

article-image-components-reusing-rules-conditions-and-actions
Packt
03 Jan 2013
4 min read
Save for later

Components - Reusing Rules, Conditions, and Actions

Packt
03 Jan 2013
4 min read
(For more resources related to this topic, see here.) Getting ready Enable the Rules and Rules UI modules on your site. How to do it... Go to Confguration | Workfow | Rules | Components. Add a new component and set the plugin to Condition set (AND). Enter a name for the component and add a parameter Entity | Node. Add a Condition, Data comparison, set the value to the author of the node, set OPERATOR to equals, enter 1 in the Data value field and tick Negate. Add an OR group by clicking on Add or, as shown in the following screenshot: Add a Condition, Node | Content is of type and set it to Article. Add a Condition, Entity | Entity has field, set Entity to node, and select the field, field_image, as shown in the following screenshot: Organize the Conditions so that the last two Conditions are in the OR group we created before. Create a new rule configuration and set the Event to Comment | After saving a new comment. Add a new Condition and select the component that we created. An example is shown in the following screenshot: Select comment:node as the parameter. Add a new Action, System | Show a message on the site and configure the message. How it works... Components require parameters to be specified, that will be used as placeholders for the objects we want to execute a rule configuration on. Depending on what our goal is, we can select from the core Rules data types, entities, or lists. In this example, we've added a Node parameter to the component, because we wanted to see who is the node's author, if it's an article or if it has an image field. Then in our Condition, we've provided the actual object on which we've evaluated the Condition. If you're familiar with programming, then you'll see that components are just like functions; they expect parameters and can be re-used in other scenarios. There's more... The main benefit of using Rules components is that we can re-use complex Conditions, Actions, and other rule configurations. That means that we don't have to configure the same settings over and over again. Instead we can create components and use them in our rule configurations. Other benefits also include exportability: components can be exported individually, which is a very useful addition when using configuration management, such as Features. Components can also be executed on the UI, which is very useful for debugging and can also save a lot of development time. Other component types Apart from Condition sets, there are a few other component types we can use. They are as follows: Action set As the name suggests, this is a set of Actions, executed one after the other. It can be useful when we have a certain chain of Actions that we want to execute in various scenarios. Rule We can also create a rule configuration as a component to be used in other rule configurations. Think about a scenario when you want to perform an action on a list of node references (which would require a looped Action) but only if those nodes were created before 2012. While it is not possible to create a Condition within an Action, we can create a Rule component so we can add a Condition and an Action within the component itself and then use it as the Action of the other rule configuration. Rule set Rule sets are a set of Rules, executed one after the other. It can be useful when we want to execute a chain of Rules when an event occurs. Parameters and provided variables Condition sets require parameters which are input data for the component. These are the variables that need to be specified so that the Condition can evaluate to FALSE or TRUE. Action sets, Rules, and Rule sets can provide variables. That means they can return data after the action is executed. Summary This article explained the benefits of using Rules components by creating a Condition that can be re-used in other rule configurations. Resources for Article : Further resources on this subject: Drupal 7 Preview [Article] Creating Content in Drupal 7 [Article] Drupal FAQs [Article]
Read more
  • 0
  • 0
  • 2574
article-image-augmentedti-application-architecture
Packt
31 Dec 2012
5 min read
Save for later

augmentedTi: The application architecture

Packt
31 Dec 2012
5 min read
(For more resources related to this topic, see here.) An overview The augmentedTi application has been developed to demonstrate Augmented Reality in action; it has been coded using the Appcelerator Titanium Framework. This framework enables a "code once, adapt everywhere" approach to mobile application development. It uses the commonJS architecture at its core and has a set of best practices, which can be read at https://wiki.appcelerator.org/display/guides/Best+Practices. The application follows these guidelines and also implements an MVC style architecture, using a controller, and event driven flow control methodology incorporating localization. At the current time trying to implement a CSS applied look and feel using the frameworks JSS method is not viable. The application gets around the issue of hard coding fonts, colors, and images into the application by using two files—ui/layout.js and ui/images.js. These files contain the look, feel, and images applied throughout the application, and are standalone modules, enabling them to be included in any other modules. The application As you start to explore the application you will see that the main bootstrap file app.js only contains the require of the controller file and the call to the initial function startApp(): var ctl = require('/control/controller'); ctl.startApp(); To implement methodology for separating the code into distinct commonJS modules, the following file structure is applied: i18n/en/strings.xml resources/app.js resources/control/controller.js resources/images resources/services/googleFeed.js location.js resources/tools/augmentedReality.js common.js iosBackgroundService.js persHandler.js ui/images.js layout.js common/activity.js titleBar.js screens/ARScreen.js homeScreen.js The main file which controls the application is controller.js. When an activity is completed, the control is returned here and the next activity is processed. This has an implication with enabling the program flow—application-level event listeners have to be added, using up resources. The application gets around this by creating a single custom event listener, which then calls a function to handle the flow. The fire event is handled within the tools/common.js file by providing a single function to be called, passing the required type and any other parameters: Ti.App.addEventListener('GLOBALLISTENER', function(inParam){ var gblParams = {}; for(var paramKeyIn in inParam) { if(inParam[paramKeyIn]) { gblParams[paramKeyIn] = inParam[paramKeyIn]; }} processGlobalListener(gblParams);}); function launchEvent(inParam){ var evtParams = {}; for(var paramKeyIn in inParam) { if(inParam[paramKeyIn]) { evtParams[paramKeyIn] = inParam[paramKeyIn]; }} Ti.App.fireEvent('GLOBALLISTENER', evtParams);} common.launchEvent({ TYPE : 'ERROR', MESS : 'E0004'}); Throughout the application's commonJS modules, a standard approach is taken, defining all functions and variables as local and exporting only those required at the end of the file: exports.startApp = startApp; In keeping with the commonJS model, the modules are only required when and where they are needed. No application-level global variables are used and each part of the application is split into its own module or set of modules. Within the application where data has to be stored, persistent data is used. It could have been passed around, but the amount of data is small and required across the whole application. The persistent data is controlled through the tools/persHandler.js module, which contains two functions—one for setting and one for getting the data. These functions accept the parameter of the record to update or return. var persNames = { lon : 'longitude', lat : 'latitude', width : 'screenWidth', height : 'screenHeight', bearing : 'bearing' }; function putPersData(inParam){ Ti.App.Properties.setString(persNames[inParam.type], inParam.data); return;} persHandler.putPersData({ type : 'width', data : Ti.Platform.displayCaps.platformWidth }); The application does not use the in-built tab navigation; instead it defines a custom title bar and onscreen buttons. This enables it to work across all platforms with the same look and feel. It also uses a custom activity indicator. Augmented Reality This section explains what Augmented Reality is and the solution provided within the augmentedTi application. With all technology something and somebody has to be first. Mobile computing and especially smart phones are still in their infancy. Resulting in new technologies, applications, and solutions being devised and applied almost daily. Augmented Reality is only now becoming viable, as the devices, technology, and coding solutions are more advanced. In this section a coding solution is given, which shows how to implement location-based Augmented Reality. It should work on most smart phones, and can be coded in most frameworks and native code. The code examples given use the Appcelerator Titanium Framework only. No additional modules or plugins are required. Summary This article dived into the open source code base of the augmentedTi example application, explaining how it has been implemented. Resources for Article : Further resources on this subject: iPhone: Customizing our Icon, Navigation Bar, and Tab Bar [Article] Animating Properties and Tweening Pages in Android 3-0 [Article] Flash Development for Android: Visual Input via Camera [Article]
Read more
  • 0
  • 0
  • 2086

article-image-null-15
Packt
26 Dec 2012
6 min read
Save for later

Extending WordPress to the Mobile World

Packt
26 Dec 2012
6 min read
Introducing jQuery Mobile jQuery Mobile (http://jquerymobile.com/) is a unified HTML5-based user interface for most popular mobile device platforms. It is based on jQuery (http://jquery.com/) and jQuery UI (http://jqueryui.com/). Our focus in this section is on jQuery Mobile, so let's get our hands dirty. We'll start by implementing jQuery Mobile using the example we created in Chapter 3, Extending WordPress Using JSON-API. Installing jQuery Mobile and theming Installing jQuery Mobile is straightforward and easy: Open up app_advanced.html and copy and paste the following code directly within the <head> tags: <meta name="viewport" content="width=device-width, initialscale= 1"> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.1/ jquery.mobile-1.1.1.min.css" /> <script src="http://code.jquery.com/jquery-1.7.1.min.js"> </script> <script src="http://code.jquery.com/mobile/1.1.1/jquery.mobile- 1.1.1.min.js"> </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/ jquery.min.js"> </script> Now save your code and open up app_advanced.html in your favourite browser. You should be seeing the following screen: Well, it looks like the webpage has gotten some form of theming, but it looks a little weird. This is because we have not implemented various HTML elements required for jQuery Mobile. Again, as mentioned in the previous chapter, the code sample assumes that your app has Internet access and hence access to jQuery and jQuery Mobile's CDN. This might reduce the app's startup time. To avoid the problem related to having no network or flaky connectivity, one basic thing you can do is to package your app together with a local copy of jQuery and jQuery Mobile. Let us move on to the next section and see how we can fix this. jQuery Mobile page template Let's go back to app_advanced.html and do some editing. Let us focus on the HTML elements found within <body> tags; change them to look like the following code snippet: <div id="main" data-role="page"> <div data-role="header"> <div data-role="controlgroup" data-type="horizontal"> <a href="#" id="previous" data-role="button">Previous</a> <a href="#" id="next" data-role="button">Next</a> <!-- <button type="button" id="create" datarole=" button">Create</button> --> <a href="#create_form" data-role="button" datatransition=" slide">Create</a> </div> </div> <div id="contents" data-role="content"></div> </div> <div data-role="page" id="create_form" data-theme="c"> <div data-role="header" addBackBtn="true"> <a href="#" data-rel="back">Back</a> <h1>Create a new Post</h1> </div> <div id="form" style="padding:15px;"> Title: <br /><input type="text" name="post_title" id="post_ title" /><br /> Content: <br /> <textarea name="post_contents" id="post_contents"></textarea> <br /> <input type="submit" value="Submit" id="create_post"/> <div id="message"></div> </div> </div> Now save your code and open it in your favourite web browser. You should see the following screen: The app now looks great! Feel free to click on the Next button and see how the app works. How does this all work? For a start, check out the highlighted lines of code. In the world of HTML5, the additional lines of HTML code we wrote, such as data-role="page" or data-theme="c", are known as custom data attributes. jQuery Mobile makes use of these specifications to denote the things we need in our mobile web app. For example, data-role="page" denotes that this particular element (in our case, a div element) is a page component. Similarly, datatheme="c" in our case refers to a particular CSS style. For more information about data theme, feel free to check out http://jquerymobile.com/test/docs/content/content-themes.html. Animation effects Now let us try a little bit with animation effects . We can create animation effects by simply leveraging what we know with jQuery. What about jQuery Mobile? There are several animation effects that are distinct to jQuery Mobile, and in this section we will try out animation effects in terms of page transitions. We will create a page transition effect using the following steps: Click on the Create button, and we will get a page transition effect to a new page, where we see our post creation form. On this Create a new Post form, as usual, type in some appropriate text in the Title and Content fields. Finally, click on the Submit button. Let's see how we can achieve the page transition effect: We need to make changes to our code. For the sake of simplicity, delete all HTML code found within your <body> tags in app_advanced.html, and then copy the following code into your <body> tags: <div id="main" data-role="page"> <div data-role="header"> <div data-role="controlgroup" data-type="horizontal"> <a href="#" id="previous" data-role="button">Previous</a> <a href="#" id="next" data-role="button">Next</a> <!-- <button type="button" id="create" datarole=" button">Create</button> --> <a href="#create_form" data-role="button" datatransition=" slide">Create</a> </div> </div> <div id="contents" data-role="content"></div> </div> <div data-role="page" id="create_form" data-theme="c"> <div data-role="header" addBackBtn="true"> <a href="#" data-rel="back">Back</a> <h1>Create a new Post</h1> </div> <div id="form" style="padding:15px;"> Title: <br /><input type="text" name="post_title" id="post_ title" /><br /> Content: <br /> <textarea name="post_contents" id="post_contents"></ textarea> <br /> <input type="submit" value="Submit" id="create_post"/> <div id="message"></div> </div> </div> Take note that we have used the transition="slide" attribute, so we have a "slide" effect. For more details or options, visit http://jquerymobile.com/test/docs/pages/page-transitions.html. Now, save your code and open it in your favorite web browser. Click on the Create button, and you will first see a slide transition, followed by the post creation form, as follows: Now type in some text, and you will see that jQuery Mobile takes care of the CSS effects in this form as well: Now click on the Submit button, and you will see a Success message below the Submit button, as shown in the following screenshot: If you see the Success message, as shown in the earlier screenshot, congratulations! We can now move on to extending our PhoneGap app, which we built in Chapter 4, Building Mobile Applications Using PhoneGap.
Read more
  • 0
  • 0
  • 2045

article-image-advanced-indexing-and-array-concepts
Packt
26 Dec 2012
6 min read
Save for later

Advanced Indexing and Array Concepts

Packt
26 Dec 2012
6 min read
(For more resources related to this topic, see here.) Installing SciPy SciPy is the scientific Python library and is closely related to NumPy. In fact, SciPy and NumPy used to be one and the same project many years ago. In this recipe, we will install SciPy. How to do it... In this recipe, we will go through the steps for installing SciPy. Installing from source: If you have Git installed, you can clone the SciPy repository using the following command: git clone https://github.com/scipy/scipy.gitpython setup.py buildpython setup.py install --user This installs to your home directory and requires Python 2.6 or higher. Before building, you will also need to install the following packages on which SciPy depends: BLAS and LAPACK libraries C and Fortran compilers There is a chance that you have already installed this software as a part of the NumPy installation. Installing SciPy on Linux: Most Linux distributions have SciPy packages. We will go through the necessary steps for some of the popular Linux distributions: In order to install SciPy on Red Hat, Fedora, and CentOS, run the following instructions from the command line: yum install python-scipy In order to install SciPy on Mandriva, run the following command line instruction: urpmi python-scipy In order to install SciPy on Gentoo, run the following command line instruction: sudo emerge scipy On Debian or Ubuntu, we need to type the following: sudo apt-get install python-scipy Installing SciPy on Mac OS X: Apple Developer Tools (XCode) is required, because it contains the BLAS and LAPACK libraries. It can be found either in the App Store, or in the installation DVD that came with your Mac, or you can get the latest version from Apple Developer's connection at https://developer.apple.com/technologies/tools/. Make sure that everything, including all the optional packages is installed. You probably already have a Fortran compiler installed for NumPy. The binaries for gfortran can be found at http://r.research.att.com/tools/. Installing SciPy using easy_install or pip: Install with either of the following two commands: sudo pip install scipyeasy_install scipy Installing on Windows: If you have Python installed already, the preferred method is to download and use the binary distribution. Alternatively, you may want to install the Enthought Python distribution, which comes with other scientific Python software packages. Check your installation: Check the SciPy installation with the following code: import scipy print scipy.__version__ print scipy.__file__ This should print the correct SciPy version. How it works... Most package managers will take care of any dependencies for you. However, in some cases, you will need to install them manually. Unfortunately, this is beyond the scope of this book. If you run into problems, you can ask for help at: The #scipy IRC channel of freenode, or The SciPy mailing lists at http://www.scipy.org/Mailing_Lists Installing PIL PIL, the Python imaging library, is a prerequisite for the image processing recipes in this article. How to do it... Let's see how to install PIL. Installing PIL on Windows: Install using the Windows executable from the PIL website http://www.pythonware.com/products/pil/. Installing on Debian or Ubuntu: On Debian or Ubuntu, install PIL using the following command: sudo apt-get install python-imaging Installing with easy_install or pip: At the t ime of writing this book, it appeared that the package managers of Red Hat, Fedora, and CentOS did not have direct support for PIL. Therefore, please follow this step if you are using one of these Linux distributions. Install with either of the following commands: easy_install PILsudo pip install PIL Resizing images In this recipe, we will load a sample image of Lena, which is available in the SciPy distribution, into an array. This article is not about image manipulation, by the way; we will just use the image data as an input. Lena Soderberg appeared in a 1972 Playboy magazine. For historical reasons, one of those images is often used in the field of image processing. Don't worry; the picture in question is completely safe for work. We will resize the image using the repeat function. This function repeats an array, which in practice means resizing the image by a certain factor. Getting ready A prerequisite for this recipe is to have SciPy, Matplotlib, and PIL installed. How to do it... Load the Lena image into an array. SciPy has a lena function , which can load the image into a NumPy array: lena = scipy.misc.lena() Some refactoring has occurred since version 0.10, so if you are using an older version, the correct code is: lena = scipy.lena() Check the shape. Check the shape of the Lena array using the assert_equal function from the numpy.testing package—this is an optional sanity check test: numpy.testing.assert_equal((LENA_X, LENA_Y), lena.shape) Resize the Lena array. Resize the Lena array with the repeat function. We give this function a resize factor in the x and y direction: resized = lena.repeat(yfactor, axis=0).repeat(xfactor, axis=1) Plot the arrays. We will plot the Lena image and the resized image in two subplots that are a part of the same grid. Plot the Lena array in a subplot: matplotlib.pyplot.subplot(211) matplotlib.pyplot.imshow(lena) The Matplotlib subplot function creates a subplot. This function accepts a 3-digit integer as the parameter, where the first digit is the number of rows, the second digit is the number of columns, and the last digit is the index of the subplot starting with 1. The imshow function shows images. Finally, the show function displays the end result. Plot the resized array in another subplot and display it. The index is now 2: matplotlib.pyplot.subplot(212) matplotlib.pyplot.imshow(resized) matplotlib.pyplot.show() The following screenshot is the result with the original image (first) and the resized image (second): The following is the complete code for this recipe: import scipy.misc import sys import matplotlib.pyplot import numpy.testing # This script resizes the Lena image from Scipy. if(len(sys.argv) != 3): print "Usage python %s yfactor xfactor" % (sys.argv[0]) sys.exit() # Loads the Lena image into an array lena = scipy.misc.lena() #Lena's dimensions LENA_X = 512 LENA_Y = 512 #Check the shape of the Lena array numpy.testing.assert_equal((LENA_X, LENA_Y), lena.shape) # Get the resize factors yfactor = float(sys.argv[1]) xfactor = float(sys.argv[2]) # Resize the Lena array resized = lena.repeat(yfactor, axis=0).repeat(xfactor, axis=1) #Check the shape of the resized array numpy.testing.assert_equal((yfactor * LENA_Y, xfactor * LENA_Y), resized.shape) # Plot the Lena array matplotlib.pyplot.subplot(211) matplotlib.pyplot.imshow(lena) #Plot the resized array matplotlib.pyplot.subplot(212) matplotlib.pyplot.imshow(resized) matplotlib.pyplot.show() How it works... The repeat function repeats arrays, which, in this case, resulted in changing the size of the original image. The Matplotlib subplot function creates a subplot. The imshow function shows images. Finally, the show function displays the end result. See also The Installing SciPy recipe The Installing PIL recipe
Read more
  • 0
  • 0
  • 3019
article-image-meet-yii
Packt
07 Dec 2012
7 min read
Save for later

Meet Yii

Packt
07 Dec 2012
7 min read
(For more resources related to this topic, see here.) Easy To run a Yii version 1.x-powered web application, all you need are the core framework files and a web server supporting PHP 5.1.0 or higher. To develop with Yii, you only need to know PHP and object-oriented programming. You are not required to learn any new configuration or templating language. Building a Yii application mainly involves writing and maintaining your own custom PHP classes, some of which will extend from the core, Yii framework component classes. Yii incorporates many of the great ideas and work from other well-known web programming frameworks and applications. So if you are coming to Yii from using other web development frameworks, it is likely that you will find it familiar and easy to navigate. Yii also embraces a convention over configuration philosophy, which contributes to its ease of use. This means that Yii has sensible defaults for almost all the aspects that are used for configuring your application. Following the prescribed conventions, you can write less code and spend less time developing your application. However, Yii does not force your hand. It allows you to customize all of its defaults and makes it easy to override all of these conventions. Efficient Yii is a high-performance, component-based framework that can be used for developing web applications on any scale. It encourages maximum code reuse in web programming and can significantly accelerate the development process. As mentioned previously, if you stick with Yii's built-in conventions, you can get your application up and running with little or no manual configuration. Yii is also designed to help you with DRY development. DRY stands for Don't Repeat Yourself , a key concept of agile application development. All Yii applications are built using the Model-View-Controller (MVC) architecture. Yiienforces this development pattern by providing a place to keep each piece of your MVC code. This minimizes duplication and helps promote code reuse and ease of maintainability. The less code you need to write, the less time it takes to get your application to market. The easier it is to maintain your application, the longer it will stay on the market. Of course, the framework is not just efficient to use, it is remarkably fast and performance optimized. Yii has been developed with performance optimization in mind from the very beginning, and the result is one of the most efficient PHP frameworks around. So any additional overhead that Yii adds to applications written on top of it is extremely negligible. Extensible Yii has been carefully designed to allow nearly every piece of its code to be extended and customized to meet any project requirement. In fact, it is difficult not to take advantage of Yii's ease of extensibility, since a primary activity when developing a Yii application is extending the core framework classes. And if you want to turn your extended code into useful tools for other developers, Yii provides easy-to-follow steps and guidelines to help you create such third-party extensions. This allows you to contribute to Yii's ever-growing list of features and actively participate in extending Yii itself. Remarkably, this ease-of-use, superior performance, and depth of extensibility does not come at the cost of sacrificing its features. Yii is packed with features to help you meet those high demands placed on today's web applications. AJAX-enabled widgets, RESTful and SOAP Web services integration, enforcement of an MVC architecture, DAO and relational ActiveRecord database layer, sophisticated caching, hierarchical role-based access control, theming, internationalization (I18N), and localization (L10N) are just the tip of the Yii iceberg. As of version 1.1, the core framework is now packaged with an official extension library called Zii. These extensions are developed and maintained by the core framework team members, and continue to extend Yii's core feature set. And with a deep community of users who are also contributing by writing Yiiextensions, the overall feature set available to a Yii-powered application is growing daily. A list of available, user-contributed extensions on the Yii framework website can be found at http://www.yiiframework.com/extensions. There is also an unofficial extension repository of great extensions that can be found at http://yiiext.github.com/, which really demonstrates the strength of the community and the extensibility of this framework. MVC architecture As mentioned earlier, Yii is an MVC framework and provides an explicit directory structure for each piece of model, view, and controller code. Before we get started with building our first Yii application, we need to define a few key terms and look at how Yii implements and enforces this MVC architecture. Model Typically in an MVC architecture, the model is responsible for maintaining the state, and should encapsulate the business rules that apply to the data that defines this state. A model in Yii is any instance of the framework class CModel or its child class. A model class is typically comprised of data attributes that can have separate labels (something user friendly for the purpose of display), and can be validated against a set of rules defined in the model. The data that makes up the attributes in the model class could come from a row of a database table or from the fields in a user input form. Yii implements two kinds of models, namely the form model (a CFormModel class) and active record (a CActiveRecord class). They both extend from the same base class CModel. The class CFormModel represents a data model that collects HTML form inputs. It encapsulates all the logic for form field validation, and any other business logic that may need to be applied to the form field data. It can then store this data in memory or, with the help of an active record model, store data in a database. Active Record (AR) is a design pattern used to abstract database access in an objectoriented fashion. Each AR object in Yii is an instance of CActiveRecord or its child class, which wraps a single row in a database table or view, that encapsulates all the logic and details around database access, and houses much of the business logic that is required to be applied to that data. The data field values for each column in the table row are represented as properties of the active record object. View Typically the view is responsible for rendering the user interface, often based on the data in the model. A view in Yii is a PHP script that contains user interface-related elements, often built using HTML, but can also contain PHP statements. Usually, any PHP statements within the view are very simple, conditional or looping statements, or refer to other Yii UI-related elements such as HTML helper class methods or prebuilt widgets. More sophisticated logic should be separated from the view and placed appropriately in either the model, if dealing directly with the data, or the controller, for more general business logic. Controller The controller is our main director of a routed request, and is responsible for taking user input, interacting with the model, and instructing the view to update and display appropriately. A controller in Yii is an instance of CController or a child class thereof. When a controller runs, it performs the requested action, which then interacts with the necessary models, and renders an appropriate view. An action, in its simplest form, is a controller class method whose name starts with the word action
Read more
  • 0
  • 0
  • 2649

article-image-adding-interactivity-and-completing-your-site
Packt
06 Dec 2012
7 min read
Save for later

Adding Interactivity and Completing Your Site

Packt
06 Dec 2012
7 min read
(For more resources related to this topic, see here.) Using jQuery HTML5 Boilerplate provides a handy and safe way to load jQuery. With jQuery, it is vastly simple to work on writing scripts to access elements. If you are writing custom jQuery script either to kick off a plugin you are using or to do some small interaction, put it in the main.js file in the js folder. Using other libraries If you are more comfortable using other libraries, you can also load and use them in a similar way to jQuery. The following is how we load jQuery: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min. js"></script> <script>window.jQuery || document.write('<script src="js/vendor/ jquery-1.8.2.min.js"></script>') </script> Let us say, you want to use another library (like MooTools ), then look up the Google Libraries API to see if that library is available at developers.google.com/speed/libraries/. If it is available, just replace the reference with the appropriate reference from the site. For example, if we want to replace our jQuery link with a link to MooTools, we would simply replace the following code: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min. js"> </script> With the following line of code: <script src="ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootoolsyui- compressed.js"> </script> We will also download Mootools' minified file to the js/vendor folder locally and replace the following code: <script>window.jQuery||document.write('<script src="js/vendor/jquery- 1.7.2.min.js"></script>') </script> With the following line of code: <script>window.jQuery||document.write('<script src="js/vendor/ mootools-core-1.4.5-full-compat-yc.js"></script>') </script> Adding smooth-scroll plugin and interaction If you have not noticed it already, the website we are building is a single page site! All content that is required is found on the same page. The way our site is currently designed, it would mean clicking on one of the site navigation links would scroll roughly to the section that the navigation link refers to. We would like this interaction to be smooth. Let us use jQuery's smooth-scroll plugin to provide this. Let us download the plugin file from the Github repository, hosted on github.com/kswedberg/jquery-smooth-scroll. In it, we find a minimized version of the plugin (jquery.smooth-scroll.min.js) that we shall open in our text editor. Then copy all the code and paste it within the plugins.js file. Let us add a class name js-scrollitem to let us distinguish that this element has a script that will be used on those elements. This way, there will be a lesser chance of accidentally deleting class names that are required for interactions prompted via JavaScript. Now, we shall write the code to invoke this plugin in the main.js file. Open the main.js file in your text editor and type: $('.js-scrollitem').smoothScroll(); This will make all the clickable links that link to sections on the same page within the parent container with class js-scrollitem scroll smoothly with the help of the plugin. If we have used our HTML5 Boilerplate defaults correctly, adding this will be more than sufficient to get started with smooth scrolling. Next, we would like the navigation links in the line up section to open the right-hand side line up depending on which day was clicked on. Right now, in the following screenshot, it simply shows the line up for the first day, and does not do anything else: Let us continue editing the main.js file and add in the code that would enable this. First, let's add the class names that we will use to control the styling, and the hiding/showing behavior within our code. The code for this functionality is as follows: <nav class="t-tab__nav"> <a class="t-tab__navitem--active t-tab__navitemjs-tabitem" href="#day- 1">Day 1</a> <a class="t-tab__navitemjs-tabitem" href="#day-2">Day 2</a> </nav> Now, we shall write the code that will show the element we clicked on. This code is as follows: var $navlinks = $('#lineup .js-tabitem'); var $tabs = $('.t-tab__body'); var hiddenClass = 'hidden'; var activeClass = 't-tab__navitem--active'; $navlinks.click(function() { // our code for showing or hiding the current day's line up $(this.hash).removeClass(hiddenClass); }); By checking how we have done so far, we notice it keeps each day's line up always visible and does not hide them once done! Let us add that too, as shown in the following code snippet: var $navlinks = $('#lineup .js-tabitem'); var $tabs = $('.t-tab__body'); var hiddenClass = 'hidden'; var activeClass = 't-tab__navitem--active'; var $lastactivetab = null; $navlinks.click(function() { var $this = $(this); //take note of what was the immediately previous tab and tab nav that was active $lastactivetab = $lastactivetab || $tabs.not('.' + hiddenClass); // our code for showing or hiding the current day's line up $lastactivetab.addClass(hiddenClass); $(this.hash).removeClass(hiddenClass); $lastactivetab = $(this.hash); return false; } You would notice that the active tab navigation item still seems to suggest it is Day 1! Let us fix that by changing our code to do something similar with the tabbed navigation anchors, as shown in the following code snippet: var $navlinks = $('#lineup .js-tabitem'); var $tabs = $('.t-tab__body'); var hiddenClass = 'hidden'; var activeClass = 't-tab__navitem--active'; var $lastactivetab = null; var $lastactivenav = null; $navlinks.click(function() { var $this = $(this); //take note of what was the immediately previous tab and tab nav that was active $lastactivetab = $lastactivetab || $tabs.not('.' + hiddenClass); $lastactivenav = $lastactivenav || $navlinks.filter('.' + activeClass); // our code for showing or hiding the current day's line up $lastactivetab.addClass(hiddenClass); $(this.hash).removeClass(hiddenClass); $lastactivetab = $(this.hash); // change active navigation item $lastactivenav.removeClass(activeClass); $this.addClass(activeClass); $lastactivenav = $this; return false; }); Bingo! We have our day-by-day line up ready. We now need to ensure our Google Maps iframe renders when users click on the Locate on a map link. We also want to use the same link to hide the map if the users want to do so. First, we add some identifiable features to the anchor element used to trigger the showing/hiding of map and the iframe for the maps, as shown in the following code snippet: <p>The festival will be held on the beautiful beaches of NgorTerrouBi in Dakar.<ahref="#" class="js-map-link">Locate it on a map</a></p><iframe id="venue-map" class="hidden" width="425"height="350" frameborder="0" scrolling="no" marginheight="0"marginwidth="0" src="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=ngor+terrou+bi,+dakar,+senegal&;aq=&sll=37.0625,-95.677068&sspn=90.404249,95.976562&ie=UTF8&hq=ngor&hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&t=m&amp;fll=14.751996,-17.513559&fspn=0.014276,0.011716&st=109146043351405611748&rq=1&ev=p&split=1&ll=14.711109,-17.483921&spn=0.014276,0.011716&output=embed"></iframe> Then we use the following JavaScript to trigger the link: $maplink = $('.js-map-link'); $maplinkText = $maplink.text(); $maplink.toggle(function() { $('#venue-map').removeClass(hiddenClass); $maplink.text('Hide Map'); }, function() { $('#venue-map').addClass(hiddenClass); $maplink.text($maplinkText); });
Read more
  • 0
  • 0
  • 2018
Modal Close icon
Modal Close icon