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

How-To Tutorials - Front-End Web Development

341 Articles
Packt
20 May 2013
15 min read
Save for later

Play! Framework 2 – Dealing with Content

Packt
20 May 2013
15 min read
(For more resources related to this topic, see here.) In order to keep the article short and to the point, we'll only see the Java part. Keep in mind that the Scala version is little different for this level of detail. Body parsing for better reactivity As noted earlier, the way to manage content in Play! 2 is to use instances of body parsers. In brief, a body parser is a component that is responsible for parsing the body of an HTTP request as a stream to be converted into a predefined structure. This has a common sense ring to it, however their strength is in their way of consuming the stream—in a reactive fashion. Reactivity, in this context, is meant to describe a process where an application won't block on a task that is actually idle. As a stream consumption task is idle when no bytes are incoming, a body parser should behave the same. It will read and construct an internal representation of the incoming bytes. But it can also decide at any time that it has read enough to terminate and return the representation. On the other hand, if no more bytes are coming into the stream, it can relax its thread in favor of another request; it pauses its work until new bytes are received. Thinking about an HTTP request that is sending a bunch of XML content, the underlying action can use the XML-related body parser to handle it correctly (read reactively); that is, by parsing it and providing a DOM representation. To understand what a body parser actually is, we'll first look at how they are used—in the actions. An action in Play! 2 represents the piece of software that is able to handle an HTTP request; therefore, they are the right place to use a body parser. In the Java API, an action is allowed to be annotated with the Of annotation available in the BodyParser class. This annotation declares the expected type of request routed to it, and it requires a parameter that is the class of the parser that will be instantiated to parse the incoming request's body. The following screenshot shows an example: Isn't this helpful? We've gone from a request to a W3C document, in a single line. Functionally speaking, this works because an action is semantically a higher-order function that takes a body parser and generates a function that takes a request (and so its body) and results in an HTTP response (result). This result will then be used to construct the HTTP response by Play! 2. In Java, it is not all that obvious how to create a higher-order function. A good way, however, to achieve this was to add an annotation. An annotation can be processed at runtime in order to execute the right body parser (in this case). To illustrate this, we'll have a quick look at the Scala version: With this Scala version, it is easy to see that an action is dealing with a function from a request to a response. There are a plenty of predefined body parsers that can be used to handle our requests, and they are all defined in the BodyParser class as static inner classes. One can have a specific behavior to be applied on its expected request body, and even though a body parser has to be implemented in Scala, a Java coder can simply extend these current implementations. Actually, they're already providing enough control to cover all custom use cases. So, we have in our hands tools to handle the following content types: JSON XML URL form encoded Multipart (for uploading files) Text Raw (fallback) As we can see from the previous list, there is, obviously, an implementation for the x-www-form-urlencoded content type. Indeed, this is the parser we've used so far to retrieve data from the client side. For example, using POST requests throughout HTML forms. But wait, we never had to add such annotations to our actions, and, moreover, we've never looked in the parsed result. That's true, Play! 2, as a great framework, is already doing a lot of stuff for us. And that's because it's a web framework; it takes advantage of HTTP; in this case, using the content-type header. Based on this hint, it seems obvious that Play! Framework 2 will look in this header to find the right parser to apply. So annotations are mandatory, but where did we use them previously? In the bindFromRequest method, of course. Let's see how. We have used form instances, and we fed them some data through the client. Those instances were applied on the request using the bindFromRequest method, and this method's job was to look for data according to the provided content type. And, of course, this content type was set in the header by the HTML forms themselves. Indeed, an HTTP GET will send data in the request URL (query string), where an HTTP POST will be sent with a body that contains all data encoded by default as URL parameters (that is, x-www-url-encoded). So, we can now give an overview of what the bindFromRequest method does. When we ask a form to be filled in with data, this method will: Gather data as URL-form encoded data, if any Gather data from parts (if the content type is multipart-data) Gather data as JSON-encoded, if any Gather data from the query string (that's why GET requests were working as well)/p> Fill in the form's data with all of them (and validate) You might be wondering the worth of such annotations; the quick answer to that is they allow new types of parsers, but they can also enforce certain actions' requests to match a given content type. Another advantage of such annotations is that they allow us to extend or narrow the length of the body that can be handled. By default, 100 K are accepted, and this can be either configured (parsers.text.maxLength=42K) or passed as an argument to the annotation. With all of this in mind, we are now ready to implement these concepts in our code, and what we're going to do is to update our code base to create a kind of forum. A forum where one can log in, initiate a chat, reply to non-closed ones (based on their date), or even attach files to them. Creating a forum In this section, we'll refactor our existing application in order to enable it to act as a forum. And, chances are high that it won't be necessary to learn anything new; we'll just re-use the skills gathered so far; but we'll also use the parsing commodities that Play! 2 offers us. Reorganizing and logging in The very first thing we have to do is to enable a user to log in; this ability was already created in the Data controller. However, for that, we'll update our Application controller a bit, to create a new index action that will check whether a user is logged in or not. So, index is now the new entry point of the application and can be routed from / in the routes file. And, it's solely meant to check if a user has logged in or not. This check is based on the session content, as we simply check whether a user's e-mail is present in the session. We never see what a session can be in Play! 2, but we saw that Play! 2 is completely stateless. So, a session in Play! 2 is only an encrypted map of the value stored in the cookie. Thus it cannot be that big, and definitely cannot contain full data. If the user is present, we redirect the request to the chatroom by calling redirect with the expected action. This will prevent the browser from posting the request again if the user reloads the page. This method is called POST-redirect-GET. Otherwise, we respond with an Unauthorized HTTP response (401) that contains the HTML login page. The two actions (shown in the next screenshot) are so simple that we won't cover them further, except for a single line: session().clear(). It is simply revoking the cookie's content, which will require the subsequent request to create a new one, which then doesn't contain the previously stored e-mail. And finally, enter, which shows how a request's body can easily be handled using the relevant method: asFormUrlEncoded. It should look like that shown in the following screenshot: Indeed, one would normally have to use a form to retrieve this information for us, which would do it for us (behind the scenes); but in this case we have only a single parameter to retrieve, so a form would be overkill. So far, so good; we are now able to create a user, log in with it, and use a login page. To target having cleaner code, it would be worth splitting the Data controller code into several pieces (matter of a good separation of subject). Hence, the Users controller is created, in which will be placed the user-related actions taken out of Data. Now, we'll move back to something we saw earlier but didn't cover—the routes. Chats.allChats() action call. Chatting In the previous section, we were introduced to the Chats controller and its allChats action. If the names are self-descriptive, the underlying code isn't that much. First of all, we're now dealing with Chat instances that must be persisted somewhere in a database, along with their underlying items. But we'll also prepare for the next section, which relates to multipart data (for instance, it's helpful for file upload). That's why we'll add a brand new type, Image, which is also linked to Chat. Having said that, it would be worth checking our new chat implementation: Before we cover the Item and Image types, we'll first go to the Chats controller to see what's going on. Finally, we can see our allChats action; it's simply rendering all existing instances within a template. Even the rest of the controller is simple; everything is done in templates, which are left as exercises (we're so good at them now!). However, there's still the loadChat action that contains something related to this article: Long chatId = Long.parseLong(queryString.get("chatid")[0]); This action handles requests asking to show a particular Chat instance, which is a resource and thus should be served using a GET request. This implies that the parameter value is stored in the query string (or in the URL itself) rather than in the request body. Regarding query string access, it's more interesting to analyze the following line: Map<String,String[]> queryString = request().queryString(); In fact, all actions contextually refer to a request object, which is accessible using the request() method. This request object declares a queryString() method that returns a map of string and an array of strings. What comes next is trivial; we just get chatid out of this map (ok... in a very unsafe way). Until now, we have been able to log in and access the chatroom, where we can create or show chat instances. But we're still unable to reply to a chat. That's what will be tackled now. For that, we need to create an action that will, based on a chat ID, post a new message linked to the logged in user, and then attach this message as an item of the underlying Chat instance. For this, we must update the Item class with persistence information. Afterwards, we'll be able to update the Chats controller in order to create instances. Ok, it's like a beefed-up POJO; let's jump into the action that will create Item instances. The workflow to post a message for a user starts by enabling him/her to participate in a chat. This is done by loading it (using the loadChat action) where the user will be able to post a new message (an overview of the UI will be presented at the end of this article for illustration only). The following screenshot shows how it can be done: Observe how the user was recovered using the session. Still, nothing cumbersome to review here, we've just re-used a lot of stuff we've already covered. The action receives a POST request in which information about the message is given, and then we can bind the request to itemForm and finally save to the database the item contained in the resulting form. At most, we should notice that we're still free to encode the body as we want, and also that the chat ID is not a part of the form but a part of the action signature—that's because it is a part of the URL (routing). We've almost finished our forum; the only thing needed is to enable users to post images. Handling multipart content types The HTTP protocol is ready to accept, from a client, a lot of data and/or large chunks of data, at once. A way to achieve this is to use a specific encoding type: multipart/form-data. Such requests will have a body that can hold several data pieces formatted differently and attributed with different names. So, Play! 2 is a web framework that fits into HTTP as much as possible; that's why it deals with such requests goods, and provides an API that hides almost all of the tricky parts. In this section, we'll see how one could upload an image along with some caption text that will be attached to a specific chat. Before diving into the workflow, let's first create the holding structure: Image. This newly introduced type is not hard to understand as well; only two things should be pointed out: The pic() method that relies on the filePath field to recover the file itself. It uses a File instance to memorize subsequent calls. The enum type that prepares the action logic to filter the incoming files based on the given MIME type. This logic could also be defined in the validate method. These instances are always locked in with the connected user who uploaded it and will be added to a Chat instance. This will allow a chatroom to display all attached images with their caption beside the messages themselves. Now we're ready to look at the file upload itself by paying some attention to the last action of the Chats controller, that is, receiveImage. As we are used to simplifying the code (Play! 2 is there to ease our work, after all) and to get straight to the point, we reflected this in our receiveImage action.. In a very few lines, we declared a new action that expects requests to be multipart encoded containing at least two parts, where the first is a map of data (no matter how this map is encoded) to fill in imageForm (essentially a caption). The second will be the image part. After binding the request with the form and verifying that no errors have occurred, we can move to the body content in order to recover the binary data that was sent along with its metadata: the file content, its content type, its length, and so on. That was quite an intuitive thing to do – asking the body to be parsed as a multipart/multidata and and get it as an Http.MultipartFormData object, which has a getFile method that returns an Http.MultipartFormData.FilePart value. To understand why we didn't specify a body parser, recall that Play! 2 is able, most of the time, to discover which method fits best by itself. The Http.MultipartFormData. FilePart type is not only allowing us to recover the content as a file, but also its key in the multipart body, its filename header, and (especially) its content type. Having all of these things in hand, we are now able to check the content-type validity against the image's enum, and to store the image by getting the file path of the provided file. This file path will target the Temp directory of your machine. In the real world, the file should be relocated in a dedicated folder or maybe on an S3 repository. Et voilà! We have now learned about some of the features that can provide a very simple forum. The following screenshot shows what it could look like (without any efforts on the design, of course). First, the forms to show and enter archived and active chats: On entering an active chat, let's say the one named Today, we reach a page similar to the one shown next: Using the Attach an image form, we can select an image on our filesystem to be sent to the server. The result obtained is shown as follows: Until now, we have spoken about handling various content types coming from the outside world, but what about our application having to render content other than HTML? That's what we're about to see next.
Read more
  • 0
  • 0
  • 1330

article-image-basic-use-local-storage
Packt
26 Apr 2013
5 min read
Save for later

Basic use of Local Storage

Packt
26 Apr 2013
5 min read
(For more resources related to this topic, see here.) Getting ready For this article, all you need is your browser and favorite text editor. How to do it... Perform the following steps: Let's begin with creating a blank document in your text editor. Then, add the following code and save it as a test localdemo.html: <!DOCTYPE html> <html> <head> <script src = "http://code.jquery.com/jquery-1.8.1.min.js"></script> <script type="text/javascript"> </script> </head> <body> </body> </html> In between the <script> tags, add the following function. This copes with storing the information within the browser. <script type="text/javascript"> function storeItem() { var item = $('#item').val(); var items = localStorage.getItem('myItems'); if (items != null) { items = JSON.parse(items); } else { items = new Array(); } items.push(item); localStorage.setItem('myItems', JSON.stringify(items)); refresh(); } </script> We need to add another function to retrieve information and refresh the content displayed on screen. So go ahead and update the script as highlighted: <script type="text/javascript"> function storeItem() { var item = $('#item').val(); var items = localStorage.getItem('myItems'); if (items != null) { items = JSON.parse(items); } else { items = new Array(); } items.push(item); localStorage.setItem('myItems', JSON.stringify(items)); refresh(); } function refresh() { var items = localStorage.getItem('myItems'); var ul = $('ul'); ul.html(''); if (items != null) { items = JSON.parse(items); $(items).each(function (index, data) { ul.append('<li>' + data + '</li>'); }); } } $(function () { refresh(); }); </script> We finish by adding a basic form—while the purists amongst you will notice that it doesn't have all of the proper forms of tag, it is enough to illustrate how this demo works. Add the following code snippet, just above the closing </body> tag: Enter item: <input type="text" id="item" /> <input type="button" value= "store" onclick="storeItem()" /> <br /> <ul></ul> Crack open your browser and preview the results. Here's a screenshot of what you should see, with some example values already entered: How it works... Now we've seen Local Storage in action, let's take a look at how it works in detail. HTML5 Local Storage works on the principle of named key/value pairs, where you store information using a named key and retrieve it by calling that named key. Everything is stored locally on the user's PC; it cuts down the need to retrieve information from the server, thereby acting as a form of caching. You may have noticed that we've used jQuery in this article—basic use of LocalStorage (and SessionStorage) doesn't necessarily need jQuery; you could use pure JavaScript if you prefer. It all depends on your requirements; if you are already using jQuery in your pages, for example, you may prefer to use this over JavaScript. (You will see I have used a mix of both throughout this book, to show you how you can use either jQuery or JavaScript). In this article, we've used jQuery to reference LocalStorage; if you take a look at the code, you will see two lines of particular importance: var items = localStorage.getItem('myItems'); localStorage.setItem('myItems', JSON.stringify(items)); These two handle the retrieval and setting of values respectively. In this demo, we begin with either fetching the contents of any existing stored information and inserting them into an array, or creating a new one, if nothing exists within the store. We then use JSON. stringify() to convert information from the form into a string, push this into the storage, and then refresh the page so that you can see the updated list. To get the information back, we simply repeat the same steps, but in the reverse way. The beauty of using JSON as part of storing information in this way is that you are not entirely limited to just plain text; you can store some other things in the LocalStorage area, as we will see later in this book. There's more... By now, you will start to see that using Local Storage works very much in the same way that cookies do—indeed some people often refer to Local Storage as "cookies on steroids". This said, there are still some limitations that you need to be aware of when using Local Storage, such as the following: Local Storage will only support text as a format and is set to a suggested arbitary limit of 5 MB, although this is inconsistent across browsers. If you exceed this, the QUOTA_EXCEEDED_ERR error is thrown. At the time of writing this book, there is no support built in for requesting more space. Some browsers such as Opera will allow the user to control each site's quota, but this is a purely userbased action. Web Storage is no more secure than cookies; although use of the HTTPS protocol can resolve a lot of security issues, it is still up to you as a developer to ensure that sensitive information (such as passwords) is not sent to or stored locally on the client using Web Storage. With careful use, we can take advantage of the ability to store relevant information on a user's PC, and avoid the need to push it back to the server. Once the information has been stored, there will be occasions when you will need to view the raw information from within your browser—this is easy enough to do, although the method varies from browser to browser, which we will see as part of the next article. Summary In this article we discussed basic use of HTML5 Local Storage. Resources for Article : Further resources on this subject: Blocking versus Non blocking scripts [Article] Building HTML5 Pages from Scratch [Article] HTML5 Games Development: Using Local Storage to Store Game Data [Article]
Read more
  • 0
  • 0
  • 1641

article-image-so-what-easeljs
Packt
18 Apr 2013
7 min read
Save for later

So, what is EaselJS?

Packt
18 Apr 2013
7 min read
(For more resources related to this topic, see here.) EaselJS is part of the CreateJS suite, a JavaScript library for building rich and interactive experiences, such as web applications and web-based games that run on desktop and mobile web browsers. The standard HTML5 canvas' syntax can be very hard for beginners, especially if you need to animate and draw many objects. EaselJS greatly simplifies application development in HTML5 canvas using a syntax and an architecture very similar to the ActionScript 3.0 language. As a result, Flash/Flex developers will immediately feel at home, but it's very easy to learn even if you've never opened Flash in your life. CreateJS is currently supported by Adobe, AOL, and Microsoft, and it's developed by Grant Skinner, an internationally recognized leader in the field of rich Internet application development. Thanks to EaselJS, you can easily manage many types of graphic elements (vector shapes, bitmap, spritesheets, texts, and HTML elements) and it also supports touch events, animations, and many other interesting features in order to quickly develop cross-platform HTML5 games and applications, providing a look and feel as well as a behavior very similar to native applications for iOS and Android. Following are the five reasons to choose EaselJS and HTML5 canvas to build your applications: Cross-platform — Using this technology will help you create HTML5 canvas applications that will be supported from: Desktop browsers such as Chrome, Safari, Firefox, Opera, and IE9+ iPhone, iPad, and iPod 4+ (iOS 3.2+) Android smartphones and tablets (OS 2.1+) BlackBerry browser (7.0 and 10.0+) Every HTML5 browser (go to http://caniuse.com/canvas for more information) The following screenshot shows how the same application can run on different devices and resolutions: Easy Integration — EaselJS applications run on browsers and finally can be seen by almost every desktop and mobile user without any plugin installed. The HTML5 canvas element behaves just like any other HTML element. It can overlap other elements or become part of an existing HTML page. So, your canvas application can fill the entire browser area or just a small part of an existing HTML page. You can create amazing image galleries for your sites, product configurators, microsites, games, and interactive banners, and replicate a lot of features that used to be created with Adobe Flash or Apache Flex. One source code — A single codebase can be used to create a responsive application that works on almost all devices and resolutions. If you've ever created a liquid or fluid layout using HTML, Flash, or Flex then you already know this concept. As shown in the previous screenshot, you can also adapt UI and change behaviors according to the size of the device being used. No creativity limits — As in Flash, you can now forget HTML DOM compatibility issues. When you display a graphic element using EaselJS, you can be sure it will be placed at the same position in every browser, desktop and mobile (except for texts because every browser uses a different font renderer, and there may be some minor differences between them and of course Internet Explorer 8 and lower versions that do not support HTML5 syntax). Furthermore the CreateJS suite includes a lot of additional tools helping developers and designers to create amazing stuff: TweenJS: An useful tween engine to create runtime animations PreloadJS: To load assets and create nice preloaders Zoë: To convert SWF (Adobe Flash native web format) into spritesheets and JSON for EaselJS SoundJS: A library to play sounds (this topic is not covered in this book) CreateJS Toolkit for Flash CS6: To export Flash timeline animations in an EaselJS-compatible format Freedom — Developers can now create and publish games and applications skipping the App Store submission process. Of course, the performance of HTML5 applications are not comparable to those achieved by the native applications but can still be an alternative solution to many needs. From a business perspective, it's a great opportunity because it is now possible to avoid following the Apple guidelines that usually don't allow publishing applications that are primarily marketing material or advertisements, duplicated applications or applications that are not very useful, or simply websites bundled as applications. Users can now have a cool touch experience directly while navigating through a website, avoiding having to download, install, and open a native application. Furthermore, developers can also use PhoneGap (http://www.phonegap.com) and many other technologies to convert their HTML applications in native applications for iOS, Android, Windows Phones, BlackBerry, Bada, or WebOS. After the previous introduction you will be guided through the process of downloading, installing and configuring EaselJS in your local machine (this part of the book is not copied in this article). The book continues with the traditional "Hello World" example, as shown in the next paragraph: Quick start — creating your first canvas application Now we'll see how to create our first HTML5 canvas application with EaselJS. Step 1 — creating the HTML template Take a look at the following code that represents the boilerplate we'll use: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>EaselJS Starter: Template Page</title> <script src = "lib/easeljs-0.6.0.min.js"></script> <script> // Your code here function init() { } </script> </head> <body onload="init();" style="background-color:# ccc "> <h1> EaselJS Starter: Template page </h1> <canvas id="mycanvas" width="960" height="450" style="background-color:#fff"></canvas> </body> </html> The following are the most important steps of the previous code: Define an HTML5 <canvas> object with a width of 960 pixels and a height of 450 pixels. This represents the drawing area of your EaselJS application. When the page is completely loaded, the onload event is fired and the init() function is called. The <script> block is the place where you have to add the code but you should always wait for the onload events before you do anything. Set the <body> and <canvas> background CSS styles. The result is a white container inside an HTML page, as shown in the following screenshot: Step 2 – creating a "Hello World" example Now replace the init() function with the following code: function init() { var canvas = document.getElementById("mycanvas"); var stage = new createjs.Stage(canvas); var text = new createjs.Text("Hello World!", "36px Arial", "#777"); stage.addChild(text); text.x = 360; text.y = 200; stage.update(); } Congrats! You have created your first canvas application! The following screenshot shows the output of the previous code, with a text field at the center of the canvas: The following are the most important steps of the previous code: Use the getElementById method to get a canvas reference. In order to use EaselJS, create a Stage property, passing the canvas reference as a parameter. Create a new Text property and add it to the stage. Assign values for the x and y coordinates in order to see the text at the center of the stage. Call the update() method on the stage to render it to the canvas. The Stage property represents the root level for the display list, which is the main container for all the other graphic elements. Now you only need to know that every graphic element must be added to the Stage property, and that every time you need to update your content you have to refresh the stage calling the update() method. Summary After the previous "Hello World" example the book will help you to learn how to use the most important EaselJS topics with practical examples, technical information, and a lot of tip and tricks, creating a small advertising interactive web application. By the end of book you will be able to draw graphic primitives and texts, load and preload images, handle mouse events, add animations and spritesheets, use TweenJS, PreloadJS, and Zoe and optimize your code for desktop and mobile devices. This article helped you to learn what EaselJS actually is, what you can do with it, and why it's so great. It also helped on hoe to create your first HTML5 canvas application "Hello World". Resources for Article : Further resources on this subject: HTML5: Developing Rich Media Applications using Canvas [Article] HTML5 Games Development: Using Local Storage to Store Game Data [Article] HTML5: Getting Started with Paths and Text [Article]
Read more
  • 0
  • 0
  • 2828
Banner background image

article-image-show-hide-rows-and-highlighting-cells
Packt
09 Apr 2013
7 min read
Save for later

Show/hide rows and Highlighting cells

Packt
09 Apr 2013
7 min read
(For more resources related to this topic, see here.) Show/hide rows Click a link to trigger hiding or displaying of table rows. Getting ready Once again, start off with an HTML table. This one is not quite as simple a table as in previous recipes. You'll need to create a few <td> tags that span the entire table, as well as provide some specific classes to certain elements. How to do it... Again, give the table an id attribute. Each of the rows that represent a department, specifically the rows that span the entire table, should have a class attribute value of dept. <table border="1" id="employeeTable"> <thead> <tr> <th>Last Name</th> <th>First Name</th> <th>Phone</th> </tr> </thead> <tbody> <tr> <td colspan="3" class="dept"> </td> </tr> Each of the department names should be links where the <a> elements have a class of rowToggler. <a href="#" class="rowToggler">Accounting</a> Each table row that contains employee data should have a class attribute value that corresponds to its department. Note that class names cannot contain spaces. So in the case of the Information Technology department, the class names should be InformationTechnology without a space. The issue of the space will be addressed later. <tr class="Accounting"> <td>Frang</td> <td>Corey</td> <td>555-1111</td> </tr> The following script makes use of the class names to create a table whose rows can be easily hidden or shown by clicking a link: <script type="text/javascript"> $( document ).ready( function() { $( "a.rowToggler" ).click( function( e ) { e.preventDefault(); var dept = $( this ).text().replace( /s/g, "" ); $( "tr[class=" + dept + "]" ).toggle(); }) }); </script> With the jQuery implemented, departments are "collapsed", and will only reveal the employees when the link is clicked. How it works... The jQuery will "listen" for a click event on any <a> element that has a class of rowToggler. In this case, capture a reference to the event that triggered the action by passing e to the click handler function. $( "a.rowToggler" ).click( function( e ) In this case, e is simply a variable name. It can be any valid variable name, but e is a standard convention. The important thing is that jQuery has a reference to the event. Why? Because in this case, the event was that an <a> was clicked. The browser's default behavior is to follow a link. This default behavior needs to be prevented. As luck would have it, jQuery has a built-in function called preventDefault(). The first line of the function makes use of this by way of the following: e.preventDefault(); Now that you've safely prevented the browser from leaving or reloading the page, set a variable with a value that corresponds to the name of the department that was just clicked. var dept = $( this ).text().replace( /s/g, "" ); Most of the preceding line should look familiar. $( this ) is a reference to the element that was clicked, and text() is something you've already used. You're getting the text of the <a> tag that was clicked. This will be the name of the department. But there's one small issue. If the department name contains a space, such as "Information Technology", then this space needs to be removed. .replace( /s/g, "" ) replace() is a standard JavaScript function that uses a regular expression to replace spaces with an empty string. This turns "Information Technology" into "InformationTechnology", which is a valid class name. The final step is to either show or hide any table row with a class that matches the department name that was clicked. Ordinarily, the selector would look similar to the following: $( "tr.InformationTechnology" ) Because the class name is a variable value, an alternate syntax is necessary. jQuery provides a way to select an element using any attribute name and value. The selector above can also be represented as follows: $( "tr[class=InformationTechnology]" ) The entire selector is a literal string, as indicated by the fact that it's enclosed in quotes. But the department name is stored in a variable. So concatenate the literal string with the variable value: $( "tr[class=" + dept + "]" ) With the desired elements selected, either hide them if they're displayed, or display them if they're hidden. jQuery makes this very easy with its built-in toggle() method. Highlighting cells Use built-in jQuery traversal methods and selectors to parse the contents of each cell in a table and apply a particular style (for example, a yellow background or a red border) to all cells that meet a specified set of criteria. Getting ready Borrowing some data from Tiobe (http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html), create a table of the top five programming languages for 2012. To make it "pop" a bit more, each <td> in the Ratings column that's over 10 percent will be highlighted in yellow, and each <td> in the Delta column that's less than zero will be highlighted in red. Each <td> in the Ratings column should have a class of ratings, and each <td> in the Delta column should have a class of delta. Additionally, set up two CSS classes for the highlights as follows: .highlight { background-color: #FFFF00; } /* yellow */ .highlight-negative { background-color: #FF0000; } /* red */ Initially, the table should look as follows: How to do it... Once again, give the table an id attribute (but by now, you knew that), as shown in the following code snippet: <table border="1" id="tiobeTable"> <thead> <tr> <th>Position<br />Dec 2012</th> <th>Position<br />Dec 2011</th> <th>Programming Language</th> <th>Ratings<br />Dec 2012</th> <th>Delta<br />Dec 2011</th> </tr> </thead> Apply the appropriate class names to the last two columns in each table row within the <tbody>, as shown in the following code snippet: <tbody> <tr> <td>1</td> <td>2</td> <td>C</td> <td class="ratings">18.696%</td> <td class="delta">+1.64%</td> </tr> With the table in place and properly marked up with the appropriate class names, write the script to apply the highlights as follows: <script type="text/javascript"> $( document ).ready( function() { $( "#tiobeTable tbody tr td.ratings" ).each( function( index ) { if ( parseFloat( $( this ).text() ) > 10 ) { $( this ).addClass( "highlight" ); } }); $( "#tiobeTable tbody tr td.delta" ).each( function( index ) { if ( parseFloat( $( this ).text() ) < 0 ) { $( this ).addClass( "highlight-negative" ); } }); }); </script> Now, you will see a much more interesting table with multiple visual cues: How it works... Select the <td> elements within the tbody tag's table rows that have a class of ratings. For each iteration of the loop, test whether or not the value (text) of the <td> is greater than 10. Because the values in <td> contain non-numeric characters (in this case, % signs), we use JavaScript's parseFloat() to convert the text to actual numbers: parseFloat( $( this ).text() ) Much of that should be review. $( this ) is a reference to the element in question. text() retrieves the text from the element. parseFloat() ensures that the value is numeric so that it can be accurately compared to the value 10. If the condition is met, use addClass() to apply the highlight class to <td>. Do the same thing for the Delta column. The only difference is in checking to see if the text is less than zero. If it is, apply the class highlight-negative. The end result makes it much easier to identify specific data within the table. Summary In this article we covered two recipes Show/hide rows and Highlighting cells. Resources for Article : Further resources on this subject: Tips and Tricks for Working with jQuery and WordPress5 [Article] Using jQuery Script for Creating Dynamic Table of Contents [Article] Getting Started with jQuery [Article]
Read more
  • 0
  • 0
  • 2051

article-image-building-custom-version-jquery
Packt
04 Apr 2013
9 min read
Save for later

Building a Custom Version of jQuery

Packt
04 Apr 2013
9 min read
(For more resources related to this topic, see here.) Why Is It Awesome? While it's fairly common for someone to say that they use jQuery in every site they build (this is usually the case for me), I would expect it much rarer for someone to say that they use the exact same jQuery methods in every project, or that they use a very large selection of the available methods and functionality that it offers. The need to reduce file size as aggressively as possible to cater for the mobile space, and the rise of micro-frameworks such as Zepto for example, which delivers a lot of jQuery functionality at a much-reduced size, have pushed jQuery to provide a way of slimming down. As of jQuery 1.8, we can now use the official jQuery build tool to build our own custom version of the library, allowing us to minimize the size of the library by choosing only the functionality we require. For more information on Zepto, see http://zeptojs.com/. Your Hotshot Objectives To successfully conclude this project we'll need to complete the following tasks: Installing Git and Make Installing Node.js Installing Grunt.js Configuring the environment Building a custom jQuery Running unit tests with QUnit Mission Checklist We'll be using Node.js to run the build tool, so you should download a copy of this now. The Node website (http://nodejs.org/download/) has an installer for both 64 and 32-bit versions of Windows, as well as a Mac OS X installer. It also features binaries for Mac OS X, Linux, and SunOS. Download and install the appropriate version for your operating system. The official build tool for jQuery (although it can do much more besides build jQuery) is Grunt.js, written by Ben Alman. We don't need to download this as it's installed via the Node Package Manager (NPM). We'll look at this process in detail later in the project. For more information on Grunt.js, visit the official site at http://gruntjs.com. First of all we need to set up a local working area. We can create a folder in our root project folder called jquery-source. This is where we'll store the jQuery source when we clone the jQuery Github repository, and also where Grunt will build the final version of jQuery. Installing Git and Make The first thing we need to install is Git, which we'll need in order to clone the jQuery source from the Github repository to our own computer so that we can work with the source files. We also need something called Make, but we only need to actually install this on Mac platforms because it gets installed automatically on Windows when Git is installed. As the file we'll create will be for our own use only and we don't want to contribute to jQuery by pushing code back to the repository, we don't need to worry about having an account set up on Github. Prepare for Lift Off First we'll need to download the relevant installers for both Git and Make. Different applications are required depending on whether you are developing on Mac or Windows platforms. Mac developers Mac users can visit http://git-scm.com/download/mac for Git. Next we can install Make. Mac developers can get this by installing XCode. This can be downloaded from https://developer.apple.com/xcode/. Windows developers Windows users can install msysgit, which can be obtained by visiting https://code.google.com/p/msysgit/downloads/detail?name=msysGit-fullinstall-1.8.0-preview20121022.exe. Engage Thrusters Once the installers have downloaded, run them to install the applications. The defaults selected by the installers should be fine for the purposes of this mission. First we should install Git (or msysgit on Windows). Mac developers Mac developers simply need to run the installer for Git to install it to the system. Once this is complete we can then install XCode. All we need to do is run the installer and Make, along with some other tools, will be installed and ready. Windows developers Once the full installer for msysgit has finished, you should be left with a Command Line Interface (CLI) window (entitled MINGW32) indicating that everything is ready for you to hack. However, before we can hack, we need to compile Git. To do this we need to run a file called initialize.sh. In the MINGW32 window, cd into the msysgit directory. If you allowed this to install to the default location, you can use the following command: cd C:msysgitmsysgitsharemsysGit Once we are in the correct directory, we can then run initialize.sh in the CLI. Like the installation, this process can take some time, so be patient and wait for the CLI to return a flashing cursor at the $ character. An Internet connection is required to compile Git in this way. Windows developers will need to ensure that the Git.exe and MINGW resources can be reached via the system's PATH variable. This can be updated by going to Control Panel | System | Advanced system settings | Environment variables. In the bottom section of the dialog box, double-click on Path and add the following two paths to the git.exe file in the bin folder, which is itself in a directory inside the msysgit folder wherever you chose to install it: ;C:msysgitmsysgitbin; C:msysgitmsysgitmingwbin; Update the path with caution! You must ensure that the path to Git.exe is separated from the rest of the Path variables with a semicolon. If the path does not end with a semicolon before adding the path to Git.exe, make sure you add one. Incorrectly updating your path variables can result in system instability and/or loss of data. I have shown a semicolon at the start of the previous code sample to illustrate this. Once the path has been updated, we should then be able to use a regular command prompt to run Git commands. Post-installation tasks In a terminal or Windows Command Prompt (I'll refer to both simply as the CLI from this point on for conciseness) window, we should first cd into the jquery-source folder we created at the start of the project. Depending on where your local development folder is, this command will look something like the following: cd c:jquery-hotshotsjquery-source To clone the jQuery repository, enter the following command in the CLI: git clone git://github.com/jquery/jquery.git Again, we should see some activity on the CLI before it returns to a flashing cursor to indicate that the process is complete. Depending on the platform you are developing on, you should see something like the following screenshot: Objective Complete — Mini Debriefing We installed Git and then used it to clone the jQuery Github repository in to this directory in order to get a fresh version of the jQuery source. If you're used to SVN, cloning a repository is conceptually the same as checking out a repository. Again, the syntax of these commands is very similar on Mac and Windows systems, but notice how we need to escape the backslashes in the path when using Windows. Once this is complete, we should end up with a new directory inside our jquery-source directory called jquery. If we go into this directory, there are some more directories including: build: This directory is used by the build tool to build jQuery speed: This directory contains benchmarking tests src: This directory contains all of the individual source files that are compiled together to make jQuery Test: This directory contains all of the unit tests for jQuery It also has a range of various files, including: Licensing and documentation, including jQuery's authors and a guide to contributing to the project Git-specific files such as .gitignore and .gitmodules Grunt-specific files such as Gruntfile.js JSHint for testing and code-quality purposes Make is not something we need to use directly, but Grunt will use it when we build the jQuery source, so it needs to be present on our system. Installing Node.js Node.js is a platform for running server-side applications built with JavaScript. It is trivial to create a web-server instance, for example, that receives and responds to HTTP requests using callback functions. Server-side JS isn't exactly the same as its more familiar client-side counterpart, but you'll find a lot of similarities in the same comfortable syntax that you know and love. We won't actually be writing any server-side JavaScript in this project – all we need Node for is to run the Grunt.js build tool. Prepare for Lift Off To get the appropriate installer for your platform, visit the Node.js website at http://nodejs.org and hit the download button. The correct installer for your platform, if supported, should be auto-detected. Engage Thrusters Installing Node is a straightforward procedure on either the Windows or Mac platforms as there are installers for both. This task will include running the installer, which is obviously simple, and testing the installation using a CLI. Installing Node is a straightforward procedure on either the Windows or Mac platforms as there are installers for both. This task will include running the installer, which is obviously simple, and testing the installation using a CLI. On Windows or Mac platforms, run the installer and it will guide you through the installation process. I have found that the default options are fine in most cases. As before, we also need to update the Path variable to include Node and Node's package manager NPM. The paths to these directories will differ between platforms. Mac Mac developers should check that the $PATH variable contains a reference to usr/local/bin. I found that this was already in my $PATH, but if you do find that it's not present, you should add it. For more information on updating your $PATH variable, see http://www.tech-recipes.com/rx/2621/os_x_change_path_environment_variable/. Windows Windows developers will need to update the Path variable, in the same way as before, with the following paths: C:Program Filesnodejs; C:UsersDesktopAppDataRoamingnpm; Windows developers may find that the Path variable already contains an entry for Node so may just need to add the path to NPM. Objective Complete — Mini Debriefing Once Node is installed, we will need to use a CLI to interact with it. To verify Node has installed correctly, type the following command into the CLI: node -v The CLI should report the version in use, as follows: We can test NPM in the same way by running the following command: npm -v
Read more
  • 0
  • 0
  • 2528

article-image-getting-started-primefaces
Packt
04 Apr 2013
14 min read
Save for later

Getting Started with PrimeFaces

Packt
04 Apr 2013
14 min read
Setting up and configuring the PrimeFaces library PrimeFaces is a lightweight JSF component library with one JAR file, which needs no configuration and does not contain any required external dependencies. To start with the development of the library, all we need is to get the artifact for the library. Getting ready You can download the PrimeFaces library from http://primefaces.org/downloads.html and you need to add the primefaces-{version}.jar file to your classpath. After that, all you need to do is import the namespace of the library, which is necessary to add the PrimeFaces components to your pages, to get started. If you are using Maven (for more information on installing Maven, please visit http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html), you can retrieve the PrimeFaces library by defining the Maven repository in your Project Object Model (POM) file as follows: <repository> <id>prime-repo</id> <name>PrimeFaces Maven Repository</name> <url>http://repository.primefaces.org</url> </repository> Add the dependency configuration as follows: <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>3.4</version> </dependency> At the time of writing this book, the latest and most stable version of PrimeFaces was 3.4. To check out whether this is the latest available or not, please visit http://primefaces.org/downloads.html The code in this book will work properly with PrimeFaces 3.4. In prior versions or the future versions, some methods, attributes, or components' behaviors may change. How to do it... In order to use PrimeFaces components, we need to add the namespace declarations into our pages. The namespace for PrimeFaces components is as follows: For PrimeFaces Mobile, the namespace is as follows: That is all there is to it. Note that the p prefix is just a symbolic link and any other character can be used to define the PrimeFaces components. Now you can create your first page with a PrimeFaces component as shown in the following code snippet: <html > <f:view contentType="text/html"> <h:head /> <h:body> <h:form> <p:spinner /> </h:form> </h:body> </f:view> </html> This will render a spinner component with an empty value as shown in the following screenshot: A link to the working example for the given page is given at the end of this recipe. How it works... When the page is requested, the p:spinner component is rendered with the renderer implemented by the PrimeFaces library. Since the spinner component is a UI input component, the request-processing lifecycle will get executed when the user inputs data and performs a post back on the page. For the first page, we also needed to provide the contentType parameter for f:view, since the WebKit-based browsers, such as Google Chrome and Apple Safari, request the content type application/xhtml+xml by default. This would overcome unexpected layout and styling issues that might occur. There's more... PrimeFaces only requires Java 5+ runtime and a JSF 2.x implementation as mandatory dependencies. There are some optional libraries for certain features. Dependency Version Type Description JSF runtime iText Apache POI Rome commons-fileupload commons-io 2.0 or 2.1 2.1.7 3.7 1.0 1.2.1 1.4 Required Optional Optional Optional Optional Optional Apache MyFaces or Oracle Mojarra DataExporter (PDF) DataExporter (Excel) FeedReader FileUpload FileUpload Please ensure that you have only one JAR file of PrimeFaces or specific PrimeFaces Theme in your classpath in order to avoid any issues regarding resource rendering. Currently PrimeFaces supports the web browsers IE 7, 8, or 9, Safari, Firefox, Chrome, and Opera. PrimeFaces Cookbook Showcase application This recipe is available in the PrimeFaces Cookbook Showcase application on GitHub at https://github.com/ova2/primefaces-cookbook. You can find the details there for running the project. When the server is running, the showcase for the recipe is available at http://localhost:8080/primefaces-cookbook/views/chapter1 /yourFirstPage.jsf" AJAX basics with Process and Update PrimeFaces provides a partial page rendering (PPR) and view-processing feature based on standard JSF 2 APIs to enable choosing what to process in the JSF lifecycle and what to render in the end with AJAX. PrimeFaces AJAX Framework is based on standard server-side APIs of JSF 2. On the client side, rather than using the client-side API implementations of JSF implementations, such as Mojarra and MyFaces, PrimeFaces scripts are based on the jQuery JavaScript library. How to do it... We can create a simple page with a command button to update a string property with the current time in milliseconds on the server side and an output text to show the value of that string property, as follows: <p:commandButton update="display" action="#{basicPPRController. updateValue}" value="Update" /> <h:outputText id="display" value="#{basicPPRController.value}"/> If we would like to update multiple components with the same trigger mechanism, we can provide the IDs of the components to the update attribute by providing them a space, comma, or both, as follows: <p:commandButton update="display1,display2" /> <p:commandButton update="display1 display2" /> <p:commandButton update="display1,display2 display3" /> In addition, there are reserved keywords that are used for a partial update. We can also make use of these keywords along with the IDs of the components, as described in the following table: Keyword Description @this The component that triggers the PPR is updated @parent The parent of the PPR trigger is updated @form The encapsulating form of the PPR trigger is updated @none PPR does not change the DOM with AJAX response @all The whole document is updated as in non-AJAX requests We can also update a component that resides in a different naming container from the component that triggers the update. In order to achieve this, we need to specify the absolute component identifier of the component that needs to be updated. An example for this could be the following: <h:form id="form1"> <p:commandButton update=":form2:display" action="#{basicPPRController.updateValue}" value="Update" /> </h:form> <h:form id="form2"> <h:outputText id="display" value="#{basicPPRController.value}"/> </h:form> public String updateValue() { value = String.valueOf(System.currentTimeMillis()); return null; } PrimeFaces also provides partial processing, which executes the JSF lifecycle phases—Apply Request Values, Process Validations, Update Model, and Invoke Application—for determined components with the process attribute. This provides the ability to do group validation on the JSF pages easily. Mostly group-validation needs arise in situations where different values need to be validated in the same form, depending on an action that gets executed. By grouping components for validation, errors that would arise from other components when the page has been submitted can be overcome easily. Components like commandButton, commandLink, autoComplete, fileUpload, and many others provide this attribute to process partially instead of the whole view. Partial processing could become very handy in cases when a drop-down list needs to be populated upon a selection on another drop down and when there is an input field on the page with the required attribute set to true. This approach also makes immediate subforms and regions obsolete. It will also prevent submission of the whole page, thus this will result in lightweight requests. Without partially processing the view for the drop downs, a selection on one of the drop downs will result in a validation error on the required field. An example for this is shown in the following code snippet: <h:outputText value="Country: " /> <h:selectOneMenu id="countries" value="#{partialProcessingController. country}"> <f:selectItems value="#{partialProcessingController.countries}" /> <p:ajax listener= "#{partialProcessingController.handleCountryChange}" event="change" update="cities" process="@this"/> </h:selectOneMenu> <h:outputText value="City: " /> <h:selectOneMenu id="cities" value="#{partialProcessingController. city}"> <f:selectItems value="#{partialProcessingController.cities}" /> </h:selectOneMenu> <h:outputText value="Email: " /> <h:inputText value="#{partialProcessingController.email}" required="true" /> With this partial processing mechanism, when a user changes the country, the cities of that country will be populated in the drop down regardless of whether any input exists for the email field. How it works... As seen in partial processing example for updating a component in a different naming container, <p:commandButton> is updating the <h:outputText> component that has the ID display, and absolute client ID :form2:display, which is the search expression for the findComponent method. An absolute client ID starts with the separator character of the naming container, which is : by default. The <h:form>, <h:dataTable>, composite JSF components along with <p:tabView>, <p:accordionPanel>, <p:dataTable>, <p:dataGrid>, <p:dataList>, <p:carousel>, <p:galleria>, <p:ring>, <p:sheet>, and <p:subTable> are the components that implement the NamingContainer interface. The findComponent method, which is described at http://docs.oracle.com/javaee/6/api/javax/faces/component/UIComponent.html, is used by both JSF core implementation and PrimeFaces. There's more... JSF uses : (a colon) as the separator for the NamingContainer interface. The client IDs that will be rendered in the source page will be like :id1:id2:id3. If needed, the configuration of the separator can be changed for the web application to something other than the colon with a context parameter in the web.xml file of the web application, as follows: <context-param> <param-name>javax.faces.SEPARATOR_CHAR</param-name> <param-value>_</param-value> </context-param> It's also possible to escape the : character, if needed, in the CSS files with the character, as :. The problem that might occur with the colon is that it's a reserved keyword for the CSS and JavaScript frameworks, like jQuery, so it might need to be escaped. PrimeFaces Cookbook Showcase application This recipe is available in the PrimeFaces Cookbook Showcase application on GitHub at https://github.com/ova2/primefaces-cookbook. You can find the details there for running the project. For the demos of the showcase, refer to the following: Basic Partial Page Rendering is available at http://localhost:8080/ primefaces-cookbook/views/chapter1/basicPPR.jsf Updating Component in Different Naming Container is available at http://localhost:8080/primefaces-cookbook/views/chapter1/ componentInDifferentNamingContainer.jsf A Partial Processing example at http://localhost:8080/primefacescookbook/ views/chapter1/partialProcessing.jsf Internationalization (i18n) and Localization (L10n) Internationalization (i18n) and Localization (L10n) are two important features that should be provided in the web application's world to make it accessible globally. With Internationalization, we are emphasizing that the web application should support multiple languages; and with Localization, we are stating that the texts, dates, or any other fields should be presented in the form specific to a region. PrimeFaces only provides the English translations. Translations for the other languages should be provided explicitly. In the following sections, you will find the details on how to achieve this. Getting ready For Internationalization, first we need to specify the resource bundle definition under the application tag in faces-config.xml, as follows: <application> <locale-config> <default-locale>en</default-locale> <supported-locale>tr_TR</supported-locale> </locale-config> <resource-bundle> <base-name>messages</base-name> <var>msg</var> </resource-bundle> </application> A resource bundle would be a text file with the .properties suffix that would contain the locale-specific messages. So, the preceding definition states that the resource bundle messages_{localekey}.properties file will reside under classpath and the default value of localekey is en, which is English, and the supported locale is tr_TR, which is Turkish. For projects structured by Maven, the messages_{localekey}.properties file can be created under the src/main/resources project path. How to do it... For showcasing Internationalization, we will broadcast an information message via FacesMessage mechanism that will be displayed in the PrimeFaces growl component. We need two components, the growl itself and a command button, to broadcast the message. <p:growl id="growl" /> <p:commandButton action="#{localizationController.addMessage}" value="Display Message" update="growl" /> The addMessage method of localizationController is as follows: public String addMessage() { addInfoMessage("broadcast.message"); return null; } That uses the addInfoMessage method, which is defined in the static MessageUtil class as follows: public static void addInfoMessage(String str) { FacesContext context = FacesContext.getCurrentInstance(); ResourceBundle bundle = context.getApplication(). getResourceBundle(context, "msg"); String message = bundle.getString(str); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, "")); } Localization of components, such as calendar and schedule, can be achieved by providing the locale attribute. By default, locale information is retrieved from the view's locale and it can be overridden by a string locale key or the java.util.Locale instance. Components such as calendar and schedule use a shared PrimeFaces.locales property to display labels. PrimeFaces only provides English translations, so in order to localize the calendar we need to put corresponding locales into a JavaScript file and include the scripting file to the page. The content for the German locale of the Primefaces.locales property for calendar would be as shown in the following code snippet. For the sake of the recipe, only the German locale definition is given and the Turkish locale definition is omitted. PrimeFaces.locales['de'] = { closeText: 'Schließen', prevText: 'Zurück', nextText: 'Weiter', monthNames: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], monthNamesShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], dayNamesShort: ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'], dayNamesMin: ['S', 'M', 'D', 'M ', 'D', 'F ', 'S'], weekHeader: 'Woche', FirstDay: 1, isRTL: false, showMonthAfterYear: false, yearSuffix: '', timeOnlyTitle: 'Nur Zeit', timeText: 'Zeit', hourText: 'Stunde', minuteText: 'Minute', secondText: 'Sekunde', currentText: 'Aktuelles Datum', ampm: false, month: 'Monat', week: 'Woche', day: 'Tag', allDayText: 'Ganzer Tag' }; Definition of the calendar components with the locale attribute would be as follows: <p:calendar showButtonPanel="true" navigator="true" mode="inline" id="enCal"/> <p:calendar locale="tr" showButtonPanel="true" navigator="true" mode="inline" id="trCal"/> <p:calendar locale="de" showButtonPanel="true" navigator="true" mode="inline" id="deCal"/> They will be rendered as follows: How it works... For Internationalization of the Faces message, the addInfoMessage method retrieves the message bundle via the defined variable msg. It then gets the string from the bundle with the given key by invoking the bundle.getString(str) method. Finally, the message is added by creating a new Faces message with severity level FacesMessage.SEVERITY_INFO. There's more... For some components, Localization could be accomplished by providing labels to the components via attributes, such as with p:selectBooleanButton. <p:selectBooleanButton value="#{localizationController.selectedValue}" onLabel="#{msg['booleanButton.onLabel']}" offLabel="#{msg['booleanButton.offLabel']}" /> The msg variable is the resource bundle variable that is defined in the resource bundle definition in Faces configuration file. The English version of the bundle key definitions in the messages_en.properties file that resides under classpath would be as follows: booleanButton.onLabel=Yes booleanButton.offLabel=No PrimeFaces Cookbook Showcase application This recipe is available in the PrimeFaces Cookbook Showcase application on GitHub at https://github.com/ova2/primefaces-cookbook. You can find the details there for running the project. For the demos of the showcase, refer to the following: Internationalization is available at http://localhost:8080/primefacescookbook/ views/chapter1/internationalization.jsf Localization of the calendar component is available at http://localhost:8080/ primefaces-cookbook/views/chapter1/localization.jsf Localization with resources is available at http://localhost:8080/ primefaces-cookbook/views/chapter1/localizationWithResources. jsf For already translated locales of the calendar, see https://code.google.com/archive/p/primefaces/wikis/PrimeFacesLocales.wiki
Read more
  • 0
  • 0
  • 2661
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at £15.99/month. Cancel anytime
article-image-creating-and-optimizing-your-first-retina-image
Packt
03 Apr 2013
6 min read
Save for later

Creating and optimizing your first Retina image

Packt
03 Apr 2013
6 min read
(For more resources related to this topic, see here.) Creating your first Retina image (Must know) Apple's Retina Display is a brand name for their high pixel density screens. These screens have so many pixels within a small space that the human eye cannot see pixelation, making images and text appear smoother. To compete with Apple's display, other manufacturers are also releasing devices using high-density displays. These types of displays are becoming standard in high quality devices. When you first start browsing the Web using a Retina Display, you'll notice that many images on your favorite sites are blurry. This is a result of low-resolution images being stretched to fill the screen. The effect can make an otherwise beautiful website look unattractive. The key to making your website look exceptional on Retina Displays is the quality of the images that you are using. In this recipe, we will cover the basics of creating high-resolution images and suggestions on how to name your files. Then we'll use some simple HTML to display the image on a web page. Getting ready Creating a Retina-ready site doesn't require any special software beyond what you're already using to build web pages. You'll need a graphics editor (such as Photoshop or GIMP) and your preferred code/text editor. To test the code on Retina Display you'll also need a web server that you can reach from a browser, if you aren't coding directly on the Retina device. The primary consideration in getting started is the quality of your images. A Retina image needs to be at least two times as large as it will be displayed on screen. If you have a photo you'd like to add to your page that is 500 pixels wide, you'll want to start out with an image that is at least 1000 pixels wide. Trying to increase the size of a small image won't work because the extra pixels are what make your image sharp. When designing your own graphics, such as icons and buttons, it's best to create them using a vector graphics program so they will be easy to resize without affecting the quality. Once you have your high-resolution artwork gathered, we're ready to start creating Retina images. How to do it... To get started, let's create a folder on your computer called retina. Inside that folder, create another folder called images. We'll use this as the directory for building our test website. To create your first Retina image, first open a high-resolution image in your graphics editor. You'll want to set the image size to be double the size of what you want to display on the page. For example, if you wanted to display a 700 x 400 pixel image, you would start with an image that is 1400 x 800 pixels. Make sure you aren't increasing the size of the original image or it won't work correctly. Next, save this image as a .jpg file with the filename [email protected] inside of the /images/ folder within the /retina/ folder that we created. Then resize the image to 50 percent and save it as myImage.jpg to the same location. Now we're ready to add our new images to a web page. Create an HTML document called retinaTest.html inside the /retina/ folder. Inside of the basic HTML structure add the two images we created and set the dimensions for both images to the size of the smaller image. <body> <img src = "images/[email protected]" width="700" height="400" /> <img src = "images/myImage.jpg" width="700" height="400" /> </body> If you are working on a Retina device you should be able to open this page locally; if not, upload the folder to your web server and open the page on your device. You will notice how much sharper the first image is than the second image. On a device without a Retina Display, both images will look the same. Congratulations! you've just built your first Retina-optimized web page. How it works... Retina Displays have a higher amount of pixels per inch (PPI) than a normal display. In Apple's devices they have double the PPI of older devices, which is why we created an image that was two times as large as the final image we wanted to display. When that large image is added to the code and then resized to 50 percent, it has more data than what is being shown on a normal display. A Retina device will see that extra pixel data and use it to fill the extra PPI that its screen, contains. Without the added pixel data, the device will use the data available to fill the screen creating a blurry image. You'll notice that this effect is most obvious on large photos and computer graphics like icons. Keep in mind this technique will work with any image format such as .jpg, .png, or .gif. There's more... As an alternative to using the image width and height attributes in HTML, like the previous code, you can also give the image a CSS class with width and height attributes. This is only recommended if you will be using many images that are of the same size and you want to be able to change them easily. <style> .imgHeader { width: 700px; height: 400px; } </style> <img src = "images/[email protected]" class="imgHeader" /> Tips for creating images We created both a Retina and a normal image. It's always a good idea to create both images because the Retina image will be quite a bit larger than the normal one. Then you'll have the option of which image you'd like to have displayed so users without a Retina device don't have to download the larger file. You'll also notice that we added @2x to the filename of the larger image. It's a good practice to create consistent filenames to differentiate the images that are high-resolution. It'll make our coding work much easier going forward. Pixels per inch and dots per inch When designers with a print background first look into creating graphics for Retina Displays there can be some confusion regarding dots per inch (DPI). Keep in mind that computer displays are only concerned with the number of pixels in an image. An 800 x 600 pixel image at 300 DPI will display the same as an 800 x 600 pixel image at 72 DPI.
Read more
  • 0
  • 0
  • 12166

article-image-so-what-django
Packt
26 Mar 2013
7 min read
Save for later

So, what is Django?

Packt
26 Mar 2013
7 min read
(For more resources related to this topic, see here.) I would like to introduce you to Django by using a definition straight from its official website: Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. The first part of this definition makes clear that Django is a software framework written in Python and designed to support the development of web applications by offering a series of solutions to common problems and an abstraction of common design patterns for web development. The second part already gives you a it clear idea of the basic concepts on which Django is built, by highlighting its capabilities on rapid development without compromising the quality and the maintainability of the code. To get the job done in a fast and clean way, the Django stack is made up of a series of layers that have nearly no dependencies between them. This introduces great benefits as it will drive you to code with almost no knowledge sharing between components making future changes easy to apply and avoiding side effects on other components. All this identifies Django as a loosely coupled framework and its structure is a consequence of the just described approach and can be defined as the Model-Template-View (MTV) framework, a variation of the well know architectural pattern called Model-View-Controller (MVC). The MTV structure can be explained in the following way: Model: The application data View: Which data is presented Template: How the data is presented As you can understand from the architectural structure of the framework one of the most basic and important Django components is the Object Relational Mapper (ORM) that lets you define your data models entirely in Python and offers a complete dynamic API to access your database. The template engine also plays an important role in making the framework so great and easy to use—it is built to be designer-friendly. This means the templates are just HTML and that the template language doesn't add any variable assignments or advanced logic, offering only "programming-esque" functionality such as looping. Another innovative concept in the Django template engine is the introduction of template inheritance. The possibility to extend a base template discourages redundancy and helps you to keep the information in one place. The key to the success of a web framework is to also make it possible to easily plug third part modules in it. Django uses this concept and it comes—like Python—with "batteries included". It is built with a system to plug in applications in an easy way and the framework itself already includes a series of useful applications that you can feel free to use or not. One of the included applications that makes Django successful is the automatic admin interface, a complete, user-friendly, and production-ready web admin interface for your projects. It's easy to customize and extend and is a great added value that helps you to speed up most common web projects. In modern web application development, systems are often built for a global audience, and web frameworks have to take into account the need to provide support for internalization and localization. Django has full support for the translation of text, formatting of dates, times, and numbers, and time zones, and all this makes it possible to create multilingual web projects in a clear and easy way. On top of all these great features, Django is shipped with a complete cache framework that is a must-have support in a web framework if we want to grant great performance with high load. This component makes caching an easy task offering supports for different types of cache backends, from memory cache to the most famous, memacached. There are several other reasons that make Django a great framework and most of them can be really understood by diving into the framework, so do not hesitate and let's jump into Django. Installation Installing Django on your system is very easy. As it is just Python, you will only need a small effort to get it up and running on your machine. We will do it in two easy steps: Step 1 – What do I need? The only thing you need on your system to get Django running is obviously Python. At the time of writing this book, the latest version available is the 1.5c1 (release candidate) and it works on all Python versions from 2.6.5 to 2.7, and it also features experimental support for Version 3.2 and Version 3.3. Get the right Python package for your system at http://www.python.org. If you are running Linux or Mac OSX, Python is probably already installed in your operating system. If you are using Windows you will need to add the path of the Python installation folder (C:Python27) to the environment variables. You can verify that Python is installed by typing python in your shell. The expected result should look similar to the following output: Python 2.7.2 (default, Jun 20 2012, 16:23:33) [GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> Step 2 – Get and install Django Now we will see two methods to install Django: through a Python package manager tool called pip and the manual way. Feel free to use the one that you prefer. At the time of writing this book the Django Version 1.5 is in the release candidate status, if this is still the case jump to the manual installation step and download the 1.5 release candidate package in place of the last stable one. Installing Django with pip Install pip; the easiest way is to get the installer from http://www.pip-installer.org: If you are using a Unix OS execute the following command: $ sudo pip install Django If you are using Windows you will need to start a shell with administrator privileges and run the following command: $ pip install Django Installing Django manually Download the last stable release from the official Django website https://www.djangoproject.com/download/. Uncompress the downloaded file using the tool that you prefer. Change to the directory just created (cd Django-X.Y). If you are using a Unix OS execute the following command: $ sudo python setup.py install If you are using Windows you will need to start a shell with administrator privileges and run the command: $ python setup.py install Django Verifying the Django installation To verify that Django is installed on your system you just need to open a shell and launch a Python console by typing python. In the Python console try to import Django: >>> import django >>> django.get_version() '1.5' c1 And that's it!! Now that Django is installed on your system we can start to explore all its potential. Summary In this article we learned about what Django actually is, what you can do with it, and why it's so great. We also learned how to download and install Django with minimum fuss and then set it up so that you can use it as soon as possible. Resources for Article : Further resources on this subject: Creating an Administration Interface in Django [Article] Creating an Administration Interface with Django 1.0 [Article] Views, URLs, and Generic Views in Django 1.0 [Article]
Read more
  • 0
  • 0
  • 1819

article-image-animating-built-button
Packt
19 Mar 2013
8 min read
Save for later

Animating a built-in button

Packt
19 Mar 2013
8 min read
(For more resources related to this topic, see here.) Note that there might be more states to a fully functioning button, for example, there is also a Disabled state, but whether a button is disabled or not usually does not depend on mouse movements or positions, it does not have to be animated, and we do not describe it here. Our purpose in this section is not to create a fully functioning button, but rather to demonstrate some generic concepts for re-styling a control and providing custom animations for it. Let's create a Silverlight project containing a single page with the button in its center. The following is the resulting XAML code of the main page: <UserControl x_Class="AnimatingButtonStates.MainPage" > <Grid x_Name="LayoutRoot" Background="White"> <Button Width="100" Height="25" Background="LightGray" Content="Press Me" /> </Grid> </UserControl> We want to re-style this button completely, modifying it shape, border, colors, and creating custom animations for the transition between states. Now, we'll create a very simple custom template for the button by changing the button code to the following code: <!-- Here we provide custom button template --> <Button> <Button.Template> <ControlTemplate TargetType="Button"> <Grid x_Name="TopLevelButtonGrid"> <!--Button Border--> <Border x_Name="ButtonBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> <!-- button content is placed here--> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </ControlTemplate> </Button.Template> <Button> If we run the code, as it is, we shall be able to see the button and its Press Me content, but the button will not react visually to mouse over or press events. That is because once we replace the button's template we will have to provide our own solution to the visual changes for different button states. Now, let's discuss how we want the button to look in the different states and how we want it to handle the transitions between states. When the mouse is over the button, we want a blue border to appear. The animation to achieve this can be fast or even instantaneous. When the button is pressed, we want it to scale down significantly and we want the button to scale up and down several times, each time with lower amplitude before achieving a steady pressed state. Note that the control template developers and designers usually try to avoid changing colors within animations (they are considered to be more complex and less intuitive); instead, they try to achieve color-changing effects by changing opacities of several template parts. So to change the border to blue on mouse over, let's create another border element MouseOverBorder with blue BorderBrush, and non-zero BorderThickness within the control template. At normal state, its opacity property will be 0, and it will be completely transparent. When the state of the button changes to MouseOver, the opacity of this border will change to 1. After we add the MouseOverBorder element together with the visual state manager functionality, the resulting template code will look as follows: <Button> <Button.Template> <ControlTemplate TargetType="Button"> <Grid x_Name="TopLevelButtonGrid"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualStateGroup.Transitions> <!-- duration for the MouseOver animation is set here to 0.2 seconds --> <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2" /> </VisualStateGroup.Transitions> <VisualState x_Name="Normal" /> <VisualState x_Name="MouseOver"> <VisualState.Storyboard> <Storyboard> <!--animation performed when the button gets into "MouseOver" State--> <DoubleAnimation Storyboard. TargetName="MouseOverBorder" Storyboard.TargetProperty="Opacity" To="1" /> </Storyboard> </VisualState.Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!--Button Border--> <Border x_Name="ButtonBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> <!--MouseOverBorder has opacity 0 normally. Only when the mouse moves over the button, the opacity is changed to 1--> <Border x_Name="MouseOverBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" BorderBrush="Blue" BorderThickness="2" Opacity="0"> </Border> <!-- button content is placed here--> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </ControlTemplate> </Button.Template> </Button> Now, if we start the application, we'll see that the border of the button becomes blue, if the mouse pointer is placed over it, and returns to its usual color when the mouse pointer is moved away from the button, as shown in the following screenshot: The next step is to animate the pressed state. To achieve this, we add a ScaleTransform object to the top-level grid of the button's template: <ControlTemplate TargetType="Button"> <Grid x_Name="TopLevelButtonGrid" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <!-- scale transform is used to shrink the button when it is pressed --> <ScaleTransform x_Name="OnPressedScaleTransform" ScaleX="1" ScaleY="1" /> </Grid.RenderTransform> ... The purpose of the ScaleTransform object is to shrink the button once it is pressed. Originally, its ScaleX and ScaleY parameters are set to 1, while the animation that starts when the button is pressed changes them to 0.5. This animation is defined within VisualState defined as Pressed: <VisualStateGroup> ... <VisualState x_Name="Pressed"> <VisualState.Storyboard> <Storyboard> <!-- animation performed when the button gets into "Pressed" State will scale down the button by a factor of 0.5 in both dimensions --> <DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="TheScaleTransform" To="0.5" /> <DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="TheScaleTransform" To="0.5" /> </Storyboard> </VisualState.Storyboard> </VisualState> ... </VisualStateGroup> VisualState defines the animation storyboard to be triggered once the button switches to the Pressed state. We can also add VisualStateTransition to the VisualStateGroup element's Transition property: <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualStateGroup.Transitions> ... <VisualTransition To="Pressed" GeneratedDuration="0:0:0.5"> <VisualTransition.GeneratedEasingFunction> <!-- elastic ease will provide a few attenuating bounces before the pressed button reaches a steady state --> <ElasticEase /> </VisualTransition.GeneratedEasingFunction> </VisualTransition> </VisualStateGroup.Transitions> ... </VisuateStateGroup> </VisualStateManager.VisualStateGroups> VisualTransition elements allow us to modify the animation behavior depending on what the original and final states of the transition are. It has properties such as From and To for the purpose of specifying the original and final states. In our case, we set only its To property to Pressed, which means that it applies to transit from any state to the Pressed state. VisualTransition sets the duration of the animation to 0.5 second and adds the ElasticEase easing function to it, which results in the button size bouncing effect. Once we started talking about easing functions, we can explain in detail how they work, and give examples of other easing functions. Easing functions provide a way to modify Silverlight (and WPF) animations. A good article describing easing functions can be found at http://tinyurl.com/arbitrarypathanimations. The easing formula presented in this article is: v = (V2 – V1)/T * f(t/T) + V1 Here v is the resulting animation value, t is the time parameter, T is the time period in question (either time between two frames in an animation with frames or time between the To and From values in the case of a simple animation), V2 and V1 are the animation values at the end and beginning of the animation correspondingly at the absence of easing, and f is the easing function. In the previous formula, we assumed a linear animation (not a spline one). There are a bunch of built-in easing functions that come together with the Silverlight framework, for example, BackEase, BounceEase, CircleEase, and so on. For a comprehensive list of built-in easing functions, please check the following website: http://tinyurl.com/silverlighteasing.. Most easing functions have parameters described on this website. As an exercise you can change the easing function in the previous VisualTransition XAML code, modify its parameters, and observe the changes in button animation. Summary Here we have just learned how to animate a built-in button using Silverlight. Resources for Article : Further resources on this subject: Customized Effects with jQuery 1.4 [Article] Python Multimedia: Fun with Animations using Pyglet [Article] Animating Properties and Tweening Pages in Android 3-0 [Article]
Read more
  • 0
  • 0
  • 907

article-image-look-high-level-programming-operations-php-language
Packt
11 Mar 2013
3 min read
Save for later

A look into the high-level programming operations for the PHP language

Packt
11 Mar 2013
3 min read
(For more resources related to this topic, see here.) Accessing documentation PhpStorm offers four different operations that will help you to access the documentation: Quick Definition, Quick Documentation, Parameter Info, and External Documentation. The first one, Quick Definition, presents the definition of a given symbol. You can use it for a variable, function, method, or class. Quick Documentation allows easy access to DocBlocks. It can be used for all kinds of symbols: variables, functions, methods, and classes. The next operation, Parameter Info, presents simplified information about a function or method interface. Finally, External Documentation will help you to access the official PHP documentation available at php.com. Their shortcuts are as follows: Quick Definition (Ctrl + Shift + I, Mac: alt + Space bar) Quick Documentation (Ctrl + Q, Mac: F1) Parameter Info (Ctrl + P, Mac: command + P) External Documentation (Shift + F1, Mac: shift + F1) The Esc (Mac: shift + esc) hotkey will close any of the previous windows. If you place the cursor inside the parenthesis of $s = str_replace(); and run Parameter Info (Ctrl + P, Mac: command + P), you will get the hint showing all the parameters for the str_replace() function. If that is not enough, place the cursor inside the str_replace function name and press Shift + F1 (Mac: shift + F1). You will get the manual for the function. If you want to test the next operation, open the project created in the Quick start – your first PHP application section and place the cursor inside the class name Controller in the src/My/HelloBundle/Controller/DefaultController.php file. The place where you should place the cursor is denoted with bar | in the following code: class DefaultController extends Cont|roller { } The Quick Definition operation will show you the class definition: The Quick Documentation operation will show you the documentation defined with PhpDoc blocks: It is a formal standard for commenting on the PHP code. The official documentation is available at http://www.phpdoc.org. Generators PhpStorm enables you to do the following: Implement magic methods Override inherited methods Generate constructor, getters, setters, and docblocks All of these operations are available in Code | Generate (Alt + Insert, Mac: command + N). Perform the following steps: Create a new class Foo and place the cursor at the position of | : class Person { | } The Generate dialog box will contain the following operations: The Implement Methods dialog box contains all available magic methods: Create the class with two private properties: class Lorem { private $ipsum; private $dolor; } Then go to Code | Generate | Getters and Setters. In the dialog box select both properties: Then press OK. PhpStorm will generate the following methods: class Lorem { private $ipsum; private $dolor; public function setDolor($dolor) { $this->dolor = $dolor; } public function getDolor() { return $this->dolor; } public function setIpsum($ipsum) { $this->ipsum = $ipsum; } public function getIpsum() { return $this->ipsum; } } Next, go to Code | Generate | DocBlocks and in the dialog box select all the properties and methods: PhpStorm will generate docblocks for each of the selected properties and methods, for example: /** * @param $dolor */ public function setDolor($dolor) { $this->dolor = $dolor; } Summary We just learned that in some cases you don't have to type the code at all, as it can be generated automatically. Generators discussed in this article lifted the burden of type setters, getters and magic functions from your shoulders. We also dived into different ways to access documentation here. Resources for Article : Further resources on this subject: Installing PHP-Nuke [Article] An Introduction to PHP-Nuke [Article] Creating Your Own Theme—A Wordpress Tutorial [Article]
Read more
  • 0
  • 0
  • 1256
article-image-yii-adding-users-and-user-management-your-site
Packt
21 Feb 2013
9 min read
Save for later

Yii: Adding Users and User Management to Your Site

Packt
21 Feb 2013
9 min read
(For more resources related to this topic, see here.) Mission Checklist This project assumes that you have a web development environment prepared. The files for this project include a Yii project directory with a database schema. To prepare for the project, carry out the following steps replacing the username lomeara with your own username: Copy the project files into your working directory. cp –r ~/Downloads/project_files/Chapter 3/project_files ~/projects/ch3 Make the directories that Yii uses web writeable. cd ~/projects/ch3/ sudo chown -R lomeara:www-data protected/runtime assets protected/models protected/controllers protected/views If you have a link for a previous project, remove it from the webroot directory. rm /opt/lampp/htdocs/cddb Create a link in the webroot directory to the copied directory. cd /opt/lampp/htdocs sudo ln -s ~/projects/ch3 cbdb Import the project into NetBeans (remember to set the project URL to http://localhost/cbdb) and configure for Yii development with PHPUnit. Create a database named cbdb and load the database schema (~/projects/ch3/ protected/data/schema.sql) into it. If you are not using the XAMPP stack or if your access to MySQL is password protected, you should review and update the Yii configuration file (in NetBeans it is ch3/Source Files/protected/config/main.php). Adding a User Object with CRUD As a foundation for our user management system, we will add a User table to the database and then use Gii to build a quick functional interface. Engage Thrusters Let's set the first building block by adding a User table containing the following information: A username Password hash Reference to a person entry for first name and last name In NetBeans, open a SQL Command window for the cbdb database and run the following command: CREATE TABLE 'user' ( 'id' int(10) unsigned NOT NULL AUTO_INCREMENT, 'username' varchar(20) NOT NULL, 'pwd_hash' char(34) NOT NULL, 'person_id' int(10) unsigned NOT NULL, PRIMARY KEY ('id'), UNIQUE KEY 'username' ('username'), CONSTRAINT 'userperson_ibfk_2' FOREIGN KEY ('person_id') REFERENCES 'person' ('id') ON DELETE CASCADE ) ENGINE=InnoDB; Open a web browser to the Gii URL http://localhost/cbdb/index.php/gii(the password configured in the sample code is yiibook) and use Gii to generate a model from the user table. Then, use Gii to generate CRUD from the user model. Back in NetBeans, add a link to the user index in your site's logged in menu (ch3 | Source Files | protected | views | layouts | main.php). It should look like this: } else { $this->widget('zii.widgets.CMenu',array( 'activeCssClass' => 'active', 'activateParents' => true, 'items'=>array( array('label'=>'Home', 'url'=>array('/site/index')), array('label'=>'Comic Books', 'url'=>array('/book'), 'items' => array( array('label'=>'Publishers', 'url'=>array('/publisher')), ) ), array('label'=>'Users', 'url'=>array('/user/index')), array('label'=>'Logout ('.Yii::app()->user- >name.')', 'url'=>array('/site/logout')) ), )); } ?> Right-click on the project name, run the site, and log in with the default username and password (admin/admin). You will see a menu that includes a link named Users. If you click on the Users link in the menu and then click on Create User, you will see a pretty awful-looking user-creation screen. We are going to fix that. First, we will update the user form to include fields for first name, last name, password, and repeat password. Edit ch3 | Source Files | protected | views | user | _form.php and add those fields. Start by changing all instances of $model to $user. Then, add a call to errorSummary on the person data under the errorSummary call on user. <?php echo $form->errorSummary($user); ?> <?php echo $form->errorSummary($person); ?> Add rows for first name and last name at the beginning of the form. <div class="row"> <?php echo $form->labelEx($person,'fname'); ?> <?php echo $form->textField($person,'fname',array ('size'=>20,'maxlength'=>20)); ?> <?php echo $form->error($person,'fname'); ?> </div> <div class="row"> <?php echo $form->labelEx($person,'lname'); ?> <?php echo $form->textField($person,'lname',array ('size'=>20,'maxlength'=>20)); ?> <?php echo $form->error($person,'lname'); ?> </div> Replace the pwd_hash row with the following two rows: <div class="row"> <?php echo $form->labelEx($user,'password'); ?> <?php echo $form->passwordField($user,'password',array ('size'=>20,'maxlength'=>64)); ?> <?php echo $form->error($user,'password'); ?> </div> <div class="row"> <?php echo $form->labelEx($user,'password_repeat'); ?> <?php echo $form->passwordField($user,'password_repeat',array ('size'=>20,'maxlength'=>64)); ?> <?php echo $form->error($user,'password_repeat'); ?> </div> Finally, remove the row for person_id. These changes are going to completely break the User create/update form for the time being. We want to capture the password data and ultimately make a hash out of it to store securely in the database. To collect the form inputs, we will add password fields to the User model that do not correspond to values in the database. Edit the User model ch3 | Source Files | protected | models | User.php and add two public variables to the class: class User extends CActiveRecord { public $password; public $password_repeat; In the same User model file, modify the attribute labels function to include labels for the new password fields. public function attributeLabels() { return array( 'id' => 'ID', 'username' => 'Username', 'password' => 'Password', 'password_repeat' => 'Password Repeat' ); } In the same User model file, update the rules function with the following rules: Require username Limit length of username and password Compare password with password repeat Accept only safe values for username and password We will come back to this and improve it, but for now, it should look like the following: public function rules() { // NOTE: you should only define rules for those attributes //that will receive user inputs. return array( array('username', 'required'), array('username', 'length', 'max'=>20), array('password', 'length', 'max'=>32), array('password', 'compare'), array('password_repeat', 'safe'), ); } In order to store the user's first and last name, we must change the Create action in the User controller ch3 | Source Files | protected | controllers | UserController. php to create a Person object in addition to a User object. Change the variable name $model to $user, and add an instance of the Person model. public function actionCreate() { $user=new User; $person=new Person; // Uncomment the following line if AJAX validation is //needed // $this->performAjaxValidation($user); if(isset($_POST['User'])) { $user->attributes=$_POST['User']; if($user->save()) $this->redirect(array('view','id'=>$user->id)); } $this->render('create',array( 'user'=>$user, 'person'=>$person, )); } Don't reload the create user page yet. First, update the last line of the User Create view ch3 | Source Files | protected | views | user | create.php to send a User object and a Person object. <?php echo $this->renderPartial('_form', array('user'=>$user, 'person' =>$person)); ?> Make a change to the attributeLabels function in the Person model (ch3 | Source Files | protected | models | Person.php) to display clearer labels for first name and last name. public function attributeLabels() { return array( 'id' => 'ID', 'fname' => 'First Name', 'lname' => 'Last Name', ); } The resulting user form should look like this: Looks pretty good, but if you try to submit the form, you will receive an error. To fix this, we will change the User Create action in the User controller ch3 | Source Files | protected | controllers | UserController.php to check and save both User and Person data. if(isset($_POST['User'], $_POST['Person'])) { $person->attributes=$_POST['Person']; if($person->save()) { $user->attributes=$_POST['User']; $user->person_id = $person->id; if($user->save()) $this->redirect(array('view','id'=>$user->id)); } } Great! Now you can create users, but if you try to edit a user entry, you see another error. This fix will require a couple of more changes. First, in the user controller ch3 | Source Files | protected | controllers | UserController.php, change the loadModel function to load the user model with its related person information: $model=User::model() ->with('person') ->findByPk((int)$id); Next, in the same file, change the actionUpdate function. Add a call to save the person data, if the user save succeeds: if($model->save()) { $model->person->attributes=$_POST['Person']; $model->person->save(); $this->redirect(array('view','id'=>$model->id)); } Then, in the user update view ch3 | Source Files | protected | views | user | update.php, add the person information to the form render. <?php echo $this->renderPartial('_form', array('user'=>$model, 'person' => $model->person)); ?> One more piece of user management housekeeping; try deleting a user. Look in the database for the user and the person info. Oops. Didn't clean up after itself, did it? Update the User controller ch3 | Source Files | protected | controllers | UserController.php once again. Change the call to delete in the User delete action: $this->loadModel($id)->person->delete(); Objective Complete - Mini Debriefing We have added a new object, User, to our site, and associated it with the Person object to capture the user's first and last name. Gii helped us get the basic structure of our user management function in place, and then we altered the model, view, and controller to bring the pieces together.
Read more
  • 0
  • 0
  • 9911

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

Layout with Ext.NET

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

article-image-augmentedti-application-architecture
Packt
31 Dec 2012
5 min read
Save for later

augmentedTi: The application architecture

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

Meet Yii

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

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

Adding Interactivity and Completing Your Site

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