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

How-To Tutorials - CMS & E-Commerce

830 Articles
article-image-cocoa-and-objective-c-animating-calayers
Packt
27 May 2011
6 min read
Save for later

Cocoa and Objective-C: Animating CALayers

Packt
27 May 2011
6 min read
Cocoa and Objective-C Cookbook Understanding the CALayer class In this recipe, we will use multiple layers to draw our custom view. Using a delegate method, we will draw the background of our view. A second layer will be used to include an image centered in the view. When complete, the sample application will resemble the following screenshot: Getting ready In Xcode, create a new Cocoa Application and name it CALayer. How to do it... In the Xcode project, right-click on the Classes folder and choose Add…, then choose New File… Under the MacOS X section, select Cocoa Class, then select Objective-C class. Finally, choose NSView in the Subclass of popup. Name the new file MyView.m. In the Xcode project, expand the Frameworks group and then expand Other Frameworks. Right-click on Other Frameworks and choose Add…, then choose Existing Frameworks… Find QuartzCore.framework in the list of frameworks and choose Add. Click on MyView.m to open it and add the following import: #import <QuartzCore/QuartzCore.h> Remove the initWithFrame: and drawRect: methods. Add the following awakeFromNib method: - (void) awakeFromNib { CALayer *largeLayer = [CALayer layer]; [largeLayer setName:@"large"]; [largeLayer setDelegate:self]; [largeLayer setBounds:[self bounds]]; [largeLayer setBorderWidth:4.0]; [largeLayer setLayoutManager:[CAConstraintLayoutManager layoutManager]]; CALayer *smallLayer = [CALayer layer]; [smallLayer setName:@"small"]; CGImageRef image = [self convertImage:[NSImage imageNamed:@"LearningJQuery"]]; [smallLayer setBounds:CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))]; [smallLayer setContents:(id)image]; [smallLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]]; [smallLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX relativeTo:@"superlayer" attribute:kCAConstraintMidX]]; CFRelease(image); [largeLayer addSublayer:smallLayer]; [largeLayer setNeedsDisplay]; [self setLayer:largeLayer]; [self setWantsLayer:YES]; } Add the following two methods to the MyView class as well: - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context { CGContextSetRGBFillColor(context, .5, .5, .5, 1); CGContextFillRect(context, [layer bounds]); } - (CGImageRef) convertImage:(NSImage *)image { CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef )[image TIFFRepresentation], NULL); CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL); CFRelease(source); return imageRef; } Open the MyView.h file and add the following method declaration: - (CGImageRef) convertImage:(NSImage *)image; Right-click on the CALayer project in Xcode's project view and choose Add…, then choose Existing Files…. Choose the LearningJQuery.jpg image and click on Add. Double-click on the MainMenu.xib file in the Xcode project. From Interface Builder's Library palette, drag a Custom View into the application window. From Interface Builder's Inspectors palette, select the Identity tab and set the Class popup to MyView. Back in Xcode, choose Build and Run from the toolbar to run the application. How it works... We are creating two layers for our view. The first layer is a large layer, which will be the same size as our MyView view. We set the large layers delegate to self so that we can draw the layer in the drawLayer: delegate method. The drawLayer: delegate method simply fills the layer with a mid-gray color. Next, we set the bounds property and a border width property on the larger layer. Next, we create a smaller layer whose contents will be the image that we included in the project. We also add a layout manager to this layer and configure the constraints of the layout manager to keep the smaller layer centered both horizontally and vertically relative to the larger view using the superlayer keyword. Lastly, we set the small layer as a sub-layer of the large layer and force a redraw of the large layer by calling setNeedsDisplay. Next, we set the large layer as the MyView's layer. We also need to call the setWantsLayer:YES on the MyView to enable the use of layers in our view. There's more... Since we used a layout manager to center the image in the view, the layout manager will also handle the centering of the image when the user resizes the view or window. To see this in action, modify the Size properties in Interface Builder for the custom view as shown in the screenshot below: Animation by changing properties Cocoa provides a way to animate views by changing properties using implied animations. In this recipe, we will resize our custom view when the resize button is clicked, by changing the views frame size. Getting ready In Xcode, create a new Cocoa Application and name it ChangingProperties. How to do it... In the Xcode project, right-click on the Classes folder and choose Add…, then choose New File… Under the MacOS X section, select Cocoa Class, then select Objective-C class. Finally, choose NSView from the Subclass of popup. Name the new file MyView.m. Click on the MyView.m file to open it and add the following in the drawRect: method: NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[ self bounds] xRadius:8.0 yRadius:8.0]; [path setClip]; [[NSColor whiteColor] setFill]; [NSBezierPath fillRect:[self bounds]]; [path setLineWidth:3.0]; [[NSColor grayColor] setStroke]; [path stroke]; Click on the ChangingPropertiesAppDelegate.h to open it. Next, insert an import for the MyView.h header file: #import "MyView.h" Add the following variables to the class interface: NSButton *button; MyView *myView; Add the following properties to the class interface: @property (assign) IBOutlet NSButton *button; @property (assign) IBOutlet MyView *myView; Add the method declaration for when the Resize button is clicked: - (IBAction) resizeButtonHit:(id)sender; Click on the ChangingPropertiesAppDelegate.m file to open it. Add our synthesized variables below the synthesized window variable: @synthesize button; @synthesize myView; Create a global static boolean for tracking the size of the view: static BOOL isSmall = YES; Add the resizeButtonHit: method to the class implementation: - (IBAction) resizeButtonHit:(id)sender { NSRect small = NSMakeRect(20, 250, 150, 90); NSRect large = NSMakeRect(20, 100, 440, 240); if (isSmall == YES) { [[myView animator] setFrame:large]; isSmall = NO; } else { [[myView animator] setFrame:small]; isSmall = YES; } } Double-click on the MainMenu.xib file in the Xcode project. From Interface Builders Library palette, drag a Custom View into the application window. From Interface Builder's Inspector's palette, select the Identity tab and set the Class popup to MyView. From the Library palette, drag a Push Button into the application window. Adjust the layout of the Custom View and button so that it resembles the screenshot below: From Interface Builder's Inspector's palette, select the Identity tab and set the Class popup to MyView. Right-click on the Changing Properties App Delegate so that you can connect the outlets to the MyView Custom View, the Resize Push Button, and the resizeButtonHit action: Back in Xcode, choose Build and Run from the toolbar to run the application. How it works... We define two sizes for our view, one small size that is the same as the initial size of the view, and one large size. Depending on the state of the isSmall global variable, we set the view's frame size to one of our predefined sizes. Note that we set the view's frame via the views animator property. By using this property, we make use of the implicit animations available in the view. There's more... Using the same technique, we can animate several other properties of the view such as its position or opacity. For more information on which properties can be implicitly animated, see Apple's Core Animation Programming Guide.
Read more
  • 0
  • 0
  • 3190

article-image-joomla-virtuemart-product-list-templates
Packt
26 May 2011
23 min read
Save for later

Joomla! VirtueMart: Product List Templates

Packt
26 May 2011
23 min read
Joomla! VirtueMart 1.1 Theme and Template Design Give a unique look and feel to your VirtueMart e-Commerce store         Read more about this book       (For more resources on Joomla!, see here.) The product list page Product list page is the most important starting page for the shopping life cycle. While the landing page will give some general information regarding the shop, the list of items for sale in the shop is the major job of the product list page. Some shop owners even prefer to use product list page as their home page. Product list page is in singular, but actually the product list page is a series of pages. The total number of pages in the series varies from store-to-store and typically depends on the number of categories you have in the site. Each category will have its own page or even pages, if the category contains many products. Furthermore, the product list page is also used to list the products that relate to a particular manufacturer. It is also used for the keyword search and advanced search, if you enable the product search and advanced search Joomla! modules or the product search Joomla! plugin. To simplify our discussion, we will first restrict ourselves to the study of category listing. The manufacturer listing and search listing are very similar. Let's take a look at a typical category listing. From the preceding screenshot, we can identify a number of important elements on a product list page: Page header: This includes the category name, category description, the PDF, and print icons. The layout of the page header will depend on the page header templates. Navigation: This includes the order by form, the order by direction button (toggle between ascending and descending), number per page drop-down box, and the page navigation links. Note that the page navigation links can appear both at the top and the bottom. The navigation layout is controlled by the navigation templates. Product listing: This is the major item of the page, where the products are listed in a way defined by the product listing style and the number of products per row settings. Each of the products displayed within the listing is controlled by the core browse template (the core browse template is explained in the section Core browse templates). Addendum elements: This includes the recent products, latest products, featured products, and so on. Each of the addenda may have its own template. Page footer: This is the element placed at the end of the listing. Right now, there is only one element within the page footer, the page navigation. As we shall see, the layout of each of these elements is controlled by one or more templates. By customizing any one of these templates, we may be able to change the look of the page completely. We need to distinguish the usage between the terms browse templates and core browse templates. For the purpose of making things clear, we retain the term "browse templates" to refer to all templates within the browse template group. Within this broad template group, there are two subgroups: those which control the layout detail of each individual product (each product in the product listing section) and those which control all the other elements. We refer to them as core and non-core templates, respectively. The core browse templates reside directly under the templates/browse subdirectory. All the non-core templates reside under the subdirectory templates/browse/includes. The difference between the core and non-core templates will become clear in the following explanation.   Looking at our first template While VirtueMart templates are different from each other, they actually follow a definite pattern. To understand how the template is structured, probably the best way is to look at a sample. Let's take a look at the file browse_1.tpl.php as an example. This is one of the core browse templates. The full text of this file is as follows (with line numbers added): 1. <?php if( !defined( '_VALID_MOS' ) && !defined( '_JEXEC' ) )die( 'Direct Access to '.basename(__FILE__).' is not allowed.' );2. mm_showMyFileName(__FILE__);3. ?>4. <div class="browseProductContainer">5. <h3 class="browseProductTitle"><a title="<?php echo$product_name ?>" href="<?php echo $product_flypage ?>">6. <?php echo $product_name ?></a>7. </h3>8.9. <div class="browsePriceContainer">10. <?php echo $product_price ?>11. </div>12.13. <div class="browseProductImageContainer">14. <script type="text/javascript">//<![CDATA[15. document.write('<a href="javascript:void window.open('<?php echo $product_full_image ?>', 'win2', 'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=<?php echo $full_image_width ?>,height=<?php echo $full_image_height ?>,directories=no,location=no');">');16. document.write( '<?php echo ps_product::image_tag( $product_thumb_image, 'class="browseProductImage" border="0"title="'.$product_name.'" alt="'.$product_name .'"' ) ?></a>' );17. //]]>18. </script>19. <noscript>20. <a href="<?php echo $product_full_image ?>"target="_blank" title="<?php echo $product_name ?>">21. <?php echo ps_product::image_tag($product_thumb_image, 'class="browseProductImage" border="0"title="'.$product_name.'" alt="'.$product_name .'"' ) ?>22. </a>23. </noscript>24. </div>25.26. <div class="browseRatingContainer">27. <?php echo $product_rating ?>28. </div>29. <div class="browseProductDescription">30. <?php echo $product_s_desc ?>&nbsp;31. <a href="<?php echo $product_flypage ?>"title="<?php echo $product_details ?>"><br />32. <?php echo $product_details ?>...</a>33. </div>34. <br />35. <span class="browseAddToCartContainer">36. <?php echo $form_addtocart ?>37. </span>38.39. </div> Downloading the example code You can download the example code files here HTML fragments The coding is pretty typical of a VirtueMart template file. You can see that the template is basically an HTML fragment embedded with PHP coding. All PHP code is enclosed within the tag <?php … ?>. In most cases, the PHP code uses the statement echo $field_name to add the field value to the HTML code. We will be looking at those PHP constructs in the next subsection. After parsing the template, the output should be a well-formed HTML code. You should note that the template is just an HTML fragment, meaning no <html>, <head>, and <body> tags are needed. As you can recall, VirtueMart is just a Joomla! component that will handle the main content. So the HTML fragment produced by the template (together with other code, if any, built up by the page file) will be returned to the Joomla! engine for further processing. Typically, the Joomla! engine will pass this HTML fragment into the Joomla! template which, in turn, will insert the HTML into a location designated by the template. The final output of the Joomla! template will then be a valid HTML document. The <html>, <head>, and <body> tags will therefore be the responsibility of the Joomla! template. Let's look at the code to see how these 39 lines of code work. Remarks will only be needed for lines with the PHP tag. All the rest are HTML code that you should be familiar with. Lines 1 to 3 are actually some housekeeping code following the Joomla!/VirtueMart pattern. They will restrict direct access to the code and print out the template filename when debugging. Line 5 will output the product title with the product name embedded inside a hot link pointing to the product detail page. Line 10 will output the product price. Lines 14 to 23 contain a lengthy JavaScript code. The purpose is to output the image thumbnail embedded inside a hot link to open the full image. We need JavaScript here because we want to ensure the pop-up window size fits the full image size. (Otherwise, the pop-up window size will depend on the default size of the browser.) The window size cannot be controlled by HTML and so we need JavaScript help. If JavaScript is not enabled in a client browser, we will fall back to HTML code to handle the pop-up. Line 27 outputs the product rating, as reviewed by the user. Line 30 outputs the product's short description. Lines 31 to 33 outputs the text of product details within a hot link pointing to the product details page. Line 36 outputs the add-to-cart form, which includes the add-to-cart button, the quantity box, and so on. PHP crash course While we are not going to present all the complex program structure of PHP, it will be useful if we have a basic understanding of some of its major constructs. You may not fully understand what exactly each line of code does at first, but stick with us for a little while. You will soon grasp the concept as the pattern appears repeatedly in the exercise we will work on. In the preceding sample template, the PHP coding is pretty simple. (The most complex structure is actually the JavaScript that tries to spit out some HTML on the client browser, not PHP!) We can identify a few basic PHP constructs among the sample code: Variables: Just like any other programming language, a variable is a basic element in PHP. All PHP variables start with the dollar sign $. A variable name consists of alphanumeric characters and the underscore _ character. The first character must be either alphabetical or _, while numerals can also be used after the first character. It should be noted that the space character, together with most punctuation characters, are not allowed in a variable name. Alphabetic characters can be either uppercase or lowercase. Conventionally, VirtueMart will use only lowercase letters for variable names. While both uppercase and lowercase letters can be used without restrictions, variable names are case sensitive, meaning that $Product and $product will be treated as two different variables. The variable name chosen usually reflects the actual usage of the variable. In the sample template, $product_name and $product_flypage, for example, are typical variables and they will represent the value of a product name and product flypage, respectively. VirtueMart uses _ to separate words within a variable name to make the variable name more readable. Actually, many of the variables are passed into the template by the VirtueMart page file. These variables are called available fields. We will have more to say about that in the next subsection. Constants: Variables are changing values. You can assign a new value to it at any time and it will take up the new value. There are times when you want to keep the value unchanged. You can use a constant for that purpose. A constant name is pretty much the same as a variable name, but you don't need the $ character. In line 1 of the sample template, both _VALID_MOS and _JEXEC are constants. You probably recognize that they both use capital letters. This is conventional for Joomla! and VirtueMart so that constants stand out within the code. Constants are values that cannot be changed. If you try to give it another value, PHP will complain and fail. Data type: Any variable will have a data type associated with it. Data type can be a number, a string (that is, a series of characters or text), or other possibilities. Since the major purpose of a VirtueMart template is to produce HTML code, we will find that most of the variables we deal with are strings. Often, we will need to write out a literal string in our coding. To distinguish our string from the rest of the coding, we need to enclose the literal string with quotes. We can use single or double quotes. Single and double quotes actually have subtle differences, but we won't go into the detail for the time being. According to the VirtueMart program standard, a literal string should be enclosed in single quotes such as 'product name'. Note that 'product name' is a literal string containing the text product name. It is different from $product_name, which is a variable and may contain characters like 'circular saw' instead. Operators: You learnt addition and subtraction at school. They are mathematical operations to combine numbers. In PHP, we also have other operations to combine two or more variables. The most important one in our exercises is probably string concatenation, symbolized by . (the dot character). String concatenation combines two or more strings together to form a single string. The operation 'hello'.'world' will give a new string 'helloworld'. Note that there is no space character between the words. To make sure the words are separated by a space, we will need to use two concatenations such as 'hello'.' '.'world', which will give you the new string 'hello world'. Functions: Often, we will find that the same pattern of program code is used repeatedly to produce a given result. In PHP, we can group those code together to form a function. Each function will have a name and can be invoked using the following syntax: function_name (parameters) Here, parameters are values that will need to be passed into the function to evaluate the result. In PHP, we have lots of functions that deal with strings. The function strlen($product_name), for example, will return the number of characters in the string variable $product_name. If $product_name contains the string 'circular saw', strlen($product_name) will return 12. (You probably recognize that strlen is just a short form for string length.) We will learn some more functions along the way. echo statements: This is the most common statement in the template. echo is used to send the value of a string to the output buffer. So echo $product_name literally means "print out the value of the variable $product_name to the output buffer". Sometimes, the echo statement is mistaken to be a function. So you may try to write something like echo($product_name), instead of echo $product_name. While this is acceptable in PHP most of the time, the braces are actually not needed. (You may be aware that sometimes the command print function is used to send data to the output buffer in the place of echo. While print and echo seem interchangeable, echo runs faster than print and so should be the preferred choice to output data.) if statements: The if statement is a construct to test a condition before taking a certain action. The action will be taken only if the condition evaluates to true. The syntax of an if statement is as follows: if (condition) action where the condition is an expression for testing and action is a statement or a series of statements to be performed, if the expression evaluates to true. The expression can be a true-false type condition (such as $i>0), a mathematical expression (such as $i+$j), or some kind of complex operation involving functions. In any case, it will be considered as true, if it evaluates to a nonzero number or a non-empty string. Statement separator: One important PHP construct we usually overlook is the statement separator ; (the semicolon). We need this to separate two or more statements, even if they are on new lines of their own. In the preceding sample code, we have a ";" at the end of line 1 and 2. This ; is very important. Without that, the PHP parser will be confused and will probably refuse to execute and will give you a fatal error. These are just a few constructs in PHP for the time being. We will have more to say about PHP as we encounter more constructs along the way. Available fields Since many of the variables in our template code are passed down from the VirtueMart page file, one natural question to ask is "What variables can we use in our code?". Variables that we can use in a template are known as available fields. The available fields we have inside a template will vary with the template itself. A field which is available in the flypage template may not be available in a browse template. Even among the browse templates, there may be differences. To maximize our customization effort on a template, it is essential to be aware of the available fields in each template. However, there are so many available fields in a template that it may not be wise to list them all here. For now, it will be useful to distinguish four different types of available fields: Database fields: Most of the data we have comes from the database. Often, the VirtueMart page file just passes those fields directly to the template without changing anything. They are called database fields. The same data you put into the database from the backend will be at your fingertips. Examples are $product_id and $product_sku. Formatted database fields: Sometimes the data you stored in the database is raw data. You will need a different format in the presentation. VirtueMart will do some formatting on the data before passing it to the template. An example is $product_available_date, which is stored in the database as an integer. However, you need to display it in a form that is appropriate to your culture such as yyyy-mm-dd, mm-dd-yyyy, and so on. Processed data: Sometimes there may be complex logic before you can produce data that is useful in the template. A typical example is the $product_price. Do not expect this to be a simple number or a formatted number with the currency symbol added. Actually, the product price will depend on a number of factors such as whether the user has logged in, the shopper group, discount, tax, and so on. So the $product_price in the frontend may be different from the value you entered in the backend. Sometimes it is a formatted number and sometimes it is a message such as call for price. Another example is $product_thumb_image. You may expect this to be just the file location you see in the backend, but its value will depend on whether it is an out of site image, whether the image exists, and whether you want the image to be resized from the full image. VirtueMart class object: In certain cases, VirtueMart developers may think there are too many possibilities for the use of a piece of data. So they decided to let the template designer control what to do with the data. In those cases, VirtueMart will simply pass a class object to the template. An example of this is $ps_product. There are lots of opportunities to make good use of these class objects. However, you will need to understand how this can be properly used and bear all the complexities to make it work.   Core browse templates Product listing is unarguably the most important element on the product list page. There are two major factors that will affect the product listing: the product listing style, and the core browse template. Core browse templates are used to define the layout and styles for each product in the product list. There are actually six different core browse templates in the default theme. We can define a default core browse template for general use and also a specific template for each of the product categories. If you take a closer look at the templates, you will find that they are pretty much the same, except the last one which is for creating a PDF file. We already saw the detail coding in the browse_1.php. We don't need to repeat it here again. So, let's start on some exercises with the browse_1 template right away. Exercise 3.1: Adding an Ask-Seller link to the browse page We know that in the product detail page, there is an Ask-Seller link which will bring up a form so that a shopper can ask a question about the product. This link is not available on the product list page. In this exercise, we will add a similar link to the browse page. While we can use the exact same link here, we purposely use a simpler way to do it to make it easier to understand. Steps Open your favorite text editor. Navigate to the VirtueMart frontend root. Open the file themes/default/templates/browse/browse_1.php. Insert the following line of code after line 5: <a href="index.php?option=com_virtuemart&page=shop.ask&product_id=<?php echo $product_id ?>">Ask a question about thisproduct</a><br /> Save the file and upload it to your server. Point your browser to any VirtueMart browse page that uses the browse_1.php template, you should see the Ask-Seller link added to every product. (This exercise is done on the browse_1 template only. If you browse to the product list of an individual category, the new styles will show only if the category is using the browse_1 template. The same applies to most of the following exercises.) Notes The Ask-Seller link is an <a> tag with the href pointing to the Ask Seller page. The href is built using three parameters: option=com_virtuemart points to the VirtueMart component. page=shop.ask points to the actual Ask Seller page. By changing the page parameter, we can point the shopper to any of the VirtueMart pages. product_id=<? echo $product_id ?> provides the product ID to the Ask Seller page so that it knows which product the shopper has questions on. We need to use a variable because the product_id will vary from product to product. In the previous code, we purposely hardcoded the link as a relative URL to make the code simpler. This works unless SEF is enabled. To cater for SEF, a more generic way to create the link will be needed. The text Ask a question about this product is static text. Feel free to change it to anything you think appropriate. This will not affect the function of the link. <br /> is needed to insert a line break after the link. Exercise 3.1 demonstrates the basic technique to modify a template. You can add static text to a template in whatever way you want. If you need variable data, simply insert the appropriate echo statement at the required place.   Exercise 3.2: Changing core browse template CSS One major task of customizing a template is changing the style of HTML elements. In this exercise, we are going to add some CSS styles to the core browse template. Preparation This exercise is built upon the browse_1.php file we modified in Exercise 3.1. If you start from the original template file, the exact line number may differ. Steps Open your favorite text editor. Navigate to the VirtueMart frontend root. Open the file themes/default/templates/browse/browse_1.php. At line 4 (that is, the top of the file), insert the following lines of code: <?php if (!defined(VM_CUSTOM_CSS)) { define ('VM_CUSTOM_CSS',1);?> <style> .browseProductContainer {border:1px solid #999;padding:5px;background:#eee;margin:5px;} </style><?php } ?> Save the file and upload it to your server. Point your browser to any VirtueMart browse page that uses the browse_1.php template. You should see the product list now with the border, margin, and padding added. Notes We added a stylesheet for the class browseProductContainer in the template file. The stylesheet will be included as part of the HTML output to the browser. The core browse template will be applied for each product. So any coding added to it will be repeated for each product. To ensure that the stylesheet is included only once in the HTML, we define a constant named VM_CUSTOM_CSS the first time the stylesheet is included. The if condition at the start of the coding tests for the existence of the constant VM_CUSTOM_CSS. When the code is executed a second time, VM_CUSTOM_CSS is already defined and so the statements within the braces will be skipped. Exercise 3.2 demonstrates another basic technique to modify a template. The technique applies not only to a CSS stylesheet, but to all coding in general. It can be used for JavaScript inclusion, and for other coding that you only need to appear once in the HTML.   Exercise 3.3: Moving and modifying data In this exercise, we are going to experiment with moving data around and adding some new data fields that are available for the template. Preparation This exercise is built upon the browse_1.php file we modified in Exercise 3.2. If you start from the original template file, the exact line numbers may differ. Steps Open your favorite text editor. Navigate to the VirtueMart frontend root. Open the file themes/default/templates/browse/browse_1.php. At line 40, insert the following line of code: <br />Weight: <?php echo number_format($product_weight,1) .' ' . $product_weight_uom ?><br /> Move the Ask-Seller link from line 13 to line 47, that is, after the closing </span> tag for form_addtocart. Move the <br /> tag from the end of line 47 to the beginning of the line, that is, the line will become: <br /><a href="index.php?option=com_virtuemart&page=shop.ask&product_id=<?php echo $product_id ?>">Ask a question about thisproduct</a> Save the file and upload it to your server. Point your browser to any VirtueMart browse page that uses the browse_1.php template and you should see that the Ask-Seller link has moved to the end of the display, and the product weight and unit has been added to every product. Notes In this exercise, we have performed two modifications. We moved the Ask-Seller link to the bottom instead of the top and added the product_weight field to the browse template. Actually, the order of appearance of the product fields can be changed at will. You can move it around to fit your requirement similar way. To add new data to the display, you first need to determine what you want to show and whether the data is within the list of available fields. Since we know $product_weight and $product_weight_uom (uom stands for unit of measure) are available, we can simply use concatenation to build the final text for the output. The weight is rounded off to 1 decimal place using the number_format() function to make it look nicer. You can change the number of decimal places by changing the second parameter to the number_format() function.  
Read more
  • 0
  • 0
  • 2763

article-image-getting-started-internet-explorer-mobile
Packt
23 May 2011
13 min read
Save for later

Getting Started with Internet Explorer Mobile

Packt
23 May 2011
13 min read
  Microsoft SharePoint 2010 Enterprise Applications on Windows Phone 7 Create enterprise-ready websites and applications that access Microsoft SharePoint on Windows Phone 7 To get started with Internet Explorer Mobile let's look at basic web page architecture.   Web page architecture Web pages on the client side mainly consist of three vital components: HTML, CSS, and JavaScript. The exact version of each of these varies, but in the end it all comes down to these three pieces. HyperText Markup Language (HTML) HyperText Markup Language (HTML) is the container for the page content. The page should contain just that content and nothing else. A properly coded site would leave the presentation and functionality portions of the page to CSS and JavaScript. In addition, the content should be constructed in a manner that makes logical sense for the content that is being delivered. This is called semantic HTML. People with disabilities use devices, such as a screen reader, to get the content of a site. These screen readers can only gather information from the actual markup of the site. If we have a PNG image with text in it, the screen reader cannot "see" that information. In that particular case, we can use the alt attribute of the image to provide a hint to the content, but it would be better to put the content inside a paragraph, unordered list, or some other textual tag and then replace it with an image if absolutely required using JavaScript. The other case that was mentioned earlier was that search engines can better determine the contents of a web page with semantic markup. This will help our page rankings and hopefully drive more visitors to our site. Think about the HTML markup like the script of a movie. Although we'll add lights, actors, and probably special effects later, right now the black and white text on paper has to convey all of the meaning. The same is true of the HTML markup for your site. As you build websites, constantly keep in mind what information you are trying to impart with the page and make that the focus. Cascading Style Sheets (CSS) Cascading Style Sheets (CSS) are documents that describe the way HTML should be displayed. The CSS language allows the web developer to separate the design aspects (layout, colors, fonts, and so on) from the page content. One could easily change the entire look and feel of a page simply by replacing the CSS files. An amazing group of examples of this is available at http://csszengarden.com. The CSS Zen Garden website demonstrates the amazing power that CSS has on the presentation of HTML content. Utilizing a proper style sheet can result in content that will quickly display the relevant information that a Windows Phone 7 user has come to expect from the applications on the phone. When developing websites that are going to be viewed on Internet Explorer Mobile, it is important to keep in mind some very important potential problems. Although float works great on desktop browsers and will work on many mobile browsers, the content within these containers may not look good on a small screen. The CSS float attribute was one of the first tools that allowed web developers to break free from table based layouts, that is, laying out the contents of a page using tables. Float allowed developers to group content in div elements and then float those block elements into position. It is a very powerful tool, but on a mobile device, the limited screen size would hamper the ability for the user to view the content. Instead, they would be constantly scrolling left and right or up and down to find all the content. A better way of handling this would be to utilize float on the desktop version of the site and then leave the div elements in block display allowing the IE Mobile browser to handle the content layout. Along these same lines, the CSS attributes, padding and margin, work great for precise positioning of elements on a desktop browser. However, the limited screen real-estate of a Mobile browser limits the usefulness of this positioning power. Try to limit the use of these attributes on the mobile device and only use them to highlight useful information. Finally, because pixels are absolute values, a pixel is a precise defined scale of measurement with no room for interpretation; the phone has to work more to display those elements that are positioned using pixel measurements. Using points, em, or percentage measurements instead, allow the phone to be more fluid with the layout. Be sure to test the site on Windows Phone 7 devices to ensure the content is legible and the display is fine. JavaScript JavaScript, otherwise known as ECMAScript, is the scripting language that is used to create dynamic user interfaces and allow a page to update "on the fly". Users have come to expect a certain fluidity to their web experiences, and now with the power of Internet Explorer Mobile for Windows Phone 7, they can have that same power in the palm of their hand. Remember that the user is probably looking at a 3.5 inch screen, has fingers that are roughly 40-80 pixels square, and those fingers are incapable of registering a hover command to the browser. If your navigation, for example, requires the user to hover over something, this will not work in Internet Explorer Mobile. Instead, make the navigation an easy to use, unordered list of hyperlinks Putting HTML, CSS, and JavaScript together Windows Phone 7 is about getting the relevant information viewable with minimal fuss. The following are some tips for creating a website for Windows Phone 7's Internet Explorer Mobile: Show only the content that is relevant for the page requested Reduce the use of images and colors Remove the extra-large hero images Hero images are those large images usually at the top of the main content section, but usually used as a graphic headline. Usually, they don't contain any content and only serve to enhance the design of the site. Rearrange the navigation to take up a minimum amount of space Move the navigation to the bottom of the page if possible Remove flashy loading screens Utilizing HTML, CSS, and JavaScript with proper discipline will result in more satisfied customers. Developing websites is not a trivial task. Mastering each of these three components is a great task. It is important, while developing websites, to try and minimize as much duplication as possible, not only in the JavaScript code that so many developers tended to focus on, but also in the CSS and the HTML content. Reducing duplication will allow for maintainable, upgradable, and understandable code. Also, by reducing duplication, the amount of data sent to the browser is also reduced. This is helpful when dealing with a browser that is connecting from a patchy cellular network. Historically, building a mobile version of a website meant a completely different team of designers and web developers built a totally separate web application from the desktop version of the site. Then, using the server side code, the mobile browsers were detected and redirected to the mobile version. SharePoint does this by redirecting mobile browsers to {server}/_layout/mobile/mblwiki.aspx?Url=%2FSitePages%2FHome%2Easpx as an example. When starting a new web application, a general rule of thumb is to use content adaptation techniques for the application. However, for a baseline you must have at least: ECMAScript 3 W3C DOM Level 1 W3C standard box model support CSS2 rendering Client-side cookies support XMLHttpRequest object support By targeting this lowest common denominator of browser, we will ensure that our web applications will run well on most browsers on the web. Remember that common practices on desktop browsers may end up being annoyances on a mobile device. Try not to open modal dialog boxes, or even open pop-ups. Opening a pop-up window will cause a whole new tab to appear. This may even close a tab that the user had previously opened if they already had six tabs open. When designing the user interaction for a website, always keep the user in mind. They are busy people coming to your website. Be kind to them. Give them the information they are looking for without hassle.   Internet Explorer Mobile Windows Phone 7 comes with a new browser that is based on the rendering engine of Internet Explorer 7 and some JavaScript improvements from Internet Explorer 8. Additionally, it includes some enhancements that aren't found in either of those desktop browsers. Internet Explorer Mobile User Agent The Internet Explorer Mobile User Agent string is as follows: Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; <DeviceManufacturer>; <DeviceModel>) This UA String allows the device manufacturer to insert their name and the model of the phone in the string. Knowing the User Agent string is helpful when reviewing server logs to determine what browsers are coming to your website. This will help you optimize your site for the people who actually are viewing your content. Like previous versions of Internet Explorer Mobile, the user can select either a Mobile version or a Desktop version display engine. When the Desktop version is selected, the User Agent string changes to the following: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; XBLWP7; ZuneWP7) Changing the display engine mode can be accomplished on the Internet Explorer SETTINGS screen, as shown in the following screenshot: Although this choice could complicate things, as we develop our sites, we should make careful consideration of how we are going to treat the mobile version, but try not to detect the desktop version. If the user makes a conscious choice to view the desktop version, we should not force them to view something different from what they would see on a real desktop browser. Client side browser detection Many people use the user agent string to detect at runtime what to display on the browser. Although this works, there are better techniques to find out if the browser is mobile. Those techniques should be used instead of User Agent detection. Using property detection instead of browser detection will allow your site to be forward compatible. Forward compatibility isn't a very complex idea. It is just thinking about programming so that as new browsers come along with new capabilities, we won't have to rewrite our applications to take advantage of these capabilities. The application just takes advantage of whatever functionality is available to it in whatever browser in which it is currently running. An example of property detection is as follows: function hasAdvancedDOM() { // check for a feature that is known to be advanced if(document.getElementsByClassName) return true; return false } Downloading the example code You can download the example code files from here The preceding code simply detects if the DOM function document.getElementsByClassName() exists or not. Internet Explorer Mobile has this function, as does Firefox 2+, Safari, Chrome, and Internet Explorer 9. However, previous versions of Internet Explorer Mobile did not have this function. If we had this in a previous version of a website, we wouldn't have to do anything special to get this to work in Windows Phone 7's Internet Explorer Mobile. Although, the code we would actually write in a web page would be much more complicated, this example demonstrates a starting point. Server-side detection Server-side detection usually uses the User Agent string along with a large list of mobile device User Agent strings to determine the capabilities of the browsers requesting a page. This list of mobile devices and their capabilities are kept in a .browser file. There are some projects on the web to keep and maintain this .browser file. The best known of these, "Mobile Device Browser File", available at http://mdbf.codeplex.com, lost funding from Microsoft. There is another one that can be found at http://aspnet.codeplex.com/releases/view/41420. The main topic of this article is SharePoint 2010 development for Windows Phone 7. However, ASP.NET 3.5 SP1 is the framework that SharePoint 2010 development is based on. This framework has a smaller list of browsers in the .browser file than the more current ASP.NET 4. One of the omissions is IEMobile. What this means is that in ASP.NET 4, you can use the following code to detect a mobile browser: Request.Browser.IsMobileDevice This code will work in ASP.NET 3.5 SP1, but it will not return true for Windows Phone 7's Internet Explorer Mobile by default. The simplest solution is to use code like this to detect the IE Mobile browser: Request.UserAgent.ToString().Contains("IEMobile") We could probably do better here. In the first place, we could update SharePoint's compat.browser file to include Windows Phone 7. The compat.browser can be found here: <drive>:inetpubwwwrootwssVirtualDirectories<site>80App_Browserscompat.browser The structure of this file can be found at the following URL: http://msdn.microsoft.com/en-us/library/ms228122.aspx If you look at SharePoint's compat.browser file, the fourth browser listed looks like it might be for the Windows Phone 7 Internet Explorer Mobile. However, a closer examination will show that this browser is actually for the Office Hub in Windows Phone 7. To add the Internet Explorer Mobile browser, copy the browser elements for Internet Explorer Mobile for Windows Mobile 6.5 and edit it like this: <browser id="IE7MobileDesktopMode" parentID="IE6to9"> <identification> <userAgent match="XBLWP7" /> </identification> <capabilities> <capability name="supportsTouchScreen" value="true" /> </capabilities> </browser> <browser id=”IE7MobileMobileMode” parentID=”Mozilla”> <identification> <userAgent match="(?i)Windows Mobile OSs7.d.*IEMobile/ (?'version'd+).(?'minor'd+)" /> </identification> <capabilities> <capability name="browser" value="IE Mobile" /> <capability name="canInitiateVoiceCall" value="true" /> <capability name="isMobileDevice" value="true" /> <capability name="javascript" value="true" /> <capability name="optimumPageWeight" value="1500" /> <capability name="tables" value="true" /> <capability name="version" value="${version}" /> <capability name="supportsTouchScreen" value="true" /> </capabilities> </browser> This will make our code easier to manage later by allowing us to use the Request.Browser.IsMobileDevice property. The change here, besides changing the browser ID, is in the regular expression which is used to detect the browser. In the desktop mode, we look for the text, XBLWP7, as this is a very obvious change in the User Agent in this state. For the mobile mode, we copied the IE Mobile 6 plus browser section. Microsoft changed the User Agent slightly between IE Mobile 6 and IE Mobile 7. The change comes in the User Agent, IE Mobile 7 doesn't have a space between the browser name IEMobile and the start of the version number. Instead, it has a forward slash. IE Mobile 6 had a space between the browser name and the version number.  
Read more
  • 0
  • 0
  • 1828
Visually different images

article-image-html5-developing-rich-media-applications-using-canvas
Packt
19 May 2011
10 min read
Save for later

HTML5: Developing Rich Media Applications using Canvas

Packt
19 May 2011
10 min read
HTML5 Multimedia Development Cookbook Recipes for practical, real-world HTML5 multimedia driven development. The cool thing with the new open-source canvas element is that not only can you create dynamic images on the fly, but the users' actions can create new images in real time as well—all without requiring a plugin. Sounds great, right? In many ways it is, but it also leaves our friends using assistive technologies out in the cold. What will happen if you're using a browser that doesn't support the new canvas element? Pretty much nothing. The browser just won't display it. That's why you'll need to be especially careful with this technology and not place anything inside the new canvas element on which your site or application absolutely depends. You must also consider fallback content. Browsers that support canvas include: Before proceeding with developing with the new canvas element, make sure you have a good foundation of skills with HTML and JavaScript. Being comfortable with object-oriented programming sure wouldn't hurt either. Now, let's get cooking! Setting up the canvas environment Creating the new canvas element is easy. How to do it... Check out how simple this is: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> </head> <body> <canvas id="FirstCanvas" width="800" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> How it works... Of course, we can use whatever height and width dimensions we need, but that simple set of tags is what we need to start. You're probably thinking we could use CSS to control the height and width, but resist that temptation. Because the new canvas element contains a 2d rendering context, that approach can cause unpredictable behavior. There's more... Next, we'll call the new canvas element JavaScript API while calling jQuery: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/ jquery.min.js"></script> <script> $(document).ready(function() { var canvas = document.getElementById("FirstCanvas"); var ctx = canvas.getContext("2d"); }); </script> </head> <body> <canvas id="FirstCanvas" width="800" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> He's smart "Let me make one thing completely clear: When you use canvas, you're not drawing on the canvas element itself. Instead, you're actually drawing on the 2d rendering context, which you're accessing through the canvas element via the JavaScript API." – Rob Hawkes What am I sayin'? Apple first introduced the new canvas element for the OSX Dashboard years ago. It was later implemented in web browsers Safari and then Chrome, with other browsers following suit. Since then it's become an official part of the HTML5 specification. What's next for <canvas>? Right now, we're barely scratching the surface of what the new canvas element can do. Now and in the future we'll use it to create animations, charts, diagrams, drawing apps, graphs, and user interfaces. What will you dream up? See also Developer Martin Angelov penned a great how-to guide titled, "An HTML5 Slideshow w/Canvas & jQuery" for Tutorial Zine at: http://tutorialzine.com/2010/09/html5-canvas-slideshow-jquery. In it, Martin demonstrates how to combine the new canvas element with jQuery, the most popular JavaScript framework, to create an intensely interactive image slideshow. Understanding the 2d rendering context It's important to understand that the new canvas element is really a "surface" on which to draw bitmapped images in the browser. How to do it... Defining a canvas tag like this only tells half the story: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> </head> <body> <canvas id="FirstCanvas" width="800" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> How it works... By itself that HTML5 code does nothing. We have to use JavaScript to make the Document Object Model retrieve the 2d rendering context in order to get something to happen: <script> $(document).ready(function() { var canvas = document.getElementById("FirstCanvas"); var ctx = canvas.getContext("2d"); }); </script> To be fair, that bit of JavaScript won't do anything without the canvas tag in the HTML either. There's more... You may be wondering about the name. If there's a 2d rendering context, isn't there probably a 3d rendering context too? The short answer is yes. But the more detailed answer isn't so simple. While a 3d rendering context does exist in theory, at the time of this publication no browser supports it. So if the new canvas element renders in 3d but nobody sees it, did it really do anything? You can master <canvas> The 2d context uses a number of different drawing contexts for the new canvas element that use syntaxes that should look quite familiar if you're experienced with CSS and JavaScript. X, meet Y When drawing, remember the X and Y axis in the top left corner of your browser window. Values increase going down the page. Respect my authority! The World Wide Web Consortium's HTML5 Canvas 2d Context specification is online at: http://dev.w3.org/html5/2dcontext. There we can dig even deeper into information like conformance requirements, the canvas state, transformations, compositing, colors and styles, line styles, shadows, simple shapes, complex shapes, focus management, text, images, pixel manipulation, drawing model, examples, and more. Processing shapes dynamically Let's look at the JavaScript functions that allow the new canvas element to draw rectangles. How to do it... fillRect(x,y,width,height) strokeRect(x,y,width,height) In order: fillRect(x,y,width,height) draws a filled rectangle. Next, strokeRect(x,y,width,height) draws an outline around the rectangle. Now, let's draw some shapes. How it works... We'll start with our basic canvas code and incorporate our new functions: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/ jquery.min.js"></script> <script> $(document).ready(function() { var canvas = document.getElementById("FirstCanvas"); var ctx = canvas.getContext("2d"); ctx.strokeRect(10, 10, 396, 236); ctx.fillStyle = "red"; ctx.fillRect(11, 11, 100, 100); ctx.fillStyle = "white"; ctx.fillRect(111, 11, 34, 100); ctx.fillStyle = "red"; ctx.fillRect(156, 11, 249, 100); ctx.fillStyle = "white"; ctx.fillRect(11, 111, 394, 34); ctx.fillStyle = "red"; ctx.fillRect(11, 145, 100, 100); ctx.fillStyle = "white"; ctx.fillRect(111, 145, 34, 100); ctx.fillStyle = "red"; ctx.fillRect(156, 145, 249, 100); }); </script> </head> <body> <canvas id="FirstCanvas" width="416" height="256"> <p>Flag of Denmark</p> </canvas> </body> </html> What we've created resembles the flag of Denmark! There's more... This example may not seem overwhelming at first, but when you remember that we've created an image with hardly any HTML and no CSS whatsoever, the new canvas element starts to look pretty impressive. Any way you want it Note that while we used color names ("white" and "red") we could also use hexadecimal values or RGB or even HSL! Use whatever makes the most sense for you and your interactive project. Similar to tables? Think of the color and size specifications for this example almost as the old-school tables we used to build back in the day for layout. While certainly not the same, there are definitely similarities to that technique in this case. Be a square first Mastering rectangles is the first canvas technique that's important to have under your belt after the ability to set up the element itself. Understanding the basics of this approach will help you grasp the fundamentals of the next few recipes. Drawing borders for images using canvas Let's take a closer look at the super simple method of drawing borders around images using the new canvas element. How to do it... First, we'll start with our basic canvas code and add one new line to draw a border: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/ jquery.min.js"></script> <script> $(document).ready(function() { var canvas = document.getElementById("FirstCanvas"); var ctx = canvas.getContext("2d"); ctx.strokeRect(10, 20, 100, 100); }); </script> </head> <body> <canvas id="FirstCanvas" width="800" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> How it works... That one line of JavaScript tells the browser to create a rectangle starting at 10 pixels from the left and 20 pixels from the top of the new canvas element. It draws the box 100 pixels square. There's more... That's nice, but if we want the border to be any other color than the default, we'll need to specify that: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/ jquery.min.js"></script> <script> $(document).ready(function() { var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); ctx.strokeStyle = "rgb(0, 128, 0)"; ctx.strokeRect(10, 20, 100, 100); }); </script> </head> <body> <canvas id="myCanvas" width="600" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> In this case we've used strokeStyle to specify an RGB color of pure green. Style first If you plan to style a border, you'll need to specify that before the border is drawn by the browser. If you specify that style afterward, the browser will simply ignore it. Many color values work The style attribute we just used was RGB, but the method also works with colors ("green", for example), hexadecimal values, HSL, and RGBA. I like big borders and I cannot lie If no border width is specified, the browser will automatically draw a one-pixel border. Here's how to change that: <!DOCTYPE html> <html> <head> <title>Canvas</title> <meta charset="utf-8" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/ jquery.min.js"></script> <script> $(document).ready(function() { var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); ctx.lineWidth = 10; ctx.strokeStyle = "rgb(0, 128, 0)"; ctx.strokeRect(10, 20, 100, 100); }); </script> </head> <body> <canvas id="myCanvas" width="600" height="600"> <!-- Fallback code goes here --> </canvas> </body> </html> It's just this easy:  
Read more
  • 0
  • 0
  • 2484

article-image-installation-silverstripe-24
Packt
13 May 2011
11 min read
Save for later

Installation of SilverStripe 2.4

Packt
13 May 2011
11 min read
  SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide Create smashing SilverStripe applications by extending modules, creating themes, and adding widgets         Read more about this book       (For more resources on SilverStripe, see here.) Setting up the environment There are many possible scenarios and environments you might require, depending on the complexity of your project. However, we'll keep this short and simple: We'll set up a development environment, which is based on Windows (Windows XP or newer) as it is the most common operating system on desktops and laptops. We'll also set up one live or deployment environment, which is based on Linux as it is the most common operating system for web servers. We'll use Ubuntu in our example as it is freely available and widely used. If you prefer a different distribution some paths and commands will vary, but the general approach should be very similar. In case you want to use a testing or staging environment as well, we'll assume that you simply reuse the previous setup—so we don't need to configure another system. Now that we've decided on the general purpose of the systems and their operating systems, we'll need to choose between different implementations for setting up the web server and database. Specifically, whether to use prebuilt packages or select the components ourselves. To demonstrate both approaches we'll use a prebuilt package on our development machine (as we want to get up and running quickly) and handpick the components on our live site, where we want to have maximum control. To keep our development and live environments closely related, we'll use the same applications for both—disqualifying Windows-only solutions: For the web server we'll use the Apache HTTP Server (http://httpd.apache.org) as it's the most widely used, cross-platform server. Alternatives would be Microsoft's Internet Information Services (http://www.iis.net), which are only available on Windows, and Lighttpd (http://www.lighttpd.net) or Nginx (http://nginx.org), which are both fast, but not as widely used as the Apache web server, and are a little trickier to set up. For the database we'll use the popular MySQL (http://www.mysql.com). Alternatively you could use Microsoft SQL Server (https://www.microsoft.com/sqlserver/2008/en/us/default.aspx), which requires Windows; PostgreSQL (http://www.postgresql.org), SQLite (http://www.sqlite.org), or an Oracle database (http://www.oracle.com/us/products/database/index.html). However, each of these alternatives requires an additional SilverStripe module to support its specific SQL dialect, which generally receive less attention than MySQL. Unless you have a good reason for changing the database, like you're already using MS SQL for everything else, stick with MySQL. For a change the programming language PHP (http://www.php.net) doesn't require any decisions as there are no alternative implementations. For the prebuilt package we'll use XAMPP (http://www.apachefriends.org/en/xampp.html), which matches our requirements. It uses the Apache HTTP Server and MySQL and is available on Windows, Linux, Mac OS X, and Solaris. If your development machine doesn't use Windows, you should still be able to follow the installation steps with minor variations. On Windows there's also Microsoft's Web Platform Installer (http://www.microsoft.com/web/downloads/platform.aspx). It doesn't only include the web server, database and PHP, but also SilverStripe itself (http://www.microsoft.com/web/gallery/silverstripecms.aspx)—which can be downloaded on demand among many other web applications. However, as this is very different to our live site, we won't cover it. If you're looking for a, Windows-only solution this is nevertheless an interesting option as it is very easy to set up. The Windows development system Let's start off by setting up our development system, based on the freely available XAMPP package. Time for action - installing XAMPP We'll assume that the operating system is Windows XP or newer—for Linux, Mac OS X, and Solaris you should only need to get a different download file and do some minor variations of the steps described: Download the XAMPP package at http://www.apachefriends.org/en/xampp-windows.html. We're using the 7zip package as it doesn't require an installation, is compact to download and also portable: you can copy it to a USB drive and use the environment on any Windows computer. Extract the archive to a top-level folder on your internal drive (C: for example), or your portable external drive (U: for example). To do this, you'll need the free 7zip archive utility, which you can download at http://www.7-zip.org. Open up the file xampp/mysql/bin/my.ini and add the following line in the [mysqld] section: lower_case_table_names=2 This setting is important for exchanging database dumps between Windows and Linux systems. As Windows paths are case insensitive, MySQL lowercases database and table names by default (as they are internally stored as folders and files), but only on Windows. On Linux proper cases are preserved, which leads to problems when using dumps on different platforms. The previous statement forces MySQL on Windows to behave like on Linux. Inside the XAMPP folder, start the file xampp-control.exe and use it to Start Apache, MySql and Mercury. XAMPP's control panel should look like this after starting the three applications: If a service doesn't start, check that its port is not already in use—this is the main reason for problems. To do this, open the command line tool and enter netstat-ao. This will show you the ports currently in use and the process IDs (PIDs) of the processes using them. Using Window's Task-Manager you can then find out the name of the process causing the problem, and stop or reconfigure it. The following screenshot illustrates this scenario—the web server cannot be started as Skype is already using port 80: After successfully starting all three services, navigate to http://localhost in your browser. This should redirect you to XAMPP's welcome page. In case you need to send e-mails for testing purposes, you'll need to perform two additional steps to configure your SMTP server: Enable SMTP relaying of non-local mail. However, ensure that no one can access your mail server from outside or you might be abused as a spam relay (your router or firewall will protect you). In XAMPP's control panel, click on Admin... next to the Mercury label. Next go to Configuration, MercuryS SMTP Server and on the Connection control tab uncheck Do not permit SMTP relaying of non-local mail. Provide a DNS server so domain names can be looked up: Under Configuration, MercuryE SMTP Client fill in the field Name server with your provider's DNS server. That's it for our general purpose development machine. In case you want to run automatic tests or generate translation files, you'll also need to install PHPUnit through PEAR: While XAMPP includes PEAR and PHPUnit, the bundled versions are hopelessly outdated. Furthermore the update process doesn't work reliably, so we'll better start anew. First remove xampp/php/PEAR/, xampp/php/pear.bat, xampp/php/pear.ini, xampp/php/peardev.bat and xampp/php/pear-update.bat. Next enable PHP's cURL extension: Open xampp/php/php.ini, find the line ;extension=php_curl.dll and remove the leading semicolon. Then download http://pear.php.net/go-pear.phar into xampp/php/. Next install PEAR on the command line (start it as an admin user). Note that you must be in the folder xampp/php/ for the following commands to work: php go-pear.phar Now we can use PEAR to update its channels and upgrade all packages: pear update-channelspear upgrade --alldeps Finally you can install PHPUnit and all of its dependencies: pear channel-discover pear.phpunit.depear channel-discover components.ez.nopear channel-discover pear.symfony-project.compear install phpunit/PHPUnit That's it, you've successfully installed PHPUnit! The Linux live system Next we'll set up our live system. Thanks to package managers this isn't much harder—you just shouldn't be afraid of the shell. Time for action - installing the requirements by hand In our example we're using Ubuntu, so we'll rely on its package manager Apt, abbreviation of Advanced Package Tool. Note that we won't only install the bare necessities, but also some more tools to make our system ready for production. Open the terminal and install the Apache HTTP Server together with PHP and PHP's GD library (needed for image manipulation) through the following commands. Note that all required dependencies are added automatically, though you may need to manually accept them: sudo apt-get install apache2 php5 php5-gd Next we'll install MySQL and its binding to PHP, again through the terminal. You'll be prompted for a password, which we'll need again later on. sudo apt-get install mysql-server php5-mysql Enable Apache's rewrite module, which SilverStripe requires to use pretty URLs: sudo a2enmod rewrite Edit the file /etc/apache/sites-available/default and replace the line AllowOverride None with AllowOverride All inside the <Directory /var/www/> block. This enables the rewrite module inside the /var/www/ folder. Install Alternative PHP Cache (APC), which will accelerate PHP programs—SilverStripe benefits a lot from this. While there are some alternatives, it is currently planned that APC will be included in PHP 6, which makes it sound like a future-proof decision for our installation: sudo apt-get install php-apc If you want to see APC in action, you'll need its management tool. By default it is located in the file /usr/share/doc/php-apc/apc.php.gz. Unpack and copy it to your web-root to see detailed statistics on how well it's working for you, but protect it against unauthorized access (you can set credentials inside the file). Edit the file /etc/php5/apache2/php.ini, using whatever text-editor you prefer (this can be quite a sensitive topic with programmers). Replace the line ;date.timezone = with date.timezone = US/New_York or your current location. See http://php.net/manual/en/timezones.php for all possible values. Note that removing the semicolon at the beginning is important, otherwise the line will be considered a comment. Restart the web server to apply all the settings we've just made: sudo /etc/init.d/apache2 reload Now it's time to test our installation. Go to the directory /var/www/ which is the default web-root directory: cd /var/www/ It should already contain a file index.html, which you can view if you visit http://127.0.0.1 in your browser (or whichever IP address you can access your server under). However, this is only a static HTML file. To see if PHP is also working, first set the file permissions, assuming our current user is ubuntu (which we'll use to edit files) and the web server is run as www-data (which is the default). So we'll make our user the owner of the files with full permissions, and set the group to the one of the web server with read and execute permissions only: sudo chown ubuntu:www-data -R /var/www/sudo chmod 0755 -R /var/www/ After adding new files, you'll need to rerun these two commands. Next create a file index.php in /var/www/: touch index.php Add the following code to it: <?php phpinfo();?> In your browser load the page http://127.0.0.1/index.php (again use your specific IP address). The output should look something like this: This shows that PHP is working. Also check that you can find mod_rewrite and a full section on APC in the output to be sure they are enabled. That's it, our live system is now ready for action. We haven't installed PEAR as we'll assume that testing and translating is done in the development environment, not on the live server. We've also left out how to install and configure an SMTP server. Unfortunately this is pretty complicated and beyond the scope of this article—especially since you don't want to become a spam relay. If your provider or distribution hasn't already set this up for you, take a look at a specific SMTP server how-to and documentation—Postfix (http://www.postfix.org) is widely used for example.
Read more
  • 0
  • 0
  • 1452

article-image-silverstripe-24-creating-our-own-theme
Packt
12 May 2011
8 min read
Save for later

SilverStripe 2.4: Creating our Own Theme

Packt
12 May 2011
8 min read
Time for action - files and folders for a new theme We could start off from scratch, but let's not make it more complicated than necessary: Simply copy the BlackCandy theme to a new folder in the same directory. We'll just call it bar as the page should be for a bar business. Now reload the CMS backend and you should be able to switch to the new bar theme. As we won't use any of the available images we can delete all image files, but leave the folder intact—we'll add our own pictures later on. Basic layout Next, we'll create our page's general layout. Time to put our template skills into action! Here's the basic layout we want to create: So far it's a pretty basic page. We'll take a good look at the templates and basic structure but won't spend much time on the HTML and CSS specifics. Do, however pay attention on how to set up the different CSS files to make the most out of them. We won't list every line of code involved. If you'd prefer, you can simply copy the missing parts from the code provided here (Ch:2) File themes/bar/templates/Page.ss This page is pretty empty. We'll later add an intro page with a different structure, so the code these templates will share is rather limited. Time for action - the base page Add the following code to the file themes/bar/templates/Page.ss: <!doctype html> <html lang="$ContentLocale"> <head> <meta charset="utf-8"/> <% base_tag %> <title> <% if MetaTitle %> $MetaTitle <% else %> $Title <% end_if %> </title> $MetaTags(false) <link rel="shortcut icon" href="favicon.ico"/> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"> </script> <![endif]--> </head> <body> $Layout <noscript> <br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp; <div><p> <b>Please activate JavaScript.</b><br/> Otherwise you won't be able to use all available functions properly... </p></div> </noscript> </body> </html> What just happened? The highlighted parts are SilverStripe specific: First, we set the language of our content. Depending on what you've selected during the installation process this can vary. By default, it will be: <html lang="en-US"> Setting the page's base; this can be useful when referencing images and external files. Depending on how you set up your system this will vary. Setting the title just like in the BlackCandy theme. Next, adding meta tags without the title element. These are only set if you actually enter them in the CMS on the Metadata tab on the desired page's Content tab. Empty fields are simply left out in the output. Only the SilverStripe note is set in any case. Finally, including the page's specific layout. The JavaScript we include for Internet Explorer versions before 9 fixes their inability to correctly render HTML5 tags. To learn more about the specific code, head over to https://code.google.com/p/html5shim/. Why HTML5? The motivation behind it isn't to stay buzz-word compliant. While HTML5 is not a finished standard yet, it already adds new features and makes the development a little easier. Take a look at the doctype declaration for example: that's much shorter than XHTML. Now there's a real chance of actually remembering it and not needing to copy it every time you start from scratch. New features include some very handy tags, but we'll come to those in the next code sample. The output on the final HTML page for the second and third elements (we've already taken a look at the first) in the header looks like the following listing. Which part in the template is responsible for which line or lines? <title>home</title> <meta name="generator" content="SilverStripe - http://silverstripe.org" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="keywords" content="some keyword" /> <meta name="description" content="the description of this page" /> Did you notice that there is no reference to a CSS file and the styling is still applied? Remember that CSS files are automagically included if you stick to the naming convention we've already discussed. File themes/bar/templates/Layout/Page.ss Now let's move beyond the basics and do something a bit more interesting. Time for action - the layout page Add the following code to the file themes/bar/templates/Layout/Page.ss: <div> <img src="$ThemeDir/images/background.jpg" alt="Background" id="background"/> </div> <section id="content" class="transparent rounded shadow"> <aside id="top"> <% include BasicInfo %> </aside> <% include Menu %> <section class="typography"> $Content $Form </section> </section> <% include Footer %> We rely on just three includes which are very easy to reuse on different pages. We then reference the page's content and possible forms (no comments will be required). The only template part we've not yet covered is the $ThemeDir. This is replaced by the path to our theme, in our case themes/bar/. So you don't need to worry about hard-coded paths when copying template files between different themes. You only need to take care of paths in the CSS files as they are not processed by the template engine. The includes: BasicInfo.ss, Menu.ss, and Footer.ss In the previous code segment, we've referenced three includes. Let's not forget to create them. Time for action - the includes The includes we're yet to explore are Menu.ss, BasicInfo.ss, and Footer.ss. The menu is very simple, we only include the first level, highlighting the currently active item, as we won't have more subpages: <nav id="menu"> <ul> <% control Menu(1) %> <li class="$Linkingmode"> <a href="$Link">$MenuTitle</a> </li> <% end_control %> </ul> </nav> BasicInfo.ss only contains the $ThemeDir placeholder besides good old HTML: <a href="home"> <img src="$ThemeDir/images/logo.png" alt="Logo" id="logo"/> </a> <ul id="details-first"> <li>Phone: <b>01 23456789</b></li> <li>Contact: <a href="contact">[email protected]</a></li> <li>Address: <a href="location">Bar Street 123</a></li> </ul> <div id="details-second"> <div class="left">Opening hours:</div> <div class="right"><p> <b>Mon - Thu 2pm to 2am</b><br/> <b>Fri - Sat 2pm to 4am</b> </p></div> </div> <a href="http://www.facebook.com/pages/"> <img src="$ThemeDir/images/facebook.png" alt="Facebook" id="facebook"/> </a> Be sure to replace bar.com with your own domain. However, using it here is quite fitting because we're making a page for a bar and http://www.bar.com is only a placeholder itself. It's derived from foobar or foo bar, a placeholder name often used in computer programming. But take a look at the site yourself for more information. Finally, the footer makes use of the $Now placeholder and the date formatter .Year to retrieve the current year: <footer> <span><a href="imprint">Imprint</a></span> <span>&copy; Bar $Now.Year</span> </footer> Have a go hero - create the layout and pages Now that we've gone over all of the content, it's time to build the page. Feel free to copy some code as we're not a typing class, but take careful note of every SilverStripe specific part, so you understand what you're doing. We use three includes, so create these files and remove the rest still available from BlackCandy as well as the unused templates/Layout/Page_results.ss. And don't forget to flush the cache by appending ?flush=all to the page's URL! When working with includes it will save you a lot of trouble. We've hardcoded some links to different pages in the template files. Make sure you add all necessary pages including the imprint, but don't add it to the menu.
Read more
  • 0
  • 0
  • 1936
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 $15.99/month. Cancel anytime
article-image-cms-made-simple-application-user-defined-tags
Packt
10 May 2011
9 min read
Save for later

CMS Made Simple: Application of User-Defined Tags

Packt
10 May 2011
9 min read
CMS Made Simple Development Cookbook Over 70 simple but incredibly effective recipes for extending CMS Made Simple with detailed explanations – useful for beginners and experts alike! These recipes have been specially selected to demonstrate capabilities. While they may be useful as provided, they are designed to show the range of what can be done with tags, and to provide examples of useful operations such as setting Smarty variables, interfacing with the database, interacting with modules, and consuming data from remote web services. You are encouraged to use these recipes as starting points for your own projects. Introduction One of the most popular uses of CMS Made Simple involves an administrator who creates a basic site structure and template, and one or more editors who maintain page content without having to worry about the site layout. In this configuration, you can think of the CMS essentially as a big template engine with some utilities to add content. Each page of the site comprises a page template with areas that get populated with various kinds of content. These areas are either tags or variables, where the distinction is that a tag involves the execution of code, while a variable is a simple substitution of values. The CMS comes with a large assortment of built-in tags, including the fundamental "content" tag and a variety of useful supporting tags for building navigation, links, including images, and so forth. Because CMS Made Simple can be seen as being built around tags, it is not surprising that there are facilities for creating your own tags. You can create tags directly through the Admin panel—these are called User-Defined Tags or UDTs. If you want even more extensive capabilities in your tag, you can have those capabilities by creating a file that follows a few basic conventions. The template engine used by CMS Made Simple comes from the Smarty project. Pages are Smarty templates, and the built-in CMS tag types are all Smarty tags. Behind the scenes, both UDTs and file-based tags also become Smarty tags. For additional information on Smarty, the documentation provided by the Smarty project is invaluable. You can read more at http://www.smarty.net/docsv2/en/ Displaying the User's IP address from a User-Defined Tag This recipe demonstrates creating a very simple User-Defined Tag, and using it to display information, that it gets from PHP globally-defined variables. Getting ready For this recipe, you will need to have CMS Made Simple installed and working. You will need login access to the site's Administration area as a member of the "admin" group, or as a member of a group with permissions to "Modify User-Defined Tags" and "Manage All Content". How to do it... Log in to your CMS Administration area. Using the top menu, go to "Extensions" and click on "User Defined Tags". Click on the "Add User Defined Tag" button. In the "Name" field type "user_ip". In the "Code" text area, type the following code: echo 'Welcome user from '.$_SERVER['REMOTE_ADDR'].' -- enjoy your visit!'; Click on the "Submit" button. Using the top menu, go to "Content" and click on "Pages". Click on the "Add New Content" button. In the "Title" and "Menu Text" fields, type "Tag Test". In the "Content" text area, type the following code: {user_ip} Click on the "Submit" button. View your site from the user side. Click on the new "Tag Test" page. How it works... User-Defined Tags work by linking a piece of PHP code to a tag which is recognized by Smarty. When Smarty parses a template and encounters that tag, it executes the code in question, and substitutes the tag markup with any output from that PHP code. When we create a UDT in the CMS Made Simple admin area, the name we enter into the text field becomes the tag which Smarty will look for, and the code we enter into the text area is the PHP associated with the tag. This recipe is an example of outputting text directly from a User-Defined Tag. It works by echoing a string, that then replaces the {user_ip} tag in the content. This substitution of the tag can take place either in a page template or in the page content, which might seem a little confusing since it's stated earlier that Smarty processes tags that it finds in templates. The confusion, though, is mostly due to terminology; CMS Made Simple processes both layout templates and page content through Smarty, so while it is being processed, page content serves as a template from Smarty's perspective. The User-Defined Tag we create accesses one of the PHP "superglobals"—the $_SERVER variable . This variable contains information about the HTTP request and some environmental information about the PHP server. In this case, we're getting the user's IP address information to display. Using the CmsObject and the current content object in a User-Defined Tag This recipe shows you how to access the Page Content object via the CmsObject in a User-Defined Tag. The primary technique that it demonstrates—getting a reference to the CmsObject and using the CmsObject to get a reference to other important CMS runtime objects—is one that you will use to solve many different kinds of problems. In this recipe, we use the CmsObject to get a reference to the Page Content object. Once we have a reference to this object, we can call upon its methods to report all kinds of interesting information about the current page content. Getting ready For this recipe, you will need login access to your site's Administration area with permission to "Modify User-Defined Tags" and "Manage All Content". How to do it... Log in to your CMS Administration area. Using the top menu, go to "Extensions" and click on "User Defined Tags". Click on the "Add User Defined Tag" icon. In the "Name" field, type "content_description". In the "Code" field, type the following code: $gCms = cmsms(); $contentops = $gCms->GetContentOperations(); $content_obj = $contentops->getContentObject(); echo 'Current content object is "'.$content_obj->Name().'"<br />'; echo 'which was created on '.$content_obj->GetCreationDate().'<br />'; echo 'its alias is "'.$content_obj->Alias().'"<br />'; echo 'and its URL is "'.$content_obj->GetURL().'"<br />'; Click on the "Submit" button. Using the top menu, select "Content" and click on "Pages". Click on the "Add New Content" button. Enter "New Content Page" into the "Title" and "Menu Text" fields. In the "Content" field, enter: {content_description} Click on the "Submit" button. View your site from the user side. Click on the new "Content Page" page. How it works... CMS Made Simple uses an internal object called "CmsObject" to keep track of a great deal of what it needs to serve content. This information includes the site hierarchy, the installed and active modules, references to the database, and more. The CmsObject is available to Modules, Tags, and User-Defined Tags via the cmsms() function. In this recipe, we want to display information from the current Content object. However, this object is not directly accessible. To get access to this object, we need to make a static call to the ContentOperations object, but this object is also not directly accessible from our code. To get access to these objects, we need to get references to them. We start by gaining access to the CmsObject by calling the global cmsms() function. From our reference to the CmsObject, we request a reference to the ContentOperations object, that we then use to request a reference to the current content object. Once we have the current content object, we can call assorted methods on it to retrieve information about the current content. In this recipe, we get the content's name, when it was last modified, its alias, and its URL. Since this recipe is an example, we don't format these various pieces of information or use a template, but simply echo them. In a production UDT or one in which there's any complexity to what is being displayed, it would be more advisable to use the values to populate Smarty variables for later display, or use a template for formatting them. There's more... There are a number of interesting objects, that CmsObject manages. References can be requested to: BookmarkOperations— used in the Admin area ContentOperations—which has methods to handle Content and content metadata Db— which wraps the ADODB database API GlobalContentOperations— which has methods to handle Global Content Blocks GroupOperations— which has methods to handle Admin Groups HierarchyManager— which has methods for handling site content hierarchies ModuleOperations— which has methods for managing Modules Smarty— which wraps the Smarty template engine StylesheetOperations—which has methods for handling TemplateOperations— which has methods for handling Smarty templates UserOperations— which has methods for handling Admin Users UserTagOperations— which has methods for handling User-Defined Tags Getting attributes using page_attr If you're looking to display information about the current content object, CMS Made Simple has a custom Smarty tag that provides some attributes: {page_attr}. You can use this tag to display page attribute information—simply by specifying a key to the information you're requesting. For example, to get the page's "image" attribute, you could use the tag {page_attr key="image"}. Other keys that are supported include: target image thumbnail extra1 extra2 extra3 searchable pagedata disable_wysiwyg content_en As you can see, this is not as rich a collection of information as you can get from the content object directly using your own UDT. Old code and the use of globals If you look at old modules or User-Defined Tags that have been posted in the CMS Made Simple forum, you may see the following code: global $gCms; instead of the $gCms = cmsms() used here. For a long time, the use of the global declaration was the preferred way to access the CmsObject. This approach is now deprecated for a number of reasons, most important of which is a security issue and also including portability of code between CMS Made Simple 1.x and the upcoming 2.x versions. While use of the global declaration to access the CmsObject will likely still work, it is strongly discouraged.  
Read more
  • 0
  • 0
  • 3486

article-image-wordpress-3-building-widget
Packt
06 May 2011
10 min read
Save for later

WordPress 3: Building a Widget

Packt
06 May 2011
10 min read
  WordPress 3 Plugin Development Essentials Create your own powerful, interactive plugins to extend and add features to your WordPress site         Read more about this book       (For more resources on WordPress, see here.) The plan What exactly do we want this plugin to do? Our widget will display a random bit of text from the database. This type of plugin is frequently used for advertisement rotations or in situations where you want to spruce up a page by rotating content on a periodic basis. Each instance of our plugin will also have a "shelf life" that will determine how frequently its content should be randomized. Let's take a moment to come up with some specifications for this plugin. We want it to do the following: Store multiple chunks of content, such as bits of Google Adsense code Be able to randomly return one of the chunks Set a time limit that defines the "shelf life" of each chunk, after which the "random" chunk will be updated Widget overview Even if you are already familiar with widgets, take a moment to look at how they work in the WordPress manager under Appearance | Widgets. You know that they display content on the frontend of your site, usually in a sidebar, and they also have text and control forms that are displayed only when you view them inside the manager. If you put on your thinking cap, this should suggest to you at least two actions: an action that displays the content on the frontend, and an action that displays the form used to update the widget settings inside the manager. There are actually a total of four actions that determine the behavior of a standard widget, and you can think of these functions as a unit because they all live together in a single widget object. In layman's terms, there are four things that any widget can do. In programmatic terms, the WP_Widget object class has four functions that you may implement: The constructor: The constructor is the only function that you must implement. When you "construct" your widget, you give it a name, a description, and you define what options it has. Its name is often __ construct(), but PHP still accepts the PHP 4 method of naming your constructor function using the name of the class. widget(): It displays content to users on the frontend. form(): It displays content to manager users on the backend, usually to allow them to update the widget settings. update(): It prepares the updated widget settings for database storage. Override this function if you require special form validation. In order to make your widget actually work, you will need to tell WordPress about it by registering it using the WordPress register_widget() function. If you want to get a bit more information about the process, have a look at WordPress' documentation here. Let's outline this in code so you can see how it works. Preparation As always, we're going to go through the same setup steps to get our plugin outlined so we can get it activated and tested as soon as possible. Create a folder inside the wp-content/plugins/ directory. We are naming this plugin "Content Rotator", so create a new folder inside wp-content/ plugins/ named content-rotator. Create the index.php file. Add the Information Head to the index.php file. If you forgot the format, just copy and modify it from the Hello Dolly plugin like we did in the previous article, Anatomy of a WordPress Plugin. We're giving you bigger sections of code than before because hopefully by now you're more comfortable adding and testing them. Here is what our index.php looks like: <?php/*------------------------------------------------------------------------------Plugin Name: Content RotatorPlugin URI: http://www.tipsfor.us/Description: Sample plugin for rotating chunks of custom content.Author: Everett GriffithsVersion: 0.1Author URI: http://www.tipsfor.us/------------------------------------------------------------------------------*/// include() or require() any necessary files here...include_once('includes/ContentRotatorWidget.php');// Tie into WordPress Hooks and any functions that should run onload.add_action('widgets_init', 'ContentRotatorWidget::register_this_widget');/* EOF */ Add the folders for includes and tpls to help keep our files organized. Add a new class file to the includes directory. The file should be named ContentRotatorWidget.php so it matches the include statement in the index.php file. This is a subclass which extends the parent WP_Widget class. We will name this class ContentRotatorWidget, and it should be declared using the extends keyword. <?php /*** ContentRotatorWidget extends WP_Widget** This implements a WordPress widget designed to randomize chunksof content.*/class ContentRotatorWidget extends WP_Widget { public $name = 'Content Rotator'; public $description = 'Rotates chunks of content on a periodic basis'; /* List all controllable options here along with a default value. The values can be distinct for each instance of the widget. */ public $control_options = array(); //!!! Magic Functions // The constructor. function __construct() { $widget_options = array( 'classname' => __CLASS__, 'description' => $this->widget_desc, ); parent::__construct( __CLASS__, $this->name,$widget_ options,$this->control_options); } //!!! Static Functions static function register_this_widget() { register_widget(__CLASS__); } } /* EOF */ This is the simplest possible widget—we constructed it using only the __ construct() function. We haven't implemented any other functions, but we are supplying enough information here for it to work. Specifically, we are supplying a name and a description, and that's enough to get started. Let's take a moment to explain everything that just happened, especially since the official documentation here is a bit lacking. When we declared the ContentRotatorWidget class, we used the extends keyword. That's what makes this PHP class a widget, and that's what makes object-oriented code so useful. The __construct() function is called when an object is first created using the new command, so you might expect to see something like the following in our index. php file: <?php $my_widget = new ContentRotatorWidget();?> However, WordPress has obscured that from us—we just have to tell WordPress the classname of the widget we want to register via the register_widget() function, and it takes care of rest by creating a new instance of this ContentRotatorWidget. There is a new instance being created, we just don't see it directly. Some of the official documentation still uses PHP 4 style examples of the constructor function— that is to say that the function whose name shares the name of the class. We feel that naming the constructor function __construct is clearer. You may have wondered why we didn't simply put the following into our index.php file: register_widget('ContentRotatorWidget'); // may throw errors if called too soon! If you do that, WordPress will try to register the widget before it's ready, and you'll get a fatal error: "Call to a member function register() on a non-object". That's why we delay the execution of that function by hooking it to the widgets_ init action. We are also tying into the construct of the parent class via the parent::__ construct() function call. We'll explain the hierarchy in more detail later, but "parent" is a special keyword that can be used by a child class in order to call functions in the parent class. In this case, we want to tie into the WP_Widget __ construct() function in order to properly instantiate our widget. Note our use of the PHP __CLASS__ constant—its value is the class name, so in this case, we could replace it with ContentRotatorWidget, but we wanted to provide you with more reusable code. You're welcome. Lastly, have a look at the class variables we have declared at the top of the class: $name, $description, and $control_options. We have put them at the top of the class for easy access, then we have referenced them in the __construct() function using the $this variable. Note the syntax here for using class variables. We are declaring these variables as class variables for purposes of scope: we want their values to be available throughout the class. Please save your work before continuing. Activating your plugin Before we can actually use our widget and see what it looks like, we first have to activate our plugin in the manager. Your widget will never show up in the widget administration area if the plugin is not active! Just to be clear, you will have to activate two things: your plugin, and then your widget. The code is simple enough at this point for you to be able to quickly track down any errors. Activating the widget Now that the plugin code is active, we should see our widget show up in the widget administration area: Appearance | Widgets. Take a moment to notice the correlation between the widget's name and description and how we used the corresponding variables in our constructor function. Drag your widget into the primary widget area to make it active. Once it has been activated, refresh your homepage. Your active widget should print some text in the sidebar. (Move the mouse over the image to enlarge it.) Congratulations! You have created your first WordPress widget! It is printing a default message: function WP_Widget::widget() must be over-ridden in a sub-class, which is not very exciting, but technically speaking you have a functional widget. We still need to enable our widget to store some custom options, but first we should ensure that everything is working correctly. Having problems? No widget? If you have activated your plugin, but you do not see your widget showing up in the widget administration area, make sure you have tied into a valid WordPress action! If you misspell the action, it will not get called! The action we are using in our index.php is widgets_init—don't forget the "s"! White screen? Even if you have PHP error-reporting enabled, sometimes you suddenly end up with a completely white screen in both the frontend and in the manager. If there is a legitimate syntax error, that displays just fine, but if your PHP code is syntactically correct, you end up with nothing but a blank page. What's going on? A heavy-handed solution for when plugins go bad is to temporarily remove your plugin's folder from /wp-content/plugins, then refresh the manager. WordPress is smart enough to deactivate any plugin that it cannot find, so it can recover from this type of surgery. If you are experiencing the "White Screen of Death", it usually means that something is tragically wrong with your code, and it can take a while to track it down because each time you deactivate the plugin by removing the folder, you have to reactivate it by moving the folder back and reactivating the plugin in the WordPress manager. This unenviable situation can occur if you accidentally chose a function name that was already in use (for example, register()—don't use that as a function name). You have to be especially careful of this when you are extending a class because you may inadvertently override a vital function when you meant to create a new one. If you think you may have done this, drop and do 20 push-ups and then have a look at the original parent WP_Widget class and its functions in wp-includes/widgets.php. Remember that whenever you extend a class, it behooves you to look at the parent class' functions and their inputs and outputs. If this sounds like Greek to you, then the next section is for you.
Read more
  • 0
  • 0
  • 2138

article-image-silverstripe-24-customizing-layout
Packt
06 May 2011
10 min read
Save for later

SilverStripe 2.4: Customizing the Layout

Packt
06 May 2011
10 min read
Templates and themes All pages within SilverStripe are rendered using a template, which is basically an HTML/XHTML file with added control code. A template allows you to make conditional statements, create menus, access data stored in the database, and much more. Instead of using PHP for these enhancements, templates rely on a dedicated template engine. When the user accesses a page the engine replaces the control code with PHP. This transformation is then evaluated by the web server to regular markup code, which every browser can display. A theme consists of a collection of template, CSS, and image files. Design-specific JavaScript is also stored here. Together they form the layout of a page. Switching between themes You can have multiple themes and switch between them whenever you like. You're definitely encouraged to give everything described here a try. It helps you in becoming an active developer instead of a passive user. So let's get things started! Time for action - change the default theme Simply perform the following steps in the CMS and you're all set: Log into the CMS by appending /admin to your page's base URL. Provide the credentials you defined during the installation and you should be logged-in. Go to the general configuration page by clicking on the globe within the Page Tree section. The default text of this element is Your Site Name. The Theme is set to (Use default theme) by default; change this to tutorial. Click on the Save button. Go to the base URL / and reload the page. What just happened? We've successfully changed the theme of our website. It's as easy as that. Note that you need to package your theme into a subfolder of themes/ to be able to switch between them. While you can also put the contents of a theme directly into the mysite/ folder, keeping your system modularized is a good practice. Therefore we won't integrate the layout into the site specific folder and will instead always create a dedicated, switchable theme. Getting more themes After unpacking a theme, copy it to the themes/ folder, change the theme in the CMS, and you're good to go. Using a prebuilt theme really is that simple. Next, we'll take a look at the facilities for building our own themes—specifically, the template engine that powers all themes in SilverStripe. By the end of this article and next, you'll even be ready to upload and share your own themes with the rest of the community at the address above. New contributions are always welcome. Template engine As described earlier, the SilverStripe architecture consists of three layers, each serving a specific purpose. The one responsible for the layout is called View, which we'll cover in detail in this article. Another template engine? One might wonder why it is necessary to learn another template language, while there are already so many others available and PHP can do all of it as well. The main reasons behind this are: The template engine and the rest of the system fit perfectly together. After getting the hang of it, it makes the creation of templates and communication with the other layers faster and easier. The available control code is very simple. Designers without a lot of programming knowledge can create feature-rich layouts. It enforces good coding practice. Without the ability to use raw PHP, one cannot by-pass the other layers and undermine the architecture. Only layout and rendering information should be used within templates. Taking a look at BlackCandy First of all, switch back to the BlackCandy theme as we want to take a better look at it. Within your installation, navigate to the folder themes/blackcandy/ and you'll see three folders: css/, images/, and templates/. The images/ folder contains any image used in your theme; if you like, you can create subfolders to keep things organized. The remaining folders are a bit more complicated, so let's break them down. CSS At first this looks a bit messy—five files for the CSS; couldn't we use just a single one? We could, but many developers consider it a good practise splitting the functionality into different parts, making it easier to navigate later on. Sticking to this convention adds functionality as well. This is a common principle, called convention over configuration. If you do things the way they are expected by the system, you don't need to configure them specifically. Once you know the "way" of the system, you'll work much quicker than if you had to configure the same things over and over again. editor.css This file is automagically loaded by SilverStripe's what you see is what you get (WYSIWYG) editor. So if you apply the correct styling via this file, the content in the CMS' backend will look like the final output in the frontend. Additionally you'll have all custom elements available under the Styles dropdown, so the content editors don't need to mess around with pure HTML. As this file is not automatically linked to the frontend, it's common practice to put all frontend styling information into typography.css and reference that file in editor.css: @import "typography.css"; If you want to provide any styling information just for the CMS, you can put it below the @import. layout.css, form.css, and typography.css These files are automagically included in the frontend if they are available in your theme. While layout.css is used for setting the page's basic sections and layout, form.css deals with the form related styling. typography.css covers the layout of content entered into the CMS, generally being imported by editor.css as we've just discussed. Elements you will include here are headers (<h1>, <h2>, and so on), text (for example <p>), lists, tables, and others you want to use in the CMS (aligning elements, <hr>, and so on). ie6.css This file isn't part of the SilverStripe convention, but is a useful idea you might want to adopt. You must include it manually but it will still be a good idea to stick to this naming schema: ie.css for styling elements in any version of Internet Explorer, ie6.css for Internet Explorer 6 specifics, and so on. What about performance? Cutting down on the number of files being loaded is an effective optimization technique for websites. We'll take a look at how to do that. Templates Now that we've discussed the styling, let's take a look at how to put the content together with the help of templates. Learning the very basics Before we continue, some basic facts and features of templates: Templates must use the file extension .ss instead of .html or .php. Templates can be organized alongside their PHP Controllers, so you can use the same powerful mechanism as in the other layers. We'll take a better look at what this means a little later. Page controls consist of placeholders and control structures, which are both placed within the regular markup language. Placeholders start with a $ and are processed and replaced by the template engine. Control structures are written between opening <% and closing %>. They look a bit like HTML tags and they are used the same way. Some consist of a single element, like HTML's <br>, whereas others consist of two or more. Starting to use templates Now that we've covered the basics, let's put them into practice. Time for action - using site title and slogan We shall use placeholders, taking a look at the code level and how to use them in the CMS: Open the file themes/blackcandy/templates/Page.ss in your preferred editor. If the syntax highlighting is disabled due to the unknown file extension, set it to HTML. Find the two placeholders $SiteConfig.Title and $SiteConfig.Tagline in the code. Go to the general configuration page in the CMS, the one where we've changed the theme. Edit the Site title and Site Tagline/Slogan to something more meaningful. Save the page. Go to the base URL and hit refresh. If you view the page's source, you can see that the two placeholders have been replaced by the text we have just entered in the CMS. If you are wondering about the short doctype declaration: there is nothing missing, this is HTML5, which SilverStripe is already using in its default theme. If you prefer XHTML or an older HTML standard, you can freely change it. The CMS happily works with all of them. What just happened? The file we've just edited is the base template. It's used for every page (unless specifically overwritten). You can define your general layout once and don't have to repeat it again. You should always try to avoid repeating code or content. This is generally called don't repeat yourself (DRY) or duplication is evil (DIE). SilverStripe supports you very well in doing this. The site title and slogan are globally available. You can use them on every page and they share the same content across the whole website. These placeholders are prefixed with SiteConfig. as well as a $ sign. In the CMS they are all available on the site's root element, the one with the globe. By default, there are just two, but we'll later see how to add more. Other placeholders are available on specific pages or can be different on each page. We'll come to those next. Layout Looking again at the Page.ss we've just opened, you'll also see a $Layout placeholder. This is replaced by a file from the themes/blackcandy/templates/Layout folder. There are only two files available by default and for every standard page Page.ss is used. When a page is loaded, the template engine first finds the base templates/Page.ss (excluding the theme specific part of the path as this can vary). It's evaluated and the $Layout is replaced by templates/Layout/Page.ss, which is also evaluated for further SilverStripe controls. Ignore Page_results.ss for the moment. It's only used for search queries which we'll cover later. We'll also add more page types so the layout's Page.ss can then be replaced by a more specific template, while the base templates/Page.ss is always used. Includes Both Page.ss files include statements like <% include BreadCrumbs %>. These controls are replaced by files from the themes/blackcandy/templates/Includes/ folder. For example, the above include grabs the themes/blackcandy/templates/Includes/BreadCrumbs.ss file. Note that filenames are case sensitive. Otherwise you're free to select a meaningful name. Try sticking to one naming convention to make your own life easier later on, and also note that you mustn't include the <code>.ss</code> extension. If you're seeing a Filename cannot be empty error, make sure the included file really exists. Have a go hero - using page name, navigation label, and metadata title Now that we've explored all available files and how they are used, let's take a better look at the system. In the CMS backend, go to the Home page. Change the text currently entered into Page name, Navigation label (both in the Main tab), and Title (Metadata tab). Take a look at: Where on the page they are used In which file they are located (take a look at all three possible locations) What template placeholders represent them You might notice $MetaTitle, $Title, and $MenuTitle in your template files (for the moment ignore the appended .XML). We will explore these later on.
Read more
  • 0
  • 0
  • 1696

article-image-core-data-ios-designing-data-model-and-building-data-objects
Packt
05 May 2011
7 min read
Save for later

Core Data: Designing a Data Model and Building Data Objects

Packt
05 May 2011
7 min read
To design a data model with Core Data, we need to create a new project. So, let's start there... Creating a new project To create a new project, perform the following steps: Launch Xcode and create a new project by selecting the File | New Project option. The New Project Assistant window will appear, prompting us to select a template for the new project, as shown in the next screenshot. We will select the Navigation-based Application template. Ensure that the Use Core Data for storage checkbox is checked and click on the Choose... button. On selecting the Choose... button, we will get a dialog box to specify the name and the location of the project. Let us keep the location the same as default (Documents folder) and assign the project name as: prob (any name). Click on Save. Xcode will then generate the project files and the project gets opened in the Xcode project window. The checkbox Use Core Data for storage will ask Xcode to provide all the default code that is required for using Core Data. This option is visible with only two project templates: Navigationbased Application and Window-based Application templates. Designing the data model Designing a data model means defining entities, attributes, and relationships for our application using a special tool. Xcode includes a data modeling tool (also known as Data Model Editor or simply a modeler) that facilitates the creation of entities, defining attributes, and the relationships among them. Data Model Editor The Data Model Editor is a data modeling tool provided by Xcode that makes the job of designing a data model quite easy. It displays the browser as well as a diagram view of the data model. The Browser view displays two panes, the Entity pane and the Properties pane, for defining entities and their respective properties. The diagram view displays rounded rectangles that designate entities and lines to show relationships among the entities. Adding an entity To add an entity to our data model, perform the following steps: Invoke the data modeling tool by double-clicking the prob.xcdatamodel file in the Resources group found in the Xcode Project window. Xcode's data modeling tool will open and we will find that an entity by default is already created for us by the name: Event (as shown in the next image) with an attribute: timeStamp. We can delete or rename the default entity Event as desired. Let us select the default Event entity and delete it by clicking on the minus (-) button in the Entity pane followed by either choosing plus (+) button in the Entity pane or by choosing Design | Data Model | Add Entity option from the menu bar. This will add a blank entity (by the name Entity) to our data model, which we can rename as per our requirements. Let us set the name of the new entity as: Customer. Automatically, an instance of NSManagedObject will be created to represent our newly created Customer entity. The next step is to add attributes to this entity. Adding an attribute property We want to add three attributes by name—name, emailid, and contactno—to the Customer entity. Let's follow the steps mentioned next for the same: Select the entity and choose the Design | Data Model | Add Attribute option from the menu bar or select the + (plus) button in the Property pane. A menu with several options such as Add Attribute, Add Fetched property, Add Relationship, and Add Fetch Request will pop up. We select the Add Attribute option from the popped up menu. We see that a new attribute property is created for our Customer entity by a default name: newAttribute in the inspector. Let us rename our new attribute as: name (as we will be using this attribute to store the names of the customers). Then, we set the type of the name attribute to String as shown in the next screenshot (as names consists of strings): Below the Name field are three checkboxes: Optional, Transient, and Indexed. Though we will be using the Optional checkbox for the name attribute, let us see the usage of all three: Optional: If this checkbox is checked, it means the entity can be saved even if the attribute is nil (empty). If this checkbox is unchecked and we try to save the entity with this attribute set to nil, it will result in a validation error. When used with a relationship, if the checkbox is checked it means that the relationship can be empty. Suppose that we create one more entity say: Credit Card (where information of the customer's credit card is kept). In that case, the relationship from customer to the credit card will be optional (we have to leave this checkbox checked) as a customer may or may not have a credit card. And if we create an entity say: Product—in that case, the relationship from the Customer to the Product cannot be empty as a customer will definitely buy at least a single product (the checkbox has to be unchecked). Transient: This checkbox, if checked, means that the attribute or the relationship is of a temporary nature and we don't want it to be stored (persist) in the persistent store. This checkbox must be unchecked for the attributes or relationship that we want to persist (to be stored on the disk). Indexed: This checkbox has to be checked to apply indexing on the attribute. It is used when we want to perform sorting or searching on some attribute. By checking this checkbox, an index will be created on that attribute and the database will be ordered on that attribute. Types of attributes Using the Type drop-down list control, we select the data type (that is, numerical, string, date, and so on) of the attribute to specify the kind of information that can be stored in the attribute. The following is the list of data types: Integer 16, Integer 32, and Integer 64 data types are for storing signed integers. The range of values that these types are able to store is as follows: Integer 16:-32,768 to 32, 767 Integer 32:-2,147,483,648 to 2,147,483,647 Integer 64:-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 Decimal, Double, and Float data types are for storing fractional numbers. The Double data type uses 64 bits to store a value while the Float data type uses 32 bits for storing a value. The only limitation with these two data types is that they round off the values. To avoid any rounding of values, the Decimal data type is preferred. The Decimal type uses fixed point numbers for storing values, so the numerical value stored in it is not rounded off. String data type is used for storing text contents. Boolean data type is used for storing YES or NO values. Date data type is used for storing dates as well as timestamps. Binary data type is used for storing binary data. Transformable data type works along with Value Transformers that help us create attributes based on any Objective-C class, that is, we can create custom data types other than the standard data types. This data type can be used to store an instance of UIColor, UIImage, and so on. It archives objects to instances of NSData. Below the Type drop-down menu, we will see a few more fields in the detail pane, as shown in the next screenshot: Fields applying constraints Min Length: and Max Length: fields are for applying constraints of minimum and maximum number of characters to an attribute. If we exceed the range supplied in these fields, we get a validation error. Meaning, if we enter the string of fewer characters than the value supplied in Min Length: or the string has more characters than the value supplied in Max Length: field, this will result in a validation error while saving managed objects. Reg. Ex: field stands for regular expression and is used for applying validation checks on the data entered in the attribute by making use of regular expressions. Default Value: field is for specifying default value of the attribute. If we create a new managed object, the attribute will automatically be set to the default value specified in this field. Let us add two more attributes to the Customer entity: emailid and contactno (for storing a customer's e-mail address and contact number, respectively). These two attributes will also be of type: String as shown in the next screenshot. Now, save the .xcdatamodel.
Read more
  • 0
  • 0
  • 6672
article-image-animation-effects-aspnet-using-jquery
Packt
03 May 2011
9 min read
Save for later

Animation Effects in ASP.NET using jQuery

Packt
03 May 2011
9 min read
  ASP.NET jQuery Cookbook Over 60 practical recipes for integrating jQuery with ASP.NET   Introduction Some useful inbuilt functions in jQuery that we will explore in this article for achieving animation effects are: animate ( properties, [ duration ], [ easing ], [ complete ] ): This method allows us to create custom animation effects on any numeric css property. The parameters supported by this method are: properties: This is the map of css properties to animate, for e.g. width, height, fontSize, borderWidth, opacity, etc. duration: This is the duration of the animation in milliseconds. The constants slow and fast can be used to specify the durations, and they represent 600 ms and 200 ms respectively. easing: This is the easing function to use. Easing indicates the speed of the animation at different points during the animation. jQuery provides inbuilt swing and linear easing functions. Various plugins can be interfaced if other easing functions are required. complete: This indicates the callback function on completion of the animation. fadeIn ( [ duration ], [ callback ] ): This method animates the opacity of the matched elements from 0 to 1 i.e. transparent to opaque. The parameters accepted are: duration: This is the duration of the animation callback: This is the callback function on completion of the animation fadeOut( [ duration ], [ callback ] ): This method animates the opacity of the matched elements from 1 to 0 i.e. opaque to transparent. The parameters accepted are: duration: This is the duration of the animation callback: This is the callback function on completion of the animation slideUp( [ duration ], [ callback ] ): This method animates the height of the matched elements with an upward sliding motion. When the height of the element reaches 0, the css property display of the element is updated to none so that the element is hidden on the page. The parameters accepted are: duration: This is the duration of the animation callback: This is the callback function on completion of the animation slideDown( [ duration ], [ callback ] ): This method animates the height of the matched elements from 0 to the specified maximum height. Thus, the element appears to slide down on the page. The parameters accepted are: duration: This is the duration of the animation callback: This is the callback function on completion of the animation slideToggle( [ duration ], [ callback ] ): This method animates the height of the matched elements. If the element is initially hidden, it will slide down and become completely visible. If the element is initially visible, it will slide up and become hidden on the page. The parameters accepted are: duration: This is the duration of the animation callback: This is the callback function on completion of the animation jQuery.fx.off: If there is a need to disable animations because of a resource constraint or due to difficulties in viewing the animations, then this utility can be used to turn off the animation completely. This is achieved by setting all animated controls to their final state. stop ( [ clearQueue ], [ jumpToEnd ] ): This method stops the currently running animations on the page. The parameters accepted are: clearQueue: This indicates whether any queued up animations are required to be cleared. The default value is false. jumpToEnd: This indicates if the current animation is to be cleared immediately. The default value is false. In this article, we will cover some of the animation effects that can be achieved in ASP.NET using the capabilities of jQuery. Getting started Let's start by creating a new ASP.NET website in Visual Studio and name it Chapter5. Save the jQuery library in a script folder js in the project. To enable jQuery on any web form, drag-and-drop to add the following to the page: <scriptsrc="js/jquery-1.4.1.js" type="text/javascript"></script> Now let's move on to the recipes where we will see different animation techniques using jQuery. Enlarging text on hover In this recipe, we will animate the font size of text content on hover. Getting ready Add a new web form Recipe1.aspx to the current project. Create a Css class for the text content that we want to animate. The font size specified in the css Class is the original font size of the text before animation is applied to it: .enlarge { font-size:12.5px; font-family:Arial,sans-serif; } Add an ASP.NET Label control on the form and set its Css Class to the preceding style: <asp:LabelCssClass="enlarge"runat="server">Lorem ipsum dolor sit ...............</asp:Label> Thus, the ASPX markup of the form is as follows: <form id="form1" runat="server"> <div align="center"> Mouseover to enlarge text:<br /> <fieldset id="content" style="width:500px;height:300px;"> <asp:LabelCssClass="enlarge" runat="server">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</ asp:Label> </fieldset> </div> </form> Thus, initially, the page will display the Label control as follows: We will now animate the font size of the Label on hover on the containing fieldset element. How to do it… In the document.ready() function of the jQuery script block, retrieve the original font size of the Label: var origFontSize = parseFloat($(".enlarge").css('font-size')); The parseFloat() function takes in an input string and returns the first floating point value in the string. It discards any content after the floating point value. For example, if the css property returns 12.5 px, then the function will discard the px. Define the hover event of the containing fieldset element: $("#content").hover( In the mouseenter event handler of the hover method, update the cursor style to pointer: function() { $(".enlarge").css("cursor", "pointer"); Calculate the maximum font size that we want to animate to. In this example, we will set the maximum size to thrice the original: var newFontSize = origFontSize * 3; Animate the fontSize css property of the Label in 300 ms: $(".enlarge").animate({ fontSize: newFontSize }, 300); }, In the mouseleave event handler of the hover method, animate the fontSize to the original value in 300 ms as shown: function() { $(".enlarge").animate({ fontSize: origFontSize }, 300); } ); Thus, the complete jQuery solution is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function() { var origFontSize = parseFloat($(".enlarge").css('fontsize')); $("#content").hover( function() { $(".enlarge").css("cursor", "pointer"); var newFontSize = origFontSize * 3; $(".enlarge").animate({ fontSize: newFontSize }, 300); }, function() { $(".enlarge").animate({ fontSize: origFontSize }, 300); } ); }); </script> How it works… Run the web form. Mouseover on the fieldset area. The text size will animate over the stated duration and change to the maximum specified font size as displayed in the following screenshot: On removing the mouse from the fieldset area, the text size will return back to the original. Creating a fade effect on hover In this recipe, we will create a fade effect on an ASP.NET Image control on hover. We will use the fadeIn and fadeOut methods to achieve the same. Getting ready Add a new web form Recipe2.aspx to the current project. Add an image control to the form: <asp:Image src="images/Image1.jpg" ID="Image1" runat="server" /> Define the properties of the image in the css: #Image1 { width:438px; height:336px; } Thus, the complete ASPX markup of the web form is as follows: <form id="form1" runat="server"> <div align="center"> Mouseover on the image to view fade effect: <fieldset id="content" style="width:480px;height:370px;"> <br /> <asp:Image src="images/Image1.jpg" ID="Image1" runat="server" /> </fieldset> </div> </form> On page load, the image is displayed as follows: We will now create a fade effect on the image on hover on the containing fieldset area. How to do it… In the document.ready() function of the jQuery script block, define the hover event on the containing fieldset area: $("#content").hover( In the mouseenter event handler of the hover method, update the cursor to pointer: function() { $("#Image1").css("cursor", "pointer"); Apply the fadeOut method on the Image control with an animation duration of 1000 ms: $("#Image1").fadeOut(1000); }, In the mouseleave event handler of the hover method, apply the fadeIn method on the Image control with an animation duration of 1000 ms: function() { $("#Image1").fadeIn(1000); } ); Thus, the complete jQuery solution is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function() { $("#content").hover( function() { $("#Image1").css("cursor", "pointer"); $("#Image1").fadeOut(1000); }, function() { $("#Image1").fadeIn(1000); } ); }); </script> How it works... Run the web page. Mouseover on the Image control on the web page. The image will slowly fade away as shown in the following screenshot: On mouseout from the containing fieldset area, the image reappears. Sliding elements on a page In this recipe, we will use the slideUp and slideDown methods for achieving sliding effects on an ASP.NET panel. Getting ready Add a new web form Recipe3.aspx in the current project. Add an ASP.NET panel to the page as follows: <asp:Panel class="slide" runat="server"> Sliding Panel </asp:Panel> The css class for the panel is defined as follows: .slide { font-size:12px; font-family:Arial,sans-serif; display:none; height:100px; background-color:#9999FF; } Add a button control to trigger the sliding effect on the panel: <asp:Button ID="btnSubmit" runat="server" Text="Trigger Slide" /> Thus, the complete ASPX markup of the web form is as follows: <form id="form1" runat="server"> <div align="center"> <fieldset style="width:400px;height:150px;"> <asp:Button ID="btnSubmit" runat="server" Text="Trigger Slide" /> <br /><br/> <asp:Panel class="slide" runat="server"> Sliding Panel </asp:Panel> </fieldset> </div> </form> On page load, the page appears as shown in the following screenshot: We will now use jQuery to slide up and slide down the panel. How to do it… In the document.ready() function of the jQuery script block, define the click event of the button control: $("#btnSubmit").click(function(e) { Prevent default form submission: e.preventDefault(); Check if the ASP.NET panel control is hidden: if ($(".slide").is(":hidden")) The jQuery selector :hidden selects matched elements that are hidden on the page. If yes, then slide down the panel until its height reaches the maximum (100 px) defined in the css property. $(".slide").slideDown("slow"); If the panel is initially visible then slide up so that its height slowly reduces until it becomes 0 and the panel disappears from the page: else $(".slide").slideUp("slow"); }); Thus, the complete jQuery solution is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function() { $("#btnSubmit").click(function(e) { e.preventDefault(); if ($(".slide").is(":hidden")) $(".slide").slideDown("slow"); else $(".slide").slideUp("slow"); }); }); </script>  
Read more
  • 0
  • 0
  • 8067

article-image-silverstripe-24-adding-some-spice-widgets-and-short-codes
Packt
02 May 2011
10 min read
Save for later

SilverStripe 2.4: Adding Some Spice with Widgets and Short Codes

Packt
02 May 2011
10 min read
SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide: RAW Create smashing SilverStripe applications by extending modules, creating themes, and adding widgets Why can't we simply use templates and $Content to accomplish the task? Widgets and short codes generally don't display their information directly like a placeholder does They can be used to fetch external information for you—we'll use Google and Facebook services in our examples Additionally they can aggregate internal information—for example displaying a tag cloud based on the key words you've added to pages or articles Widget or short code? Both can add more dynamic and/or complex content to the page than the regular fields. What’s the difference? Widgets are specialized content areas that can be dynamically dragged and dropped in a predefined area on a page in the CMS. You can't insert a widget into a rich-text editor field, it needs to be inserted elsewhere to a template. Additionally widgets can be customised from within the CMS. Short codes are self-defined tags in squared brackets that are entered anywhere in a content or rich-text area. Configuration is done through parameters, which are much like attributes in HTML. So the main difference is where you want to use the advanced content. Creating our own widget Let's create our first widget to see how it works. The result of this section should look like this: Time for action – embracing Facebook Facebook is probably the most important communication and publicity medium in the world at the moment. Our website is no exception and we want to publish the latest news on both our site and Facebook, but we definitely don't want to do that manually. You can either transmit information from your website to Facebook or you can grab information off Facebook and put it into your website. We'll use the latter approach, so let's hack away: In the Page class add a relation to the WidgetArea class and make it available in the CMS: public static $has_one = array( 'SideBar' => 'WidgetArea', ); public function getCMSFields(){ $fields = parent::getCMSFields(); $fields->addFieldToTab( 'Root.Content.Widgets', new WidgetAreaEditor('SideBar') ); return $fields; } Add $SideBar to templates/Layout/Page.ss in the theme directory, wrapping it inside another element for styling later on (the first and third line are already in the template, they are simply there for context): $Form <aside id="sidebar">$SideBar</aside> </section> <aside> is one of the new HTML5 tags. It's intended for content that is only "tangentially" related to the page's main content. For a detailed description see the official documentation at http://www.w3.org/TR/html-markup/aside.html. Create the widget folder in the base directory. We'll simply call it widget_facebookfeed/. Inside that folder, create an empty _config.php file. Additionally, create the folders code/ and templates/. Add the following PHP class—you'll know the filename and where to store it by now. The Controller's comments haven't been stripped this time, but are included to encourage best practice and provide a meaningful example: <?php class FacebookFeedWidget extends Widget { public static $db = array( 'Identifier' => 'Varchar(64)', 'Limit' => 'Int', ); public static $defaults = array( 'Limit' => 1, ); public static $cmsTitle = 'Facebook Messages'; public static $description = 'A list of the most recent Facebook messages'; public function getCMSFields(){ return new FieldSet( new TextField( 'Identifier', 'Identifier of the Facebook account to display' ), new NumericField( 'Limit', 'Maximum number of messages to display' ) ); } public function Feeds(){ /** * URL for fetching the information, * convert the returned JSON into an array. */ $url = 'http://graph.facebook.com/' . $this->Identifier . '/feed?limit=' . ($this->Limit + 5); $facebook = json_decode(file_get_contents($url), true); /** * Make sure we received some content, * create a warning in case of an error. */ if(empty($facebook) || !isset($facebook['data'])){ user_error( 'Facebook message error or API changed', E_USER_WARNING ); return; } /** * Iterate over all messages and only fetch as many as needed. */ $feeds = new DataObjectSet(); $count = 0; foreach($facebook['data'] as $post){ if($count >= $this->Limit){ break; } /** * If no such messages exists, log a warning and exit. */ if(!isset($post['from']['id']) || !isset($post['id'] || !isset($post['message'])){ user_error( 'Facebook detail error or API changed', E_USER_WARNING ); return; } /** * If the post is from the user itself and not someone * else, add the message and date to our feeds array. */ if(strpos($post['id'], $post['from']['id']) === 0){ $posted = date_parse($post['created_time']); $feeds->push(new ArrayData(array( 'Message' => DBField::create( 'HTMLText', nl2br($post['message']) ), 'Posted' => DBField::create( 'SS_Datetime', $posted['year'] . '-' . $posted['month'] . '-' . $posted['day'] . ' ' . $posted['hour'] . ':' . $posted['minute'] . ':' . $posted['second'] ), ))); $count++; } } return $feeds; } Define the template, use the same filename as for the previous file, but make sure that you use the correct extension. So the file widget_facebookfeed/templates/FacebookFeedWidget.ss should look like this: <% if Limit == 0 %> <% else %> <div id="facebookfeed" class="rounded"> <h2>Latest Facebook Update<% if Limit == 1 %> <% else %>s<% end_if %></h2> <% control Feeds %> <p> $Message <small>$Posted.Nice</small> </p> <% if Last %><% else %><hr/><% end_if %> <% end_control %> </div> <% end_if %> Also create a file widget_facebookfeed/templates/WidgetHolder.ss with just this single line of content: $Content We won't cover the CSS as it's not relevant to our goal. You can either copy it from the final code provided or simply roll your own. Rebuild the database with /dev/build?flush=all. Log into /admin. On each page you should now have a Widgets tab that looks similar to the next screenshot. In this example, the widget has already been activated by clicking next to the title in the left-hand menu. If you have more than one widget installed, you can simply add and reorder all of them on each page by drag-and-drop. So even novice content editors can add useful and interesting features to the pages very easily. Enter the Facebook ID and change the number of messages to display, if you want to. Save and Publish the page. Reload the page in the frontend and you should see something similar to the screenshot at the beginning of this section. allow_url_fopen must be enabled for this to work, otherwise you're not allowed to use remote objects such as local files. Due to security concerns it may be disabled, and you'll get error messages if there's a problem with this setting. For more details see http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen. What just happened? Quite a lot happened, so let's break it down into digestible pieces. Widgets in general Every widget is actually a module, although a small one, and limited in scope. The basic structure is the same: residing in the root folder, having a _config.php file (even if it's empty) and containing folders for code, templates, and possibly also JavaScript or images. Nevertheless, a widget is limited to the sidebar, so it's probably best described as an add-on. We'll take a good look at its bigger brother, the module, a little later. You're not required to name the folder widget_*, but it's a common practice and you should have a good reason for not sticking to it. Common use cases for widgets include tag clouds, Twitter integration, showing a countdown, and so forth. If you want to see what others have been doing with widgets or you need some of that functionality, visit http://www.silverstripe.org/widgets/. Keeping widgets simple In general widgets should work with default settings and if there are additional settings they should be both simple and few in number. While we'll be able to stick to the second part, we can't provide meaningful default settings for a Facebook account. Still, keep this idea in mind and try to adhere to it where possible. Facebook graph API We won't go into details of the Facebook Graph API, but it's a powerful tool—we've just scratched the surface with our example. Looking at the URL http://graph.facebook.com/<username>/feed?limit=5 you only need to know that it fetches the last five items from the user's feed, which consists of the wall posts (both by the user himself and others). <username> must obviously be replaced by the unique Facebook ID—either a number or an alias name the user selected. If you go to the user's profile, you should be able to see it in the URL. For example, SilverStripe Inc's Facebook profile is located at https://www.facebook.com/pages/silverstripe/44641219945?ref=ts&v=wall—so the ID is 44641219945. That's also what we've used for the example in the previous screenshot. For more details on the Graph API see http://developers.facebook.com/docs/api. Connecting pages and widgets First we need to connect our pages and widgets in general. You'll need to do this step whenever you want to use widgets. You'll need to do two things to make this connection: Reference the WidgetArea class in the base page's Model and make it available in the CMS through getCMSFields(). Secondly, we need to place the widget in our page. $SideBar You're not required to call the widget placeholder $SideBar, but it's a convention as widgets are normally displayed on a website's sidebar. If you don't have a good reason to do it otherwise, stick to it. You're not limited to a single sidebar As we define the widget ourselves, we can also create more than one for some or all pages. Simply add and rename the $SideBar in both the View and Model with something else and you're good to go. You can use multiple sidebars in the same region or totally different ones—for example creating header widgets and footer widgets. Also, take the name "sidebar" with a grain of salt, it can really have any shape you want. What about the intro page? Right. We've only added $SideBar to the standard templates/Layout/Page.ss. Shouldn't we proceed and put the PHP code into ContentPage.php? We could, but if we wanted to add the widget to another page type, which we'll create later, we'd have to copy the code. Not DRY, so let's keep it in the general Page.php. The intro page is a bit confusing right now. While you can add widgets in the backend, they can’t be displayed as the placeholder is missing in the template. To clean this up, let's simply remove the Widget tab from the intro page. It's not strictly required, but it prevents content authors from having a field in the CMS that does nothing visible on the website. To do this, simply extend the getCMSFields() in the IntroPage.php file, like this: function getCMSFields() { $fields = parent::getCMSFields(); $fields->removeFieldFromTab('Root.Content.Main', 'Content'); $fields->removeFieldFromTab('Root.Content', 'Widgets'); return $fields; }
Read more
  • 0
  • 0
  • 3079

article-image-aspnet-using-jquery-ui-widgets
Packt
29 Apr 2011
5 min read
Save for later

ASP.NET: Using jQuery UI Widgets

Packt
29 Apr 2011
5 min read
ASP.NET jQuery Cookbook Over 60 practical recipes for integrating jQuery with ASP.NET      The reader can benefit from the previous article on ASP.NET: Creating Rich Content. Using the datepicker control The datepicker is a popular control for date fields in online submission forms. In this recipe, let's see how to use the jQuery UI to attach a datepicker to an ASP.NET TextBox control. Getting Ready Create a new web form Recipe5.aspx in the current project. Add controls to create a simple search form that accepts an input date field as follows: <form id="form1" runat="server"> <div align="center"> <asp:Label ID="lblDate" runat="server">Search by registration date: </asp:Label> <asp:TextBox ID="txtDate" runat="server"></asp:TextBox> <asp:Button ID="btnSubmit" Text="Search" runat="server" /> </div> </form> Thus, on page load, the web form appears as shown in the following screenshot: We will now use jQuery UI to attach a datepicker to the TextBox control. How to do it... In the document.ready() function of the jQuery script block, apply the datepicker() method to the TextBox control: $("#txtDate").datepicker(); Thus, the complete jQuery solution for the given problem is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function(){ $("#txtDate").datepicker(); }); </script> How it works... Run the web form. On mouseclick on the TextBox control, the datepicker is displayed as shown in the following screenshot: The desired date can be picked from the displayed calendar as required. There's more… For detailed documentation on the jQuery UI datepicker widget, please visit http://jqueryui.com/demos/datepicker/. Using the progress bar control jQuery UI provides a Progressbar widget to show the processing status during a wait time in an application. In this recipe, we will learn to create a Progressbar in ASP.NET. Getting Ready Include an animated gif file pbar-ani.gif in the images folder in the project. Add a new web form Recipe6.aspx to the current project. Add an ASP.NET panel control for the progressbar as follows: <asp:Panel id="progressbar" runat="server"></asp:Panel> Define some basic css style for the above as follows: #progressbar { width:300px; height:22px; } The jQuery UI progressbar uses the jQuery UI CSS Framework for styling. Hence, to set the background of the progressbar to the animated gif file, add the following css style: .ui-progressbar-value { background-image: url(images/pbar- ani.gif); } Create another content panel that is initially hidden and displayed only after the progressbar loads completely. <asp:Panel id="contentArea" runat="server">Page successfully loaded</asp:Panel> We will use the following css class to hide this panel: .hide 21 { display:none; } Thus, the complete aspx markup of the form is as follows: <form id="form1" runat="server"> <div align="center"> <asp:Panel id="progressbar" runat="server"></asp:Panel> <asp:Panel id="contentArea" runat="server">Page successfully loaded</asp:Panel> </div> </form> Now, we will look at the jQuery solution for applying the Progressbar widget to the ASP.NET panel. How to do it... In the document.ready() function of the jQuery script block, hide the display message: $("#contentArea").addClass("hide"); Initialise a counter: var cnt = 0; Define the maximum value of the counter: var maxCnt = 100; Use the JavaScript timer function setInterval() to define the timeout interval and the callback function after each interval: var id = setInterval(showprogress, 10); Now, define the previous callback function: function showprogress() { Check if the current value of the counter is less than or equal to the maximum allowable value: if (cnt <= maxCnt) { If yes, then apply the progressbar() function with the current counter value: $("#progressbar").progressbar({ value: cnt }); Increment the counter: cnt++; } If the current value of the counter is greater than the maximum value, clear the timer using the respective ID: lse { clearInterval(id); Show the display message: $("#contentArea").removeClass("hide"); Hide the progress bar: $("#progressbar").addClass("hide"); } } Thus, the complete jQuery solution is a follows: <script language="javascript" type="text/javascript"> $(document).ready(function() { $("#contentArea").addClass("hide"); var cnt = 0; var maxCnt = 100; var id = setInterval(showprogress, 10); function showprogress() { if (cnt <= maxCnt) { $("#progressbar").progressbar({ value: cnt }); cnt++; } else { clearInterval(id); $("#contentArea").removeClass("hide"); $("#progressbar").addClass("hide"); } } }); </script> In this solution, we have used the JavaScript timer setInterval(customFunction, timeout) to call a custom function after the timeout (in milliseconds). Important points to note are: The setInterval method returns a numeric number,id to track the timeout. This ID can be later used to clear the timer. The timer calls the custom function showprogress() repeatedly after every timeout interval until the clearInterval(id) is called. After every timeout, we will increment the variable cnt by 1 and apply it to the progressbar. When cnt reaches maxCnt, the progressbar loads completely. How it works... Run the web form. You will see that the progressbar loads in steps, as shown in the following screenshot: After the load is complete, the progressbar is hidden and the content panel is displayed instead, as follows: There's more… For detailed documentation on the jQuery UI progressbar widget, please visit http://jqueryui.com/demos/progressbar/.  
Read more
  • 0
  • 0
  • 2988
article-image-aspnet-and-jquery-how-to-create-rich-content
Packt
27 Apr 2011
7 min read
Save for later

ASP.NET and jQuery: how to create rich content

Packt
27 Apr 2011
7 min read
In a nutshell, the jQuery UI library provides the following: Completely configurable widgets like accordion, tabs, progressbar, datepicker, slider, autocomplete, dialog, and button Interactive features like draggable, droppable, resizable, selectable, and sortable Advanced animation effects like show, hide, toggle, blind, bounce, explode, fade, highlight, pulsate, puff, scale, slide, etc Customisable themes to suit the look and feel of your website Using jQuery and ASP.NET together In this article, we will primarily take a look at integration of jQuery UI with ASP.NET to build rich content quickly and easily. Read more: ASP.NET: Using jQuery UI Widgets Getting started Let's start by creating a new ASP.NET website Chapter9 in Visual Studio. Go to the download page of jQuery UI at http://jqueryui.com/download, which allows customizable downloads based on the features required in the web application. For the purpose of this article, we will download the default build as shown next: (Move the mouse over the image to enlarge.) jQuery UI allows various custom themes. We will select the Sunny theme for our project: Save the downloaded file. The download basically consists of the following: css folder consisting of the the theme files development-bundle folder consisting of demos, documents, raw script files, etc. js folder consisting of the minified version of jQuery library and jQuery UI Save the earlier mentioned css folder in the current project. Save the minified version of jQuery UI and jQuery library in a script folder js in the project. In addition to including the jQuery library on ASP.NET pages, also include the UI library as shown: <script src="js/jquery-1.4.1.js" type="text/javascript"></script> <script src="js/jquery-ui-1.8.9.custom.min.js" type="text/javascript"></script> Include the downloaded theme on the aspx pages as follows: <link href="css/sunny/jquery-ui-1.8.9.custom.css" rel="stylesheet" type="text/css" /> Now let's move on to the recipes and explore some of the powerful functionalities of jQuery UI. Creating an accordion control The jQuery accordion widget allows the creation of collapsible panels on the page without the need for page refresh. Using an accordion control, a single panel is displayed at a time while the remaining panels are hidden. Getting Ready Create a new web form Recipe1.aspx in the current project. Add a main content panel to the page. Within the main panel, add pairs of headers and subpanels as shown next: <asp:Panel id="contentArea" runat="server"> <h3><a href="#">Section 1</a></h3> <asp:Panel ID="Panel1" runat="server"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </asp:Panel> <h3><a href="#">Section 2</a></h3> <asp:Panel ID="Panel2" runat="server"> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </asp:Panel> <h3><a href="#">Section 3</a></h3> <asp:Panel ID="Panel3" runat="server"> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </asp:Panel> <h3><a href="#">Section 4</a></h3> <asp:Panel ID="Panel4" runat="server"> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum </asp:Panel> </asp:Panel> Add some styling to the main content panel as required: #contentArea { width: 300px; height: 100%; } Our accordion markup is now ready. We will now transform this markup into an accordion control using the functionalities of jQuery UI. How to do it... In the document.ready() function of the jQuery script block, apply the accordion() method to the main content panel: $("#contentArea").accordion(); Thus, the complete jQuery UI solution for the problem at hand is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function(){ $("#contentArea").accordion(); }); </script> How it works... Run the web page. The accordion control is displayed as shown in the following screenshot: Click on the respective panel headers to display the required panels. Note that the accordion control only displays the active panel at a time. The remaining panels are hidden from the user. There's more... For detailed documentation on the jQuery UI accordion widget, please visit http://jqueryui.com/demos/accordion/. Creating a tab control The jQuery UI tab widget helps to create tab controls quickly and easily on ASP.NET web pages. The tab control helps in organizing content on a page thus improving the presentation of bulky content. With the help of jQuery UI tab widget, the content can also be retrieved dynamically using AJAX. In this recipe, we will see a simple example of applying this powerful widget to ASP.NET forms. Getting Ready Create a new web form Recipe2.aspx in the current project. Add an ASP.NET container panel to the page. Within this container panel, add subpanels corresponding to the tab contents. Also add hyperlinks to each of the subpanels. Thus the complete aspx markup of the web form is as shown next: <form id="form1" runat="server"> <asp:panel id="contentArea" runat="server"> <ul> <li><a href="#tab1">Tab 1</a></li> <li><a href="#tab2">Tab 2</a></li> <li><a href="#tab3">Tab 3</a></li> <li><a href="#tab4">Tab 4</a></li> </ul> <asp:panel ID="tab1" runat="server"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </asp:panel> <asp:panel ID="tab2" runat="server"> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </asp:panel> <asp:panel ID="tab3" runat="server"> <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p> </asp:panel> <asp:panel ID="tab4" runat="server"> <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p> </asp:panel> </asp:panel> </form> Next, we will see how we can transform this markup into a tab control using jQuery UI. How to do it... In the document.ready() function of the jQuery script block, apply the tabs() method to the container panel as follows: $("#contentArea").tabs(); Thus, the complete jQuery UI solution for creating the tab control is as follows: <script language="javascript" type="text/javascript" $(document).ready(function(){ $("#contentArea").tabs(); }); </script> How it works... Run the web form. The page displays the tabbed content as follows: Click on the respective tab headers to view the required content. There's more… For detailed documentation on the jQuery UI tabs widget, visit the jQuery website.
Read more
  • 0
  • 0
  • 3293

article-image-content-management-system-understanding-extensions
Packt
26 Apr 2011
14 min read
Save for later

Content Management System: Understanding Extensions

Packt
26 Apr 2011
14 min read
  CMS Made Simple Development Cookbook Over 70 simple but incredibly effective recipes for extending CMS Made Simple with detailed explanations – useful for beginners and experts alike!         Read more about this book       (For more resources on Content management, see here.) Introduction CMS Made Simple is a powerful system for creating websites. Even the base install enables you to easily produce sites with many sophisticated features. There are times, however, when you need to be able to do things that are beyond the basic capabilities. You can often find pre-made extensions on the official CMS Made Simple sites: Tags and Modules in the Developer's Forge (or directly through the Module Manager), and examples of User-Defined Tags on Wiki or posted in the forum. What are these different kinds of extension? This article will answer that question in greater detail. However, we will define them briefly here. All three types of extension share some things in common: they are PHP code which can be embedded in site pages, templates, or Global Content Blocks, or may be called by other code. A User-Defined Tag is distinct in that you can create and edit it through the CMSMS admin area. A Tag is similar, but must be placed as a file on your server, and provides more information to the site administrator. A module has available to it the rich functionality of the Module API, and enables the creation of much more complex applications. As mentioned before, there is a wealth of pre-made extensions which are available to you. But even if these pre-made extensions don't meet your needs, all is not lost. You can jump in and create your own extensions! You will discover that the power of CMS Made Simple is only limited by your imagination. In this article, we will learn how to approach the problem you're trying to solve. Is it something that can be solved without writing an extension? Would you be able to use or adapt an existing extension? If not, what conditions will the extension need to handle? The requirements that you think of will help you determine what kind of extension you should implement. There are three recipes here that will help you to identify which kind of extension is appropriate for a given problem, and three recipes that go over the basics of creating each major type. Will a User-Defined Tag solve my problem? You have reached the point where you know you need to extend CMS Made Simple to solve some particular problem, but you may not yet know what approach to take. Your options are to create a Tag, a User-Defined Tag (UDT), or a Module, but which will be best to solve your specific problem? This recipe will help you examine your problem and consider whether creating a UDT is the most appropriate solution. How to do it... First, we determine if the problem you want to solve is one that will require you to write some custom code. This is the easy part. You've already considered whether or not an existing solution will suffice and have decided that it will not. So the next step is to figure out whether or not a User-Defined Tag is the correct approach to solving the problem. Go through the following list, and for each item, determine if it applies to the problem you are trying to solve. Feel free to write down a list of your answers (yes/no). Can your problem be solved with Smarty logic or standard CMS authoring practices like using Global Content Blocks in your page template? Are you trying to solve a problem that requires multiple actions? An example of multiple actions would be both displaying a form and processing its results. Will you need to support localization and internationalization to solve your problem? For example, if your code will be displaying messages, will the messages need to be translated into multiple languages? Will your solution require an Administration panel? Will you want to share this solution with other people so that they can install it into their own CMS Made Simple sites? Do you need to create new database tables or set up new preferences to solve your problem? Do you want your code to display help text in the Admin area, so site administrators understand what parameters are available and what the code does? Will your solution serve as a Smarty modifier (a modifier in Smarty is a function that does something to convert a variable for display)? An example of a Smarty modifier would be {$variableuppercase|} where the modifier ("uppercase") serves to transform the variable ("$variable"). If you answered "no" to all of the above questions, a User-Defined Tag is a good candidate! How it works... A User-Defined Tag is a way to connect a tag, that will be recognized by Smarty, to an arbitrary bit of PHP code. That PHP code can do anything. While there are very few things that cannot be done in CMS Made Simple using UDTs, it doesn't necessarily mean that a UDT is the best approach for everything. Because User-Defined Tags are so versatile, the best way to determine if they are the ideal approach is by disqualification. We ask questions about the few things for which UDTs are less optimal, to see if any of those things match our requirements. If none of them match, then a User-Defined Tag is probably the best approach. If we do find that our requirements include functionality for which UDTs are not ideally suited, we should consider using a Tag or a module instead. For now, let's look at those qualifying questions again and examine why they would encourage us to use a different approach. Disqualifying Question If you answered "Yes" Can the problem be solved by simply using Smarty? We don't need to write any PHP code at all! Does your problem require multiple actions? It is, in fact, possible to handle multiple actions using a User- Defined Tag, but it is not elegant. If you need to support multiple actions, the CMS Made Simple Module API has extensive support for doing so, as well as conventions that will help keep the code separated nicely into maintainable chunks. Do you need localization or internationalization? Again, this would be possible to do in a User-Defined Tag, but you would have to do all the work. The Module API provides utilities for simplifying this enormously. Will you need an Administration Panel? There is no easy way to implement an Administration panel in a UDT, so this would strongly push you in the direction of using a Module, where a rich set of functions make the task easier. Will you want to share your code? While nothing would stop you from sharing the code you write as a User-Defined Tag, there are neither facilities for making the process simple nor standards for documenting the UDT. Furthermore, UDTs exist only in the database, as contrasted with Tags and Modules that exist as files, so they are not as easy to simply package up and share. Do you need to create database tables or preferences? You could write logic into your UDT to check on the existence and conditionally create database tables or preferences, but it would be easier to use the Module API that has specific support and standards for doing those operations. Do you want your code to display help text in the Admin area? As mentioned before, User-Defined Tags offer no facility for displaying help text to the Admin. Both Tags and Modules, on the other hand, have standard methods for doing so. Will your solution serve as a Smarty modifier? User-Defined Tags cannot natively work as Smarty modifiers, while Tags can do so easily. Will a Tag Solve My Problem? As in the previous recipe, you know that we have three different possibilities for extending CMS Made Simple and solving a problem: User-Defined Tag, Tags, and Modules. Deciding which of these is the best approach, however, requires additional knowledge about the strengths and weaknesses of each technique. This recipe will help you examine your problem and consider whether creating a Tag is the most appropriate solution. How to do it... The criteria for deciding to use a Tag to extend CMS Made Simple are quite similar to the criteria for a User-Defined Tag. To figure this out, consult the following list, and determine if each item applies to the problem you are trying to solve. Feel free to write down a list of your answers (yes/no). Can your problem be solved with Smarty logic in your page template? Are you trying to solve a problem that requires multiple actions? An example of multiple actions would be both displaying a form and processing its results. Will you need to support localization and internationalization to solve your problem? For example, if your code will be displaying messages, will the messages need to be translated into multiple languages? Will your solution require an Administration panel? Do you need to create new database tables or set up new preferences to solve your problem? If you answered "no" to all of the above questions, either a Tag or a User-Defined Tag would be a viable approach. To decide whether a Tag would be better than a UDT, consider the following questions: Will you want to share this solution with other people so they can install it into their own CMS Made Simple sites, or will you want to reuse this code yourself on other sites? Do you want your code to display help text in the Admin area, so site administrators understand what parameters are available and what the code does? Will your solution serve as a Smarty modifier? A Smarty modifier is a function that reformats a variable for display, for example, {$variableuppercase}} where the modifier ("uppercase") serves to transform the variable ("$variable"). If you answer "yes" to any of these three questions, you should write a Tag instead of a User-Defined Tag. How it works... A Tag is a way to connect a Smarty tag to some PHP code. The PHP code can do anything. Like in the case of User-Defined Tags, there are very few things that cannot be done in CMS Made Simple using Tags. Because Tags are so versatile, the best way to determine if they are the ideal approach is by disqualification. We ask questions about the few things for which Tags are not ideal, to see if any of those things match our requirements. If none of them match, then the problem could be solved by either a Tag or a User-Defined Tag. To make the decision between those two approaches, we consider a few other criteria that will steer us in the right direction. Let's consider the disqualifying questions again and examine why they would encourage us to use a different approach. The first five questions are the same as they were for User-Defined Tags. Disqualifying Question If you answered "Yes" Can the problem be solved simply using Smarty? If this is the case, we don't need to extend CMS Made Simple at all! Does your problem require multiple actions? It is, in fact, possible to handle multiple actions using a Tag, but the CMS Made Simple Module API has extensive support to simplify multiple actions, as well as conventions that will help keep the code separated nicely into maintainable chunks. Thus a Module would be a much better choice. Do you need localization or internationalization? These features could theoretically be implemented using a Tag, but there is no built-in support for either. The Module API, on the other hand, has facilities specifically to simplify those tasks. Will you need an Administration Panel? There is no easy way to implement an Administration panel in a Tag, while the Module API has numerous methods specifically for this purpose. Do you need to create database tables or preferences? You could write logic into your Tag to check on the existence and conditionally create database tables or preferences, but it would be easier to use the Module API which has specific support and standards for doing those operations. Now, let's consider the three things that differentiate a Tag from a User-Defined Tag: Tag Qualifying Question If you answered "Yes" Will you be sharing this solution with other people? A Tag is stored as a file on the server, which makes it easier to share with other CMS Made Simple users, since they can simply place the file in their own installation. A User-Defined Tag, on the other hand, is stored in the database, that adds extra steps if you want to share it. Do you want your code to display help text in the Admin area? The structure of a Tag has a special method for presenting information to the site administrator, while a User-Defined Tag has no such mechanism. Will your solution serve as a Smarty modifier? There are several kinds of Tags, including Smarty modifier tags. There is only one kind of User-Defined Tag, and it will not work as a Smarty modifier. Will a Module solve my problem? The previous two recipes have shown you how to assess two possible types of CMS extension, and to see if they are optimal for any specific problem. This recipe rounds out the analysis and shows you how to determine whether creating a Module is the most appropriate solution. How to do it... By examining your requirements, and comparing them to the strengths of the Module API, we can figure out whether or not a Module is the best way to implement your extension. To do so, consult the following list, and determine if each item applies to the problem you are trying to solve. Feel free to write down a list of your answers (yes/no). Are you trying to solve a problem that requires multiple actions? An example of multiple actions would be both displaying a form and processing its results. Will you need to support localization and internationalization to solve your problem? For example, if your code will be displaying messages, will the messages need to be translated into multiple languages? Will your solution require an Administration panel? Will you want to share this solution with other people so they can install it into their own CMS Made Simple sites? Do you need to create new database tables or set up new preferences to solve your problem? Do you want your code to display help text in the Admin area, so site administrators understand what parameters are available and what the code does? If you answered "yes" to any of the above questions, a Module is going to be the best way to implement your extension—with one possible exception. If you want to write an extension that you can apply to Smarty variables within a template to reformat their output (that is, a Smarty modifier), you will need to use a Tag. However, outside of that one case, a Module will be your best bet. If you answered "no" to all of the above questions, you could still use a module, but you might want to consider using a Tag or User-Defined Tag, as you will still be able to solve your problem with less complexity and overhead. How it works... A Module is PHP code that extends the CMSModule Class, which means that you start with a rich API that will save you a great deal of work. Module code can do virtually anything that PHP can do. The only thing that Modules cannot do (and which Tags can do) is act directly as Smarty modifiers. Modules are extremely powerful and versatile, but that power comes with additional complexity. If you find that it would be possible to solve your problem with a Tag or User-Defined Tag, you should opt for the simpler approach. If, however, your requirements go beyond the capabilities of those extensions, there are very few limits to what you can accomplish with a Module!  
Read more
  • 0
  • 0
  • 1320