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

How-To Tutorials

7018 Articles
article-image-article-30-discount-available-enterprise-newsletter-subscribers
Packt
27 Jul 2011
1 min read
Save for later

Exclusive Discount for Enterprise Newsletter Subscribers

Packt
27 Jul 2011
1 min read
Once subscribed you'll receive your discount code in the next newsletter (due at the start of August) - simply enter the discount code provided at checkout to take advantage of this offer New titles you might like to use your exclusive discount on include: Microsoft SQL Server 2008 R2 Master Data Services Microsoft BizTalk 2010: Line of Business Systems Integration Oracle WebCenter 11g PS3 Adminstration Cookbook ...don't forget you can use your discount code on ANY eBook
Read more
  • 0
  • 0
  • 1263

article-image-exchange-server-2010-windows-powershell-working-distribution-groups
Packt
27 Jul 2011
8 min read
Save for later

Exchange Server 2010 Windows PowerShell: Working with Distribution Groups

Packt
27 Jul 2011
8 min read
Microsoft Exchange 2010 PowerShell Cookbook Manage and maintain your Microsoft Exchange 2010 environment with the Exchange Management Shell and Windows PowerShell 2.0 using this book and eBook Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010 Click on the Exchange Management Shell shortcut Reporting on distribution group membership One of the common requests you are likely to receive as an Exchange administrator is to generate a report detailing which recipients are members of one or more distribution groups. In this recipe, we'll take a look at how to retrieve this information from the Exchange Management Shell. How to do it... To view a list of each distribution group member interactively, use the following code: foreach($i in Get-DistributionGroup -ResultSize Unlimited) { Get-DistributionGroupMember $i -ResultSize Unlimited | Select-Object @{n="Member";e={$_.Name}}, RecipientType, @{n="Group";e={$i.Name}} } This will generate a list of Exchange recipients and their associated distribution group membership. How it works... This code loops through each item returned from the Get-DistributionGroup cmdlet. As we process each group, we run the Get-DistributionGroupMember cmdlet to determine the member list for each group and then use Select-Object to construct a custom object that provides Member, RecipientType, and Group properties. Notice that, when running both Exchange cmdlets, we're setting the -ResultSize parameter to Unlimited to ensure that the details will be retrieved in the event that there are more than 1,000 groups or group members. There's more... The previous code sample will allow you to view the output in the shell. If you want to export this information to a CSV file, use the following code: $report=foreach($i in Get-DistributionGroup -ResultSize Unlimited) { Get-DistributionGroupMember $i -ResultSize Unlimited | Select-Object @{n="Member";e={$_.Name}}, RecipientType, @{n="Group";e={$i.Name}} } The difference this time is that the output from our code is being saved in the $report variable. Once the report has been generated, the $report object is then exported to a CSV file that can be opened in Excel. Adding members to a distribution group from an external file When working in large or complex environments, performing bulk operations is the key to efficiency. Using PowerShell core cmdlets such as Get-Content and Import-CSV, we can easily import external data into the shell and use this information to perform bulk operations on hundreds or thousands of objects in a matter of seconds. Obviously, this can vastly speed up the time we spend on routine tasks and greatly increase our efficiency. In this recipe, we'll use these concepts to add members to distribution groups in bulk from a text or CSV file using the Exchange Management Shell. How to do it... Create a text file called c:users.txt that lists the recipients in your organization that you want to add to a group. Make sure you enter them one line at a time, as shown in the following screen shot: Next, execute the following code to add the list of recipients to a distribution group: Get-Content c:users.txt | ForEach-Object { Add-DistributionGroupMember -Identity Sales -Member $_ } When the code runs, each user listed in the c:users.txt file will be added to the Sales distribution group. How it works... When importing data from a plain text file, we use the Get-Content cmdlet, which will read the content of the file into the shell one line at a time. In this example, we pipe the content of the file to the ForEach-Object cmdlet, and as each line is processed we execute the Add-DistributionGroupMember. Inside the For-EachObject script block we use the Add-DistributionGroupMember cmdlet and assign the $_ object, which is the current recipient item in the pipeline, to the -Member parameter. To remove recipients from a distribution group, you can use the Remove-DistributionGroupMember cmdlet. Keep in mind that this text file does not have to contain the SMTP address of the recipient. You can also use the Active Directory account name, User Principal Name, Distinguished Name, GUID, or LegacyExchangeDN values. The important thing is that the file contains a valid and unique value for each recipient. If the identity of the recipient cannot be determined, the Add-DistributionGroupMember command will fail. There's more... In addition to using plain text files, we can also import recipients from a CSV file and add them to a distribution group. Let's say that you have a CSV file setup with multiple columns, such as FirstName, LastName, and EmailAddress. When you import the CSV file, the data can be accessed using the column headers as the property names for each object. Take a look at the following screenshot: Here you can see that each item in this collection has an EmailAddress property. As long as this information corresponds to the recipient data in the Exchange organization, we can simply loop through each record in the CSV file and add these recipients to a distribution group: Import-Csv C:users.csv | ForEach-Object { Add-DistributionGroupMember Sales -Member $_.EmailAddress } The given code uses the Import-CSV cmdlet to loop through each item in the collection. As we process each record, we add the recipient to the Sales distribution group using the $_.EmailAddress object. Previewing dynamic distribution group membership The concept of the dynamic distribution group was introduced with the initial release of Exchange 2007 and included a new way to create and manage distribution groups. Unlike regular distribution groups whose members are statically defined, a dynamic distribution group determines its members based on a recipient filter. These recipient filters can be very complex, or they can be based on simple conditions, such as including all the users with a common value set for their Company or Department attributes in Active Directory. Since these dynamic groups are based on a query, they do not actually contain group members and if you want to preview the results of the groups query in the shell you need to use a series of commands. In this recipe, we'll take a look at how to view the membership of dynamic distribution groups in the Exchange Management Shell. How to do it... Imagine that we have a dynamic distribution group named Legal that includes all of the users in Active Directory with a Department attribute set to the word Legal. We can use the following commands to retrieve the current list of recipients for this group: $legal= Get-DynamicDistributionGroup -Identity legal Get-Recipient -RecipientPreviewFilter $legal.RecipientFilter How it works... Recipient filters for dynamic distribution groups use OPATH filters that are accessible through the RecipientFilter property of a dynamic distribution group object. As you can see here, we have specified the Legal groups OPATH filter when running the Get-Recipient cmdlet with the –RecipientPreviewFilter parameter. Conceptually, this would be similar to running the following command: Get-Recipient -RecipientPreviewFilter "Department -eq 'Legal'" Technically, there is a little bit more to it than that. If we were to actually look at the value for the RecipientFilter property of this dynamic distribution group, we would see much more information in addition to the filter defined for the Legal department. This is because Exchange automatically adds several additional filters when it creates a dynamic distribution group that excludes system mailboxes, discovery mailboxes, arbitration mailboxes, and more. This ends up being quite a bit of information, and creating an object instance of the dynamic distribution group gives us easy access to the existing OPATH filter that can be previewed with the Get-Recipient cmdlet. There's more... When working with regular distribution groups, you may notice that there is a cmdlet called Get-DistributionGroupMember. This allows you to retrieve a list of every user that is a member of a distribution group. Unfortunately, there is no equivalent cmdlet for dynamic distribution groups, and we need to use the method outlined previously that uses the Get-Recipient cmdlet to determine the list of recipients in a dynamic distribution group. If you find yourself doing this frequently, it probably makes sense to wrap these commands up into a function that can be added to your PowerShell profile. This will allow you to determine the members of dynamic distribution group using a single command that will be available to you every time you start the shell. Here is the code for a function called Get-DynamicDistributionGroupMember, which can be used to determine the list of recipients included in a dynamic distribution group: function Get-DynamicDistributionGroupMember { param( [Parameter(Mandatory=$true)] $Identity ) $group = Get-DynamicDistributionGroup -Identity $Identity Get-Recipient -RecipientPreviewFilter $group.RecipientFilter } Once this function is loaded into your shell session, you can run it just like a cmdlet: You can see that the command returns the recipients that match the OPATH filter for the Legal distribution group and is much easier to type than the original example.
Read more
  • 0
  • 0
  • 5813

article-image-jquery-ui-themes-theme-icons-standalone-icons-and-icon-states
Packt
27 Jul 2011
9 min read
Save for later

jQuery UI Themes: Theme icons, Standalone Icons, and Icon States

Packt
27 Jul 2011
9 min read
  jQuery UI Themes Beginner's Guide Create new themes for your JQuery site with this step-by-step guide   What are theme icons? In any user interface, we see icons all over the place. On your desktop, you see icons that represent the various application shortcuts as well as any files you've placed there. The window containing your web browser has icons for the maximize, minimize, and close actions. The benefit of using icons is that they're incredibly space-efficient, as long as they're descriptive. Using icons out of context defeats their purpose - you don't want a button with a "down arrow" icon in your toolbar. This doesn't mean anything to the user. Having a button with a "trashcan" icon in the tool-bar does make sense—it means I want to delete what I'm looking at. Another potentially harmful use is using icons in places where a text description would better inform the user. For instance, displaying a "trashcan" button in the toolbar might confuse the user if there are several things displayed on the same page, even if they've selected something. In these scenarios, we're often better off using a combination of text and an icon. The jQuery UI theming framework provides a large selection of icons we can use in our user interfaces. Some of these icons are already used in some widgets, for instance, the accordion uses arrow icons by default. Not only are the icon graphics provided to us - we can choose icon colors in the ThemRoller application - but we also have powerful CSS class we use to apply the icons. Using these classes, we can give existing jQuery UI widgets new icons or we can place them strategically in our application user interface where they prove helpful. Sometimes, the provided icon set will only go so far. You'll find that at one point or another, you need new icons that better reflect the concepts of your application domain. Time for action - preparing the example It's time to set up an environment for examples throughout the remainder of this article. If you haven't already, download and extract the jQuery UI package into a directory called jQuery UI from http://jqueryui.com/download. At the same level as the jQuery UI directory, create a new index.html file with the following content: <html > <head> <title>Creating Theme Icons</title> <link href="jqueryui/development-bundle/themes/base/ jquery.ui.all.css" rel="stylesheet" type="text/css" /> <script src="jqueryui/js/jquery-1.5.x.min.js" type="text/ javascript"></script> <script src="jqueryui/js/jquery-ui-1.8.x.custom.min.js" type="text/javascript"></script> <script src="index.js" type="text/javascript"></script> </head> <body style="font-size: 10px;"> <button id="my_button">Click Me</button> </body> </html> At the same level as the jqueryui directory, create a new index.js file with the following content. $(document).ready(function(){ $("#my_button").button(); }); Open index.html in your web browser; you should see something similar to the following: Icons in widgets Several jQuery UI widgets have icons from the theming framework embedded inside them. We use icons inside widgets to decorate them and to add meaning. Icons are similar to interaction cues, they help guide the user through the application workflow by given subtle hints. Before we start modifying icons used in our theme, we need to take a closer look at the role they play in widgets. Time for action - default widget icons Let's take a look at some of the icons displayed in jQuery UI widgets by default: Edit the index.html file created earlier and replace the content with the following: <html > <head> <title>Creating Theme Icons</title> <link href="jqueryui/development-bundle/themes/base/ jquery.ui.all.css" rel="stylesheet" type="text/css" /> <script src="jqueryui/js/jquery-1.5.x.min.js" type="text/ javascript"></script> <script src="jqueryui/js/jquery-ui-1.8.x.custom.min.js" type="text/javascript"></script> <script src="index.js" type="text/javascript"></script> </head> <body style="font-size: 10px;"> <input id="my_datepicker" type="text" style="margin- bottom: 170px;"/> <div style="width: 40%;"> <div id="my_accordion"> <h3><a href="#">First</a></h3> <div> <p>First paragraph</p> <p>Second paragraph</p> <p>Third paragraph</p> </div> <h3><a href="#">Second</a></h3> <div></div> <h3><a href="#">Third</a></h3> <div></div> </div> </div> </body> </html> Edit the index.js file created earlier and replace the content with the following: $(document).ready(function(){ $("#my_accordion").accordion(); $("#my_datepicker").datepicker(); }); Reload index.html in your web browser. You should see something similar to the following:   What just happened?   We've just created two widgets—a date-picker and an accordion. In index.html, we've created the markup for both widgets and in index.js, we construct the jQuery UI components when the page has finished loading. You'll notice that both widgets have icons in them by default. The date-picker widget has two arrows beside the month and year. The accordion widget has an arrow in each accordion section header. These widgets have icons by default because they help bring meaning to the widget succinctly. As a user, I can easily deduce the meaning of the arrows in the date-picker: move to the next or previous month. Additionally, the text "Next" and "Previous" are added to their respective icons as titles. An alternate presentation of these controls is a text link or button: "next month", "previous month". This doesn't add any value; it only takes away from the space inside the widget. The arrow icon role in the accordion widget is even more obvious. The down arrow represents the currently expanded accordion section. The right arrows represent collapsed sections. Without these arrows, the user would eventually figure out how to work the accordion controls; however, the icons make it much more obvious in a non-intrusive way. Time for action - setting widget icons In addition to using the default icons in widgets, we have the option to set the icon in certain widgets. Let's see how this is done: Edit the index.html file created earlier and replace the content with the following: <html > <head> <title>Creating Theme Icons</title> <link href="jqueryui/development-bundle/themes/base/ jquery.ui.all.css" rel="stylesheet" type="text/css" /> <script src="jqueryui/js/jquery-1.5.x.min.js" type="text/ javascript"></script> <script src="jqueryui/js/jquery-ui-1.8.x.custom.min.js" type="text/javascript"></script> <script src="index.js" type="text/javascript"></script> </head> <body style="font-size: 10px;"> <button id="my_button" style="margin-bottom: 10px;">View</ button> <div style="width: 40%;"> <div id="my_accordion"> <h3><a href="#">First</a></h3> <div> <p>First paragraph</p> <p>Second paragraph</p> <p>Third paragraph</p> </div> <h3><a href="#">Second</a></h3> <div></div> <h3><a href="#">Third</a></h3> <div></div> </div> </div> </body> </html> Edit the index.js file created earlier and replace the content with the following: $(document).ready(function(){ $("#my_button").button({icons: {primary: "ui-icon-video"}}); $("#my_accordion").accordion({icons: {header: "ui-icon-circle- triangle-e", headerSelected: "ui-icon-circle-triangle-s"} }); }); Reload index.html in your web browser. You should see something similar to the following:   What just happened? In index.html, we've created a button and an accordion widget. In index.js, we build the jQuery UI components of these widgets when the page has finished loading. In the constructor of the button widget, we pass an object to the icons parameter. This object has a primary value of ui-icon-video. This will give our button a small video icon to the left of the text. Likewise, we pass an object to the icon's parameter in the accordion constructor. This object has two values - header has a value of ui-icon-circletriangle- e and headerSelected has a value of ui-icon-circle-triangle-s. The jQuery UI theme framework has several arrow icons to choose from. The framework uses the "compass notation" for arrow icon classes. Say you want an arrow that points up. You could use ui-icon-circletriangle- n, as this arrow points "north". The button widget has built-in support for adding a button to text in order to provide additional meaning. In our example, the text view isn't very meaningful to the user. With the video icon beside the text view, it becomes very obvious what the button does. What we've done with the accordion widget is slightly different. The accordion widget displays icons by default; we've just specified different ones. This is a pure embellishment of the accordion - we've found icons that we'd like to use and replaced the default ones. We might even want to replace them with our own icons that we create.
Read more
  • 0
  • 0
  • 3925

article-image-implementing-alfresco-javascript-api-functionalities
Packt
27 Jul 2011
6 min read
Save for later

Implementing Alfresco JavaScript API Functionalities

Packt
27 Jul 2011
6 min read
Alfresco 3 Cookbook Over 70 recipes for implementing the most important functionalities of Alfresco The reader can benefit from the previous article on Alfresco 3: Writing and Executing Scripts.   Add/Change contents of a document Let’s explore some example JavaScript. In the following example scripts, you will be able to witness the APIs and functionalities. Getting ready We will store the JavaScript files in the Company Home>Data Dictionary>Scripts>Cookbook folder (this folder does not exist in your repository and create this folder). And will run the sample scripts against a document – Test_JS_API.txt in the folder Company Home>InfoAxon>Chapter 8. I have uploaded this text file with a simple line of text: A sample Document created to investigate in JavaScript API. and used our custom content type iabook:Product. if (document.hasPermission("Write")) { if (document.mimetype == "text/plain") { if (!document.hasAspect("cm:versionable")) document.addAspect("cm:versionable"); var wcopy = document.checkout(); var cnt = wcopy.content; cnt += "rnThis line is added using the JavaScript."; wcopy.content = cnt; wcopy.checkin("Sample Line added via JS"); } } How to do it... Create a new script file in the Company Home>Data Dictionary>Scripts>Cookbook folder and save this code; let’s say the file is named changecontent.js Execute the script using Run Action on the document Test_JS_API.txt in the Chapter 8 folder. After running the script, a new version of the document will be created and a new line will be added in the document. Thus each time you run the script for this document, a line will be appended at the end of the content and a new version will be created. How it works... The document object here automatically refers to the current document, in our case, it is Test_JS_API.txt, since we have executed the script against this document. First we have checked whether we have proper permission to perform the write operation on the document. If the permission is there, we check the mimetype of the document, since the textual content writing operation is possible only for a few mimetypes such as text, html, and so on. After that, we check whether the document is versionable or not, by default, any content you upload in the repository is not versionable. So we add the cm:versionable aspect in case it is not there already. Then we checkout the document and append the line of text we want in the working copy. After updating the content, we checking the working copy with a commit comment. This comment is visible in the Version History of the document. Though it is not always mandatory to check for the required permissions, it is a good practice to confirm for the relevant permissions, otherwise Alfresco may throw runtime errors in case the required permissions are not available.   Creating a backup copy of a document In this recipe, we will write a script to create a backup copy of a particular document. How to do it... Create a new script file in the Company Home>Data Dictionary>Scripts>Cookbook folder and add the following code. Let’s say the file is named createbackup.js var back = space.childByNamePath("Backup"); if (back == null && space.hasPermission("CreateChildren")) { back = space.createFolder("Backup"); } if (back != null && back.hasPermission("CreateChildren")) { var copied = document.copy(back); if (copied != null) { var backName = "Backup of " + copied.name; copied.name = backName; copied.properties.description = "This is a Backup copy created by JS"; copied.save(); } } Execute the script using Run Action on the document Test_JS_API.txt in the Chapter 8 folder. After executing the script, a new folder named Backup will be created (if it does not exist already) and a copy of this document (named Backup of Test_JS_API.txt) will be created in the backup folder. (Move the mouse over the image to enlarge.) How it works... The space object here automatically refers to the current space. In our case, it is Chapter 8, since we have executed the script against a document from this folder. The document object here automatically refers to the current document. In our case, it is Test_JS_API.txt, since we have executed the script against this document. First we have checked whether a space already exists there with the name Backup under Chapter 8. If not, we create the space. This is the space where we intend to create our backup copy. After that, we check whether we have the proper permission to create a new document in the backup folder. We do this by checking the CreateChildren permission. If we have the proper required permission, we create a copy of the document in the backup folder. Then we change a few properties of the copied document – we change the name and description, for instance. After changing the properties, we save the changes. Note that you do not need to save after changing the content of a document. However, you need to do this in case you change any property of the content item.   Adding a tag to a document In this recipe, we will write a script that can be used to tag a document. How to do it… Create a new script file in the Company Home>Data Dictionary>Scripts>Cookbook folder and add the following code; let’s say the file is named addtag.js if (!document.hasAspect("cm:taggable")) document.addAspect("cm:taggable"); document.addTag("test"); Execute the script using Run Action on the document Test_JS_API.txt in the Chapter 8 folder. The document will not be taggable, and a new tag has been added with the document – test. This is reflected in the property sheet of the document. Now, you can also add more tags using the property editor dialog. How it works... The code we presented is rather simple in this case. As usual, the document object here automatically refers to the current document. In our case, it is Test_JS_API.txt, since we have executed the script against this document. First we have checked whether the document already has the cm:taggable aspect associated with it, if not we add this aspect. Then it is just about adding a tag – we added a tag test. You can also add multiple tags at a time using the addTags method (we have used the addTag method to add a single tag in our example).  
Read more
  • 0
  • 0
  • 2914

article-image-apache-solr-spellchecker-statistics-and-grouping-mechanism
Packt
27 Jul 2011
5 min read
Save for later

Apache Solr: Spellchecker, Statistics, and Grouping Mechanism

Packt
27 Jul 2011
5 min read
Computing statistics for the search results Imagine a situation where you want to compute some basic statistics about the documents in the results list. For example, you have an e-commerce shop where you want to show the minimum and the maximum price of the documents that were found for a given query. Of course, you could fetch all the documents and count it by yourself, but imagine if Solr can do it for you. Yes it can and this recipe will show you how to use that functionality. How to do it... Let's start with the index structure (just add this to the fields section of your schema.xml file): <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="name" type="text" indexed="true" stored="true" /> <field name="price" type="float" indexed="true" stored="true" /> The example data file looks like this: <add> <doc> <field name="id">1</field> <field name="name">Book 1</field> <field name="price">39.99</field> </doc> <doc> <field name="id">2</field> <field name="name">Book 2</field> <field name="price">30.11</field> </doc> <doc> <field name="id">3</field> <field name="name">Book 3</field> <field name="price">27.77</field> </doc> </add> Let's assume that we want our statistics to be computed for the price field. To do that, we send the following query to Solr: http://localhost:8983/solr/select?q=name:book&stats=true&stats. field=price The response Solr returned should be like this: <?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">0</int> <lst name="params"> <str name="q">name:book</str> <str name="stats">true</str> <str name="stats.field">price</str> </lst> </lst> <result name="response" numFound="3" start="0"> <doc> <str name="id">1</str> <str name="name">Book 1</str> <float name="price">39.99</float> </doc> <doc> <str name="id">2</str> <str name="name">Book 2</str> <float name="price">30.11</float> </doc> <doc> <str name="id">3</str> <str name="name">Book 3</str> <float name="price">27.77</float> </doc> </result> <lst name="stats"> <lst name="stats_fields"> <lst name="price"> <double name="min">27.77</double> <double name="max">39.99</double> <double name="sum">97.86999999999999</double> <long name="count">3</long> <long name="missing">0</long> <double name="sumOfSquares">3276.9851000000003</double> <double name="mean">32.62333333333333</double> <double name="stddev">6.486118510583508</double> </lst> </lst> </lst> </response> As you can see, in addition to the standard results list, there was an additional section available. Now let's see how it works. How it works... The index structure is pretty straightforward. It contains three fields—one for holding the unique identifier (the id field), one for holding the name (the name field), and one for holding the price (the price field). The file that contains the example data is simple too, so I'll skip discussing it. The query is interesting. In addition to the q parameter, we have two new parameters. The first one, stats=true, tells Solr that we want to use the StatsComponent, the component which will calculate the statistics for us. The second parameter, stats.field=price, tells the StatsComponent which field to use for the calculation. In our case, we told Solr to use the price field. Now let's look at the result returned by Solr. As you can see, the StatsComponent added an additional section to the results. This section contains the statistics generated for the field we told Solr we want statistics for. The following statistics are available: min: The minimum value that was found in the field for the documents that matched the query max: The maximum value that was found in the field for the documents that matched the query sum: Sum of all values in the field for the documents that matched the query count: How many non-null values were found in the field for the documents that matched the query missing: How many documents that matched the query didn't have any value in the specified field sumOfSquares: Sum of all values squared in the field for the documents that matched the query mean: The average for the values in the field for the documents that matched the query stddev: The standard deviation for the values in the field for the documents that matched the query You should also remember that you can specify multiple stats.field parameters to calculate statistics for different fields in a single query. Please be careful when using this component on the multi-valued fields. It can sometimes be a performance bottleneck.
Read more
  • 0
  • 0
  • 2418

article-image-alfresco-3-writing-and-executing-scripts
Packt
27 Jul 2011
4 min read
Save for later

Alfresco 3: Writing and Executing Scripts

Packt
27 Jul 2011
4 min read
  Alfresco 3 Cookbook Over 70 recipes for implementing the most important functionalities of Alfresco The reader can benefit from the previous article on Implementing Alfresco JavaScript API Functionalities. Introduction Alfresco, like any other enterprise open source framework, exposes a number of APIs including Alfresco SDK (Software Development Kit) a set of development tools that allows the creation of an application for a certain software package or framework and JavaScript API. Available JavaScript APIs Alfresco JavaScript API exposes all important repository objects as JavaScript objects that can be used in a script file. The API follows the object-oriented programming model for well known Alfresco concepts such as Nodes, Properties, Associations, and Aspects. The JavaScript API is capable of performing several essential functions for the script developer, such as: Create Node, Update Node: You can create, upload, or update files using these. Check In/Check Out: You can programmatically check-out and check-in your content. Access Rights Management Permissioning: You can manage your content’s security aspects. Transformation: You can transform your content using this. For example, you want to generate a PDF version of your MS-Office document. Tagging: Tagging APIs will help you tag your contents. Classifying: You can categorize or classify your contents using this. People: Using these APIs, you can handle all user-and group-related operations in your script; such as creating a new user, changing the password of a user, and so on. Searching: One of most important and powerful APIs exposed. You can search your contents using these APIs. You can perform Lucene-based search or XPath-based search operations using these APIs. Workflow: You can manage the tasks and workflows in your system using these APIs and services. Thumbnail: Exposes APIs to manage the thumbnail operations of various content items. Node operations: You use these APIs to perform several node-related functions such as Manage Properties, Manage Aspects, copying, deleting, moving, and so on. Thus, as you can see, pretty much most of the things can be done in a JavaScript file using these APIs. However, one thing is important, that you should not mix the usual JavaScript code you write for your HTML or JSP web pages. Those scripts are executed by your browser (this means, at the client side). The scripts you write using Alfresco JavaScript API are not client-side JavaScript file – this means these do not get executed by your browser. Instead, they get executed in your server and the browser has nothing to do in these scripts. It is called JavaScript API since the APIs are exposed using the ECMA script model and syntaxes. The programs you develop using these APIs are written in JavaScript language. The JavaScript API model Alfresco has provided a number of objects in the JavaScript API – these are more usually named as Root Scope Objects. These objects are your entry point into the repository. Each of the root level objects refers to a particular entity or functional point in the repository. For example, userhome object refers to the home space node of the current user. Each of these objects presents a number of properties and functionalities, thus enabling the script writer to implement several different requirements. For example, the userhome.name statement will return the name of the root folder of the current user. Some important and most frequently used root scope objects are: Companyhome: Returns the company home script node object Userhome: Returns the home folder node of the current user Person: Represents the current user person object Space: Stands for the current space object Document: Returns the currently selected document Search: Offers fully functional search APIs People: Encapsulates all functionalities related to user, groups, roles, permissions, and so on. Sites: Exposes the site service functionalities Actions: Provides invocation methods for registered actions Workflow: Handles all functionalities related to workflow implementation within the repository Among these, companyhome, userhome, person, space, and document objects represent Alfresco Node objects and allow access to the properties and aspects of the corresponding node object. Each of the node objects provides a number of APIs which are termed ScriptNode API. The others – search, people, sites, workflow, and actions – expose several methods that would help you implement specific business requirements. For example, if you want to write a script that searches some documents and contents, you would use the search API. If you want to create a new user – the people API will help you.  
Read more
  • 0
  • 0
  • 2799
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 €18.99/month. Cancel anytime
article-image-exchange-server-2010-windows-powershell-working-address-lists
Packt
27 Jul 2011
6 min read
Save for later

Exchange Server 2010 Windows PowerShell: working with address lists

Packt
27 Jul 2011
6 min read
Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010 Click on the Exchange Management Shell shortcut The reader would benefit by reffering the previous article on Working with Distribution Groups. Creating address lists Just like dynamic distribution groups, Exchange address lists can be comprised of one or more recipient types and are generated using a recipient filter or using a set of built-in conditions. You can create one or more address list(s), made up of users, contacts, distribution groups, or any other mail-enabled objects in your organization. This recipe will show you how to create an address list using the Exchange Management Shell. How to do it... Let's say we need to create an address list for the sales representatives in our organization. We can use the New-AddressList cmdlet to accomplish this, as shown next: New-AddressList -Name 'All Sales Users' ` -RecipientContainer contoso.com/Sales ` -IncludedRecipients MailboxUsers How it works... This example uses the New-AddressList cmdlet's built-in conditions to specify the criteria for the recipients that will be included in the list. You can see from the command that, in order for a recipient to be visible in the address list, they must be located within the Sales OU in Active Directory and the recipient type must be MailboxUsers, which only applies to regular mailboxes and does not include other types such as resource mailboxes, distribution groups, and so on. You can use the built-in conditions when you need to configure a basic filter for the list, and they can be easily edited from within the Exchange Management Console. There's more... When you need to create an address list based on a more complex set of conditions, you'll need to use the -RecipientFilter parameter to specify an OPATH filter. For example, the following OPATH filter is not configurable when creating or modifying an address list in EMC: New-AddressList -Name MobileUsers ` -RecipientContainer contoso.com ` -RecipientFilter { HasActiveSyncDevicePartnership -ne $false } You can see here that we're creating an address list for all the mobile users in the organization. We've set the RecipientContainer to the root domain, and, within the recipient filter, we've specified that all recipients with an ActiveSync device partnership should be included in the list. You can create global address lists using the New-GlobalAddress list cmdlet. You can combine multiple conditions in your recipient filters using PowerShell's logical operators. For instance, we can extend our previous example to add an additional requirement in the OPATH filter: New-AddressList -Name MobileUsers ` -RecipientContainer contoso.com ` -RecipientFilter { (HasActiveSyncDevicePartnership -ne $false) -and (Phone -ne $null) } This time, in addition to having an ActiveSync device partnership, the user must also have a number defined within their Phone attribute in order for them to be included in the list. If you need to modify a recipient filter after an address list has already been created, use the Set-AddressList cmdlet. Exchange supports a various number of both common and advanced properties that can be used to construct OPATH filters, as shown in the previous example. Exporting address list membership to a CSV file When it comes to working with address lists, a common task is exporting the list of members to an external file. In this recipe, we'll take a look at the process of exporting the contents of an address list to a CSV file. How to do it... Let's start off with a simple example. The following commands will export the All Users address list to a CSV file: $allusers = Get-AddressList "All Users" Get-Recipient -RecipientPreviewFilter $allusers.RecipientFilter | Select-Object DisplayName,Database | Export-Csv -Path c:allusers.csv -NoTypeInformation When the command completes, a list of user display names and their associated mailbox databases will be exported to c:allusers.csv. How it works... The first thing we do in this example is create the $allusers variable that stores an instance of the All Users address list. We can then run the Get-Recipient cmdlet and specify the OPATH filter, using the $allusers.RecipientFilter object as the value for the -RecipientPreviewFilter parameter. The results are then piped to the select-object cmdlet that grabs the DisplayName and Database properties of the recipient. Finally, the data is exported to a CSV file. Of course, the given example may not be that practical, as it does not provide the e-mail addresses for the user. We can also export this information, but it requires some special handling on our part. Let's export only the DisplayName and EmailAddresses for each user. To do so, use the following code: $allusers = Get-AddressList "All Users" Get-Recipient -RecipientPreviewFilter $allusers.RecipientFilter | Select-Object DisplayName, @{n="EmailAddresses";e={$_.EmailAddresses -join ";"}} | Export-Csv -Path c:allusers.csv -NoTypeInformation Since each recipient can have multiple SMTP e-mail addresses, the EmailAddresses property of each recipient is a multi-valued object. This means we can't simply export this value to an external file, since it is actually an object and not a simple string value. In the given command, we're using the Select-Object cmdlet to create a calculated property for the EmailAddresses collection. Using the -Join operator within the calculated property expression, we are adding each address in the collection to a single string that will be delimited with the semi-colon (;) character. There's more... The given method will work for any of the address lists in your organization. For example, you can export the recipients of the Global Address List (GAL) using the following code: $GAL = Get-GlobalAddressList "Default Global Address List" Get-Recipient -RecipientPreviewFilter $GAL.RecipientFilter | Select-Object DisplayName, @{n="EmailAddresses";e={$_.EmailAddresses -join ";"}} | Export-Csv -Path c:GAL.csv -NoTypeInformation As you can see here, the main difference is that this time we are using the Get-GlobalAddressList cmdlet to export the default global address list. You can use this technique for any address list in your organization: just specify the name of the address list you want to export when using either the Get-AddressList or Get-GlobalAddress list cmdlets.
Read more
  • 0
  • 0
  • 4479

article-image-using-additional-solr-functionalities
Packt
26 Jul 2011
9 min read
Save for later

Using Additional Solr Functionalities

Packt
26 Jul 2011
9 min read
  Apache Solr 3.1 Cookbook Over 100 recipes to discover new ways to work with Apache’s Enterprise Search Server         Read more about this book       (For more resources on this subject, see here.) Getting more documents similar to those returned in the results list Let's imagine a situation where you have an e-commerce library shop and you want to show users the books similar to the ones they found while using your application. This recipe will show you how to do that. How to do it... Let's assume that we have the following index structure (just add this to your schema.xml file's fields section): <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="name" type="text" indexed="true" stored="true" termVectors="true" /> The test data looks like this: <add> <doc> <field name="id">1</field> <field name="name">Solr Cookbook first edition</field> </doc> <doc> <field name="id">2</field> <field name="name">Solr Cookbook second edition</field> </doc> <doc> <field name="id">3</field> <field name="name">Solr by example first edition</field> </doc> <doc> <field name="id">4</field> <field name="name">My book second edition</field> </doc> </add> Let's assume that our hypothetical user wants to find books that have first in their names. However, we also want to show him the similar books. To do that, we send the following query: http://localhost:8983/solr/select?q=name:edition&mlt=true&mlt. fl=name&mlt.mintf=1&mlt.mindf=1 The results returned by Solr are as follows: <?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">1</int> <lst name="params"> <str name="mlt.mindf">1</str> <str name="mlt.fl">name</str> <str name="q">name:edition</str> <str name="mlt.mintf">1</str> <str name="mlt">true</str> </lst> </lst> <result name="response" numFound="1" start="0"> <doc> <str name="id">3</str> <str name="name">Solr by example first edition</str> </doc> </result> <lst name="moreLikeThis"> <result name="3" numFound="3" start="0"> <doc> <str name="id">1</str> <str name="name">Solr Cookbook first edition</str> </doc> <doc> <str name="id">2</str> <str name="name">Solr Cookbook second edition</str> </doc> <doc> <str name="id">4</str> <str name="name">My book second edition</str> </doc> </result> </lst> </response> Now let's see how it works. How it works... As you can see, the index structure and the data are really simple. One thing to notice is that the termVectors attribute is set to true in the name field definition. It is a nice thing to have when using more like this component and should be used when possible in the fields on which we plan to use the component. Now let's take a look at the query. As you can see, we added some additional parameters besides the standard q one. The parameter mlt=true says that we want to add the more like this component to the result processing. Next, the mlt.fl parameter specifies which fields we want to use with the more like this component. In our case, we will use the name field. The mlt.mintf parameter tells Solr to ignore terms from the source document (the ones from the original result list) with the term frequency below the given value. In our case, we don't want to include the terms that will have the frequency lower than 1. The last parameter, mlt.mindf, tells Solr that the words that appear in less than the value of the parameter documents should be ignored. In our case, we want to consider words that appear in at least one document. Finally, let's take a look at the search results. As you can see, there is an additional section (<lst name="moreLikeThis">) that is responsible for showing us the more like this component results. For each document in the results, there is one more similar section added to the response. In our case, Solr added a section for the document with the unique identifier 3 (<result name="3" numFound="3" start="0">) and there were three similar documents found. The value of the id attribute is assigned the value of the unique identifier of the document that the similar documents are calculated for. Presenting search results in a fast and easy way Imagine a situation where you have to show a prototype of your brilliant search algorithm made with Solr to the client. But the client doesn't want to wait another four weeks to see the potential of the algorithm, he/she wants to see it very soon. On the other hand, you don't want to show the pure XML results page. What to do then? This recipe will show you how you can use the Velocity response writer (a.k.a. Solritas) to present a prototype fast. How to do it... Let's assume that we have the following index structure (just add this to your schema.xml file to the fields section): <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="name" type="text" indexed="true" stored="true" /> The test data looks like this: <add> <doc> <field name="id">1</field> <field name="name">Solr Cookbook first edition</field> </doc> <doc> <field name="id">2</field> <field name="name">Solr Cookbook second edition</field> </doc> <doc> <field name="id">3</field> <field name="name">Solr by example first edition</field> </doc> <doc> <field name="id">4</field> <field name="name">My book second edition</field> </doc> </add> We need to add the response writer definition. To do this, you should add this to your solrconfig.xml file (actually this should already be in the configuration file): <queryResponseWriter name="velocity" class="org.apache.solr. request.VelocityResponseWriter"/> Now let's set up the Velocity response writer. To do that we add the following section to the solrconfig.xml file (actually this should already be in the configuration file): <requestHandler name="/browse" class="solr.SearchHandler"> <lst name="defaults"> <str name="wt">velocity</str> <str name="v.template">browse</str> <str name="v.layout">layout</str> <str name="title">Solr cookbook example</str> <str name="defType">dismax</str> <str name="q.alt">*:*</str> <str name="rows">10</str> <str name="fl">*,score</str> <str name="qf">name</str> </lst> </requestHandler> Now you can run Solr and type the following URL address: http://localhost:8983/solr/browse You should see the following page: (Move the mouse over the image to enlarge it.) How it works... As you can see, the index structure and the data are really simple, so I'll skip discussing this part of the recipe. The first thing in configuring the solrconfig.xml file is adding the Velocity Response Writer definition. By adding it, we tell Solr that we will be using velocity templates to render the view. Now we add the search handler to use the Velocity Response Writer. Of course, we could pass the parameters with every query, but we don't want to do that, we want them to be added by Solr automatically. Let's go through the parameters: wt: The response writer type; in our case, we will use the Velocity Response Writer. v.template: The template that will be used for rendering the view; in our case, the template that Velocity will use is in the browse.vm file (the vm postfix is added by Velocity automatically). This parameter tells Velocity which file is responsible for rendering the actual page contents. v.layout: The layout that will be used for rendering the view; in our case, the template that velocity will use is in the layout.vm file (the vm postfix is added by velocity automatically). This parameter specifies how all the web pages rendered by Solritas will look like. title: The title of the page. defType: The parser that we want to use. q.alt: Alternate query for the dismax parser in case the q parameter is not defined. rows: How many maximum documents should be returned. fl: Fields that should be listed in the results. qf: The fields that we should be searched. Of course, the page generated by the Velocity Response Writer is just an example. To modify the page, you should modify the Velocity files, but this is beyond the scope of this article. There's more... If you are still using Solr 1.4.1 or 1.4, there is one more thing that can be useful. Running Solritas on Solr 1.4.1 or 1.4 Because the Velocity Response Writer is a contrib module in Solr 1.4.1, we need to do the following operations to use it. Copy the following libraries from the /contrib/velocity/ src/main/solr/lib directory to the /lib directory of your Solr instance: apache-solr-velocity-1.4.dev.jar commons-beanutils-1.7.0.jar commons-collections-3.2.1.jar velocity-1.6.1.jar velocity-tools-2.0-beta3.jar Then copy the contents of the /velocity (with the directory) directory from the code examples to your Solr configuration directory.
Read more
  • 0
  • 0
  • 2047

article-image-being-cross-platform-haxe
Packt
26 Jul 2011
10 min read
Save for later

Being Cross-platform with haXe

Packt
26 Jul 2011
10 min read
  haXe 2 Beginner's Guide Develop exciting applications with this multi-platform programming language What is cross-platform in the library The standard library includes a lot of classes and methods, which you will need most of the time in a web application. So, let's have a look at the different features. What we call standard library is simply a set of objects, which is available when you install haXe. Object storage The standard library offers several structures in which you can store objects. In haXe, you will see that, compared to many other languages, there are not many structures to store objects. This choice has been made because developers should be able to do what they need to do with their objects instead of dealing with a lot of structures, which they have to cast all the time. The basic structures are array, list, and hash. All of these have a different utility: Objects stored in an array can be directly accessed by using their index Objects in a list are linked together in an ordered way Objects in an hash are tied to what are called "keys", but instead of being an Int, keys are a String There is also the IntHash structure that is a hash-table using Int values as keys. These structures can be used seamlessly in all targets. This is also, why the hash only supports String as indexes: some platforms would require a complex class that would impair performances to support any kind of object as indexes. The Std class The Std class is a class that contains methods allowing you to do some basic tasks, such as parsing a Float or an Int from a String, transforming a Float to an Int, or obtaining a randomly generated number. This class can be used on all targets without any problems. The haxe package The haxe package (notice the lower-case x) contains a lot of class-specific to haXe such as the haxe.Serializer class that allows one to serialize any object to the haXe serialization format or its twin class haxe.Unserializer that allows one to unserialize objects (that is "reconstruct" them). This is basically a package offering extended cross-platform functionalities. The classes in the haxe package can be used on all platforms most of the time. The haxe.remoting package This package also contains a remoting package that contains several classes allowing us to use the haXe remoting protocol. This protocol allows several programs supporting it to communicate easily. Some classes in this package are only available for certain targets because of their limitations. For example, a browser environment won't allow one to open a TCP socket, or Flash won't allow one to create a server. Remoting will be discussed later, as it is a very interesting feature of haXe. The haxe.rtti package There's also the rtti package. RTTI means Run Time Type Information. A class can hold information about itself, such as what fields it contains and their declared types. This can be really interesting in some cases, such as, if you want to create automatically generated editors for some objects. The haxe.Http class The haxe.Http class is one you are certainly going to use quite often. It allows you to make HTTP requests and retrieve the answer pretty easily without having to deal with the HTTP protocol by yourself. If you don't know what HTTP is, then you should just know that it is the protocol used between web browsers and servers. On a side-note, the ability to make HTTPS requests depends on the platform. For example, at the moment, Neko doesn't provide any way to make one, whereas it's not a problem at all on JS because this functionality is provided by the browser. Also, some methods in this class are only available on some platforms. That's why, if you are writing a cross-platform library or program, you should pay attention to what methods you can use on all the platforms you want to target. You should note that on JS, the haxe.Http class uses HttpRequest objects and as such, they suffer from security restrictions, the most important one being the same-domain policy. This is something that you should keep in mind, when thinking about your solution's architecture. You can make a simple synchronous request by writing the following: var answer = Http.requestUrl("http://www.benjamindasnois.com"); It is also possible to make some asynchronous requests as follows: var myRequest = new Http("http://www.benjamindasnois.com"); myRequest.onData = function (d : String) { Lib.println(d); } myRequest.request(false); This method also allows you to get more information about the answer, such as the headers and the return code. The following is an example displaying the answer's headers: import haxe.Http; #if neko import neko.Lib; #elseif php import php.Lib; #end class Main { static function main() { var myRequest = new Http("http://www.benjamindasnois.com"); myRequest.onData = function (d : String) { for (k in myRequest.responseHeaders.keys()) { Lib.println(k + " : " + myRequest.responseHeaders.get(k)); } }; myRequest.request(false); } } The following is what it displays: X-Cache : MISS from rack1.tumblr.com X-Cache-Lookup : MISS from rack1.tumblr.com:80 Via : 1.0 rack1.tumblr.com:80 (squid/2.6.STABLE6) P3P : CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL" Set-Cookie : tmgioct=h6NSbuBBgVV2IH3qzPEPPQLg; expires=Thu, 02-Jul-2020 23:30:11 GMT; path=/; httponly ETag : f85901c583a154f897ba718048d779ef Link : <http://assets.tumblr.com/images/default_avatar_16.gif>; rel=icon Vary : Accept-Encoding Content-Type : text/html; charset=UTF-8 Content-Length : 30091 Server : Apache/2.2.3 (Red Hat) Date : Mon, 05 Jul 2010 23:31:10 GMT X-Tumblr-Usec : D=78076 X-Tumblr-User : pignoufou X-Cache-Auto : hit Connection : close Regular expressions and XML handling haXe offers a cross-platform API for regular expressions and XML that can be used on most targets' target. Regular expressions The regular expression API is implemented as the EReg class. You can use this class on any platform to match a RegExp, split a string according to a RegExp, or do some replacement. This class is available on all targets, but on Flash, it only starts from Flash 9. The following is an example of a simple function that returns true or false depending on if a RegExp matches a string given as parameter: public static function matchesHello(str : String) : Bool { var helloRegExp = ~/.*hello.*/; return helloRegExp.match(str); } One can also replace what is matched by the RegExp and return this value. This one simply replaces the word "hello" with "bye", so it's a bit of an overkill to use a RegExp to do that, and you will find some more useful ways to use this possibility when making some real programs. Now, at least you will know how to do it: public static function replaceHello(str : String) : String { var helloRegExp = ~/hello/; helloRegExp.match(str); return helloRegExp.replace(str, "bye"); } XML handling The XML class is available on all platforms. It allows you to parse and emit XML the same way on many targets. Unfortunately, it is implemented using RegExp on most platforms, and therefore can become quite slow on big files. Such problems have already been raised on the JS targets, particularly on some browsers, but you should keep in mind that different browsers perform completely differently. For example, on the Flash platform, this API is now using the internal Flash XML libraries, which results in some incompatibilities. The following is an example of how to create a simple XML document: <pages> <page id="page1"/> <page id="page2"/> </pages> Now, the haXe code to generate it: var xmlDoc : Xml; var xmlRoot : Xml; xmlDoc = Xml.createDocument(); //Create the document xmlRoot = Xml.createElement("pages"); //Create the root node xmlDoc.addChild(xmlRoot); //Add the root node to the document var page1 : Xml; page1 = Xml.createElement("page"); //create the first page node page1.set("id", "page1"); xmlRoot.addChild(page1); //Add it to the root node var page2 : Xml; page2 = Xml.createElement("page"); page2.set("id", "page2"); xmlRoot.addChild(page2); trace(xmlDoc.toString()); //Print the generated XML Input and output Input and output are certainly the most important parts of an application; indeed, without them, an application is almost useless. If you think about how the different targets supported by haXe work and how the user may interact with them, you will quickly come to the conclusion that they use different ways of interacting with the user, which are as follows: JavaScript in the browser uses the DOM Flash has its own API to draw on screen and handle events Neko uses the classic input/output streams (stdin, stdout, stderr) and so do PHP and C++ So, we have three different main interfaces: DOM, Flash, and classic streams. The DOM interface The implementation of the DOM interface is available in the js package. This interface is implemented through typedefs. Unfortunately, the API doesn't provide any way to abstract the differences between browsers and you will have to deal with them in most cases by yourself. This API is simply telling the compiler what objects exist in the DOM environment; so, if you know how to manipulate the DOM in JavaScript, you will be able to manipulate it in haXe. The thing that you should know is that the document object can be accessed through js.Lib.document. The js package is accessible only when compiling to JS. The Flash interface In a way that is similar to how the Flash is implemented in the flash and flash9 packages, the js package implements the DOM interface. When reading this sentence, you may wonder why there are two packages. The reason is pretty simple, the Flash APIs pre and post Flash 9 are different. You also have to pay attention to the fact that, when compiling to Flash 9, the flash9 package is accessible through the flashpath and not through flash9. Also, at the time of writing, the documentation for flash and flash9 packages on haxe. org is almost non-existent; but, if you need some documentation, you can refer to the official documentation. The standard input/output interface The standard input/output interface refers to the three basic streams that exist on most systems, which are as follows: stdin (most of the time the keyboard). stdout (the standard output which is most of the time the console, or, when running as a web-application, the stream sent to the client). stderr (the standard error output which is most of the time directed to the console or the log file). Neko, PHP and C++ all make use of this kind of interface. Now, there are two pieces news for you: one good and one bad. The bad one is that the API for each platform is located in a platform-specific package. So, for example, when targeting Neko, you will have to use the neko package, which is not available in PHP or C++. The good news is that there is a workaround. Well, indeed, there are three. You just have to continue reading through this article and I'll tell you how to handle that.  
Read more
  • 0
  • 0
  • 2866

article-image-phplist-2-e-mail-campaign-manager-personalizing-e-mail-body
Packt
26 Jul 2011
5 min read
Save for later

phpList 2 E-mail Campaign Manager: Personalizing E-mail Body

Packt
26 Jul 2011
5 min read
Enhancing messages using built-in placeholders For simple functionality's sake, we generally want our phpList messages to contain at least a small amount of customization. For example, even the default footer, which phpList attaches to messages, contains three placeholders, customizing each message for each recipient: -- If you do not want to receive any more newsletters, [UNSUBSCRIBE] To update your preferences and to unsubscribe, visit [PREFERENCES] Forward a Message to Someone [FORWARD] The placeholders [UNSUBSCRIBE],[PREFERENCES], and [FORWARD] will be replaced with unique URLs per subscriber, allowing any subscriber to immediately unsubscribe, adjust their preferences, or forward a message to a friend simply by clicking on a link. There's a complete list of available placeholders documented on phpList's wiki page at http://docs.phplist.com/Placeholders. Here are some of the most frequently used ones: [CONTENT]: Use this while creating standard message templates. You can design a styled template which is re-used for every mailing and the [CONTENT] placeholder will be replaced with the unique content for that particular message. [EMAIL]: This is replaced by the user's e-mail address. It can be very helpful in the footer of an e-mail, so that subscribers know which e-mail address they used to sign up for list subscription. [LISTS]: The lists to which a member is subscribed. Having this information attached to system confirmation messages makes it easy for subscribers to manage their own subscriptions. Note that this placeholder is only applicable in system messages and not in general list messages. [UNSUBSCRIBEURL]: Almost certainly, you'll want to include some sort of "click here to unsubscribe" link on your messages, either as a pre-requisite for sending bulk mail (perhaps imposed by your ISP) or to avoid users inadvertently reporting you for spamming. [UNSUBSCRIBE]: This placeholder generates the entire hyperlink for you (including the link text, "unsubscribe"), whereas the [UNSUBSCRIBEURL] placeholder simply generates the URL. You would use the URL only if you wanted to link an image to the unsubscription page, as opposed to a simple link, or if you wanted the HTML link text to be something other than "unsubscribe". [USERTRACK]: This inserts an invisible tracker image into HTML messages, helping you to measure the effectiveness of your newsletter. You might combine several of these placeholders to add a standard signature to your messages, as follows: -- You ([EMAIL]) are receiving this message because you subscribed to one or more of our mailing lists. We only send messages to subscribers who have requested and confirmed their subscription (double-opt-in). You can adjust your list membership at any time by clicking on [PREFERENCES] or unsubscribe altogether by clicking on [UNSUBSCRIBE]. -- Placeholders in confirmation messages Some placeholders (such as [LISTS]) are only applicable in confirmation messages (that is, "thank you for subscribing to the following lists..."). These placeholders allow you to customize the following: Request to confirm: Sent initially to users when they subscribe, confirming their e-mail address and subscription request Confirmation of subscription: Sent to users to confirm that they've been successfully added to the requested lists (after they've confirmed their e-mail address) Confirmation of preferences update: Sent to users to confirm their updates when they change their list subscriptions/preferences themselves Confirmation of unsubscription: Sent to users after they've unsubscribed to confirm that their e-mail address will no longer receive messages from phpList Personalizing messages using member attributes Apart from the built-in placeholders, you can also use any member attributes to further personalize your messages. Say you captured the following attributes from your new members: First Name Last Name Hometown Favorite Food You could craft a personalized message as follows: Dear [FIRST NAME], Hello from your friends at the Funky Town Restaurant. We hope the [LAST NAME] family is well in the friendly town of [HOMETOWN]. If you're ever in the mood for a fresh [FAVORITE FOOD], please drop in - we'd be happy to have you! ... This would appear to different subscribers as: Dear Bart, Hello from your friends at the Funky Town Restaurant. We hope the Simpson family is well in the friendly town of Springfield. If you're ever in the mood for a fresh pizza, please drop in - we'd be happy to have you! ... Or: Dear Clark, Hello from your friends at the Funky Town Restaurant. We hope the Kent family is well in the friendly town of Smallville. If you're ever in the mood for a fresh Krypto-Burger, please drop in - we'd be happy to have you! ... If a user doesn't have an attribute for a particular placeholder, it will be replaced with a blank space. For example, if user "Mary" hadn't entered any attributes, her message would look like: Dear, Hello from your friends at the Funky Town Restaurant. We hope the family is well in the friendly town of . If you're ever in the mood for a fresh , please drop in - we'd be happy to have you! ... If the attributes on your subscription form are optional, try to structure your content in such a way that a blank placeholder substitution won't ruin the text. For example, the following text will look awkward with blank substitutions: Your name is [FIRST NAME], your favorite food is [FAVORITE FOOD], and your last name is [LAST NAME] Whereas the following text would at least "degrade gracefully": Your name: [FIRST NAME] Your favorite food: [FAVORITE FOOD] Your last name [LAST NAME]
Read more
  • 0
  • 0
  • 2547
article-image-android-30-application-development-managing-menus
Packt
26 Jul 2011
7 min read
Save for later

Android 3.0 Application Development: Managing Menus

Packt
26 Jul 2011
7 min read
Android 3.0 Application Development Cookbook All Android handsets have a hard menu key for calling up secondary choices that do not need to be made available from the main screen or perhaps need to be made available across an application. In concord with Android's philosophy of separating appearance from function, menus are generally created in the same way as other visual elements, that is, with the use of a definitive XML layout file. There is a lot that can be done to control menus dynamically and Android provides classes and interfaces for displaying context-sensitive menus, organizing menu items into groups, and including shortcuts. Creating and inflating an options menu To keep our application code separate from our menu layout information, Android uses a designated resource folder (res/menu) and an XML layout file to define the physical appearance of our menu; such as the titles and icons we see in Android pop-up menus. The Activity class contains a callback method, onCreateOptionsMenu(), that can be overridden to inflate a menu. Getting ready Android menus are defined in a specific, designated folder. Eclipse does not create this folder by default so start up a new project and add a new folder inside the res folder and call it menu. How to do it... Create a new XML file in our new res/menu folder and call it my_menu.xml. Complete the new file as follows: <?xml version="1.0" encoding="utf-8"?> <menu > <item android_id="@+id/item_one" android_title="first item" /> <item android_id="@+id/item_two" android_title="second item" /> </menu> In the Java application file, include the following overridden callback: @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.my_menu, menu); return true; } Run the application on a handset or emulator and press the hard menu key to view the menu: How it works... Whenever we create an Android menu using XML we must place it in the folder we used here (res/menu). Likewise, the base node of our XML structure must be <menu>. The purpose of the id element should be self explanatory and the title attribute is used to set the text that the user sees when the menu item is inflated. The MenuInflater object is a straightforward way of turning an XML layout file into a Java object. We create a MenuInflater with getMenuInflater() which returns a MenuInflater from the current activity, of which it is a member. The inflate() call takes both the XML file and the equivalent Java object as its parameters. There's more... The type of menu we created here is referred to as an options menu and it comes in two flavors depending on how many items it contains. There is also a neater way to handle item titles when they are too long to be completely displayed. Handling longer options menus When an options menu has six or fewer items it appears as a block of items at the bottom of the screen. This is called the icon menu and is, as its name suggests, the only menu type capable of displaying icons. On tablets running API level 11 or greater the Action bar can also be used to access the menu. The icon menu is also the only menu type that cannot display radio buttons or check marks. When an inflated options menu has more than six items, the sixth place on the icon menu is replaced by the system's own More item, which when pressed calls up the extended menu which displays all items from the sixth onwards, adding a scroll bar if necessary. Providing condensed menu titles If Android cannot fit an item's title text into the space provided (often as little as one third of the screen width) it will simply truncate it. To provide a more readable alternative, include the android:titleCondensed="string" attribute alongside android:title in the item definition. Adding Option menu items to the Action Bar For tablet devices targeting Android 3.0 or greater, option menu items can be added to the Action Bar. Adjust the target build of the above project to API level 11 or above and replace the res/menu/my_menu.xml file with the following: <?xml version="1.0" encoding="utf-8"?> <menu > <item android_id="@+id/item_one" android_title="first item" android_icon="@drawable/icon" android_showAsAction="ifRoom" /> <item android_id="@+id/item_two" android_title="second item" android_icon="@drawable/icon" android_showAsAction="ifRoom|withText" /> <item android_id="@+id/item_three" android_title="third item" android_icon="@drawable/icon" android_showAsAction="always" /> <item android_id="@+id/item_four" android_title="fourth item" android_icon="@drawable/icon" android_showAsAction="never" /> </menu> Note from the output that unless the withText flag is included, the menu item will display only as an icon: Designing Android compliant menu icons The menu items we defined in the previous recipe had only text titles to identify them to the user, however nearly all Icon Menus that we see on Android devices combine a text title with an icon. Although it is perfectly possible to use any graphic image as a menu icon, using images that do not conform to Android's own guidelines on icon design is strongly discouraged, and Android's own development team are particularly insistent that only the subscribed color palette and effects are used. This is so that these built-in menus which are universal across Android applications provide a continuous experience for the user. Here we examine the colors and dimensions prescribed and also examine how to provide the subsequent images as system resources in such a way as to cater for a variety of screen densities. Getting ready The little application we put together in the last recipe makes a good starting point for this one. Most of the information here is to do with design of the icons, so you may want to have a graphics editor such as GIMP or PhotoShop open, or you may want to refer back here later for the exact dimensions and palettes. How to do it... Open the res/menu/my_menu.xml file and add the android:icon elements seen here to each item: <?xml version="1.0" encoding="utf-8"?> <menu > <item android_id="@+id/item_one" android_icon="@drawable/my_menu_icon" android_title="first item" /> <item android_id="@+id/item_two" android_icon="@drawable/my_menu_icon" android_title="second item" /> </menu> With your graphics editor, create a new transparent PNG file, precisely 48 by 48 pixels in dimension. Ensuring that there is at least a 6 pixel border all the way around, produce your icon as a simple two-dimensional flat shape. Something like this: Fill the shape with a grayscale gradient that ranges from 47% to 64% (white) with the lighter end at the top. Provide a black inner shadow with the following settings: 20% opaque 90° angle (top to bottom) 2 pixel width 2 pixel distance Next, add an inner bevel with: Depth of 1% 90° altitude 70% opaque, white highlight 25% opaque, black shadow Now give the graphic a white outer glow with: 55% opacity 3 pixel size 10% spread Make two copies of our graphic, one resized to 36 by 36 pixels and one 72 by 72 pixels. Save the largest file in the res/drawable-hdpi as my_menu_icon.png. Save the 48 by 48 pixel file with the same name in the drawable-mdpi folder and the smallest image in drawable-ldpi. To see the full effect of these three files in action you will need to run the software on handsets with different screen resolutions or construct emulators to that purpose. How it works... As already mentioned, Android currently insists that menu icons conform to their guidelines and most of the terms used here should be familiar to anyone who has designed an icon before. The designated drawable folders allow us to provide the best possible graphics for a wide variety of screen densities. Android will automatically select the most appropriate graphic for a handset or tablet so that we can refer to our icons generically with @drawable/. It is only ever necessary to provide icons for the first five menu items as the Icon Menu is the only type to allow icons.  
Read more
  • 0
  • 0
  • 4310

article-image-haxe-2-using-templates
Packt
25 Jul 2011
10 min read
Save for later

haXe 2: Using Templates

Packt
25 Jul 2011
10 min read
  haXe 2 Beginner's Guide Develop exciting applications with this multi-platform programming language Introduction to the haxe.Template class As developers our job is to create programs that allow the manipulation of data. That's the basis of our job, but beyond this part of the job, we must also be able to present that data to the user. Programs that don't have a user interface exist, but since you are reading this article about haXe, there is a greater chance that you are mostly interested in web applications, and almost all web applications have a User Interface of some kind. However, these can also be used to create XML documents for example. The haXe library comes with the haxe.Template class. This class allows for basic, yet quite powerful, templating: as we will see, it is not only possible to pass some data to it, but also possible to call some code from a template. Templates are particularly useful when you have to present data—in fact, you can, for example, define a template to display data about a user and then iterate over a list of users displaying this template for each one. We will see how this is possible during this article and we will see what else you can do with templates. We will also see that it is possible to change what is displayed depending on the data and also that it is easy to do some quite common things such as having a different style for one row out of two in a table. The haxe.Template is really easy to use—you just have to create an instance of it passing it a String that contains your template's code as a parameter. Then it is as easy as calling the execute method and giving it some data to display. Let's see a simple example: class TestTemplate { public static function main(): Void { var myTemplate = new haxe.Template("Hi. ::user::"); neko.Lib.println(myTemplate.execute({user : "Benjamin"})); } } This simple code will output "Hi. Benjamin". This is because we have passed an anonymous object as a context with a "user" property that has "Benjamin" as value. Obviously, you can pass objects with several properties. Moreover, as we will see it is even possible to pass complex structures and use them. In addition, we certainly won't be hard coding our templates into our haXe code. Most of the time, you will want to load them from a resource compiled into your executable by calling haxe.Resource.getString or by directly loading them from the filesystem or from a database. Printing a value As we've seen in the preceding sample, we have to surround an expression with :: in order to print its value. Expressions can be of several forms:     Form Explanation ::variableName:: The value of the variable. ::(123):: The integer 123. Note that only integers are allowed. ::e1 operator e2:: Applies the operator to e1 and e2 and returns the resulting value. The syntax doesn't manage operator precedence, so you should wrap expressions inside parenthesis. ::e.field:: Accesses the field and returns the value. Be warned that this doesn't work with properties' getters and setters as these properties are a compile-time only feature. Branching The syntax offers the if, else, and elseif: class TestTemplate { public static function main(): Void { var templateCode = "::if (sex==0):: Male ::elseif (sex==1):: Female ::else:: Unknown ::end::"; var myTemplate = new haxe.Template(templateCode); neko.Lib.print(myTemplate.execute({user : "Benjamin", sex:0})); } } Here the output will be Male. But if the sex property of the context was set to 1 it would print Female, if it is something else, it will print "Unknown". Note that our keywords are surrounded by :: (so the interpreter won't think that it is just some raw-text to be printed). Also note that the "end" keyword has been introduced since we do not use braces. Using lists, arrays, and other iterables The template engine allows one to iterate over an iterable and repeat a part of the template for each object in the iterable. This is done using the ::foreach:: keyword. When iterating, the context will be modified and will become the object that is actually selected in the iterable. It is also possible to access this object (indeed, the context's value) by using the __current__ variable. Let's see an example: class Main { public static function main() { //Let's create two departments: var itDep = new Department("Information Technologies Dept."); var financeDep = new Department("Finance Dept."); //Create some users and add them to their department var it1 = new Person(); it1.lastName = "Par"; it1.firstName = "John"; it1.age = 22; var it2 = new Person(); it2.lastName = "Bear"; it2.firstName = "Caroline"; it2.age = 40; itDep.workers.add(it1); itDep.workers.add(it2); var fin1 = new Person(); fin1.lastName = "Ha"; fin1.firstName = "Trevis"; fin1.age = 43; var fin2 = new Person(); fin2.lastName = "Camille"; fin2.firstName = "Unprobable"; fin2.age = 70; financeDep.workers.add(fin1); financeDep.workers.add(fin2); //Put our departements inside a List: var depts = new List<Department>(); depts.add(itDep); depts.add(financeDep); //Load our template from Resource: var templateCode = haxe.Resource.getString("DeptsList"); //Execute it var template = new haxe.Template(templateCode); neko.Lib.print(template.execute({depts: depts})); } } class Person { public var lastName : String; public var firstName : String; public var age : Int; public function new() { } } class Department { public var name : String; public var workers : List<Person>; public function new(name : String) { workers = new List<Person>(); this.name = name; } } In this part of the code we are simply creating two departments, some persons, and adding those persons into those departments. Now, we want to display the list of departments and all of the employees that work in them. So, let's write a simple template (you can save this file as DeptsList.template): <html> <head> <title>Workers</title> </head> <body> ::foreach depts:: <h1>::name::</h1> <table> ::foreach workers:: <tr> <td>::firstName::</td> <td>::lastName::</td> <td>::if (age < 35)::Junior::elseif (58): :Senior::else::Retired::end::</td> </tr> ::end:: </table> ::end:: </body> </html> When compiling your code you should add the following directive: -resource DeptsList.template@DeptsList The following is the output you will get: <html> <head> <title>Workers</title> </head> <body> <h1>Information Technologies Dept.</h1> <table> <tr> <td>John</td> <td>Par</td> <td>Junior</td> </tr> <tr> <td>Caroline</td> <td>Bear</td> <td>F</td> </tr> </table> <h1>Finance Dept.</h1> <table> <tr> <td>Trevis</td> <td>Ha</td> <td>Senior</td> </tr> <tr> <td>Unprobable</td> <td>Camille</td> <td>Retired</td> </tr> </table> </body> </html> As you can see, this is indeed pretty simple once you have your data structure in place. Time for action – Executing code from a template Even though templates can't contain haXe code, they can make calls to so-called "template macros". Macros are defined by the developer and, just like data they are passed to the template.execute function. In fact, they are passed exactly in the same way, but as the second parameter. Calling them is quite easy, instead of surrounding them with :: we will simply prefix them with $$, we can also pass them as parameters inside parenthesis. So, let's take our preceding sample and add a macro to display the number of workers in a department. First, let's add the function to our Main class: public static function displayNumberOfWorkers(resolve : String->Dynamic, department : Department) { return department.workers.length + " workers"; } Note that the first argument that the macro will receive is a function that takes a String and returns a Dynamic. This function will allow you to retrieve the value of an expression in the context from which the macro has been called. Then, other parameters are simply the parameters that the template passes to the macro. So, let's add a call to our macro: <html> <head> </head> <body> ::foreach depts:: <h1>::name:: ($$displayNumberOfWorkers(::__current__::))</h1> <table> ::foreach workers:: <tr> <td>::firstName::</td> <td>::lastName::</td> <td>::if (sex==0)::M::elseif (sex==1)::F::else::?::end::</td> </tr> ::end:: </table> ::end:: </body> </html> As you can see, we will pass the current department to the macro when calling it to display the number of workers. So, here is what you get: <html> <head> </head> <body> <h1>Information Technologies Dept. (2 workers)</h1> <table> <tr> <td>John</td> <td>Par</td> <td>M</td> </tr> <tr> <td>Caroline</td> <td>Bear</td> <td>F</td> </tr> </table> <h1>Finance Dept. (2 workers)</h1> <table> <tr> <td>Trevis</td> <td>Ha</td> <td>M</td> </tr> <tr> <td>Unprobable</td> <td>Camille</td> <td>?</td> </tr> </table> </body> </html>   What just happened?   We have written the displayNumberOfWorkers macro and added a call to it in the template. As a result, we've been able to display the number of workers in a department. Integrating subtemplates Sub-templates do not exist as such in the templating system. The fact is that you can include sub-templates into a main template, which is not a rare process. Some frameworks, not only in haXe, have even made this standard behavior. So, there are two ways of doing this: Execute the sub-template, store its return value, and pass it as a property to the main template when executing it. Create a macro to execute the sub-template and return its value. This way you just have to call the macro whenever you want to include your sub-template in your main template. Creating a blog's front page In this section, we are going to create a front page for a blog by using the haxe.Template class. We will also use the SPOD system to retrieve posts from the database.
Read more
  • 0
  • 0
  • 2305

article-image-oracle-webcenter-11g-ps3-working-navigation-models-and-page-hierarchies
Packt
25 Jul 2011
3 min read
Save for later

Oracle WebCenter 11g PS3: Working with Navigation Models and Page Hierarchies

Packt
25 Jul 2011
3 min read
  Oracle WebCenter 11g PS3 Administration Cookbook Over 100 advanced recipes to secure, support, manage, and administer Oracle WebCenter 11g with this book and eBook         Read more about this book       (For more resources on this subject, see here.) Creating a navigation model at runtime Lots of administrators will not have access to JDeveloper, but they will need to manage navigation models. In WebCenter, you can easily create and manage navigation models at runtime. In this recipe, we will show how you can add navigation models at runtime. Getting ready For this recipe, you need a WebCenter Portal application. How to do it... Run your portal application. Log in as an administrator. Go to the administration page. Select Navigations from the Resource tab. Press the Create button. Specify a name, for example, hr. Specify a description, for example, Navigation model for HR users. Leave copy from empty. In this list, you can select an existing navigation model so the newly created model will copy the content from the selected model. Press the Create button: The navigation model is now created and you can add components to it. How it works... When you add a navigation model at runtime, an XML file will be generated in the background. The navigation model will be stored in the MDS. You can request the path to the actual xml file by selecting Edit properties from the Edit menu when you select a navigation model. In the properties window, you will find a field called Metadata file. This is the complete directory to the actual XML file. There's more... Even at runtime, you can modify the actual XML representation of the navigation model. This allows you to be completely flexible. Not everything is possible at runtime, but when you know what XML to add, you can do so by modifying the XML of the navigation model. This can be done by selecting Edit Source from the Edit menu. This way you will get the same XML representation of a navigation model as in JDevleoper. Adding a folder to a navigation model A folder is the simplest resource you can add to your navigation model. It does not link to a specific resource. A folder is only intended to organize your navigation model in a logical way. In this recipe, we will add a folder for the HR resources. Getting ready We will add the folder to the default navigation model so you only need the default WebCenter Portal application for this recipe. How to do it... Open default-navigation-mode.xml from Web Content/oracle/Webcenter/portalapp/navigations. Press the Add button and select Folder from the context menu. Specify an id for the folder. The id should be unique for each resource over the navigation model. Specify an expression language value for the Visible attribute. How it works... Adding a folder to a navigation model will add a folder tag to the XML with the metadata specified: <folder visible="#{true}" id="hr"> <attributes> <attribute isKey="false" value="folder" attributeId="Title"/> </attributes> <contents/> </folder> The folder tag has a contents tag as a child. This means that when you add a resource to a folder, these will be added as a child to the contents tag. There's more... You can also add a folder at runtime to a navigation model. This is done by selecting your navigation model and selecting Edit from the Edit menu. From the Add menu, you can select Folder. You are able to add the id, description, visible attribute and iconUrl.
Read more
  • 0
  • 0
  • 1540
article-image-extending-mootools
Packt
25 Jul 2011
8 min read
Save for later

Extending MooTools

Packt
25 Jul 2011
8 min read
  MooTools 1.3 Cookbook Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page         Read more about this book       (For more resources on this topic, see here.) The reader can benefit from the previous article on MooTools: Extending and Implementing Elements.   Making a Corvette out of a car-extending the base class The "base class" is a function, a method, that allows extension. Just what does extending a class entail? Buckle up and let us take a drive. Getting ready Just to show the output of our work, create a DIV that will be our canvas. <div id="mycanvas"></div> How to do it... Creating a class from the base class is as rudimentary as this: var Car = new Class();. That is not very instructive, so at the least, we add the constructor method to call at the time of instantiation: initialize. <script type="text/javascript"> var Car = new Class({ initialize: function(owner) { this.owner = owner; }}); The constructor method takes the form of a property named initialize and must be a function; however, it does not have to be the first property declared in the class. How it works... So far in our recipe, we have created an instance of the base class and assigned it to the variable Car. We like things to be sporty, of course. Let's mutate the Car into a Corvette using Extends and passing it the name of the Class to make a copy of and extend into a new class. var Corvette = new Class({ Extends: Car, mfg: 'Chevrolet', model: 'Corvette', setColor: function(color) { this.color = color; }}); Our Corvette is ready for purchase. An instantiation of the extended class will provide some new owner happiness for 5 years or 50,000 miles, whichever comes first. Make the author's red, please. var little_red = new Corvette('Jay Johnston'); little_red.setColor('red'); $('mycanvas').set('text',little_red.owner+"'s little "+little_red.color+' '+little_red.model+' made by '+little_red.mfg); </script> There's more... This entire example will work identically if Corvette Implements rather than Extends Car. Whether to Extend or to Implement Extending a class changes the prototype, creating a copy in which the this.parent property allows for the overridden parent class method to be referenced within the extended class's current method. To derive a mutation that takes class properties from multiple classes, we use Implements. Be sure to place the Extends or Implements property first before all other methods and properties. And if both extending and implementing, the Implements property follows the Extends property. See also See how Moo can muster so much class: http://mootools.net/docs/core/Class/Class#Class.   Giving a Corvette a supercharger-Implements versus Extends Be ready to watch for several things in this recipe. Firstly, note how the extended corvette methods can use this.parent. Secondly, note how the implemented corvette, the ZR1, can implement multiple classes. Getting ready Create a canvas to display some output. <h1>Speed Indexes:</h1><div id="mycanvas"></div> How to do it... Here we create a class to represent a car. This car does not have an engine until it goes through further steps of manufacturing, so if we ask what its speed is, the output is zero. Next, we create a class to represent a sporty engine, which has an arbitrary speed index of 10. // create two classes from the base Class var Car = new Class({ showSpeed: function() { return 0; } }); var SportyEngine = new Class({ speed: 10 }); Now we get to work. First, we begin by manufacturing corvettes, a process which is the extension of Car, they are faster than an empty chassis, of course, so we have them report their speed as an index rating one more than the parent class. // Extend one, Implement the other var Corvette = new Class({ Extends: Car, showSpeed: function() { // this.parent calls the overridden class return this.parent()+1; } }); Secondly, we implement both Car and SportyEngine simultaneously as ZR1. We cannot use this.parent so we return the speed if asked. Of course, the ZR1 would not have a speed if only a mutation of Car, but since it is also a mutation of SportyEngine it has the speed index of that class. var ZR1 = new Class({ // multiple classes may be implemented Implements: [Car, SportyEngine], // yep showSpeed: function() { // this.parent is not available //return this.parent()+1; // nope return this.speed; }}); How it works... When an instantiation of Corvette is created and its showSpeed() method called, it reports the speed of the parent class, Car, adding 1 to it. This is thanks to the magic Extends provides via this.parent(). var corvette = new Corvette(); var zr1 = new ZR1(); $('mycanvas').set('html', '<table>'+ '<tr><th>Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>ZR1:</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); And so, the output of this would be: Corvette: 1ZR1: 10 An instantiation of ZR1 has the properties of all classes passed to Implements. When showSpeed() is called, the value conjured by this.speed comes from the property defined within SportyEngine.   Upgrading some Corvettes—Extends versus Implements Now that we have reviewed some of the reasons to extend versus implement, we are ready to examine more closely how inheritance within Extends can be useful in our scripting. Getting ready Create a display area for the output of our manufacturing plant. <h1>Speeds Before</h1><div id="before"></div><h1>Speeds After</h1><div id="after"></div> How to do it... Create two classes, one that represents all car chassis with no engine and one that represents a fast engine that can be ordered as an upgrade. This section is identical to the last recipe; if necessary, review once more before continuing as the jist will be to alter our instantiations to display how inheritance patterns affect them. // create two classes from the base Class var Car = new Class({ showSpeed: function() { return 0; } }); var SportyEngine = new Class({ speed: 10 }); // Extend one, Implement the other var Corvette = new Class({ Extends: Car, speed: 1, showSpeed: function() { // this.parent calls the overridden class return this.parent()+1; } }); var ZR1 = new Class({ // multiple classes may be implemented Implements: [Car, SportyEngine], // yep showSpeed: function() { // this.parent is not available //return this.parent()+1; // nope return this.speed; } }); Note that the output before mutation is identical to the end of the previous recipe. var corvette = new Corvette(); var zr1 = new ZR1(); $('before').set('html', '<table>'+ '<tr><th>Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>ZR1</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); Here is what happens when the manufacturing plant decides to start putting engines in the base car chassis. That gives them a speed, where they did not have one previously. Mutate the base class by having it return an index of five rather than zero. // the mfg changes base Car speed to be +5 fasterCar = Car.implement({ showSpeed: function() { return 5; }});// but SportyEngine doesn't use the parent method$('after').set('html', '<table>'+ '<tr><th>New Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>New ZR1</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); How it works... The zr1 instantiation did not mutate. The corvette instantiation did. Since zr1 used implements, there is no inheritance that lets it call the parent method. In our example, this makes perfect sense. The base chassis comes with an engine rated with a speed of five. The ZR1 model, during manufacturing/instantiation is given a completely different engine/a completely different property, so any change/recall of the original chassis would not be applicable to that model. For the naysayer, the next recipe shows how to effect a manufacturer recall that will alter all Corvettes, even the ZR1s. There's more... There is an interesting syntax used to mutate the new version of Car, Class.implement(). That same syntax is not available to extend elements. See also Here is a link to the MooTool documentation for Class.implement(): http://mootools.net/docs/core/Class/Class#Class:implement.  
Read more
  • 0
  • 0
  • 1408

article-image-mootools-extending-and-implementing-elements
Packt
25 Jul 2011
7 min read
Save for later

MooTools: Extending and Implementing Elements

Packt
25 Jul 2011
7 min read
  MooTools 1.3 Cookbook Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page The reader can benefit from the previous article on Extending MooTools. Extending elements—preventing multiple form submissions Imagine a scenario where click-happy visitors may undo normalcy by double-clicking the submit button, or perhaps an otherwise normal albeit impatient user might click it a second time. Submit buttons frequently need to be disabled or removed using client-side code for just such a reason. Users that double-click everything It is not entirely known where double-clicking users originated from. Some believe that single-clicking-users needed to be able to double-click to survive in the wild. They therefore began to grow gills and double-click links, buttons, and menu items. Others maintain that there was a sudden, large explosion in the vapors of nothingness that resulted in hordes of users that could not fathom the ability of a link, button, or menu item that could be opened with just a single click. Either way, they are out there, and they mostly use Internet Explorer and are quickly identifiable by how they type valid URLs into search bars and then swear the desired website is no longer on the Inter-nets. How to do it... Extending elements uses the same syntax as extending classes. Add a method that can be called when appropriate. Our example, the following code, could be used in a library that is associated with every page so that no submit button could ever again be clicked twice, at least, without first removing the attribute that has it disabled: Element.implement({ better_submit_buttons: function() { if ( this.get('tag')=='input' && this.getProperty('type')=='submit') { this.addEvent('click', function(e) { this.set({ 'disabled':'disabled', 'value':'Form Submitted!' }); }); } } }); window.addEvent('load',function() { $$('input[type=submit]').better_submit_buttons(); }); How it works... The MooTools class Element extends DOM elements referenced by the single-dollar selector, the double-dollars selector, and the document.id selector. In the onLoad event, $$('input[type=submit]').submit_only_once(); all INPUT elements that have a type equal to submit are extended with the Element class methods and properties. Of course, before that infusion of Moo-goodness takes place, we have already implemented a new method that prevents those elements from being clicked twice by adding the property that disables the element. There's more... In our example, we disable the submit button permanently and return false upon submission. The only way to get the submit button live again is to click the Try again button that calls the page again. Note that reloading the page via refresh in some browsers may not clear the disabled attribute; however, calling the page again from the URL or by clicking a link will. On pages that submit a form to a second page for processing, the semi-permanently disabled button is desirable outright. If our form is processed via Ajax, then we can use the Ajax status events to manually remove the disabled property and reset the value of the button. See also Read the document on the MooTools Request class that shows the various statuses that could be used in conjunction with this extended element: http://mootools.net/docs/core/Request/Request.   Extending elements-prompt for confirmation on submit Launching off the last extension, the forms on our site may also need to ask for confirmation. It is not unthinkable that a slip of the carriage return could accidentally submit a form before a user is ready. It certainly happens to all of us occasionally and perhaps to some of us regularly. How to do it... Mutate the HTML DOM FORM elements to act upon the onSubmit event and prompt whether to continue with the submission. Element.implement({ polite_forms: function() { if (this.get('tag')=='form') { this.addEvent('submit',function(e) { if(!confirm('Okay to submit form?')) { e.stop(); } }); } } }); How it works... The polite_forms() method is added to all HTML DOM elements, but the execution is restricted to elements whose tag is form, if (this.get('tag')=='form') {...}. The onSubmit event of the form is bound to a function that prompts users via the raw JavaScript confirm() dialogue that either returns true for a positive response or false otherwise. If false, then we prevent the event from continuing by calling the MooTools-implemented Event.stop(). There's more... In order to mix the submit button enhancement with the polite form enhancement only a few small changes to the syntax are necessary. To stop our submit button from showing in process... if the form submission is canceled by the polite form request, we create a proprietary reset event that can be called via Element.fireEvent() and chained to the collection of INPUT children that match our double-dollar selector. // extend all elements with the method polite forms Element.implement({ better_submit_buttons: function() { if (this.get('tag')=='input'&&this.getProperty('type')=='submit') { this.addEvents({ 'click':function(e) { this.set({'disabled':'disabled','value':'in process...'}); }, 'reset':function() { this.set({'disabled':false,'value':'Submit!'}); } }); } }, polite_forms: function() { if (this.get('tag')=='form') { this.addEvent('submit',function(e) { if(!confirm('Okay to submit form?')) { e.stop(); this.getChildren('input[type=submit]').fireEvent('reset'); } }); } } }); // enhance the forms window.addEvent('load',function() { $$('input[type=submit]').better_submit_buttons(); $$('form').polite_forms(); });   Extending typeOf, fixing undefined var testing We could not properly return the type of an undeclared variable. This oddity has its roots in the fact that undefined, undeclared variables cannot be dereferenced during a function call. In short, undeclared variables can not be used as arguments to a function. Getting ready Get ready to see how we can still extend MooTools' typeOf function by passing a missing variable using the global scope: // will throw a ReferenceError myfunction(oops_var); // will not throw a ReferenceError myfunction(window.oops_var); How to do it... Extend the typeOf function with a new method and call that rather than the parent method. // it is possible to extend functions with new methods typeOf.extend('defined',function(item) { if (typeof(item)=='undefined') return 'undefined'; else return typeOf(item); }); //var oops_var; // commented out "on purpose" function report_typeOf(ismoo) { if (ismoo==0) { document.write('oops_var1 is: '+typeof(oops_var)+'<br/>'); } else { // concat parent to avoid error from derefrencing an undeclared var document.write('oops_var2 is: '+typeOf.defined( window.oops_var)+'<br/>'); } } The output from calling typeof() and typeOf.defined() is identical for an undefined, undeclared variable passed via the global scope to avoid a reference error. <h2>without moo:</h2> <script type="text/javascript"> report_typeOf(0); </script> <h2><strong>with</strong> moo:</h2> <script type="text/javascript"> report_typeOf(1); </script> The output is: without moo: oops_var1 is: undefined with moo: oops_var2 is: undefined How it works... The prototype for the typeOf function object has been extended with a new method. The original method is still applied when the function is executed. However, we are now able to call the property defined, which is itself a function that can still reference and call the original function. There's more... For those that are not satisfied at the new turn of syntax, the proxy pattern should suffice to help keep us using a much similar syntax. // proxying in raw javascript is cleaner in this case var oldTypeOf = typeOf; var typeOf = function(item) { if (typeof(item)=='undefined') return 'undefined'; else return oldTypeOf(item); }; The old typeOf function has been renamed using the proxy pattern but is still available. Meanwhile, all calls to typeOf are now handled by the new version. See also The Proxy Pattern The proxy pattern is one of many JavaScript design patterns. Here is one good link to follow for more information: http://www.summasolutions.net/blogposts/design-patterns-javascript-part-1. Undeclared and Undefined Variables It can be quite daunting to have to deal with multiple layers of development. When we are unable to work alone and be sure all our variables are declared properly, testing every one can really cause code bloat. Certainly, the best practice is to always declare variables. Read more about it at http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/.  
Read more
  • 0
  • 0
  • 2213
Modal Close icon
Modal Close icon