Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
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

7019 Articles
article-image-customization-using-adf-meta-data-services
Packt
15 Jun 2011
8 min read
Save for later

Customization using ADF Meta Data Services

Packt
15 Jun 2011
8 min read
Oracle ADF Enterprise Application Development—Made Simple Successfully plan, develop, test and deploy enterprise applications with Oracle ADF      Why customization? The reason ADF has customization features built-in is because Oracle Fusion Applications need them. Oracle Fusion Applications is a suite of programs capable of handling every aspect of a large organization—personnel, finance, project management, manufacturing, logistics, and much more. Because organizations are different, Oracle has to offer a way for each customer organization to fit Oracle Fusion Applications to their requirements. This customization functionality can also be very useful for organizations that do not use Oracle Fusion Applications. If you have two screens that work with the same data, but one of the screens must show more fields than the other, you can create one screen with all the fields and use customization to create another version of the same screen with fewer fields for other users. For example, the destination management application might have a data entry screen showing all details of a task to a dispatcher, but only the relevant details to an airport transfer guide: Companies such as DMC Solutions that produce software for sale realize additional benefit from the customization features in ADF. DMC Solu a base application, sell it to different customers and customize each in application to that customer without changing the base application. How does an ADF customization work? More and more Oracle products are using something called Meta Data Services to store metadata. Metadata is data that describes other pieces of information—where it came from, what it means, or how it is intended to be used. An image captured by a digital camera might include metadata about where and when the picture was taken, which camera settings were used, and so on. In the case of an ADF application, the metadata describes how the application is intended to be used. There are three kinds of customizations in ADF: Seeded customizations:They are customizations defined in advance (before the user runs the application) by customization developers. User customizations(sometimes called personalizations): They are changes to aspects of the user interface by application end users. The ADF framework offers a few user customization features, but you need additional software such as Oracle WebCenter for most user customizations. User customizations are outside the scope of this article. Design time at runtime:They are advanced customization of the application by application administrators and/or properly authorized end users. This requires that application developers have prepared the possible customizations as part of application development—it is complicated to program using only ADF, but Oracle WebCenter provides advanced components that make this easier. This is outside the scope of this article. Your customization metadata is stored in either files or a database repository. If you are only planning to use seeded customizations, a file-based repository is fine. However, if you plan to allow user customizations or design time at runtime, you should set up your production server to store customizations in a metadata database. Refer to the Fusion Middleware Administrator's Guide for information about setting up a metadata database. Applying the customization layers When an ADF application is customized, the ADF framework applies one or more customization layers on top of the base application. Each layer has a value, and customizations are assigned to a specific customization layer and value. The concept of multiple layers makes it possible to apply, for example: Industry customization (customizing the application for example, the travel industry: industry=travel) Organization customization (customizing the application for a specific travel company: org=xyztravel) Site customization (customizing the application for the Berlin office) Role-based customization (customizing the application for casual, normal, and advanced users) The XDM application that DMC Solution is building could be customized in one way for ABC Travel and in another way for XYZ Travel, and XYZ Travel might decide to further customize the application for different types of users: You can have as many layers as you need—Oracle Fusion Applications is reported to use 12 layers, but your applications are not likely to be that complex. For each customization layer, the developer of the base application must provide a customization class that will be executed at runtime, returning a value for each customization layer. The ADF framework will then apply the customizations that the customization developer has specified for that layer/value combination. This means that the same application can look in many different ways, depending on the values returned by the customization classes and the customizations registered:     Org layer value Role layer value Result qrstravel any Base application, because there are no customizations defined for QRS Travel abctravel any The application customized for ABC Travel, because there are no role layer customizations for ABC Travel, the value of the role layer does not change the application xyztravel normal The application customized for XYZ Travel and further customized for normal users in XYZ Travel xyztravel superuser The application customized for XYZ Travel and further customized for super users in XYZ Travel Making an application customizable To make an application customizable, you need to do three things: Develop a customization class for each layer of customization. Enable seeded customization in the application. Link the customization class to the application. The customization developer, who will be developing the customizations, will additionally have to set up JDeveloper correctly so that all customization levels can be accessed. This setup is described later in the article. Developing the customization classes For each layer of customization, you need to develop a customization class with a specific format—technically, it has to extend the Oracle-supplied abstract class oracle.mds.cust.CustomizationClass. A customization class has a name (returned by the getName() method) and a value (returned by the getValue() method). At runtime, the ADF framework will execute the customization classes for all layers to determine the customization value at each level. Additionally, the customization class has to return a short unique prefix to use for all customized items, and a cache hint telling ADF if this is a static or dynamic customization. Building the classes Your customization classes should go in your Common Code workspace. A customization class is a normal Java class, that is, it is created with File | New | General | Java Class. In the Create Java Class dialog, give your class a name (OrgLayerCC) and place it into a customization package (for example, com.dmcsol. xdm.customization). Choose to extend oracle.mds.cust.CustomizationClass and check the Implement Abstract Methods checkbox: Create a similar class called RoleLayerCC. Implementing the methods Because you asked the JDeveloper to implement the abstract methods, your classes already contain three methods: getCacheHint() getName() getValue(RestrictedSession, MetadataObject) The getCacheHint() method must return an oracle.mds.cust.CacheHint constant that tells ADF if the value of this layer is static (common for all users) or dynamic (depending on the user). The normal values here are ALL_USERS for static customizations or MULTI_USER for customizations that apply to multiple users. In the XDM application, you will use: ALL_USERS for OrgLevelCC, because this customization layer will apply to all users in the organization MULTI_USER for RoleLevelCC, because the role-based customization will apply to multiple users, but not necessarily to all Refer to the chapter on customization with MDS in Fusion Developer's Guide for Oracle Application Development Framework for information on other possible values. The getName() method simply returns the the name of the customization layer. The getValue() method must return an array of String objects. It will normally make most sense to return just one value—the application is running for exactly one organization, you are either a normal user or a super user. For advanced scenarios, it is possible to return multiple values, in such a case multiple customizations will be applied at the same layer. Each customization that a customization developer defines will be tied to a specific layer and value—there might be a customization that happens when org has the value xyztravel. For the OrgLayerCC class, the value is static and is defined when DMC Solutions installs the application for XYZ Travel—for example, in a property file. For the RoleLayerCC class , the value is dynamic, depending on the current user, and can be retrieved from the ADF security context. The OrgLayerCC class could look like the following: package com.dmcsol.xdm.customization; import ... public class RoleLayerCC extends CustomizationClass { public CacheHint getCacheHint() { return CacheHint.MULTI_USER; } public String getName() { return "role"; } public String[] getValue(RestrictedSession restrictedSession, MetadataObject metadataObject) { String[] roleValue = new String[1]; SecurityContext sec = ADFContext.getCurrent(). getSecurityContext(); if (sec.isUserInRole("superuser")) { roleValue[0] = "superuser"; } else { roleValue[0] = "normal"; } return roleValue; } } The GetCacheHint() method returns MULTI_USER because this is a dynamic customization—it will return different values for different users. The GetName() method simply returns the name of the layer. The GetValue() method uses oracle.adf.share.security.SecurityContext to look up if the user has the super user role and returns the value superuser or normal. Deploying the customization classes Because you place your customization class in the Common Code project, you need to deploy the Common Code project to an ADF library and have the build/ configuration manager copy it to your common library directory.
Read more
  • 0
  • 0
  • 3281

article-image-releasing-and-maintaining-application
Packt
25 Aug 2015
11 min read
Save for later

Releasing and Maintaining the Application

Packt
25 Aug 2015
11 min read
In this article by Andrey Kovalenko author of the book PhoneGap by Example we implemented several unit and integration tests with the Jasmine tool for our application. We used the headless browser PhantomJS, and we measured performance with Appium. All this is great and helps us automate the testing approach to find bugs in the early stages of application development. Once we finish creating our application and test it, we can think of delivering our application to other people. We can distribute the application in several different ways. Once we finish these tasks, we will be ready to do a full cycle of the application creation and distribution processes. We already know how to set up development environments to develop for iOS and Android. We will reuse these skills in this article as well to prepare our builds for distribution. This article read as a step-by-step tutorial for the setup of different tools. (For more resources related to this topic, see here.) We already know how to build our application using IDE (Xcode or Android Studio). However, now, we will explore how to build the application for different platforms using the PhoneGap Build service. PhoneGap Build helps us stay away from different SDKs. It works for us by compiling in the cloud. First of all, we should register on https://build.phonegap.com. It is pretty straightforward. Once we register, we can log in, and under the apps menu section, we will see something like this:   We entered a link to our git repository with source files or upload the zip archive with the same source code. However, there is a specific requirement for the structure of the folders for upload. We should take only the www directory of the Cordova/PhoneGap application, add config.xml inside it, and compress this folder. Let's look at this approach using an example of the Crazy Bubbles application. PhoneGap config.xml In the root folder of the game, we will place the following config.xml file: <?xml version="1.0" encoding="UTF-8" ?> <widget id = "com.cybind.crazybubbles" versionCode = "10" version = "1.0.0" > <name>Crazy Bubbles</name> <description> Nice PhoneGap game </description> <author href="https://build.phonegap.com" email="support@phonegap.com"> Andrew Kovalenko </author> <gap:plugin name="com.phonegap.plugin.statusbar" /> </widget> This configuration file specifies the main setup for the PhoneGap Build application. The setup is made up of these elements: widget is a root element of our XML file based on the W3C specification, with the following attributes: id: This is the application name in the reverse-domain style version: This is the version of the application in numbers format versionCode: This is optional and used only for Android name of the application description of the application name of the author with website link and e-mail List of plugins if required by the application We can use this XML file or enter the same information using a web interface. When we go to Settings | Configuration, we will see something like the following screenshot: PhoneGap plugins As you can see, we included one plugin in config.xml: <gap:plugin name="com.phonegap.plugin.statusbar" /> There are several attributes that the gap:plugin tag has. They are as follows: name: This is required, plugin ID in the reverse-domain format version: This is optional, plugin version source: This is optional, can be pgb, npm, or plugins.cordova.io. The default is pgb params: This is optional, configuration for plugin if needed We included the StatusBar plugin, which doesn't require JavaScript code. However, there are some other plugins that need JavaScript in the index.html file. So, we should not forget to add the code. Initial upload and build Once we finish the configuration steps and create a Zip archive of the www folder, we can upload it. Then, we will see the following screen:   Here, we can see generic information about the application, where we can enable remote debugging with Weinre. Weinre is a remote web inspector. It allows access to the DOM and JavaScript. Now, we can click on the Ready to build button, and it will trigger the build for us. Here, you can see that the iOS build has failed. Let's click on the application title and figure out what is going on. Once the application properties page loads, we will see the following screenshot: When we click on the Error button, we will see the reason why it failed:   So, we need to provide a signing key. Basically, you need a provisioning profile and certificate needed to build the application. We already downloaded the provisioning profile from the Apple Development portal, but we should export the certificate from the Keychain Access. We are going to open it, find our certificate in the list, and export it:   When we export it, we will be asked for the destination to store the .p12 file:   Add a password to protect the file:   Once we save the file, we can go back to the PhoneGap Build portal and create a signing key:   Just click on the No key selected button in the dropdown and upload the exported certificate and provisioning profile for the application. Once the upload is finished, the build will be triggered:   Now, we will get a successful result and can see all the build platforms:   Now, we can download the application for both iOS and Android and install it on the device. Alternatively, we can install the application by scanning the QR code on the application main page. We can do this with any mobile QR scanner application on our device. It will return a direct link for the build download for a specific platform. Once it is downloaded, we can install it and see it running on our device. Congratulations! We just successfully created the build with the PhoneGap Build service! Now, let's take a closer look at the versioning approach for the application. Beta release of the iOS application For the beta release of our application, we will use the TestFlight service from the Apple. As a developer, we need to be a member of the iOS Developer program. As a tester, we will need to install the application for beta testing and the TestFlight application from the App Store. After that, the tester can leave feedback about the application. First of all, let's go to https://itunesconnect.apple.com and login there. After that, we can go to the My Apps section and click on the plus sign in the top-left corner. We will get a popup with a request to enter some main information about the application. Let's add the information about our application so that it looks like this:   All the fields in the preceding screenshot are well known and do not require additional explanation. Once we click on the Create button, the application is created, and we can see the Versions tab of the application. Now, we need to build and upload our application. We can do this in two ways: Using Xcode Using Application Loader However, before submitting to beta testing, we need to generate a provisioning profile for distribution. Let's do it on the Developer portal. Generate a distribution provisioning profile Go to the Provisioning Profiles, and perform the following steps: Click on + to add a new provisioning profile and go to Distribution | App Store as presented in the following screenshot: Then, select the application ID. In my case, it is Travelly: After that, select the certificates to include in the provisioning profile. The certificate should be for distribution as well: Finally, generate the provisioning profile, set a name for the file, and download it: Now, we can build and upload our application to iTunes Connect. Upload to iTunes Connect with Xcode Let's open the Travelly application in Xcode. Go to cordova/platforms/ios and open Travelly.xcodeproj. After that, we have to select iOS Device to run our application. In this case, we will see the Archive option available. It would not be available if the emulator option is selected. Now, we can initiate archiving by going to Product | Archive:   Once the build is completed, we will see the list of archives:   Now, click on the Submit to App Store… button. It will ask us to select a development team if we have several teams:   At this stage, Xcode is looking for the provisioning profile we generated earlier. We would be notified if there is no distribution provisioning profile for our application. Once we click on Choose, we are redirected to the screen with binary and provisioning information:   When we click on the Submit button, Xcode starts to upload the application to iTunes Connect: Congratulations! We have successfully uploaded our build with Xcode: Upload to iTunes Connect with Application Loader Before the reviewing process of build upload with Application Loader, we need to install the tool first. Let's go to iTunes Connect | Resources and Help | App Preparation and Delivery and click on the Application Loader link. It will propose the installation file for download. We will download and install it. After that, we can review the upload process. Uploading with Application Loader is a little different than with XCode. We will follow the initial steps until we get the following screen:   In this case, on the screen, we will click on the Export button, where we can save the .ipa file. However, before that, we have to select the export method:   We are interested in distribution to the App Store, so we selected the first option. We need to save the generated file somewhere to the filesystem. Now, we will launch Application Loader and log in using our Apple Developer account:   After that, we will select Deliver Your App and pick the generated file:   In the following screenshot, we can see the application's generic information: name, version, and so on:   When we click on the Next button, we will trigger upload to iTunes Connect, which is successfully executed: During the process, the package will be uploaded to the iTunes Store, as shown here: Once the application is added, it will show you the following screenshot: Now, if we go to iTunes Connect | My Apps | Travelly | Prerelease | Builds, we will see our two uploaded builds:   As you can see, they are both inactive. We need to send our application to internal and external testers. Invite internal and external testers Let's work with version 0.0.2 of the application. First of all, we need to turn on the check box to the right of the TestFlight Beta Testing label. There are two types of testers we can invite: Internal testers are iTunes Connect users. It is possible to invite up to 25 internal testers. External testers are independent users who can install the application using the TestFlight mobile tool. To invite internal testers, let's go to the Internal Testers tab, add the e-mail of the desired tester, place the check mark, and click on the Invite button:   The user will receive an e-mail with the following content:   Users can click on the link and follow the instructions to install the application. To allow testing for external users, we will go to the External Testers tab. Before becoming available for external testing, the application should be reviewed. For the review, some generic information is needed. We need to add: Instructions for the testers on what to test Description of the application Feedback information Once this information is entered, we can click on the Next button and answer questions about cryptography usage in the application:   We do not use cryptography, so we select No and click on Submit. Now, our application is waiting for review approval:   Now, there is a button available to add external testers:   We can invite up to 1000 external testers. After the tester accepts the invite on their device, the invite will be linked to their current Apple ID. Once the application review is finished, it will become available for external testers. Summary In this article of the book, you learned how to release the PhoneGap application with the PhoneGap Build service. Also, we released the application through TestFlight for beta testing. Now, we will be able to develop different types of Cordova/PhoneGap applications, test them. I think it is pretty awesome, don't you? Resources for Article: Further resources on this subject: Geolocation – using PhoneGap features to improve an app's functionality, write once use everywhere[article] Getting Ready to Launch Your PhoneGap App in the Real World[article] Using Location Data with PhoneGap [article]
Read more
  • 0
  • 0
  • 3281

article-image-understanding-backbone
Packt
02 Sep 2013
12 min read
Save for later

Understanding Backbone

Packt
02 Sep 2013
12 min read
(For more resources related to this topic, see here.) Backbone.js is a lightweight JavaScript framework that is based on the Model-View-Controller (MVC) pattern and allows developers to create single-page web applications. With Backbone, it is possible to update a web page quickly using the REST approach with a minimal amount of data transferred between a client and a server. Backbone.js is becoming more popular day by day and is being used on a large scale for web applications and IT startups; some of them are as follows: Groupon Now!: The team decided that their first product would be AJAX-heavy but should still be linkable and shareable. Though they were completely new to Backbone, they found that its learning curve was incredibly quick, so they were able to deliver the working product in just two weeks. Foursquare: This used the Backbone.js library to create model classes for the entities in foursquare (for example, venues, check-ins, and users). They found that Backbone's model classes provide a simple and light-weight mechanism to capture an object's data and state, complete with the semantics of a classical inheritance. LinkedIn mobile: This used Backbone.js to create its next-generation HTML5 mobile web app. Backbone made it easy to keep the app modular, organized, and extensible, so it was possible to program the complexities of LinkedIn's user experience. Moreover, they are using the same code base in their mobile applications for iOS and Android platforms. WordPress.com: This is a SaaS version of Wordpress and uses Backbone.js models, collections, and views in its notification system, and is integrating Backbone.js into the Stats tab and into other features throughout the home page. Airbnb: This is a community marketplace for users to list, discover, and book unique spaces around the world. Its development team has used Backbone in many latest products. Recently, they rebuilt a mobile website with Backbone.js and Node.js tied together with a library named Rendr. You can visit the following links to get acquainted with other usage examples of Backbone.js: http://backbonejs.org/#examples Backbone.js was started by Jeremy Ashkenas from DocumentCloud in 2010 and is now being used and improved by lots of developers all over the world using Git, the distributed version control system. In this article, we are going to provide some practical examples of how to use Backbone.js, and we will structure a design for a program named Billing Application by following the MVC and Backbone pattern. Reading this article is especially useful if you are new to developing with Backbone.js. Designing an application with the MVC pattern MVC is a design pattern that is widely used in user-facing software, such as web applications. It is intended for splitting data and representing it in a way that makes it convenient for user interaction. To understand what it does, understand the following: Model: This contains data and provides business logic used to run the application View: This presents the model to the user Controller: This reacts to user input by updating the model and the view There could be some differences in the MVC implementation, but in general it conforms to the following scheme: Worldwide practice shows that the use of the MVC pattern provides various benefits to the developer: Following the separation of the concerned paradigm, which splits an application into independent parts, it is easier to modify or replace It achieves code reusability by rendering a model in different views without the need to implement model functionality in each view It requires less training and has a quicker startup time for the new developers within an organization To have a better understanding of the MVC pattern, we are going to design a Billing Application. We will refer to this design throughout the book when we are learning specific topics. Our Billing Application will allow users to generate invoices, manage them, and send them to clients. According to the worldwide practice, the invoice should contain a reference number, date, information about the buyer and seller, bank account details, a list of provided products or services, and an invoice sum. Let's have a look at the following screenshot to understand how an invoice appears: How to do it... Let's follow the ensuing steps to design an MVC structure for the Billing Application: Let's write down a list of functional requirements for this application. We assume that the end user may want to be able to do the following: Generate an invoice E-mail the invoice to the buyer Print the invoice See a list of existing invoices Manage invoices (create, read, update, and delete) Update an invoice status (draft, issued, paid, and canceled) View a yearly income graph and other reports To simplify the process of creating multiple invoices, the user may want to manage information about buyers and his personal details in the specific part of the application before he/she creates an invoice. So, our application should provide additional functionalities to the end user, such as the following: The ability to see a list of buyers and use it when generating an invoice The ability to manage buyers (create, read, update, and delete) The ability to see a list of bank accounts and use it when generating an invoice The ability to manage his/her own bank accounts (create, read, update, and delete) The ability to edit personal details and use them when generating an invoice Of course, we may want to have more functions, but this is enough for demonstrating how to design an application using the MVC pattern. Next, we architect an application using the MVC pattern. After we have defined the features of our application, we need to understand what is more related to the model (business logic) and what is more related to the view (presentation). Let's split the functionality into several parts. Then, we learn how to define models. Models present data and provide data-specific business logic. Models can be related to each other. In our case, they are as follows: InvoiceModel InvoiceItemModel BuyerModel SellerModel BankAccountModel Then, will define collections of models. Our application allows users to operate on a number of models, so they need to be organized into a special iterable object named Collection. We need the following collections: InvoiceCollection InvoiceItemCollection BuyerCollection BankAccountCollection Next, we define views. Views present a model or a collection to the application user. A single model or collection can be rendered to be used by multiple views. The views that we need in our application are as follows: EditInvoiceFormView InvoicePageView InvoiceListView PrintInvoicePageView EmailInvoiceFormView YearlyIncomeGraphView EditBuyerFormView BuyerPageView BuyerListView EditBankAccountFormView BankAccountPageView BankAccountListView EditSellerInfoFormView ViewSellectInfoPageView ConfirmationDialogView Finally, we define a controller. A controller allows users to interact with an application. In MVC, each view can have a different controller that is used to do following: Map a URL to a specific view Fetch models from a server Show and hide views Handle user input Defining business logic with models and collections Now, it is time to design business logic for the Billing Application using the MVC and OOP approaches. In this recipe, we are going to define an internal structure for our application with model and collection objects. Although a model represents a single object, a collection is a set of models that can be iterated, filtered, and sorted. Relations between models and collections in the Billing Application conform to the following scheme: How to do it... For each model, we are going to create two tables: one for properties and another for methods: We define BuyerModel properties. Name Type Required Unique id Integer Yes Yes name Text Yes   address Text Yes   phoneNumber Text No   Then, we define SellerModel properties. Name Type Required Unique id Integer Yes Yes name Text Yes   address Text Yes   phoneNumber Text No   taxDetails Text Yes   After this, we define BankAccountModel properties. Name Type Required Unique id Integer Yes Yes beneficiary Text Yes   beneficiaryAccount Text Yes   bank Text No   SWIFT Text Yes   specialInstructions Text No   We define InvoiceItemModel properties. Name Arguments Return Type Unique calculateAmount - Decimal   Next, we define InvoiceItemModel methods. We don't need to store the item amount in the model, because it always depends on the price and the quantity, so it can be calculated. Name Type Required Unique id Integer Yes Yes deliveryDate Date Yes   description Text Yes   price Decimal Yes   quantity Decimal Yes   Now, we define InvoiceModel properties. Name Type Required Unique id Integer Yes Yes referenceNumber Text Yes   date Date Yes   bankAccount Reference Yes   items Collection Yes   comments Text No   status Integer Yes   We define InvoiceModel methods. The invoice amount can easily be calculated as the sum of invoice item amounts. Name Arguments Return Type Unique calculateAmount   Decimal   Finally, we define collections. In our case, they are InvoiceCollection, InvoiceItemCollection, BuyerCollection, and BankAccountCollection. They are used to store models of an appropriate type and provide some methods to add/remove models to/from the collections. How it works... Models in Backbone.js are implemented by extending Backbone.Model, and collections are made by extending Backbone.Collection. To implement relations between models and collections, we can use special Backbone extensions. To learn more about object properties, methods, and OOP programming in JavaScript, you can refer to the following resource: https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript Modeling an application's behavior with views and a router Unlike traditional MVC frameworks, Backbone does not provide any distinct object that implements controller functionality. Instead, the controller is diffused between Backbone.Router and Backbone. View and the following is done: A router handles URL changes and delegates application flow to a view. Typically, the router fetches a model from the storage asynchronously. When the model is fetched, it triggers a view update. A view listens to DOM events and either updates a model or navigates an application through a router. The following diagram shows a typical workflow in a Backbone application: How to do it... Let's follow the ensuing steps to understand how to define basic views and a router in our application: First, we need to create wireframes for an application. Let's draw a couple of wireframes in this recipe: The Edit Invoice page allows users to select a buyer, to select the seller's bank account from the lists, to enter the invoice's date and a reference number, and to build a table of shipped products and services. The Preview Invoice page shows how the final invoice will be seen by a buyer. This display should render all the information we have entered in the Edit Invoice form. Buyer and seller information can be looked up in the application storage. The user has the option to either go back to the Edit display or save this invoice. Then, we will define view objects. According to the previous wireframes, we need to have two main views: EditInvoiceFormView and PreviewInvoicePageView. These views will operate with InvoiceModel; it refers to other objects, such as BankAccountModel and InvoiceItemCollection. Now, we will split views into subviews. For each item in the Products or Services table, we may want to recalculate the Amount field depending on what the user enters in the Price and Quantity fields. The first way to do this is to re-render the entire view when the user changes the value in the table; however, it is not an efficient way, and it takes a significant amount of computer power to do this. We don't need to re-render the entire view if we want to update a small part of it. It is better to split the big view into different, independent pieces, such as subviews, that are able to render only a specific part of the big view. In our case, we can have the following views: As we can see, EditInvoiceItemTableView and PreviewInvoiceItemTableView render InvoiceItemCollection with the help of the additional views EditInvoiceItemView and PreviewInvoiceItemView that render InvoiceItemModel. Such separation allows us to re-render an item inside a collection when it is changed. Finally, we will define URL paths that will be associated with a corresponding view. In our case, we can have several URLs to show different views, for example: /invoice/add /invoice/:id/edit /invoice/:id/preview Here, we assume that the Edit Invoice view can be used for either creating a new invoice or editing an existing one. In the router implementation, we can load this view and show it on specific URLs. How it works... The Backbone.View object can be extended to create our own view that will render model data. In a view, we can define handlers to user actions, such as data input and keyboard or mouse events. In the application, we can have a single Backbone.Router object that allows users to navigate through an application by changing the URL in the address bar of the browser. The router object contains a list of available URLs and callbacks. In a callback function, we can trigger the rendering of a specific view associated with a URL. If we want a user to be able to jump from one view to another, we may want him/her to either click on regular HTML links associated with a view or navigate to an application programmatically.
Read more
  • 0
  • 0
  • 3281

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

Joomla! VirtueMart: Product List Templates

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

article-image-building-queries
Packt
12 Dec 2013
10 min read
Save for later

Building Queries

Packt
12 Dec 2013
10 min read
(For more resources related to this topic, see here.) Understanding DQL DQL is the acronym of Doctrine Query Language. It's a domain-specific language that is very similar to SQL, but is not SQL. Instead of querying the database tables and rows, DQL is designed to query the object model's entities and mapped properties. DQL is inspired by and similar to HQL, the query language of Hibernate, a popular ORM for Java. For more details you can visit this website: http://www.hibernate.org/. Learn more about domain-specific languages at: http://en.wikipedia.org/wiki/Domain-specific_language To better understand what it means, let's run our first DQL query. Doctrine command-line tools are as genuine as a Swiss Army knife. They include a command called orm:run-dql that runs the DQL query and displays it's result. Use it to retrieve title and all the comments of the post with 1 as an identifier: php vendor/bin/doctrine.php orm:run-dql "SELECT p.title,c.bodyFROM BlogEntityPost p JOIN p.comments c WHERE p.id=1" It looks like a SQL query, but it's definitely not a SQL query. Examine the FROM and the JOIN clauses; they contain the following aspects: A fully qualified entity class name is used in the FROM clause as the root of the query All the Comment entities associated with the selected Post entities are joined, thanks to the presence of the comments property of the Post entity class in the JOIN clause As you can see, data from the entities associated with the main entity can be requested in an object-oriented way. Properties holding the associations (on the owning or the inverse side) can be used in the JOIN clause. Despite some limitations (especially in the field of subqueries), DQL is a powerful and flexible language to retrieve object graphs. Internally, Doctrine parses the DQL queries, generates and executes them through Database Abstraction Layer (DBAL) corresponding to the SQL queries, and hydrates the data structures with results. Until now, we only used Doctrine to retrieve the PHP objects. Doctrine is able to hydrate other types of data structures, especially arrays and basic types. It's also possible to write custom hydrators to populate any data structure. If you look closely at the return of the previous call of orm:run-dql, you'll see that it's an array, and not an object graph, that has been hydrated. As with all the topics covered in this book, more information about built-in hydration modes and custom hydrators is available in the Doctrine documentation on the following website: http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#hydration-modes Using the entity repositories Entity repositories are classes responsible for accessing and managing entities. Just like entities are related to the database rows, entity repositories are related to the database tables. All the DQL queries should be written in the entity repository related to the entity type they retrieve. It hides the ORM from other components of the application and makes it easier to re-use, refactor, and optimize the queries. Doctrine entity repositories are an implementation of the Table Data Gateway design pattern. For more details, visit the following website: http://martinfowler.com/eaaCatalog/tableDataGateway.html A base repository, available for every entity, provides useful methods for managing the entities in the following manner: find($id): It returns the entity with $id as an identifier or null It is used internally by the find() method of the Entity Managers. findAll(): It retrieves an array that contains all the entities in this repository findBy(['property1' => 'value', 'property2' => 1], ['property3' => 'DESC', 'property4' => 'ASC']): It retrieves an array that contains entities matching all the criteria passed in the first parameter and ordered by the second parameter findOneBy(['property1' => 'value', 'property2' => 1]): It is similar to findBy() but retrieves only the first entity or null if none of the entities match the criteria Entity repositories also provide shortcut methods that allow a single property to filter entities. They follow this pattern: findBy*() and findOneBy*(). For instance, calling findByTitle('My title') is equivalent to calling findBy(['title' => 'My title']). This feature uses the magical __call() PHP method. For more details visit the following website: http://php.net/manual/en/language.oop5.overloading.php#object.call In our blog app, we want to display comments in the detailed post view, but it is not necessary to fetch them from the list of posts. Eager loading through the fetch attribute is not a good choice for the list, and Lazy loading slows down the detailed view. A solution to this would be to create a custom repository with extra methods for executing our own queries. We will write a custom method that collates comments in the detailed view. Creating custom entity repositories Custom entity repositories are classes extending the base entity repository class provided by Doctrine. They are designed to receive custom methods that run the DQL queries. As usual, we will use the mapping information to tell Doctrine to use a custom repository class. This is the role of the repositoryClass attribute of the @Entity annotation. Kindly perform the following steps to create a custom entity repository: Reopen the Post.php file at the src/Blog/Entity/ location and add a repositoryClass attribute to the existing @Entity annotation like the following line of code: @Entity(repositoryClass="PostRepository") Doctrine command-line tools also provide an entity repository generator. Type the following command to use it: php vendor/bin/doctrine.php orm:generate:repositories src/ Open this new empty custom repository, which we just generated in the PostRepository.phpPostRepository.php file, at the src/Blog/Entity/ location. Add the following method for retrieving the posts and comments: /** * Finds a post with its comments * * @param int $id * @return Post */ public function findWithComments($id) { return $this ->createQueryBuilder('p') ->addSelect('c') ->leftJoin('p.comments', 'c') ->where('p.id = :id') ->orderBy('c.publicationDate', 'ASC') ->setParameter('id', $id) ->getQuery() ->getOneOrNullResult() ; } Our custom repository extends the default entity repository provided by Doctrine. The standard methods, described earlier in the article, are still available. Getting started with Query Builder QueryBuilder is an object designed to help build the DQL queries through a PHP API with a fluent interface. It allows us to retrieve the generated DQL queries through the getDql() method (useful for debugging) or directly use the Query object (provided by Doctrine). To increase performance, QueryBuilder caches the generated DQL queries and manages an internal state. The full API and states of the DQL query are documented on the following website: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html We will give an in-depth explanation of the findWithComments() method that we created in the PostRepository class. Firstly, a QueryBuilder instance is created with the createQueryBuilder() method inherited from the base entity repository. The QueryBuilder instance takes a string as a parameter. This string will be used as an alias of the main entity class. By default, all the fields of the main entity class are selected and no other clauses except SELECT and FROM are populated. The leftJoin() call creates a JOIN clause that retrieves comments associated with the posts. Its first argument is the property to join and its second is the alias; these will be used in the query for the joined entity class (here, the letter c will be used as an alias for the Comment class). Unless the SQL JOIN clause is used, the DQL query automatically fetches the entities associated with the main entity. There is no need for keywords like ON or USING. Doctrine automatically knows whether a join table or a foreign-key column must be used. The addSelect() call appends comment data to the SELECT clause. The alias of the entity class is used to retrieve all the fields (this is similar to the * operator in SQL). As in the first DQL query of this article, specific fields can be retrieved with the notation alias.propertyName. You guessed it, the call to the where() method sets the WHERE part of the query. Under the hood, Doctrine uses prepared SQL statements. They are more efficient than the standard SQL queries. The id parameter will be populated by the value set by the call to setParameter(). Thanks again to prepared statements and this setParameter() method, SQL Injection attacks are automatically avoided. SQL Injection Attacks are a way to execute malicious SQL queries using user inputs that have not escaped. Let's take the following example of a bad DQL query to check if a user has a specific role: $query = $entityManager->createQuery('SELECT ur FROMUserRole urWHERE ur.username = "' . $username . '" ANDur.role = "' . $role . '"'); $hasRole = count($query->getResult()); This DQL query will be translated into SQL by Doctrine. If someone types the following username: " OR "a"="a the SQL code contained in the string will be injected and the query will always return some results. The attacker has now gained access to a private area. The proper way should be to use the following code: $query = $entityManager->createQuery("SELECT ur FROMUserRole WHEREusername = :username and role = :role"); $query->setParameters([ 'username' => $username, 'role' => $role ]); $hasRole = count($query->getResult()); Thanks to prepared statements, special characters (like quotes) contained in the username are not dangerous, and this snippet will work as expected. The orderBy() call generates an ORDER BY clause that orders results as per the publication date of the comments, older first. Most SQL instructions also have an object-oriented equivalent in DQL. The most common join types can be made using DQL; they generally have the same name. The getQuery() call tells the Query Builder to generate the DQL query (if needed, it will get the query from its cache if possible), to instantiate a Doctrine Query object, and to populate it with the generated DQL query. This generated DQL query will be as follows: SELECT p, c FROM BlogEntityPost p LEFT JOIN p.comments cWHEREp.id = :id ORDER BY c.publicationDate ASC The Query object exposes another useful method for the purpose of debugging: getSql(). As its name implies, getSql() returns the SQL query corresponding to the DQL query, which Doctrine will run on DBMS. For our DQL query, the underlying SQL query is as follows: SELECT p0_.id AS id0, p0_.title AS title1, p0_.bodyAS body2,p0_.publicationDate AS publicationDate3,c1_.id AS id4, c1_.bodyAS body5, c1_.publicationDate AS publicationDate6,c1_.post_id ASpost_id7 FROM Post p0_ LEFT JOIN Commentc1_ ON p0_.id =c1_.post_id WHERE p0_.id= ? ORDER BY c1_.publicationDate ASC The getOneOrNullResult() method executes it, retrieves the first result, and returns it as a Post entity instance (this method returns null if no result is found). Like the QueryBuilder object, the Query object manages an internal state to generate the underlying SQL query only when necessary. Performance is something to be very careful about while using Doctrine. When set in production mode, ORM is able to cache the generated queries (DQL through the QueryBuilder objects, SQL through the Query objects) and results of the queries. ORM must be configured to use one of the blazing, fast, supported systems (APC, Memcache, XCache, or Redis) as shown on the following website: http://docs.doctrine-project.org/en/latest/reference/caching.html We still need to update the view layer to take care of our new findWithComments() method. Open the view-post.php file at the web/location, where you will find the following code snippet: $post = $entityManager->getRepository('BlogEntityPost')->find($_GET['id']); Replace the preceding line of code with the following code snippet: $post = $entityManager->getRepository('BlogEntityPost')->findWithComments($_GET['id']);
Read more
  • 0
  • 0
  • 3280

article-image-microsoft-enterprise-library-security-application-block
Packt
09 Dec 2010
5 min read
Save for later

Microsoft Enterprise Library: Security Application Block

Packt
09 Dec 2010
5 min read
Microsoft Enterprise Library 5.0 Develop Enterprise applications using reusable software components of Microsoft Enterprise Library 5.0 Develop Enterprise Applications using the Enterprise Library Application Blocks Set up the initial infrastructure configuration of the Application Blocks using the configuration editor A step-by-step tutorial to gradually configure each Application Block and implement its functions to develop the required Enterprise Application The first step is the process of validating an identity against a store (Active Directory, Database, and so on); this is commonly called as Authentication. The second step is the process of verifying whether the validated identity is allowed to perform certain actions; this is commonly known Authorization. These two security mechanisms take care of allowing only known identities to access the application and perform their respective actions. Although, with the advent of new tools and technologies, it is not difficult to safeguard the application, utilizing these authentication and authorization mechanisms and implementing security correctly across different types of applications, or across different layers and in a consistent manner is pretty challenging for developers. Also, while security is an important factor, it's of no use if the application's performance is dismal. So, a good design should also consider performance and cache the outcome of authentication and authorization for repeated use. The Security Application Block provides a very simple and consistent way to implement authorization and credential caching functionality in our applications. Authorization doesn't belong to one particular layer; it is a best practice to authorize user action not only in the UI layer but also in the business logic layer. As Enterprise Library application blocks are layer-agnostic, we can leverage the same authorization rules and expect the same outcome across different layers bringing consistency. Authorization of user actions can be performed using an Authorization Provider; the block provides Authorization Rule Provider or AzMan Authorization Provider; it also provides the flexibility of implementing a custom authorization provider. Caching of security credentials is provided by the SecurityCacheProvider by leveraging the Caching Application Block and a custom caching provider can also be implemented using extension points. Both Authorization and Security cache providers are configured in the configuration file; this allows changing of provider any time without re-compilation. The following are the key features of the Security block: The Security Application Block provides a simple and consistent API to implement authorization. It abstracts the application code from security providers through configuration. It provides the Authorization Rule Provider to store rules in a configuration file and Windows Authorization Manager (AzMan) Authorization Provider to authorize against Active Directory, XML file, or database. Flexibility to implement custom Authorization Providers. It provides token generation and caching of authenticated IIdentity, IPrincipal and Profile objects. It provides User identity cache management, which improves performance while repeatedly authenticating users using cached security credentials. Flexibility to extend and implement custom Security Cache Providers. Developing an application We will explore each individual Security block feature and along the way we will understand the concepts behind the individual elements. This will help us to get up to speed with the basics. To get started, we will do the following: Reference the Validation block assemblies Add the required Namespaces Set up the initial configuration To complement the concepts and allow you to gain quick hands-on experience of different features of the Security Application Block, we have created a sample web application project with three additional projects, DataProvider, BusinessLayer, and BusinessEntities, to demonstrate the features. The application leverages SQL Membership, Role, and Profile provider for authentication, role management, and profiling needs. Before running the web application you will have to run the database generation script provided in the DBScript folder of the solution, and update the connection string in web.config appropriately. You might have to open the solution in "Administrator" mode based on your development environment. Also, create an application pool with an identity that has the required privileges to access the development SQL Server database, and map the application pool to the website. A screenshot of the sample application is shown as follows: (Move the mouse over the image to enlarge.) Referencing required/optional assemblies For the purposes of this demonstration we will be referencing non-strong-named assemblies but based on individual requirements Microsoft strong-named assemblies, or a modified set of custom assemblies can be referenced as well. The list of Enterprise Library assemblies that are required to leverage the Security Application Block functionality is given next. A few assemblies are optional based on the Authorization Provider and cache storage mechanism used. Use the Microsoft strong-named, or the non-strong-named, or a modified set of custom assemblies based on your referencing needs. The following table lists the required/optional assemblies: AssemblyRequired/OptionalMicrosoft.Practices.EnterpriseLibrary.Common.dllRequiredMicrosoft.Practices.ServiceLocation.dllRequiredMicrosoft.Practices.Unity.dllRequiredMicrosoft.Practices.Unity.Interception.dllRequiredMicrosoft.Practices.Unity.Configuration.dll Optional Useful while utilizing Unity configuration classes in our code Microsoft.Practices.EnterpriseLibrary.Security.dllRequiredMicrosoft.Practices.EnterpriseLibrary.Security.AzMan.dll Optional Used for Windows Authorization Manager Provider Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll Optional Used for caching the User identity Microsoft.Practices.EnterpriseLibrary.Data.dll Optional Used for caching in Database Cache Storage Open Visual Studio 2008/2010 and create a new ASP.NET Web Application Project by selecting File | New | Project | ASP.NET Web Application; provide the appropriate name for the solution and the desired project location. Currently, the application will have a default web form and assembly references. In the Solution Explorer, right-click on the References section and click on Add Reference and go to the Browse tab. Next, navigate to the Enterprise Library 5.0 installation location; the default install location is %Program Files%Microsoft Enterprise Library 5.0Bin. Now select all the assemblies listed in the previous table, excluding the AzMan-related assembly (Microsoft.Practices.EnterpriseLibrary.Security.AzMan.dll). The final assembly selection will look similar to the following screenshot:
Read more
  • 0
  • 0
  • 3274
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-communicating-dynamics-crm-biztalk-server
Packt
20 Jul 2011
6 min read
Save for later

Communicating from Dynamics CRM to BizTalk Server

Packt
20 Jul 2011
6 min read
Microsoft BizTalk 2010: Line of Business Systems Integration A practical guide to integrating Line of Business systems with BizTalk Server 2010 There are three viable places where Dynamics CRM can communicate with BizTalk Server. First, a Dynamics CRM form is capable of executing client-side JavaScript at various points in the form lifecycle. One can definitely use JavaScript to invoke web services, including web services exposed by BizTalk Server. However, note that JavaScript invocation of web services is typically synchronous and could have a negative impact on the user experience if a form must constantly wait for responses from distributed services. Also, JavaScript that runs within Dynamics CRM is clientside and tied directly to the page on which it resides. If we programmatically interact with a Dynamics CRM entity, then any code existing in the client-side script will not get invoked. For instance, if after an "account" record is created we send a message, via JavaScript, to BizTalk, this logic would not fire if we created an "account" record programmatically. The second place where Dynamics CRM can communicate with BizTalk Server is through workflows. A workflow in Dynamics CRM is an automated process where a set of steps is executed according to rules that we define. For example, when a sales opportunity is closed, we run a workflow that adds a message to the customer record, notifies all parties tied to the opportunity, and sends a polite email to the lost prospect. Workflows are based on Windows Workflow 4.0 technology and can be built either in the Dynamics CRM application itself or within Visual Studio 2010. The Dynamics CRM web application allows us to piece together workflows using previously registered workflow steps. If we need new workflow steps or need to construct something complex, we can jump into Visual Studio 2010 and define the workflow there. Why would we choose to use a workflow to send a message to BizTalk Server? If you have a long-running process that can either be scheduled or executed on demand and want the option for users to modify the process, the workflow may be the right choice. The final strategy for communicating between Dynamics CRM and BizTalk Server is to use plugins. Plugins are server-based application extensions that execute business logic and get tied directly to an entity. This means that they are invoked whether we work in the Dynamics CRM web interface or through the API. I can run a plugin both synchronously and asynchronously, depending on the situation. For instance, if we need to validate the data on a record prior to saving it, we can set a plugin to run before the "save" operation is committed and provide some user feedback on the invalid information. Or, we could choose to asynchronously call a plugin after a record is saved and transmit data to our service bus, BizTalk Server. In the following exercise, we will leverage plugins to send data from Dynamics CRM to BizTalk Server. Integration with BizTalk Server In this first walkthrough, we will build a plugin that communicates from Dynamics CRM to a BizTalk Server located. An event message will be sent to BizTalk whenever a change occurs on an Account record in Dynamics CRM. Setup This exercise leverages a BizTalk Server project already present in your Visual Studio 2010 solution. We are going to publish a web service from BizTalk Server that takes in a message and routes it to a BizTalk send port that writes the message to the file system. If you have not already done so, go to the code package and navigate to C:LOBIntegrationChapter03Chapter3-DynamicsCRM and open the Visual Studio 2010 solution file named Chapter3-DynamicsCRM.sln. Find the BizTalk Server project named Chapter3-DynamicsCRM.AcctRouting and open it. The code package includes a custom schema named AccountEventChange_XML.xsd and notice which elements we want from Dynamics CRM 2011 when an account changes. The first element, EventSource, is used to designate the source of the change event, as there may be multiple systems that share changes in an organization's accounts. This BizTalk project should be set to deploy to a BizTalk application named Chapter3. Build and deploy the project to the designated BizTalk Server. After confirming a successful deployment, launch the BizTalk WCF Service Publishing Wizard. We are going to use this schema to expose a web service entry point into BizTalk Server that Dynamics CRM 2011 can invoke. On the WCF Service Type wizard page, select a WCF-BasicHttp adapter and set the service to expose metadata and have the wizard generate a receive location for us in the Chapter3 application: On the Create WCF Service wizard page, choose to Publish schemas as WCF service. This option gives us fine-grained control over the naming associated with our service. On the next page, delete the two-way operation already present in the service definition. Rename the topmost service definition to AccountChangeService and assign the service the same name. Right-click the service and create a new one-way operation named PublishAccountChange. Right-click the Request message of the operation and choose the AccountChangeEvent message from our BizTalk Project's DLL: On the following wizard page, set the namespace of the service to http://Chapter3/AccountServices. Next, set the location of our service to http://localhost/AccountChangeService and select the option to allow anonymous access to the generated service. Finally, complete the wizard by clicking the Create button on the final wizard page. Confirm that the wizard successfully created both an IIS-hosted web service, and a BizTalk receive port/location. Ensure that the IIS web service is running under an Application Pool that has permission to access the BizTalk databases. In order to test this service, first, go to the BizTalk Server Administration Console and locate the Chapter3 application. Right click the Send Ports folder and create a new, static one-way send port named Chapter3.SendAccountChange.FILE. Set the send port to use the FILE adapter and select the FileDropDropCustomerChangeEvent folder that is present in the code package: This send port should listen for all account change event messages, regardless of which receive location (and system) that they came from. Go to the Filters tab of this send port. Set the filter Property to BTS.MessageType and filter Value to http://Chapter3-DynamicsCRM.AcctRouting.AccountChangeEvent_XML#AccountChangeEvent. All that remains is to test our service. Open the WCF Test Client application and add a new service reference to http://localhost/AccountChangeService/AccountChangeService.svc. Invoke the PublishAccountChange method and, if everything is configured correctly, we will see a message emitted by BizTalk Server that matches our service input parameters: (Move the mouse over the image to enlarge.) We now are sufficiently ready to author the Dynamics CRM plugin, which calls this BizTalk service.  
Read more
  • 0
  • 0
  • 3274

article-image-navigating-pages-xaml-browser-applications
Packt
18 Jan 2010
4 min read
Save for later

Navigating Pages in XAML Browser Applications

Packt
18 Jan 2010
4 min read
Page navigation is an important part of application development and Windows Presentation Foundation supports navigation in two types of applications. These are the standalone application and the XAML browser application also known as XBAP applications. In addition to navigation between pages in the application it also supports navigation to other types of content such as HTML, objects and XAML files. Implementing a page Page class is one of the classes supported by WPF and you can use hyperlinks declaratively to go from page to page. You could also go from page to page programmatically using the NavigationService. In this article navigation using hyperlinks will be described. Page can be viewed as a package that consists of content which may be of many different kinds such as .NET framework objects, HTML, XAML, etc. Using the page class you can implement a Page which is a navigable object with XAML content. You implement a page declaratively by using the following markup: <Page /> Page is the root element of a Page which requires XAML namespace in its declaration as shown above. The Page can contain only one child element and you may simplify the snippet to just: <Page > <Page.Content> <!-- Page Content --> Hello, XAML</Page.Content></Page> Since a Page has the content you can access any content on the page by the dot notation Page.content as shown here above. Creating a Page in Visual Studio 2008 When you use Visual Studio 2008 you can create a WPF Browser application in C# as shown in the New Project window (opened with File | New Project...). When you create the project as above you will be creating a project which has a Page element as shown in the figure. Page1.xaml has both a preview window as well as XAML markup in a tabbed arrangement as shown here. Page1 is a named page object with a class [x:Class="Page1"]. You can review the content shown in the earlier snippet by taking out the extra namespace from the page shown here. The contents on a page can consist of other objects such as controls which can be used for various activities one of which is navigating from page to page. These controls can provoke events which can be implemented both as mark up and code that supports the page(also known as code behind). The page created by Visual Studio provides the necessary configuration to interact with the page as shown in Page1.xaml in the above figure and the code behind page shown in the figure below. The default page created by Visual Studio fulfils the three necessary criteria for a page with which you can interact by providing the following: x:Class="Page1" this markup attribute enables the MS Build engine to build a Page1 partial class which has the same name as the attribute of x:Class namely "Page1" This requires the inclusion of a namespace provided by the second namespace declaration The generated class should implement an InitializeComponent and the default page has this implemented as show above Configuring a Start Page When the application starts you need to specify that the browser should bring up a designated page. In order to support this the browser application requires an infrastructure to host the application and the WPF's Application class provides the necessary information in the form of an ApplicationDefinition file. In the XBAP application we have created you may review the information in the Application definition as shown here. You can specify the start up page as the application starts by specifying it in the Application definition as shown in the next figure. Without the StartupURI the page does not get displayed. The StartupURI can also be specified in a Startup event handler. Page appearance in the browser As the application starts up you may want to control how the page hosted in the window appears. You can set certain properties declaratively as shown where the WindowTitle, WindowWidth, WindowHeight, Title can all be set. The first three items are what you will see when the page gets displayed. For example consider the following xaml mark up: <Page x_Class="WPFSharp_Nav01.Page1" WindowWidth="500" WindowHeight="200" Title="Pagex" Background="Blue" WindowTitle="What is this?" > <TextBox Width="400" Height="25">Hello, XAML Browser App</TextBox></Page> The page gets displayed as shown when the application starts up. The WindowWidth is the outer width and the WindowHeight is the outer height of the browser window.
Read more
  • 0
  • 0
  • 3273

article-image-piwik-tracking-user-interactions
Packt
11 Oct 2012
15 min read
Save for later

Piwik: Tracking User Interactions

Packt
11 Oct 2012
15 min read
Tracking events with Piwik Many of you may be familiar with event tracking with Google Analytics; and many of you may not. In Google Analytics, event tracking is pretty structured. When you track an event with Google, you get five parameters: Category: The name for the group of objects you want to track Action: A string that is used to define the user in action for the category of object Label: This is optional and is for additional data Value: This is optional and is used for providing addition numerical data Non-interaction: This is optional and will not add the event hit into bounce rate calculation if set to true We are going over a few details on event tracking with Google Analytics because the custom variable feature we will be using for event tracking in Piwik is a little less structured. And a little structure will help you drill down the details of your data more effectively from the start. You won't have to restructure and change your naming conventions later on and lose all of your historical data in the process. We don't need to look over the code for Google Analytics. Just know that it may help to set up your event tracking with a similar structure. If you had videos on your site, enough to track, you would most likely make a category of events Videos. You can create as many as you need for the various objects you want to track on your site: Videos Maps Games Ads Blog posts (social media actions) Products As for the actions that can be performed on those Videos, I can think of a few: Play Pause Stop Tweet Like Download There are probably more than you can think of, but now that we have these actions we can connect them with elements of the site. As for the label parameter, you would probably want to use that to store the title of the movie the visitor is interacting with or the page it is located on. We will skip the value parameter which is for numeric data because with Piwik, you won't have a similar value. But non-interaction is interesting; it means that by default an action on a page counts to lower the bounce rate from that page since the user is doing something. Unfortunately, this is not a feature that we have using Piwik currently, although that could change in the future. Okay, now that we have learned one of the ways to structure our events, let's look at the way we can track events in Piwik. There is really nothing called event tracking in Piwik, but Piwik does have custom variables which will do the same job. But, since it is not really event tracking in the truest sense of the word, the bounce rate will be unaffected by any of the custom variables collected. In other words, unlike Google Analytics, you don't get the non-interaction parameter you can set. But let's see what you can do with Piwik. Custom variables are name-value pairs that you can set in Piwik. You can assign up to five custom variables for each visitor and/or each page view. The function for setting a custom variable is setCustomVariable . You must call it for each custom variable you set up to the limit of five. piwikTracker.setCustomVariable (index, name, value, scope); And here are what you set the parameters to: index: This is a number from 1 to 5 where your custom variables are stored. It should stay the same as the name of custom variable. Changing the index of a name later will reset all old data. name: This is the custom variable name or key. value: This is the value for name. scope: This parameter sets the scope of the custom variable, whether it is being tracked per visit or per page. And what scope we set depends upon what we are tracking and how complex our site is. So how do these custom variables fit our model of event tracking? Well we have to do things a little bit differently. For most of our event tracking, we will have to set our variable scope per page. There is not enough room to store much data at the visit level. That is good for other custom tracking you may need but for event tracking you will need more space for data. So with page level custom variables, you get five name-value sets per page. So, we would set up our variables similar to something like this for a video on the page: Index = 1 Name = "Video" Value = "Play","Pause","Stop","Tweet","Like", and so on Scope = "page" And this set of variables in using Piwik's custom variable function would look like one of the following: piwikTracker.setCustomVariable(1,"Video","Play","page"); piwikTracker.setCustomVariable(1,"Video","Pause","page"); piwikTracker.setCustomVariable(1,"Video","Tweet","page"); Which one you would use would depend on what action you are tracking. You would use JavaScript in the page to trigger these variables to be set, most likely by using an onClick event on the button. We will go into the details of various event tracking scenarios later in this chapter. You will notice in the previous snippets of code that the index value of each call is 1. We have set the index of the "Video" name to 1 and must stick to this now on the page or data could be overwritten. This also leaves us the two to five indexes still available for use on the same page. That means if we have banner ads on the page, we could use one of the spare indexes to track the ads. piwikTracker.setCustomVariable(2,"SidebarBanner","Click","page"); You will notice that Google event tracking has the label variable. As we are using page leveling custom variables with Piwik and the variables will be attached to the page itself, there is no need to have this extra variable in most cases. If we do need to add extra data other than an action value, we will have to concatenate our data to the action and use the combined value in Piwik's custom tracking's value variable. Most likely, if we have one banner on our video page, we will have more and to track those click events per banner, we may have to get a little creative using the following: piwikTracker.setCustomVariable(2,"SidebarBanner", "AddSlot1Click","page"); piwikTracker.setCustomVariable(2,"SidebarBanner", "AddSlot2Click","page"); piwikTracker.setCustomVariable(2,"SidebarBanner", "AddSlot3Click","page"); Of course, it is up to you whether you join your data together by using CamelCase, which means joining each piece of data together after capitalizing each. This is what I did previously. You can also use spaces or underscores as long as it is understandable to you and you stick to it. Since the name and value are in quotation marks, you can use any suitable string. And again, since these are custom variables, if you come up with a better system of setting up your event tracking that works better with your website and business model, then by all means try it. Whatever works best for you and your site is better in the long run. So now that we have a general idea of how we will be tracking events with Piwik, let's look at some specific examples and more in depth at what events are, compared to goals or page views. Tracking social engagement You know that you have a Facebook "Like" button on your page, a Twitter "tweet" button, and possibly lots more buttons that do various things at other sites that you yourself have no control over and can add no tracking code to. But you can track clicks on the button itself. You use event tracking for what you could call micro-conversions. But there is really nothing micro about them. That Facebook "Like" could end up in many more sales or conversions than a standard conversion. They could be the route on the way to one or multiple conversions. There may be a blurry line between engagement goals and micro-conversions. And really, it is up to you what weight you give to visitor actions on your site, but use events for something smaller than you would consider a goal. If your goal is sales on your website, that Facebook "Like" should cause a spike in your sales and you will be able to correlate that to your event tracking, but the "Like" is not the end of the road, or the goal. It is a stop on the way. If your website is a blog and your goal is to promote advertising or your services with your content, then tracking social engagement can tell you which topics have the highest social interest so that you can create similar content in the future. So what are some other events we can track? Of course, you would want to track anything having to do with liking, tweeting, bookmarking, or somehow spreading your site on a social network. That includes Facebook , Twitter , Digg , StumbleUpon , Pinterest , and any other social network whose button you put on your site. If you spent enough time to put the buttons on your pages, you can at least track these events. And if you don't have buttons, you have to remember that each generation is using the Internet more often; smartphones make it available everywhere, and everyone is on a social network. Get with it. And don't forget to add event tracking to any sort of Follow Me or Subscribe button. That too is an event worth tracking. We will also look at blog comments since we can consider them to be in the social realm of our tracking. Tracking content sharing So let's look at a set of social sharing buttons on our website. We aren't going to blow things out of proportion by using buttons for every social network out there, just two: Twitter and Facebook. Your site may have less and should have more, but the same methods we will explore next can be used for any amount of content sharing buttons. We are event tracking, so let's begin by defining what our custom variable data will be. We need to figure out how we are going to set up our categories of events and the actions. In this example, we will be using buttons on our Holy Hand Grenade site: You will see our Twitter button and our Facebook button right underneath the image of our Holy Hand Grenade. We are going to act as if our site has many more pages and events to track on it and use a naming convention that will leave room for growth. So we are going to use the category of product shares. That way we have room for video shares when we finally get that cinematographer and film our Holy Hand Grenade in action. Now we need to define our actions. We will be adding more buttons later after we test the effectiveness of our Facebook and Twitter buttons. This means we need a separate action to distinguish each social channel. Share on Facebook Share on Twitter And then we add more buttons: Share on Google+ Share on Digg Share on Reddit Share on StumbleUpon So let's look at the buttons in the source of the page for a minute to see what we are working with: <li class="span1"> <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script> <a href="https://twitter.com/intent/tweet?url=http%3A%2F%2Fdir23.com&text=Holy%20Hand%20Grenades"class="twitter-share-button">Tweet</a> </li> <li class="span1"></li> <li class="span1"> <script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script> <fb:like href="http://dir23.com/" show_faces="false"width="50" font=""></fb:like> </li> </ul> <p><a class="btn btn-primary btn-large">Buy Now >></a></p> You see that the buttons are not really buttons yet, they are only HTML anchors in the code and JavaScript includes. Before we start looking at the code to track clicks on these buttons, we need to go over some details about the way Piwik's JavaScript works. Setting a custom variable in Piwik using an onclick event is a very tricky procedure. To start with, you must call more than just setCustomVariable because that will not work after the Piwik tracking JavaScript has loaded and trackPageView has been called. But there is a way around this. First, you call setCustomVariable and then, in that same onclick event , you call trackLink , as in the next example: <p><a href="buynow.html" class="btn btn-primary btn-large" onclick="javascript:piwikTracker.setCustomVariable(2,'Product Pricing','ViewProduct Price','page');piwikTracker.trackLink();">Buy Now >></a></p> If you forget to add the piwikTracker.trackLink() call, nothing will happen and no custom variables will be set. Now with the sharing buttons, we have another issue when it comes to tracking clicks. Most of these buttons, including Facebook, Twitter, and Google+ use JavaScript to create an iframe that has the button. This is a problem, because the iframe is on another domain and there is not an easy way to track clicks. For this reason, I suggest using your social network's API functionality to create the button so that you can create a callback that will fire when someone likes or tweets your page. Another advantage to this method is that you will be sure that each tracked tweet or like will be logged accurately. Using an on_click event will cause a custom variable to be created with every click. If the person is not logged in to their social account at the time, the actual tweet or like will not happen until after they log in, even if they decide to do so. Facebook, Twitter, and Google+ all have APIs with this functionality. But if you decide to try to track the click on the iframe, you can take a look at the code at http://www.bennadel.com/blog/1752-Tracking-Google-AdSense- Clicks-With-jQuery-And-ColdFusion.htm to see how complicated it can get. The click is not really tracked. The blur on the page is tracked, because blur usually happens if a link in the iframe is clicked and a new page is about to load. We already have our standard Piwik tracking code on the page. This does not have to be modified in any way for event tracking. Instead we will be latching into Twitters and Facebook's APIs which we loaded in the page by including their JavaScript. <script> twttr.events.bind('tweet', function(event) { piwikTracker.setCustomVariable(1,'Product Shares','Share on Twitter','page'); piwikTracker.trackLink(); }); </script> <script type="text/javascript"> FB.Event.subscribe('edge.create', function(response) { piwikTracker.setCustomVariable(1,'Product Shares','Share onFacebook','page'); piwikTracker.trackLink(); }); </script> We add these two simple scripts to the bottom of the page. I put them right before the Piwik tracking code. The first script binds to the tweet event in Twitter's API and once that event fires, our Piwik code executes and sets our custom variable. Notice that here too we have to call trackLink right afterwards. The second script does the same thing when someone likes the page on Facebook. It is beyond the scope of this book to go into more details about social APIs, but this code will get you started and you can do more research on your chosen social network's API on your own to see what type of event tracking will be possible. For example, with the Twitter API you can bind a function to each one of these actions: click, tweet, retweet, favorite, or follow. There are definitely more possibilities with this than there is with a simple onclick event. Using event tracking on your social sharing buttons will let you know where people share your line of Holy Hand Grenades. This will help you figure out just which social networks you should have a presence on. If people on Twitter like the grenades, then you should make sure to keep your Twitter account active, and if you don't have a Twitter account and your product is going viral there, you need to get one quick and participate in the conversation about your product. Or you may want to invest in the development of a Facebook app and you are not quite sure that it is worth the investment. Well, a little bit of event tracking will tell you if you have enough people interested in your website or products to fork over the money for an app. Or maybe a person goes down deep into the pages of your site, digs out a gem, and it gets passed around StumbleUpon like crazy. This might indicate a page that you should feature on the home page of your website. And if it's a product page that's been hidden from light for years, maybe throw some advertising its way too.
Read more
  • 0
  • 0
  • 3271

article-image-creating-different-font-files-and-using-web-fonts
Packt
16 Sep 2013
12 min read
Save for later

Creating different font files and using web fonts

Packt
16 Sep 2013
12 min read
(For more resources related to this topic, see here.) Creating different font files In this recipe, we will learn how to create or get these fonts and how to generate the different formats for use in different browsers (Embedded Open Type, Open Type, True Type Font, Web Open Font Format, and SVG font) is explained in this recipe. Getting ready To get the original file of the font created during this recipe in addition to the generated font formats and the full source code of the project FontCreation; please refer to the receipe2 project folder. How to do it... The following steps are preformed for creating different font files: Firstly, we will get an original TTF font file. There are two different ways to get fonts: The first method is by downloading one from specialized websites. Both free and commercial solutions can be found with a wide variety of beautiful fonts. The following are a few sites for downloading free fonts: Google fonts, Font squirrel, Dafont, ffonts, Jokal, fontzone, STIX, Fontex, and so on. Here are a few sites for downloading commercial fonts: Typekit, Font Deck, Font Spring, and so on. We will consider the example of Fontex, as shown in the following screenshot. There are a variety of free fonts. You can visit the website at http://www.fontex.org/. The second method is by creating your own font and then generating a TIFF file format. There are a lot of font generators on the Web. We can find online generators or follow the professionals by scanning handwritten typography and finally import it to Adobe Illustrator to change it into vector based letters or symbols. For newbies, I recommend trying Fontstruct (http://fontstruct.com). It is a WYSIWYG flash editor that will help you create your first font file, as shown in the following screenshot: As you can see, we were trying to create the S letter using a grid and some different forms. After completing the font creation, we can now preview it rather than download the TTF file. The file is in the receipe2 project folder. The following screenshot is an example of a font we have created on the run: Now we have to generate the rest of file formats in order to ensure maximum compatibility with common browsers. We highly recommend the use of Font squirrel web font generator (http://www.fontsquirrel.com/tools/webfont-generator). This online tool helps to create fonts for @font-face by generating different font formats. All we need to do is to upload the original file (optionally adding same font variants bold, italic, or bold-italic), select the output formats, add some optimizations, and finally download the package. It is shown in the following screenshot: The following code explains the how to use this font: <!DOCTYPE html><html><head><title>My first @font-face demo</title><style type="text/css">@font-face {font-family: 'font_testregular';src: url('font_test-webfont.eot');src: url('font_test-webfont.eot?#iefix')format('embedded-opentype'),url('font_test-webfont.woff') format('woff'),url('font_test-webfont.ttf') format('truetype'),url('font_test-webfont.svg#font_testregular')format('svg');font-weight: normal;font-style: normal;} Normal font usage: h1 , p{font-family: 'font_testregular', Helvetica, Arial,sans-serif;}h1 {font-size: 45px;}p:first-letter {font-size: 100px;text-decoration: wave;}p {font-size: 18px;line-height: 27px;}</style> Font usage in canvas: <script src = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script><script language="javascript" type="text/javascript">var x = 30, y = 60;function generate(){var canvas = $('canvas')[0],tx = canvas.getContext('2d');var t = 'font_testregular'; var c = 'red';var v =' sample text via canvas';ctx.font = '52px "'+t+'"';ctx.fillStyle = c;ctx.fillText(v, x, y);}</script></head><body onload="generate();"><h1>Header sample</h1><p>Sample text with lettrine effect</p><canvas height="800px" width="500px">Your browser does not support the CANVAS element.Try the latest Firefox, Google Chrome, Safari or Opera.</canvas></body></html> How it works... This recipe takes us through getting an original TTF file: Font download: When downloading a font (either free or commercial) we have to pay close attention to terms of use. Sometimes, you are not allowed to use these fonts on the web and you are only allowed to use them locally. Font creation: During this process, we have to pay attention to some directives. We have to create Glyphs for all the needed alphabets (upper case and lower case), numbers, and symbols to avoid font incompatibility. We have to take care of the spacing between glyphs and eventually, variations, and ligatures. A special creation process is reserved for right- to left-written languages. Font formats generation: Font squirrel is a very good online tool to generate the most common formats to handle the cross-browser compatibility. It is recommended that we optimize the font ourselves via expert mode. We have the possibility of fixing some issues during the font creation such as missing glyphs, X-height matching, and Glyph spacing. Font usage: We will go through the following font usage: Normal font usage: We used the same method as already adopted via font-family; web-safe fonts are also applied: h1 , p{font-family: 'font_testregular', Helvetica, Arial, sans-serif;} Font usage in canvas: The canvas is a HTML5 tag that renders dynamically, bitmap images via scripts Creating 2D shapes. In order to generate this image based on fonts, we will create the canvas tag at first. An alternative text will be displayed if canvas is not supported by the browser. <canvas height="800px" width="500px">Your browser does not support the CANVAS element.Try the latest Firefox, Google Chrome, Safari or Opera.</canvas> We will now use the jQuery library in order to generate the canvas output. An onload function will be initiated to create the content of this tag: <scriptsrc = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script> In the following function, we create a variable ctx which is a canvas occurrence of 2D context via canvas.getContext('2d'). We also define font-family using t as a variable, font-size, text to display using v as a variable, and color using c as a variable. These properties will be used as follows: <script language="javascript" type="text/javascript">var x = 30, y = 60;function generate(){var canvas = $('canvas')[0],ctx = canvas.getContext('2d');var t = 'font_testregular';var c = 'red' ;var v =' sample text via canvas'; This is for font-size and family. Here the font-size is 52px and the font-family is font_testregular: ctx.font = '52px "'+t+'"'; This is for color by fillstyle: ctx.fillStyle = c; Here we establish both text to display and axis coordinates where x is the horizontal position and y is vertical one. ctx.fillText(v, x, y); Using Web fonts In this recipe, you will learn how to use fonts hosted in distant servers for many reasons such as support services and special loading scripts. A lot of solutions are widely available on the web such as Typekit, Google fonts, Ascender, Fonts.com web fonts, and Fontdeck. In this task, we will be using Google fonts and its special JavaScript open source library, WebFont loader. Getting ready Please refer to the project WebFonts to get the full source code. How to do it... We will get through four steps: Let us configure the link tag: <link rel="stylesheet" id="linker" type="text/css"href="http://fonts.googleapis.com/css?family=Mr+De+Haviland"> Then we will set up the WebFont loader: <script type="text/javascript">WebFontConfig = {google: {families: [ 'Tangerine' ]}};(function() {var wf = document.createElement('script');wf.src = ('https:' == document.location.protocol ?'https' : 'http') +'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';wf.type = 'text/javascript';wf.async = 'true';var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(wf, s);})();</script><style type="text/css">.wf-loading p#firstp {font-family: serif}.wf-inactive p#firstp {font-family: serif}.wf-active p#firstp {font-family: 'Tangerine', serif} Next we will write the import command: @import url(http://fonts.googleapis.com/css?family=Bigelow+Rules); Then we will cover font usage: h1 {font-size: 45px;font-family: "Bigelow Rules";}p {font-family: "Mr De Haviland";font-size: 40px;text-align: justify;color: blue;padding: 0 5px;}</style></head><body><div id="container"><h1>This H1 tag's font was used via @import command </h1><p>This font was imported via a Stylesheet link</p><p id="firstp">This font was created via WebFont loaderand managed by wf a script generated from webfonts.js.<br />loading time will be managed by CSS properties :<i>.wf-loading , .wf-inactive and .wf-active</i> </p></div></body></html> How it works... In this recipe and for educational purpose, we used following ways to embed the font in the source code (the link tag, the WebFont loader, and the import command). The link tag: A simple link tag to a style sheet is used referring to the address already created: <link rel="stylesheet" type="text/css"href="http://fonts.googleapis.com/css?family=Mr+De+Haviland"> The WebFont loader: It is a JavaScript library developed by Google and Typekit. It grants advanced control options over the font loading process and exceptions. It lets you use multiple web font providers. In the following script, we can identify the font we used, Tangerine, and the link to predefined address of Google APIs with the world google: WebFontConfig = {google: { families: [ 'Inconsolata:bold' ] }}; We now will create wf which is an instance of an asynchronous JavaScript element. This instance is issued from Ajax Google API: var wf = document.createElement('script');wf.src = ('https:' == document.location.protocol ?'https' : 'http') +'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';wf.type = 'text/javascript';wf.async = 'true';var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(wf, s);})(); We can have control over fonts during and after loading by using specific class names. In this particular case, only the p tag with the ID firstp will be processed during and after font loading. During loading, we use the class .wf-loading. We can use a safe font (for example, Serif) and not the browser's default page until loading is complete as follows: .wf-loading p#firstp {font-family: serif;} After loading is complete, we will usually use the font that we were importing earlier. We can also add a safe font for older browsers: .wf-active p#firstp {font-family: 'Tangerine', serif;} Loading failure: In case we failed to load the font, we can specify a safe font to avoid falling in default browser's font: .wf-inactive p#firstp {font-family: serif;} The import command: It is the easiest way to link to the fonts: @import url(http://fonts.googleapis.com/css?family=Bigelow+Rules); Font usage: We will use the fonts as we did already via font-family property: h1 {font-family: "Bigelow Rules";}p {font-family: "Mr De Haviland";} There's more... The WebFont loader has the ability to embed fonts from mutiple WebFont providers. It has some predefined providers in the script such as Google, Typekit, Ascender, Fonts.com web fonts, and Fontdeck. For example, the following is the specific source code for Typekit and Ascender: WebFontConfig ={typekit: {id: 'TypekitId'}};WebFontConfig ={ascender: {key: 'AscenderKey',families: ['AscenderSans:bold,bolditalic,italic,regular']}}; For the font providers that are not listed above, a custom module can handle the loading of the specific style sheet: WebFontConfig = {custom: {families: ['OneFont', 'AnotherFont'],urls: ['http://myotherwebfontprovider.com/stylesheet1.css','http://yetanotherwebfontprovider.com/stylesheet2.css' ]}}; For more details and options of the WebFont loader script, you can visit the following link: https://developers.google.com/fonts/docs/webfont_loader To download this API you may access the following URL: https://github.com/typekit/webfontloader How to generate the link to the font? The URL used in every method to import the font in every method (the link tag, the WebFont loader, and the import command) is composed of the Google fonts API base url (http://fonts.googleapis.com/css) and the family parameter including one or more font names, ?family=Tangerine. Multiple fonts are separated with a pipe character (|) as follows: ?family=Tangerine|Inconsolata|Droid+Sans Optionally, we can add subsets or also specify a style for each font: Cantarell:italic|Droid+Serif:bold&subset=latin Browser-dependent output The Google fonts API serves a generated style sheet specific to the client, via the browser's request. The response is relative to the browser. For example, the output for Firefox will be: @font-face {font-family: 'Inconsolata';src: local('Inconsolata'),url('http://themes.googleusercontent.com/fonts/font?kit=J_eeEGgHN8Gk3Eud0dz8jw') format('truetype');} This method lowers the loading time because the generated style sheet is relative to client's browser. No multiformat font files are needed because Google API will generate it, automatically. Summary In this way, we have learned how to create different font formats, such as Embedded Open Type, Open Type, True Type Font, Web Open Font Format, and SVG font, and how to use the different Web fonts such as Typekit, Google fonts, Ascender, Fonts.com web fonts, and Fontdeck. Resources for Article: Further resources on this subject: So, what is Markdown? [Article] Building HTML5 Pages from Scratch [Article] HTML5: Generic Containers [Article]
Read more
  • 0
  • 1
  • 3268
article-image-adding-event-calendar-your-joomla-site-using-jevents
Packt
21 Oct 2010
2 min read
Save for later

Adding an Event Calendar to your Joomla! Site using JEvents

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

article-image-creating-mobile-dashboards
Packt
06 Jul 2015
13 min read
Save for later

Creating Mobile Dashboards

Packt
06 Jul 2015
13 min read
In this article by Taha M. Mahmoud, author of the book Learning SAP BusinessObjects Dashboards, in the last few decades, the usage of smart devices, such as mobile phones, tablets, and smart watches has increased dramatically. Now, the hardware of smart devices is powerful enough to handle all that we need it to. Indeed, we are now carrying smart devices with us all the time, that act like small, but powerful, computers. Here comes the idea of Mobile BI. We need to select the most important information for the BI end user to track on the go, using their smart devices. According to the Industrial Design Center (IDC: http://www.idc.com/), by 2017, 87 percent of all connected devices sold will be tablets and smartphones. (For more resources related to this topic, see here.) SAP BusinessObjects has different BI tools that handle different user requirements. They have the following BI reporting tools: Web Intelligence (Webi) reports: This tool can be used to help business users to execute their day-to-day reports. The main advantage of Webi reports is that you can schedule them to run and be sent directly to users by e-mail. This is a very powerful tool, because it is very similar to MS Excel, so business users can start using it directly, without a lot of effort and time. Crystal reports: This is one of the most famous report types. We call it a pixel-perfect report because we can control and adjust our report design, up to the pixel level. Normally, we use these reports to create the annual and quarterly reports used and published by an organization's end users. Dashboards: This is the tool that you are learning in this book. Dashboards are a powerful way to deliver information to the top management and executives. Lumira: This tool is a data discovery tool that can help data and business analysts explore data. It is very powerful and can connect to any source data. In minutes, you can come up with neat and wonderful dashboards and charts with this tool. The idea behind this tool is that you don't have initial requirements to implement, but you have data to explore instead. Explorer: This is another powerful data discovery tool, but its main focus is on analyzing data rather than presenting it. You can use it to explore the information you have. Design studio: This is a new dashboard tool. It was released at the end of 2013 for designing and implementing dashboards. It needs coding experience, as it is heavily dependent on JavaScript. Someone with technical skills should use this tool to produce dashboards, and then make them available to the end user. A lay user will not be able to create their own dashboards using this tool, at least at the current stage. SAP is focusing on upgrading this tool to be their main dashboard tool. We can find a matrix that shows the supported content on each device, as follows: BI document* iPad* iPhone* Android tablet* Android phone* Webi Yes Yes Yes Yes Crystal Yes Yes No No Dashboards Yes No Yes No Design studio Yes Yes Yes Yes Explorer Yes Yes No No Lumira Yes No No No * This is as per Q4-2014. SAP BO Dashboard can be viewed only on tablets, and not cell phones (as per the current available release SAP BO BI platform 4.1 SP5). In this article, we will focus on the following topics: Creating dashboards for mobile devices Developing mobile dashboards Publishing mobile dashboards Accessing mobile dashboards Creating dashboards for smart devices Mobility is one of the main enterprise goals for all market leaders. Mobility is a term that refers to providing company services for the customer through smart devices (including mobile devices). So, having a mobile application is one of the factors of an organization's success. Facebook, Google, Twitter, and many other enterprises across the globe are competing with each other to reach people everywhere. You don’t need to use a computer to buy something from Amazon.com. All that you need now is to install the Amazon application on your device and buy anything, at anytime. The fact that we are carrying our smart devices all the time, and using them regularly, makes them a golden place for reaching people. Business Intelligence also found that smart devices are perfect for delivering BI content to the end users, and to achieve the concept of giving the right information to the right person at the right time. We can use SAP BO dashboards to create one of the following dashboard types: Desktop Mobile Desktop and mobile If we are targeting desktop users only, we don’t need to worry about the compatibility of dashboard components, as all components are compatible with desktops; whereas, we need to take care if we are targeting mobile users. We need to avoid unsupported components and find alternatives and workarounds, as we will discuss in this article. Here, we must mention one big difference between desktop and mobile dashboards, which is the technology used in each. The technology used in desktop dashboards is Macromedia Flash, while the technology used in mobile dashboards is HTML5. This is the main reason that all the desktop dashboard components that we discussed throughout this book are not supported in the mobile version. You will learn how to find unsupported components and how to avoid them in the first place, if you are targeting mobile users. The second thing that we need to be aware of is the hardware limitation on mobile devices in comparison with powerful desktop and client tools. We need to consider using lightweight dashboard components and presenting the most important and critical information, which the end user really wants to track and monitor on the go. These types of KPIs need immediate action and can't wait until the user returns to their office. Here are the main steps for creating mobile dashboards: Design phase: We need to consider which KPIs should be displayed in the mobile dashboard version and how they should be displayed Development phase: We need to use supported dashboard components and connections only Publishing phase: We need to publish our dashboard and make it available for end users Accessing dashboard: We need to install the SAP BI application and configure it to connect to our SAP BO system Next, we will discuss each phase. Developing a mobile SAP BO Dashboard We can use SAP BO Dashboards to develop dashboards for desktops as well as mobiles. We just need to consider the following if we are developing for mobile dashboards: Using only supported mobile components Using the recommended canvas size for iPads Using only supported mobile connections Now, we will discuss each of these topics. Using supported mobile components To make sure that we are using only supported mobile dashboard components, we can use the Mobile Only filter from the Components panel. You can see this filter in the following screenshot: You can see a list of all supported Mobile dashboard components and connections in Appendix 3, Supported Mobile Components and Connections. We can also use the Mobile Compatibility panel to highlight unsupported dashboard components. This panel is very useful because it is also used to highlight unsupported functions, such as Entry Effect. Unsupported features will simply be lost when you view the dashboard on a mobile phone. You can see the Mobile Compatibility panel in the following screenshot: Using the recommended canvas size for iPads We need also to take care of the canvas size, as the recommended canvas size is 1024 x 768 pixels if we are developing a dashboard for mobiles. We can change the canvas size from the following places: Document properties Preferences Changing the canvas size from the preferences will make it the default canvas size for all new dashboards, whereas changing it from document properties will change the canvas size for the current dashboard only. If we have selected any canvas size other than the recommended one, we will get the following warning in the Mobile Compatibility panel: Using a supported mobile data connection The next thing we need to take care of is the external data connection type, as only a few of them are supported by mobile dashboards. You can see the Data Manager window, selected via data connections, in the following screenshot: Next, we will see how to preview and publish our mobile dashboard. Publishing mobile dashboards Publishing a dashboard will make it available for end users. After developing our mobile dashboard, we will need to do the following: Preview our dashboard to see what it will look like on a tablet Publish our dashboard on the SAP BO server as a mobile dashboard Add our dashboard to the mobile category to make it available for mobile users Previewing our mobile dashboard There are two modes for previewing mobile dashboards: Mobile (Fit to Screen) Mobile (Original Size) You can see the three available options in the following screenshot. We have already explained how to use the first one. The main difference between the other two options is that Mobile (Fit to Screen) will fit the dashboard to the screen size, and the other will display the original size. We need to note that the previewing option will affect only the preview mode. It will not affect the mobile dashboard after it is published. A mobile preview exactly simulates what we will see on the iPad. You can see a preview of a mobile dashboard in the following screenshot: You may notice that some components, such as a pie chart for example, will create a different user experience on the mobile preview compared to the desktop preview. This is because a desktop preview generates a flash file, whereas a mobile preview generates an HTML5 file. Publishing our mobile dashboard The next step is to publish our dashboard on the SAP BO server. We have the following options: Save to Platform | Mobile Only Save to Platform | Desktop Only Save to Platform | Desktop and Mobile We can access the Save to Platform menu from the File menu and see these options: The options are self-explanatory. The Mobile Only option will publish the dashboard as an HTML5 object only and can be accessed only from mobile devices. The Desktop Only option will generate a flash file and can be accessed only by desktop clients. Finally, the Desktop and Mobile option will generate both HTML5 and desktop, and can be accessed by both clients. Adding our dashboard to the mobile category After publishing our mobile dashboard, we need to make it available for mobile users. By default, any dashboard or report under the Mobile category will be displayed for mobile users. To do this, we should follow the steps: Access the BI Launch Pad (the URL will be <SAP_BO_SERVER_NAME:8080>/BOE/BI). Navigate to the folder that we used to publish our mobile dashboard. Right-click on that dashboard and add it to the Mobile category. You can see these steps in the following screenshot: You can see the last step here: You may need to refer to the SAP BusinessObjects administrator guide to get more information on how to set up and configure a mobile server on the SAP BO server. We used the default configuration settings here. Next, you will learn how to access it from an iPad or an Android tablet. Accessing and using mobile dashboards The first thing we need to do before accessing our mobile dashboard is to download the SAP BusinessObjects BI mobile application from the following links: Android: https://play.google.com/store/apps/details?id=com.sap.mobi&hl=en Mac OS: https://itunes.apple.com/en/app/sap-businessobjects-mobile/id441208302?mt=8 The most strongly recommended mobile device for displaying SAP BO dashboards is the iPad. Starting from SAP BO BI platform 4.1 SP1, we can also view SAP BO dashboards on Android tablets. Then, we need to configure SAP BO mobile application to connect to our server by following these steps: You may need to create a VPN, if you want to access your mobile dashboards from outside your organization. Open the SAP BO Mobile application (SAP BI). Tap on Connect and select Create New Connection. Enter BO Server in the connection name. Enter Mobile Server URL and CMC in the connection details (this information will depend on your SAP BO server information). Fill in Authentication Details (username and password). Establish the connection that you've already created. You should be able to see our eFashion dashboard. Tap it to display it on your tablet. Introducing the main features of the SAP BI application We can use the SAP BI application as a master place to view SAP BI content produced by different SAP BI tools, such as Web Intelligence, dashboards, Lumira, and so on. We can perform the following actions: Viewing document information and adding it to favorites Annotation E-mail For a complete user guide to SAP BI applications, refer to the following links: Mac OS: http://help.sap.com/bomobileios Android: https://help.sap.com/bomobileandroid Viewing document information and adding a document to favorites We can click on the three dots beside any BI document (report or dashboard) to view the document information (metadata), such as who the author is, and what the type of this document is. A small yellow star will appear on top of the document when it's added to favorites. You can see this menu in the following screenshot: Using the Annotation feature We can use this feature to take a screenshot of the current dashboard view and start annotating and adding our comments to it. Then, we can send it to the corresponding person. You can even add voice comments, which make it ideal to communicate results with others. This feature is shown here: E-mailing dashboards We can use this feature to e-mail the BI document to a specific person. It is the same as what we did in the annotation feature, except that it will send a plain image of the current view. Summary In this article, you learned how to create a mobile dashboard using SAP BO Dashboards. Then, we discussed how to find unsupported mobile dashboard components using the mobile compatibility panel. As a best practice, we should use the Mobile Only filter from the Components panel if we are targeting mobile devices for our dashboard. Next, you learned how to preview and publish your dashboard, so that it can be used and accessed by mobile devices. After that, we had an overview of the main features of a SAP BI mobile application, such as annotation and sharing via e-mails. Throughout this article, you learned how to create a dashboard step by step, starting from the analysis phase, right up to design and development. The main challenge that you will face later is how to present your information in a meaningful way, and how to get the maximum value of your information. I hope that you enjoyed reading this article, and I am looking forward to your input and    comments. Resources for Article: Further resources on this subject: Authorizations in SAP HANA [article] SAP HANA integration with Microsoft Excel [article] SAP HANA Architecture [article]
Read more
  • 0
  • 0
  • 3265

article-image-visualization-dashboard-design
Packt
10 Jan 2017
18 min read
Save for later

Visualization Dashboard Design

Packt
10 Jan 2017
18 min read
In this article by David Baldwin, the author of the book Mastering Tableau, we will cover how you need to create some effective dashboards. (For more resources related to this topic, see here.) Since that fateful week in Manhattan, I've read Edward Tufte, Stephen Few, and other thought leaders in the data visualization space. This knowledge has been very fruitful. For instance, quite recently a colleague told me that one of his clients thought a particular dashboard had too many bar charts and he wanted some variation. I shared the following two quotes: Show data variation, not design variation. –Edward Tufte in The Visual Display of Quantitative Information Variety might be the spice of life, but, if it is introduced on a dashboard for its own sake, the display suffers. –Stephen Few in Information Dashboard Design Those quotes proved helpful for my colleague. Hopefully the following information will prove helpful to you. Additionally I would also like to draw attention to Alberto Cairo—a relatively new voice providing new insight. Each of these authors should be considered a must-read for anyone working in data visualization. Visualization design theory Dashboard design Sheet selection Visualization design theory Any discussion on designing dashboards should begin with information about constructing well-designed content. The quality of the dashboard layout and the utilization of technical tips and tricks do not matter if the content is subpar. In other words we should consider the worksheets displayed on dashboards and ensure that those worksheets are well-designed. Therefore, our discussion will begin with a consideration of visualization design principles. Regarding these principles, it's tempting to declare a set of rules such as: To plot change over time, use a line graph To show breakdowns of the whole, use a treemap To compare discrete elements, use a bar chart To visualize correlation, use a scatter plot But of course even a cursory review of the preceding list brings to mind many variations and alternatives! Thus, we will consider various rules while always keeping in mind that rules (at least rules such as these) are meant to be broken. Formatting rules The following formatting rules encompass fonts, lines, and bands. Fonts are, of course, an obvious formatting consideration. Lines and bands, however, may not be something you typically think of when formatting, especially when considering formatting from the perspective of Microsoft Word. But if we broaden formatting considerations to think of Adobe Illustrator, InDesign, and other graphic design tools, then lines and bands are certainly considered. This illustrates that data visualization is closely related to graphic design and that formatting considers much more than just textual layout. Rule – keep the font choice simple Typically using one or two fonts on a dashboard is advisable. More fonts can create a confusing environment and interfere with readability. Fonts chosen for titles should be thick and solid while the body fonts should be easy to read. As of Tableau 10.0 choosing appropriate fonts is simple because of the new Tableau Font Family. Go to Format | Font to display the Format Font window to see and choose these new fonts: Assuming your dashboard is primarily intended for the screen, sans serif fonts are best. On the rare occasions a dashboard is primarily intended for print, you may consider serif fonts; particularly if the print resolution is high. Rule – Trend line > Fever line > Reference line > Drop line > Zero line > Grid line The preceding pseudo formula is intended to communicate line visibility. For example, trend line visibility should be greater than fever line visibility. Visibility is usually enhanced by increasing line thickness but may be enhanced via color saturation or by choosing a dotted or dashed line over a solid line. The trend line, if present, is usually the most visible line on the graph. Trend lines are displayed via the Analytics pane and can be adjusted via Format à Lines. The fever line (for example, the line used on a time-series chart) should not be so heavy as to obscure twists and turns in the data. Although a fever line may be displayed as dotted or dashed by utilizing the Pages shelf, this is usually not advisable because it may obscure visibility. The thickness of a fever line can be adjusted by clicking on the Size shelf in the Marks View card. Reference lines are usually less prevalent than either fever or trend lines and can be formatted by going to Format | Reference lines. Drop lines are not frequently used. To deploy drop lines, right-click in a blank portion of the view and go to Drop lines | Show drop lines. Next, click on a point in the view to display a drop line. To format droplines, go to Format | Droplines. Drop lines are relevant only if at least one axis is utilized in the visualization. Zero lines (sometimes referred to as base lines) display only if zero or negative values are included in the view or positive numerical values are relatively close to zero. Format zero lines by going to Format | Lines. Grid lines should be the most muted lines on the view and may be dispensed with altogether. Format grid lines by going to Format | Lines. Rule – band in groups of three to five Visualizations comprised of a tall table of text or horizontal bars should segment dimension members in groups of three to five. Exercise – banding Navigate to https://public.tableau.com/profile/david.baldwin#!/ to locate and download the workbook. Navigate to the worksheet titled Banding. Select the Superstore data source and place Product Name on the Rows shelf. Double-click on Discount, Profit, Quantity, and Sales. Navigate to Format | Shading and set Band Size under Row Banding so that three to five lines of text are encompassed by each band. Be sure to set an appropriate color for both Pane and Header: Note that after completing the preceding five steps, Tableau defaulted to banding every other row. This default formatting is fine for a short table but is quite busy for a tall table. The band in groups of three to five rule is influenced by Dona W. Wong, who, in her book The Wall Street Journal Guide to Information Graphics, recommends separating long tables or bar charts with thin rules to separate the bars in groups of three to five to help the readers read across. Color rules It seems slightly ironic to discuss color rules in a black-and-white publication such as Mastering Tableau. Nonetheless, even in a monochromatic setting, a discussion of color is relevant. For example, exclusive use of black text communicates differently than using variations of gray. The following survey of color rules should be helpful to ensure that you use colors effectively in a variety of settings. Rule – keep colors simple and limited Stick to the basic hues and provide only a few (perhaps three to five) hue variations. Alberto Cairo, in his book The Functional Art: An Introduction to Information Graphics and Visualization, provides insights into why this is important. The limited capacity of our visual working memory helps explain why it's not advisable to use more than four or five colors or pictograms to identify different phenomena on maps and charts. Rule – respect the psychological implication of colors In Western society, there is a color vocabulary so pervasive, it's second nature. Exit signs marking stairwell locations are red. Traffic cones are orange. Baby boys are traditionally dressed in blue while baby girls wear pink. Similarly, in Tableau reds and oranges should usually be associated with negative performance while blues and greens should be associated with positive performance. Using colors counterintuitively can cause confusion. Rule – be colorblind-friendly Colorblindness is usually manifested as an inability to distinguish red and green or blue and yellow. Red/green and blue/yellow are on opposite sides of the color wheel. Consequently, the challenges these color combinations present for colorblind individuals can be easily recreated with image editing software such as Photoshop. If you are not colorblind, convert an image with these color combinations to grayscale and observe. The challenge presented to the 8.0% of the males and 0.5% of the females who are color blind becomes immediately obvious! Rule – use pure colors sparingly The resulting colors from the following exercise should be a very vibrant red, green, and blue. Depending on the monitor, you may even find it difficult to stare directly at the colors. These are known as pure colors and should be used sparingly; perhaps only to highlight particularly important items. Exercise – using pure colors Open the workbook and navigate to the worksheet entitled Pure Colors. Select the Superstore data source and place Category on both the Rows shelf and the Color shelf. Set the Fit to Entire View. Click on the Color shelf and choose Edit Colors…. In the Edit Colors dialog box, double-click on the color icons to the left of each dimension member; that is, Furniture, Office Supplies, and Technology: Within the resulting dialog box, set furniture to an HTML value of #0000ff, Office Supplies to #ff0000, and Technology to #00ff00. Rule – color variations over symbol variation Deciphering different symbols takes more mental energy for the end user than distinguishing color. Therefore color variation should be used over symbol variation. This rule can actually be observed in Tableau defaults. Create a scatter plot and place a dimension with many members on the Color shelf and Shape shelf respectively. Note that by default, the view will display 20 unique colors but only 10 unique shapes. Older versions of Tableau (such as Tableau 9.0) display warnings that include text such as “…the recommended maximum for this shelf is 10”: Visualization type rules We won't spend time here to delve into a lengthy list of visualization type rules. However, it does seem appropriate to review at least a couple of rules. In the following exercise, we will consider keeping shapes simple and effectively using pie charts. Rule – keep shapes simple Too many shape details impede comprehension. This is because shape details draw the user's focus away from the data. Consider the following exercise on using two different shopping cart images. Exercise – shapes Open the workbook associated and navigate to the worksheet entitled Simple Shopping Cart. Note that the visualization is a scatterplot showing the top 10 selling Sub-Categories in terms of total sales and profits. On your computer, navigate to the Shapes directory located in the My Tableau Repository. On my computer, the path is C:UsersDavid BaldwinDocumentsMy Tableau RepositoryShapes. Within the Shapes directory, create a folder named My Shapes. Reference the link included in the comment section of the worksheet to download the assets. In the downloaded material, find the images titled Shopping_Cart and Shopping_Cart_3D and copy those images into the My Shapes directory created previously. Within Tableau, access the Simple Shopping Cart worksheet. Click on the Shape shelf and then select More Shapes. Within the Edit Shape dialog box, click on the Reload Shapes button. Select the My Shapes palette and set the shape to the simple shopping cart. After closing the dialog box, click on the Size shelf and adjust as desired. Also adjust other aspects of the visualization as desired. Navigate to the 3D Shopping Cart worksheet and then repeat steps 8 to 11. Instead of using the simple shopping cart, use the 3D shopping cart: Compare the two visualizations. Which version of the shopping cart is more attractive? Likely the cart with the 3D look was your choice. Why not choose the more attractive image? Making visualizations attractive is only of secondary concern. The primary goal is to display the data as clearly and efficiently as possible. A simple shape is grasped more quickly and intuitively than a complex shape. Besides, the cuteness of the 3D image will quickly wear off. Rule – use pie charts sparingly Edward Tufte makes an acrid (and somewhat humorous) comment against the use of pie charts in his book The Visual Display of Quantitative Information. A table is nearly always better than a dumb pie chart; the only worse design than a pie chart is several of them. Given their low density and failure to order numbers along a visual dimension, pie charts should never be used. The present sentiment in data visualization circles is largely sympathetic to Tufte's criticism. There may, however, be some exceptions; that is, some circumstances where a pie chart is optimal. Consider the following visualization: Which of the four visualizations best demonstrates that A accounts for 25% of the whole? Clearly it is the pie chart! Therefore, perhaps it is fairer to refer to pie charts as limited and to use them sparingly as opposed to considering them inherently evil. Compromises In this section, we will transition from more or less strict rules to compromises. Often, building visualizations is a balancing act. It's common to encounter contradictory directions from books, blogs, consultants, and within organizations. One person may insist on utilizing every pixel of space while another urges simplicity and whitespace. One counsels a guided approach while another recommends building wide open dashboards that allow end users to discover their own path. Avant gardes may crave esoteric visualizations while those of a more conservative bent prefer to stay with the conventional. We now explore a few of the more common competing requests and suggests compromises. Make the dashboard simple versus make the dashboard robust Recently a colleague showed me a complex dashboard he had just completed. Although he was pleased that he had managed to get it working well, he felt the need to apologize by saying, “I know it's dense and complex but it's what the client wanted.” Occam's Razor encourages the simplest possible solution for any problem. For my colleague's dashboard, the simplest solution was rather complex. This is OK! Complexity in Tableau dashboarding need not be shunned. But a clear understanding of some basic guidelines can help the author intelligently determine how to compromise between demands for simplicity and demands for robustness. More frequent data updates necessitate simpler design. Some Tableau dashboards may be near-real-time. Third-party technology may be utilized to force a browser displaying a dashboard via Tableau Server to refresh every few minutes to ensure the absolute latest data displays. In such cases, the design should be quite simple. The end user must be able to see at a glance all pertinent data and should not use that dashboard for extensive analysis. Conversely, a dashboard that is refreshed monthly can support high complexity and thus may be used for deep exploration. Greater end user expertise supports greater dashboard complexity. Know thy users. If they want easy, at-a-glance visualizations, keep the dashboards simple. If they like deep dives, design accordingly. Smaller audiences require more precise design. If only a few people monitor a given dashboard, it may require a highly customized approach. In such cases, specifications may be detailed, complex, and difficult to execute and maintain because the small user base has expectations that may not be natively easy to produce in Tableau. Screen resolution and visualization complexity are proportional. Users with low-resolution devices will need to interact fairly simply with a dashboard. Thus the design of such a dashboard will likely be correspondingly uncomplicated. Conversely, high-resolution devices support greater complexity. Greater distance from the screen requires larger dashboard elements. If the dashboard is designed for conference room viewing, the elements on the dashboard may need to be fairly large to meet the viewing needs of those far from the screen. Thus the dashboard will likely be relatively simple. Conversely, a dashboard to be viewed primarily on end users desktops can be more complex. Although these points are all about simple versus complex, do not equate simple with easy. A simple and elegantly designed dashboard can be more difficult to create than a complex dashboard. In the words of Steve Jobs: Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains. Present dense information versus present sparse information Normally, a line graph should have a maximum of four to five lines. However, there are times when you may wish to display many lines. A compromise can be achieved by presenting many lines and empowering the end user to highlight as desired. The following line graph displays the percentage of Internet usage by country from 2000 to 2012. Those countries with the largest increases have been highlighted. Assuming that Highlight Selected Items has been activated within the Color legend, the end user can select items (countries in this case) from the legend to highlight as desired. Or, even better, a worksheet can be created listing all countries and used in conjunction with a highlight action on a dashboard to focus attention on selected items on the line graph: Tell a story versus allow a story to be discovered Albert Cairo, in his excellent book The Functional Art: An Introduction to Information Graphics and Visualization, includes a section where he interviews prominent data visualization and information graphics professionals. Two of these interviews are remarkable for their opposing views. I… feel that many visualization designers try to transform the user into an editor.  They create these amazing interactive tools with tons of bubbles, lines, bars, filters, and scrubber bars, and expect readers to figure the story out by themselves, and draw conclusions from the data. That's not an approach to information graphics I like. – Jim Grimwade The most fascinating thing about the rise of data visualization is exactly that anyone can explore all those large data sets without anyone telling us what the key insight is. – Moritz Stefaner Fortunately, the compromise position can be found in the Jim Grimwade interview: [The New York Times presents] complex sets of data, and they let you go really deep into the figures and their connections. But beforehand, they give you some context, some pointers as to what you can do with those data. If you don't do this… you will end up with a visualization that may look really beautiful and intricate, but that will leave readers wondering, What has this thing really told me? What is this useful for? – Jim Grimwade Although the case scenarios considered in the preceding quotes are likely quite different from the Tableau work you are involved in, the underlying principles remain the same. You can choose to tell a story or build a platform that allows the discovery of numerous stories. Your choice will differ depending on the given dataset and audience. If you choose to create a platform for story discovery, be sure to take the New York Times approach suggested by Grimwade. Provide hints, pointers, and good documentation to lead your end user to successfully interact with the story you wish to tell or successfully discover their own story. Document, Document, Document! But don't use any space! Immediately above we considered the suggestion Provide hints, pointers, and good documentation… but there's an issue. These things take space. Dashboard space is precious. Often Tableau authors are asked to squeeze more and more stuff on a dashboard and are hence looking for ways to conserve space. Here are some suggestions for maximizing documentation on a dashboard while minimally impacting screen real estate. Craft titles for clear communication Titles are expected. Not just a title for a dashboard and worksheets on the dashboard, but also titles for legends, filters and other objects. These titles can be used for effective and efficient documentation. For instance a filter should not just read Market. Instead it should say something like Select a Market. Notice the imperative statement. The user is being told to do something and this is a helpful hint. Adding a couple of words to a title will usually not impact dashboard space. Use subtitles to relay instructions A subtitle will take some extra space but it does not have to be much. A small, italicized font immediately underneath a title is an obvious place a user will look at for guidance. Consider an example: red represents loss. This short sentence could be used as a subtitle that may eliminate the need for a legend and thus actually save space. Use intuitive icons Consider a use case of navigating from one dashboard to another. Of course you could associate an action with some hyperlinked text stating Click here to navigate to another dashboard. But this seems quite unnecessary when an action can be associated with a small, innocuous arrow, such as is natively used in PowerPoint, to communicate the same thing. Store more extensive documentation in a tooltip associated with a help icon. A small question mark in the top-right corner of an application is common. This clearly communicates where to go if additional help is required. As shown in the following exercise, it's easy to create a similar feature on a Tableau dashboard. Summary Hence from this article we studied to create some effective dashboards that are very beneficial in corporate world as a statistical tool to calculate average growth in terms of revenue. Resources for Article: Further resources on this subject: Say Hi to Tableau [article] Tableau Data Extract Best Practices [article] Getting Started with Tableau Public [article]
Read more
  • 0
  • 0
  • 3264
article-image-building-ejb-30-persistence-model-oracle-jdeveloper
Packt
27 Aug 2010
5 min read
Save for later

Building an EJB 3.0 Persistence Model with Oracle JDeveloper

Packt
27 Aug 2010
5 min read
(For more resources on Oracle, see here.) WebLogic server 10.x provides some value-added features to facilitate EJB 3 development. WebLogic server 10.x supports automatic deployment of a persistence unit based on the injected variable's name. The @javax.persistence. PersistenceContext and @javax.persistence.PersistenceUnit annotation s are used to inject the persistence context in an EntityManager or EntityManagerFactory variable . A persistence context is a set of entities that are mapped to a database with a global JNDI name. If the name of the injected variable is the same as the persistence unit, the unitName attribute of the @PersistenceContext or @PersistenceUnit is not required to be specified. The EJB container automatically deploys the persistence unit and sets its JNDI name to be the same as the persistence unit name in persistence.xml. For example, if the persistence unit name in the persistence.xml file is em, an EntityManager variable may be injected with the persistence context as follows: @PeristenceContextprivate EntityManager em; We did not need to specify the unitName attribute in the @PersistenceContext because the variable name is the same as the persistence unit. Similarly, an EntityManagerFactory variable may be injected with the persistence context as follows, emf being also the persistence unit name: @PersistenceUnitprivate EntityManagerFactory emf; Another value-added feature in WebLogic server 10.x is support for vendor-specific subinterfaces of the EntityManager interface. For example, the BEA Kodo persistence provider provides the KodoEntityManager subinterface, which may be injected with the persistence context as follows: @PersistenceContextprivate KodoEntityManager em; Setting the environment Before getting started, we need to install Oracle JDeveloper 11g, which may be downloaded from http://www.oracle.com/technology/products/jdev/index.html. Download the Studio Edition, which is the complete version of JDevloper with all the features. Oracle JDeveloper 11g is distributed as a GUI self-extractor application. Click on the jdevstudio11110 install application. The Oracle Installer gets started. Click on Next in the Oracle Installer. Choose a middleware home directory and click on Next: Choose the Install Type as Complete, which includes the integrated WebLogic Server, and click on Next: Confirm the default Product Installation directories and click on Next: The WebLogic Server installation directory is the wlserver_10.3 folder within the middleware home directory. Choose a shortcut location and click on Next. The Installation Summary lists the products that are installed, which include the WebLogic Server and the WebLogic JDBC drivers. Click on Next to install Oracle JDeveloper 11g and the integrated WebLogic Server 10.3. We also need to install the Oracle database 10g/11g or the lightweight Oracle XE, which may be downloaded from http://www.oracle.com/technology/software/products/database/index.html. When installing Oracle database, also install the sample schemas. Creating a datasource in JDeveloper Next, we create a JDBC datasource in JDeveloper. We shall use the datasource in the EJB 3.0 entity bean for database persistence. First, we need to create a database table in some sample schema, OE for example. Run the following SQL script in SQL *Plus: CREATE TABLE Catalog (id INTEGER PRIMARY KEY NOT NULL,journal VARCHAR(100), publisher VARCHAR(100), edition VARCHAR(100),title VARCHAR(100), author VARCHAR(100)); A database table gets created in the OE sample schema. Next, we need to create a JDBC connection in JDeveloper with Oracle database. Open the Database Navigator or select the Database Navigator tab if already open. Right-click on the IDE Connections node and select New Connection: In the Create Database Connection window, specify a Connection Name, select Connection Type as Oracle (JDBC), specify Username as OE, which is the schema in which the Catalog table is created, and specify the password for the OE schema. Select Driver as thin, Host Name as localhost, SID as ORCL, and JDBC Port as 1521. Click on the Test Connection button to test the connection. If the connection gets established, click on OK: The OracleDBConnection gets added to the Database Navigator view. The CATALOG table that we created is listed in the Tables: (Move the mouse over the image to enlarge.) Creating an EJB 3 application In this section, we create an EJB 3.0 application in JDeveloper. Select New Application: Specify an Application Name, select the Java EE Web Application template, which consists of a Model project and a ViewController project, and click on Next: Next, specify the name (EJB3ViewController) for the View and Controller project. In the Project Technologies tab, transfer the EJB project technology from the Available list to the Selected list using the > button. We have selected the EJB project technology, as we shall be creating an EJB 3.0 model. Click on Next: Select the default Java settings for the View project and click on Next: Configure the EJB Settings for the View project. Select EJB Version as Enterprise JavaBeans 3.0 and select Using Annotations. Click on Next. Next, create the Model project. Specify the Project Name (EJB3Model for example), and in the Project Technologies tab transfer the EJB project technology from the Available list to the Selected list using the > button. We have added the EJB project technology, as the EJB 3.0 application client is created in the View project. Click on Next: Select the default Java settings for the Model project and click on Next: Similar to the View project, configure the EJB settings for the Model project. Select EJB Version as Enterprise JavaBeans 3.0, select Using Annotations and click on Finish. As we won't be using a jndi.properties file or an ejb-jar.xml file , we don't need to select the generate option for the jndi.properties file and the ejb-jar.xml file: An EJB 3.0 application, which consists of a Model project and a ViewController project, get added in the Application tab: Select the EJB3Model project in the Application navigator and select Tools | Project Properties. In the Project Properties window, select the Libraries and Classpath node. The EJB 3.0 library should be in the Classpath Entries: Select the EJB Module node and select the OracleDBConnection in the Connection drop-down list. The datasource corresponding to the OracleDBConnection is jdbc/OracleDBConnectionDS.
Read more
  • 0
  • 0
  • 3263

Packt
21 Mar 2013
13 min read
Save for later

Learn Cinder Basics – Now

Packt
21 Mar 2013
13 min read
(For more resources related to this topic, see here.) What is creative coding This is a really short introduction about what creative coding is, and I'm sure that it is possible to find out much more about this topic on the Internet. Nevertheless, I will try to explain how it looks from my perspective. Creative coding is a relatively new term for a field that combines coding and design. The central part of this term might be the "coding" one—to become a creative coder, you need to know how to write code and some other things about programming in general. Another part—the "creative" one—contains design and all the other things that can be combined with coding. Being skilled in coding and design at the same time lets you explain your ideas as working prototypes for interface designs, art installations, phone applications, and other fields. It can save time and effort that you would give in explaining your ideas to someone else so that he/she could help you. The creative coding approach may not work so well in large projects, unless there are more than one creative codes involved. A lot of new tools that make programming more accessible have emerged during the last few years. All of them are easy to use, but usually the less complicated a tool is, the less powerful it is, and vice versa. A few words about Cinder So we are up to some Cinder coding! Cinder is one of the most professional and powerful creative coding frameworks that you can get for free on the Internet. It can help you if you are creating some really complicated interactive real-time audio-visual piece, because it uses one of the most popular and powerful low-level programming languages out there—C++—and relies on minimum third-party code libraries. The creators of Cinder also try to use all the newest C++ language features, even those that are not standardized yet (but soon will be) by using the so called Boost libraries. This book is not intended as an A-to-Z guide about Cinder nor the C++ programming language, nor areas of mathematics involved. This is a short introduction for us who have been working with similar frameworks or tools and know some programming already. As Cinder relies on C++, the more we know about it the better. Knowledge of ActionScript, Java, or even JavaScript will help you understand what is going on here. Introducing the 3D space To use Cinder with 3D we need to understand a bit about 3D computer graphics. First thing that we need to know is that 3D graphics are created in a three-dimensional space that exists somewhere in the computer and is transformed into a two-dimensional image that can be displayed on our computer screens afterwards. Usually there is a projection (frustrum) that has different properties which are similar to the properties of cameras we have in the real world. Frustrum takes care of rendering all the 3D objects that are visible in frustrum. It is responsible for creating the 2D image that we see on the screen. As you can see in the preceding figure, all objects inside the frustrum are being rendered on the screen. Objects outside the view frustrum are being ignored. OpenGL (that is being used for drawing in Cinder) relies on the so called rendering pipeline to map the 3D coordinates of the objects to the 2D screen coordinates. Three kind of matrices are used for this process: the model, view, and projection matrices. The model matrix maps the 3D object's local coordinates to the world (or global) space, the view matrix maps it to the camera space, and finally the projection matrix takes care of the mapping to the 2D screen space. Older versions of OpenGL combine the model and view matrices into one—the modelview matrix. The coordinate system in Cinder starts from the top-left corner of the screen. Any object placed there has the coordinates 0, 0, 0 (these are values of x, y, and z respectively). The x axis extends to the right, y to the bottom, but z extends towards the viewer (us), as shown in the following figure: Drawing in 3D Let's try to draw something by taking into account that there is a third dimension. Create another project by using TinderBox and name it Basic3D. Open the project file ( xcode/Basic3D.xcodeproj on Mac or vc10\Basic3D.sln on Windows). Open Basic3DApp.cpp in the editor and navigate to the draw() method implementation. Just after the gl::clear() method add the following line to draw a cube: gl::drawCube( Vec3f(0,0,0), Vec3f(100,100,100) ); The first parameter defines the position of the center of the cube, the second defines its size. Note that we use the Vec3f() variables to de fine position and size within three (x, y and z) dimensions. Compile and run the project. This will draw a solid cube at the top-left corner of the screen. We are able to see just one quarter of it because the center of the cube is the reference point. Let's move it to the center of the screen by transforming the previous line as follows: gl::drawCube( Vec3f(getWindowWidth()/2,getWindowHeight()/2,0), Vec3f(100,100,100) ); Now we are positioning the cube in the middle of the screen no matter what the window's width or height is, because we pass half of the window's width (getWindowWidth()/2 ) and half of the window's height ( getWindowHeight()/2) as values for the x and y coordinates of the cube's location. Compile and run the project to see the result. Play around with the size parameters to understand the logic behind it. We may want to rotate the cube a bit. There is a built-in rotate() function that we can use. One of the things that we have to remember, though, is that we have to use it before drawing the object. So add the following line before gl::drawCube(): gl::rotate( Vec3f(0,1,0) ); Compile and run the project. You should see a strange rotation animation around the y axis. The problem here is that the rotate() function rotates the whole 3D world of our application including the object in it and it does so by taking into account the scene coordinates. As the center of the 3D world (the place where all axes cross and are zero) is in the top-left corner, all rotation is happening around this point. To change that we have to use the translate() function. It is used to move the scene (or canvas) before we rotate() or drawCube(). To make our cube rotate around the center of the screen, we have to perform the following steps: Use the translate() function to translate the 3D world to the center of the screen. Use the rotate() function to rotate the 3D world. Draw the object (drawCube()). Use the translate()function to translate the scene back. We have to use the translate() function to translate the scene back to the location, because each time we call translate() values are added instead of being replaced. In code it should look similar to the following: gl::translate( Vec3f(getWindowWidth()/2,getWindowHeight()/2,0) ); gl::rotate( Vec3f::yAxis()*1 ); gl::drawCube( Vec3f::zero(), Vec3f(100,100,100) ); gl::translate( Vec3f(-getWindowWidth()/2,-getWindowHeight()/2,0) ); So now we get a smooth rotation of the cube around the y axis. The rotation angle around y axis is increased in each frame by 1 degree as we pass the Vec3f::yAxis()*1 value to the rotate() function. Experiment with the rotation values to understand this a bit more. What if we want the cube to be in a constant rotated position? We have to remember that the rotate() function works similar to the translate function. It adds values to the rotation of the scene instead of replacing them. Instead of rotating the object back, we will use the pushMatrices() and popMatrices() functions. Rotation and translation are transformations. Every time you call translate() or rotate() , you are modifying the modelview matrix. If something is done, it is sometimes not so easy to undo it. Every time you transform something, changes are being made based on all previous transformations in the current state. So what is this state? Each state contains a copy of the current transformation matrices. By calling pushModelView() we enter a fresh state by making a copy of the current modelview matrix and storing it into the stack. We will make some crazy transformations now without worrying about how we will undo them. To go back, we call popModelView() that pops (or deletes) the current modelview matrix from the stack, and returns us to the state with the previous modelview matrix. So let's try this out by adding the following code after the gl::clear() call: gl::pushModelView(); gl::translate( Vec3f(getWindowWidth()/2,getWindowHeight()/2,0) ); gl::rotate( Vec3f(35,20,0) ); gl::drawCube( Vec3f::zero(), Vec3f(100,100,100) ); gl::popModelView(); Compile and run our program now, you should see something similar to the following screenshot: As we can see, before doing anything, we create a copy of the current state with pushModelView(). Then we do the same as before, translate our scene to the middle of the screen, rotate it (this time 35 degrees around x axis and 20 degrees around y axis), and finally draw the cube! To reset the stage to the state it was before, we have to use just one line of code, popModelView(). Using built-in eases Now, say we want to make use of the easing algorithms that we saw in the EaseGallery sample. To do that, we have to change the code by following certain steps. To use the easing functions, we have to include the Easing.h header file:#include "cinder/Easing.h" First we are going to add two more variables, startPostition and circleTimeBase: Vec2f startPosition[CIRCLE_COUNT]; Vec2f currentPosition[CIRCLE_COUNT]; Vec2f targetPosition[CIRCLE_COUNT]; float circleRadius[CIRCLE_COUNT]; float circleTimeBase[CIRCLE_COUNT]; Then, in the setup() method implementation, we have to change the currentPosition parts to startPosition and add an initial value to the circleTimeBase array members: startPosition[i].x = Rand::randFloat(0, getWindowWidth()); startPosition[i].y = Rand::randFloat(0, getWindowHeight()); circleTimeBase[i] = 0; Next, we have to change the update() method so that it can be used along with the easing functions. They are based on time and they return a floating point value between 0 and 1 that defines the playhead position on an abstract 0 to 1 timeline: void BasicAnimationApp::update() { Vec2f difference; for (int i=0; i<CIRCLE_COUNT; i++) { difference = targetPosition[i] - startPosition[i]; currentPosition[i] = easeOutExpo( getElapsedSeconds()-circleTimeBase[i]) * difference + startPosition[i]; if ( currentPosition[i].distance(targetPosition[i]) < 1.0f ) { targetPosition[i].x = Rand::randFloat(0, getWindowWidth()); targetPosition[i].y = Rand::randFloat(0, getWindowHeight()); startPosition[i] = currentPosition[i]; circleTimeBase[i] = getElapsedSeconds(); } } } The highlighted parts in the preceding code snippet are those that have been changed. The most important part of it is the currentPosition[i] calculation part. We take the distance between the start and end points of the timeline and multiply it with the position floating point number that is being returned by our easing function, which in this case is easeOutExpo() . Again, it returns a floating point variable between 0 and 1 that represents the position on an abstract 0 to 1 timeline. If we multiply any number with, say, 0.33f, we get one-third of that number, 0.5f, we get one-half of that number, and so on. So, we add this distance to the circle's starting position and we get it's current position! Compile and run our application now. You should see something as follows: Almost like a snow storm! We will add a small modification to the code though. I will add a TWEEN_SPEED definition at the top of the code and multiply the time parameter passed to the ease function with it, so we can control the speed of the circles: #define TWEEN_SPEED 0.2 Change the following line in the update() method implementation: currentPosition[i] = easeOutExpo( (getElapsedSeconds()-circleTimeBase[i])*TWEEN_SPEED) * difference + startPosition[i]; I did this because the default time base for each tween is 1 second. That means that each transition is happening exactly for 1 second and that's a bit too fast for our current situation. We want it to be slower, so we multiply the time we pass to the easing function with a floating point number that is less than 1.0f and greater than 0.0f. By doing that we ensure that the time is scaled down and instead of 1 second we get 5 seconds for our transition. So try to compile and run this, and see for yourself! Here is the full source code of our circle-creation: #include "cinder/app/AppBasic.h" #include "cinder/gl/gl.h" #include "cinder/Rand.h" #include "cinder/Easing.h" #define CIRCLE_COUNT 100 #define TWEEN_SPEED 0.2 using namespace ci; using namespace ci::app; using namespace std; class BasicAnimationApp : public AppBasic { public: void setup(); void update(); void draw(); void prepareSettings( Settings *settings ); Vec2f startPosition[CIRCLE_COUNT]; Vec2f currentPosition[CIRCLE_COUNT]; Vec2f targetPosition[CIRCLE_COUNT]; float circleRadius[CIRCLE_COUNT]; float circleTimeBase[CIRCLE_COUNT]; }; void BasicAnimationApp::prepareSettings( Settings *settings ) { settings->setWindowSize(800,600); settings->setFrameRate(60); } void BasicAnimationApp::setup() { for(int i=0; i<CIRCLE_COUNT; i++) { currentPosition[i].x=Rand::randFloat(0, getWindowWidth()); currentPosition[i].y=Rand::randFloat(0, getWindowHeight()); targetPosition[i].x=Rand::randFloat(0, getWindowWidth()); targetPosition[i].y=Rand::randFloat(0, getWindowHeight()); circleRadius[i] = Rand::randFloat(1, 10); startPosition[i].x = Rand::randFloat(0, getWindowWidth()); startPosition[i].y = Rand::randFloat(0, getWindowHeight()); circleTimeBase[i] = 0; } } void BasicAnimationApp::update() { Vec2f difference; for (int i=0; i<CIRCLE_COUNT; i++) { difference = targetPosition[i] - startPosition[i]; currentPosition[i] = easeOutExpo( (getElapsedSeconds()-circleTimeBase[i]) * TWEEN_SPEED) * difference + startPosition[i]; if ( currentPosition[i].distance( targetPosition[i]) < 1.0f ) { targetPosition[i].x = Rand::randFloat(0, getWindowWidth()); targetPosition[i].y = Rand::randFloat(0, getWindowHeight()); startPosition[i] = currentPosition[i]; circleTimeBase[i] = getElapsedSeconds(); } } } void BasicAnimationApp::draw() { gl::clear( Color( 0, 0, 0 ) ); for (int i=0; i<CIRCLE_COUNT; i++) { gl::drawSolidCircle( currentPosition[i], circleRadius[i] ); } } CINDER_APP_BASIC( BasicAnimationApp, RendererGl ) Experiment with the properties and try to change the eases. Not all of them will work with this example, but at least you will understand how to use them to create smooth animations with Cinder. Summary This article explains what is Cinder, introduces the 3D space, how to draw in 3D, and also explains in short about using built-in eases. Resources for Article : Further resources on this subject: 3D Vector Drawing and Text with Papervision3D: Part 1 [Article] Sage: 3D Data Plotting [Article] Building your First Application with Papervision3D: Part 2 [Article]
Read more
  • 0
  • 0
  • 3263
Modal Close icon
Modal Close icon